mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 10:46:58 +08:00
fix(host): qemu block device
This commit is contained in:
@@ -32,6 +32,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device"
|
||||
"yunion.io/x/onecloud/pkg/hostman/monitor"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
@@ -191,17 +192,11 @@ func (d *SGuestDiskSyncTask) changeCdrom() {
|
||||
d.guest.Monitor.GetBlocks(d.onGetBlockInfo)
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) onGetBlockInfo(results *jsonutils.JSONArray) {
|
||||
if results == nil {
|
||||
return
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) onGetBlockInfo(blocks []monitor.QemuBlock) {
|
||||
var cdName string
|
||||
rs, _ := results.GetArray()
|
||||
for _, r := range rs {
|
||||
device, _ := r.GetString("device")
|
||||
if regexp.MustCompile(`^ide\d+-cd\d+$`).MatchString(device) {
|
||||
cdName = device
|
||||
for _, r := range blocks {
|
||||
if regexp.MustCompile(`^ide\d+-cd\d+$`).MatchString(r.Device) {
|
||||
cdName = r.Device
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -811,8 +806,8 @@ func (s *SGuestResumeTask) taskFailed(reason string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SGuestResumeTask) onGetBlockInfo(results *jsonutils.JSONArray) {
|
||||
log.Debugf("onGetBlockInfo %s", results)
|
||||
func (s *SGuestResumeTask) onGetBlockInfo(blocks []monitor.QemuBlock) {
|
||||
log.Debugf("onGetBlockInfo %s", blocks)
|
||||
// for _, drv := range results.GetArray() {
|
||||
// // encryption not work
|
||||
// }
|
||||
@@ -933,19 +928,12 @@ func (s *SGuestStreamDisksTask) checkBlockDrives() {
|
||||
s.Monitor.GetBlocks(s.onBlockDrivesSucc)
|
||||
}
|
||||
|
||||
func (s *SGuestStreamDisksTask) onBlockDrivesSucc(res *jsonutils.JSONArray) {
|
||||
func (s *SGuestStreamDisksTask) onBlockDrivesSucc(blocks []monitor.QemuBlock) {
|
||||
s.streamDevs = []string{}
|
||||
drvs, _ := res.GetArray()
|
||||
for _, drv := range drvs {
|
||||
device, err := drv.GetString("device")
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
continue
|
||||
}
|
||||
inserted, err := drv.Get("inserted")
|
||||
if err == nil && inserted.Contains("file") && inserted.Contains("backing_file") {
|
||||
for _, block := range blocks {
|
||||
if len(block.Inserted.File) > 0 && len(block.Inserted.BackingFile) > 0 {
|
||||
var stream = false
|
||||
idx := device[len(device)-1] - '0'
|
||||
idx := block.Device[len(block.Device)-1] - '0'
|
||||
for i := 0; i < len(s.disksIdx); i++ {
|
||||
if int(idx) == s.disksIdx[i] {
|
||||
stream = true
|
||||
@@ -954,7 +942,7 @@ func (s *SGuestStreamDisksTask) onBlockDrivesSucc(res *jsonutils.JSONArray) {
|
||||
if !stream {
|
||||
continue
|
||||
}
|
||||
s.streamDevs = append(s.streamDevs, device)
|
||||
s.streamDevs = append(s.streamDevs, block.Device)
|
||||
}
|
||||
}
|
||||
log.Infof("Stream devices %s: %v", s.GetName(), s.streamDevs)
|
||||
@@ -1070,14 +1058,13 @@ func (s *SGuestReloadDiskTask) Start() {
|
||||
}
|
||||
|
||||
func (s *SGuestReloadDiskTask) fetchDisksInfo(callback func(string)) {
|
||||
s.Monitor.GetBlocks(func(res *jsonutils.JSONArray) { s.onGetBlocksSucc(res, callback) })
|
||||
s.Monitor.GetBlocks(func(blocks []monitor.QemuBlock) { s.onGetBlocksSucc(blocks, callback) })
|
||||
}
|
||||
|
||||
func (s *SGuestReloadDiskTask) onGetBlocksSucc(res *jsonutils.JSONArray, callback func(string)) {
|
||||
func (s *SGuestReloadDiskTask) onGetBlocksSucc(blocks []monitor.QemuBlock, callback func(string)) {
|
||||
var device string
|
||||
devs, _ := res.GetArray()
|
||||
for _, d := range devs {
|
||||
device = s.getDiskOfDrive(d)
|
||||
for i := range blocks {
|
||||
device = s.getDiskOfDrive(blocks[i])
|
||||
if len(device) > 0 {
|
||||
callback(device)
|
||||
break
|
||||
@@ -1089,18 +1076,12 @@ func (s *SGuestReloadDiskTask) onGetBlocksSucc(res *jsonutils.JSONArray, callbac
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SGuestReloadDiskTask) getDiskOfDrive(d jsonutils.JSONObject) string {
|
||||
inserted, err := d.Get("inserted")
|
||||
if err != nil {
|
||||
func (s *SGuestReloadDiskTask) getDiskOfDrive(block monitor.QemuBlock) string {
|
||||
if len(block.Inserted.File) == 0 {
|
||||
return ""
|
||||
}
|
||||
file, err := inserted.GetString("file")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
if file == s.disk.GetPath() {
|
||||
drive, _ := d.GetString("device")
|
||||
return drive
|
||||
if block.Inserted.File == s.disk.GetPath() {
|
||||
return block.Device
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -1391,24 +1372,21 @@ func (task *SGuestOnlineResizeDiskTask) Start() {
|
||||
task.Monitor.GetBlocks(task.OnGetBlocksSucc)
|
||||
}
|
||||
|
||||
func (task *SGuestOnlineResizeDiskTask) OnGetBlocksSucc(results *jsonutils.JSONArray) {
|
||||
for i := 0; i < results.Size(); i += 1 {
|
||||
result, _ := results.GetAt(i)
|
||||
fileStr, _ := result.GetString("inserted", "file")
|
||||
func (task *SGuestOnlineResizeDiskTask) OnGetBlocksSucc(blocks []monitor.QemuBlock) {
|
||||
for i := 0; i < blocks; i += 1 {
|
||||
image := ""
|
||||
if strings.HasPrefix(fileStr, "json:") {
|
||||
if strings.HasPrefix(blocks[i].Inserted.File, "json:") {
|
||||
//RBD磁盘格式如下
|
||||
//json:{"driver": "raw", "file": {"pool": "testpool01", "image": "952636e3-73ed-4a19-8648-05e69e6bb57a", "driver": "rbd", "=keyvalue-pairs": "[\"mon_host\", \"10.127.10.230;10.127.10.237;10.127.10.238\", \"key\", \"AQBZ/Ddd0j5BCxAAfuvl5oHWsmuTGer6T9LzeQ==\", \"rados_mon_op_timeout\", \"5\", \"rados_osd_op_timeout\", \"1200\", \"client_mount_timeout\", \"120\"]"}
|
||||
fileJson, err := jsonutils.ParseString(fileStr[5:])
|
||||
fileJson, err := jsonutils.ParseString(blocks[i].Inserted.File[5:])
|
||||
if err != nil {
|
||||
hostutils.TaskFailed(task.ctx, fmt.Sprintf("parse file json %s error: %v", fileStr, err))
|
||||
hostutils.TaskFailed(task.ctx, fmt.Sprintf("parse file json %s error: %v", blocks[i].Inserted.File, err))
|
||||
return
|
||||
}
|
||||
image, _ = fileJson.GetString("file", "image")
|
||||
}
|
||||
if len(fileStr) > 0 && strings.HasSuffix(fileStr, task.diskId) || image == task.diskId {
|
||||
driveName, _ := result.GetString("device")
|
||||
task.Monitor.ResizeDisk(driveName, task.sizeMB, task.OnResizeSucc)
|
||||
if len(blocks[i].Inserted.File) > 0 && strings.HasSuffix(blocks[i].Inserted.File, task.diskId) || image == task.diskId {
|
||||
task.Monitor.ResizeDisk(blocks[i].Device, task.sizeMB, task.OnResizeSucc)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1568,17 +1546,11 @@ func (task *SGuestBlockIoThrottleTask) findBlockDevices() {
|
||||
task.Monitor.GetBlocks(task.onBlockDriversSucc)
|
||||
}
|
||||
|
||||
func (task *SGuestBlockIoThrottleTask) onBlockDriversSucc(res *jsonutils.JSONArray) {
|
||||
func (task *SGuestBlockIoThrottleTask) onBlockDriversSucc(blocks []monitor.QemuBlock) {
|
||||
drivers := make([]string, 0)
|
||||
for i := 0; i < res.Length(); i++ {
|
||||
device, err := res.GetAt(i)
|
||||
if err == nil {
|
||||
driver, err := device.GetString("device")
|
||||
if err == nil {
|
||||
if strings.HasPrefix(driver, "drive_") {
|
||||
drivers = append(drivers, driver)
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(blocks); i++ {
|
||||
if strings.HasPrefix(blocks[i].Device, "drive_") {
|
||||
drivers = append(drivers, blocks[i].Device)
|
||||
}
|
||||
}
|
||||
log.Infof("Drivers %s do io throttle bps %d iops %d", drivers, task.bps, task.iops)
|
||||
@@ -1634,17 +1606,11 @@ func (task *SCancelBlockJobs) findBlockDevices() {
|
||||
task.Monitor.GetBlocks(task.onBlockDriversSucc)
|
||||
}
|
||||
|
||||
func (task *SCancelBlockJobs) onBlockDriversSucc(res *jsonutils.JSONArray) {
|
||||
func (task *SCancelBlockJobs) onBlockDriversSucc(blocks []monitor.QemuBlock) {
|
||||
drivers := make([]string, 0)
|
||||
for i := 0; i < res.Length(); i++ {
|
||||
device, err := res.GetAt(i)
|
||||
if err == nil {
|
||||
driver, err := device.GetString("device")
|
||||
if err == nil {
|
||||
if strings.HasPrefix(driver, "drive_") {
|
||||
drivers = append(drivers, driver)
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(blocks); i++ {
|
||||
if strings.HasPrefix(blocks[i].Device, "drive_") {
|
||||
drivers = append(drivers, blocks[i].Device)
|
||||
}
|
||||
}
|
||||
task.StartCancelBlockJobs(drivers)
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/regutils2"
|
||||
@@ -222,7 +221,7 @@ func (m *HmpMonitor) GetVersion(callback StringCallback) {
|
||||
m.Query("info version", _cb)
|
||||
}
|
||||
|
||||
func (m *HmpMonitor) GetBlocks(callback func(*jsonutils.JSONArray)) {
|
||||
func (m *HmpMonitor) GetBlocks(callback func([]QemuBlock)) {
|
||||
var cb = func(output string) {
|
||||
var lines = strings.Split(strings.TrimSuffix(output, "\r\n"), "\r\n")
|
||||
var mergedOutput = []string{}
|
||||
@@ -240,34 +239,30 @@ func (m *HmpMonitor) GetBlocks(callback func(*jsonutils.JSONArray)) {
|
||||
}
|
||||
|
||||
// parse to json
|
||||
var outputJson = jsonutils.NewArray()
|
||||
ret := []QemuBlock{}
|
||||
for _, line := range mergedOutput {
|
||||
parts := regexp.MustCompile(`\s+`).Split(line, -1)
|
||||
if strings.HasSuffix(parts[0], ":") ||
|
||||
regexp.MustCompile(`\(#block\d+\):`).MatchString(parts[1]) {
|
||||
|
||||
drv := jsonutils.NewDict()
|
||||
block := QemuBlock{}
|
||||
if strings.HasSuffix(parts[0], ":") {
|
||||
drv.Set("device", jsonutils.NewString(parts[0][:len(parts[0])-1]))
|
||||
block.Device = parts[0][:len(parts[0])-1]
|
||||
} else {
|
||||
drv.Set("device", jsonutils.NewString(parts[0]))
|
||||
block.Device = parts[0]
|
||||
}
|
||||
if regexp.MustCompile(`\(#block\d+\):`).MatchString(parts[1]) {
|
||||
inserted := jsonutils.NewDict()
|
||||
inserted.Set("file", jsonutils.NewString(parts[2]))
|
||||
block.Inserted.File = parts[2]
|
||||
for i := 0; i < len(parts)-2; i++ {
|
||||
if parts[i] == "Backing" && parts[i+1] == "file:" {
|
||||
inserted.Set("backing_file", jsonutils.NewString(parts[i+2]))
|
||||
block.Inserted.BackingFile = parts[i+2]
|
||||
break
|
||||
}
|
||||
}
|
||||
drv.Set("inserted", inserted)
|
||||
}
|
||||
outputJson.Add(drv)
|
||||
ret = append(ret, block)
|
||||
}
|
||||
}
|
||||
|
||||
callback(outputJson)
|
||||
callback(ret)
|
||||
}
|
||||
|
||||
m.Query("info block", cb)
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
)
|
||||
@@ -50,6 +49,61 @@ type BlockJob struct {
|
||||
speedMbps float64
|
||||
}
|
||||
|
||||
type QemuBlock struct {
|
||||
IoStatus string `json:"io-status"`
|
||||
Device string
|
||||
Locked bool
|
||||
Removable bool
|
||||
Qdev string
|
||||
TrayOpen bool
|
||||
Type string
|
||||
Inserted struct {
|
||||
Ro bool
|
||||
Drv string
|
||||
Encrypted bool
|
||||
File string
|
||||
BackingFile string
|
||||
BackingFileDepth int
|
||||
Bps int64
|
||||
BpsRd int64
|
||||
BpsWr int
|
||||
Iops int64
|
||||
IopsRd int
|
||||
IopsWr int
|
||||
BpsMax int64
|
||||
BpsRdMax int64
|
||||
BpsWrMax int64
|
||||
IopsMax int
|
||||
IopsRdMax int
|
||||
IopsWrMax int
|
||||
IopsSize int64
|
||||
DetectZeroes string
|
||||
WriteThreshold int
|
||||
Image struct {
|
||||
Filename string
|
||||
Format string
|
||||
VirtualSize int64 `json:"virtual-size"`
|
||||
BackingFile string
|
||||
FullBackingFilename string `json:"full-backing-filename"`
|
||||
BackingFilenameFormat string `json:"backing-filename-format"`
|
||||
Snapshots []struct {
|
||||
Id string
|
||||
Name string
|
||||
VmStateSize int `json:"vm-state-size"`
|
||||
DateSec int64 `json:"date-sec"`
|
||||
DateNsec int `json:"date-nsec"`
|
||||
VmClockSec int `json:"vm-clock-sec"`
|
||||
VmClockNsec int `json:"vm-clock-nsec"`
|
||||
}
|
||||
BackingImage struct {
|
||||
filename string
|
||||
format string
|
||||
VirtualSize int64 `json:"virtual-size"`
|
||||
} `json:"backing-image"`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type blockSizeByte int64
|
||||
|
||||
func (self blockSizeByte) String() string {
|
||||
@@ -105,7 +159,7 @@ type Monitor interface {
|
||||
AddCpu(cpuIndex int, callback StringCallback)
|
||||
GeMemtSlotIndex(func(index int))
|
||||
|
||||
GetBlocks(callback func(*jsonutils.JSONArray))
|
||||
GetBlocks(callback func([]QemuBlock))
|
||||
EjectCdrom(dev string, callback StringCallback)
|
||||
ChangeCdrom(dev string, path string, callback StringCallback)
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@ func (m *QmpMonitor) parseVersion(callback StringCallback) qmpMonitorCallBack {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *QmpMonitor) GetBlocks(callback func(*jsonutils.JSONArray)) {
|
||||
func (m *QmpMonitor) GetBlocks(callback func([]QemuBlock)) {
|
||||
var cb = func(res *Response) {
|
||||
if res.ErrorVal != nil {
|
||||
callback(nil)
|
||||
@@ -418,8 +418,9 @@ func (m *QmpMonitor) GetBlocks(callback func(*jsonutils.JSONArray)) {
|
||||
log.Errorf("Get %s block error %s", m.server, err)
|
||||
callback(nil)
|
||||
}
|
||||
jra, _ := jr.(*jsonutils.JSONArray)
|
||||
callback(jra)
|
||||
blocks := []QemuBlock{}
|
||||
jr.Unmarshal(&blocks)
|
||||
callback(blocks)
|
||||
}
|
||||
|
||||
cmd := &Command{Execute: "query-block"}
|
||||
|
||||
Reference in New Issue
Block a user