mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 02:37:24 +08:00
temp commit
This commit is contained in:
@@ -102,7 +102,6 @@ func (f *SLocalGuestFS) Cleandir(dir string, keepdir, caseInsensitive bool) erro
|
||||
return fmt.Errorf("No such file %s", sPath)
|
||||
}
|
||||
|
||||
// TODO
|
||||
func (f *SLocalGuestFS) Zerofiles(dir string, caseInsensitive bool) error {
|
||||
sPath := f.getLocalPath(dir, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
@@ -20,6 +19,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
const VNC_PORT_BASE = 5900
|
||||
|
||||
type SGuestManager struct {
|
||||
host hostutils.IHost
|
||||
ServersPath string
|
||||
Servers map[string]*SKVMGuestInstance
|
||||
CandidateServers map[string]*SKVMGuestInstance
|
||||
@@ -40,8 +41,9 @@ type SGuestManager struct {
|
||||
isLoaded bool
|
||||
}
|
||||
|
||||
func NewGuestManager(serversPath string) *SGuestManager {
|
||||
func NewGuestManager(host hostutils.IHost, serversPath string) *SGuestManager {
|
||||
manager := &SGuestManager{}
|
||||
manager.host = host
|
||||
manager.ServersPath = serversPath
|
||||
manager.Servers = make(map[string]*SKVMGuestInstance, 0)
|
||||
manager.CandidateServers = make(map[string]*SKVMGuestInstance, 0)
|
||||
@@ -66,14 +68,13 @@ func (m *SGuestManager) Bootstrap() {
|
||||
}
|
||||
|
||||
func (m *SGuestManager) VerifyExistingGuests(pendingDelete bool) {
|
||||
params := url.Values{
|
||||
"limit": {"0"},
|
||||
"admin": {"True"},
|
||||
"system": {"True"},
|
||||
"pending_delete": {fmt.Sprintf("%s", pendingDelete)},
|
||||
}
|
||||
// TODO get host id
|
||||
params.Set("filter.0", fmt.Sprintf("host_id.equals(%s)", "get host id "))
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("limit", jsonutils.NewInt(0))
|
||||
params.Set("admin", jsonutils.JSONTrue)
|
||||
params.Set("system", jsonutils.JSONTrue)
|
||||
params.Set("pending_delete", jsonutils.NewBool(pendingDelete))
|
||||
params.Set("filter.0", jsonutils.NewString(
|
||||
fmt.Sprintf("host_id.equals(%s)", m.host.GetHostId())))
|
||||
if len(m.CandidateServers) > 0 {
|
||||
keys := make([]string, len(m.CandidateServers))
|
||||
var index = 0
|
||||
@@ -81,9 +82,9 @@ func (m *SGuestManager) VerifyExistingGuests(pendingDelete bool) {
|
||||
keys[index] = k
|
||||
index++
|
||||
}
|
||||
params.Set("filter.1", strings.Join(keys, ","))
|
||||
params.Set("filter.1", jsonutils.NewString(strings.Join(keys, ",")))
|
||||
}
|
||||
res, err := modules.Servers.List(hostutils.GetComputeSession(context.Background()), id, params)
|
||||
res, err := modules.Servers.List(hostutils.GetComputeSession(context.Background()), params)
|
||||
if err != nil {
|
||||
m.OnVerifyExistingGuestsFail(err, pendingDelete)
|
||||
} else {
|
||||
@@ -130,7 +131,19 @@ func (m *SGuestManager) RemoveCandidateServer(server *SKVMGuestInstance) {
|
||||
}
|
||||
|
||||
func (m *SGuestManager) OnLoadExistingGuestsComplete() {
|
||||
log.Infof("Load existing guests complete...")
|
||||
err := m.host.PutHostOnline()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
|
||||
// TODO
|
||||
// hostmetrics.Init()
|
||||
|
||||
if !options.HostOptions.EnableCpuBinding {
|
||||
// TODO
|
||||
// m.cleanupCpuset()
|
||||
}
|
||||
}
|
||||
|
||||
func (m *SGuestManager) StartCpusetBalancer() {
|
||||
@@ -316,7 +329,7 @@ func (m *SGuestManager) GuestStart(ctx context.Context, sid string, body jsonuti
|
||||
if err := guest.StartGuest(ctx, params); err != nil {
|
||||
return nil, httperrors.NewBadRequestError("Failed to start server")
|
||||
} else {
|
||||
return jsonutils.NewDict(jsonutils.JSONPair{"vnc_port", jsonutils.NewInt(0)}), nil
|
||||
return jsonutils.NewDict(jsonutils.NewPair("vnc_port", jsonutils.NewInt(0))), nil
|
||||
}
|
||||
} else {
|
||||
vncPort := guest.GetVncPort()
|
||||
@@ -555,7 +568,8 @@ func (m *SGuestManager) DeleteSnapshot(ctx context.Context, params interface{})
|
||||
return guest.ExecDeleteSnapshotTask(ctx, delParams.Disk, delParams.DeleteSnapshot,
|
||||
delParams.ConvertSnapshot, delParams.PendingDelete)
|
||||
} else {
|
||||
return nil, delParams.Disk.DeleteSnapshot(delParams.DeleteSnapshot)
|
||||
return jsonutils.NewDict(jsonutils.NewPair("deleted", jsonutils.JSONTrue)),
|
||||
delParams.Disk.DeleteSnapshot(delParams.DeleteSnapshot)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,9 +591,9 @@ func Stop() {
|
||||
guestManger.ExitGuestCleanup()
|
||||
}
|
||||
|
||||
func Init(serversPath string) {
|
||||
func Init(host hostutils.IHost, serversPath string) {
|
||||
if guestManger == nil {
|
||||
guestManger = NewGuestManager(serversPath)
|
||||
guestManger = NewGuestManager(host, serversPath)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -716,9 +716,7 @@ func (s *SGuestReloadDiskTask) onResumeSucc(results string) {
|
||||
|
||||
func (s *SGuestReloadDiskTask) taskFailed(reason string) {
|
||||
log.Errorf("SGuestReloadDiskTask error: %s", reason)
|
||||
if _, err := hostutils.TaskFailed(s.ctx, reason); err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
hostutils.TaskFailed(s.ctx, reason)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -764,10 +762,7 @@ func (s *SGuestDiskSnapshotTask) onSnapshotBlkdevFail(string) {
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
_, err = hostutils.TaskFailed(s.ctx, "Reload blkdev error")
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
hostutils.TaskFailed(s.ctx, "Reload blkdev error")
|
||||
}
|
||||
|
||||
func (s *SGuestDiskSnapshotTask) onResumeSucc(res string) {
|
||||
@@ -775,7 +770,7 @@ func (s *SGuestDiskSnapshotTask) onResumeSucc(res string) {
|
||||
snapshotDir := s.disk.GetSnapshotDir()
|
||||
snapshotLocation := path.Join(snapshotDir, s.snapshotId)
|
||||
_, err := hostutils.TaskComplete(s.ctx, jsonutils.NewDict(
|
||||
jsonutils.JSONPair{"localtion", jsonutils.NewString(snapshotLocation)}))
|
||||
jsonutils.NewPair("localtion", jsonutils.NewString(snapshotLocation))))
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
@@ -882,7 +877,7 @@ func (s *SGuestSnapshotDeleteTask) onResumeSucc(res string) {
|
||||
exec.Command("rm", "-f", path.Join(snapshotDir, s.deleteSnapshot))
|
||||
}
|
||||
_, err := hostutils.TaskComplete(s.ctx,
|
||||
jsonutils.NewDict(jsonutils.JSONPair{"localtion", jsonutils.JSONTrue}))
|
||||
jsonutils.NewDict(jsonutils.NewPair("deleted", jsonutils.JSONTrue)))
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
|
||||
@@ -311,6 +311,10 @@ func (s *SKVMGuestInstance) StartMonitor(ctx context.Context) {
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) delayStartMonitor(ctx context.Context) {
|
||||
if s.GetQmpMonitorPort(-1) > 0 {
|
||||
// TODO enable hmp?
|
||||
}
|
||||
|
||||
if options.HostOptions.EnableQmpMonitor && s.GetQmpMonitorPort(-1) > 0 {
|
||||
s.Monitor = monitor.NewQmpMonitor(
|
||||
s.onMonitorDisConnect,
|
||||
@@ -333,8 +337,7 @@ func (s *SKVMGuestInstance) onGetQemuVersion(ctx context.Context, version string
|
||||
log.Infof("Guest(%s) qemu version %s", s.Id, s.QemuVersion)
|
||||
if s.Desc.Contains("live_migrate_dest_port") && ctx != nil {
|
||||
migratePort, _ := s.Desc.Get("live_migrate_dest_port")
|
||||
body := jsonutils.NewDict(
|
||||
jsonutils.JSONPair{"live_migrate_dest_port", migratePort})
|
||||
body := jsonutils.NewDict(jsonutils.NewPair("live_migrate_dest_port", migratePort))
|
||||
hostutils.TaskComplete(ctx, body)
|
||||
} else if jsonutils.QueryBoolean(s.Desc, "is_slave", false) {
|
||||
// TODO
|
||||
@@ -375,6 +378,17 @@ func (s *SKVMGuestInstance) onMonitorTimeout(ctx context.Context, err error) {
|
||||
func() { s.asyncScriptStart(ctx, jsonutils.NewDict()) })
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) GetHmpMonitorPort(vncPort int) int {
|
||||
if vncPort <= 0 {
|
||||
vncPort = s.GetVncPort()
|
||||
}
|
||||
if vncPort > 0 {
|
||||
return vncPort + MONITOR_PORT_BASE
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) GetQmpMonitorPort(vncPort int) int {
|
||||
if vncPort <= 0 {
|
||||
vncPort = s.GetVncPort()
|
||||
@@ -518,7 +532,6 @@ func (s *SKVMGuestInstance) delTmpDisks(ctx context.Context, migrated bool) {
|
||||
for _, disk := range disks {
|
||||
if disk.Contains("path") {
|
||||
diskPath, _ := disk.GetString("path")
|
||||
// TODO GetDisksByPath, storagetypes, deleteallsnapshot, delete
|
||||
d := storageman.GetManager().GetDiskByPath(diskPath)
|
||||
if d != nil && d.GetType == storagetypes.STORAGE_LOCAL && migrated {
|
||||
if err := d.DeleteAllSnapshot(); err != nil {
|
||||
@@ -1008,5 +1021,5 @@ func (s *SKVMGuestInstance) deleteStaticSnapshotFile(
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
return jsonutils.NewDict(jsonutils.JSONPair{"localtion", jsonutils.JSONTrue}), nil
|
||||
return jsonutils.NewDict(jsonutils.JSONPair{"deleted", jsonutils.JSONTrue}), nil
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ func (s *SKVMGuestInstance) generateStartScript(data *jsonutils.JSONDict) string
|
||||
cmd += fmt.Sprintf(" -cpu %s", cpu_type)
|
||||
|
||||
// TODO hmp - -
|
||||
// cmd += s.getMonitorDesc("hmqmon", s.GetQmpMonitorPort(int(vncPort)), MODE_READLINE)
|
||||
cmd += s.getMonitorDesc("hmqmon", s.GetQmpMonitorPort(int(vncPort)), MODE_READLINE)
|
||||
if options.HostOptions.EnableQmpMonitor {
|
||||
cmd += s.getMonitorDesc("qmqmon", s.GetQmpMonitorPort(int(vncPort)), MODE_CONTROL)
|
||||
}
|
||||
|
||||
@@ -41,8 +41,9 @@ var (
|
||||
)
|
||||
|
||||
type SHostInfo struct {
|
||||
isRegistered bool
|
||||
IsRegistered chan struct{}
|
||||
isRegistered bool
|
||||
IsRegistered chan struct{}
|
||||
registerCallback func()
|
||||
|
||||
kvmModuleSupport string
|
||||
nestStatus string
|
||||
@@ -644,7 +645,8 @@ func (h *SHostInfo) GetMatchNic(bridge, iface, mac string) *SNIC {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *SHostInfo) StartRegister(delay int) {
|
||||
func (h *SHostInfo) StartRegister(delay int, callback func()) {
|
||||
h.registerCallback = callback
|
||||
timeutils2.AddTimeout(delay*time.Second, h.register)
|
||||
}
|
||||
|
||||
@@ -853,6 +855,13 @@ func (h *SHostInfo) putHostOffline() {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *SHostInfo) PutHostOnline() error {
|
||||
_, err := modules.Hosts.PerformAction(
|
||||
hostutils.GetComputeSession(context.Background()),
|
||||
h.HostId, "online", nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *SHostInfo) getNetworkInfo() {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("details", jsonutils.JSONTrue)
|
||||
@@ -1103,6 +1112,10 @@ func (h *SHostInfo) onSucc() {
|
||||
// TODO
|
||||
h.StartPinger()
|
||||
|
||||
if h.registerCallback != nil {
|
||||
h.registerCallback()
|
||||
}
|
||||
|
||||
// To notify caller, host register is success
|
||||
close(h.IsRegistered)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,14 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
type IHost interface {
|
||||
GetZone() string
|
||||
GetHostId() string
|
||||
GetMediumType() string
|
||||
|
||||
PutHostOnline() error
|
||||
}
|
||||
|
||||
func GetComputeSession(ctx context.Context) *mcclient.ClientSession {
|
||||
return auth.GetAdminSession(ctx, options.HostOptions.Region, "v2")
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@ type SHostOptions struct {
|
||||
DefaultWriteBpsPerCpu int `default:"54525952" help:"Default write bps per cpu for hard IO limit"`
|
||||
DefaultWriteIopsPerCpu int `default:"416" help:"Default write iops per cpu for hard IO limit"`
|
||||
SetVncPassword bool `default:"true" help:"Auto set vnc password after monitor connected"`
|
||||
|
||||
EnableCpuBinding bool `default:"true" help:"Enable cpu binding and rebalance"`
|
||||
}
|
||||
|
||||
var HostOptions SHostOptions
|
||||
|
||||
@@ -32,23 +32,19 @@ func (host *SHostService) StartService() {
|
||||
log.Fatalf(err)
|
||||
}
|
||||
|
||||
if err := storageman.Init(hostInstance.HostId, hostInstance.Zone); err != nil {
|
||||
if err := storageman.Init(hostInstance); err != nil {
|
||||
log.Fatalf(err)
|
||||
}
|
||||
// wait host registerd
|
||||
|
||||
// Firewall.Init()
|
||||
guestman.Init(hostInstance, options.HostOptions.ServersPath)
|
||||
|
||||
var c = make(chan struct{})
|
||||
cloudcommon.InitAuth(&options.HostOptions.Options, func() {
|
||||
log.Infof("Auth complete!!")
|
||||
|
||||
hostinfo.Instance().StartRegister()
|
||||
hostInstance.StartRegister(5, guestman.GetGuestManager().Bootstrap)
|
||||
<-hostinfo.Instance().IsRegistered
|
||||
|
||||
guestman.Init(options.HostOptions.ServersPath)
|
||||
guestman.GetGuestManager().Bootstrap()
|
||||
|
||||
close(c)
|
||||
})
|
||||
|
||||
|
||||
@@ -7,20 +7,14 @@ import (
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/storagetypes"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
)
|
||||
|
||||
const MINIMAL_FREE_SPACE = 128
|
||||
|
||||
type IHost interface {
|
||||
GetZone() string
|
||||
GetHostId() string
|
||||
|
||||
GetMediumType() string
|
||||
}
|
||||
|
||||
type SStorageManager struct {
|
||||
host IHost
|
||||
host hostutils.IHost
|
||||
|
||||
Storages []IStorage
|
||||
AgentStorage IStorage
|
||||
@@ -32,7 +26,7 @@ type SStorageManager struct {
|
||||
NfsStorageImagecacheManagers map[string]IImageCacheManger
|
||||
}
|
||||
|
||||
func NewStorageManager(host IHost) (*SStorageManager, error) {
|
||||
func NewStorageManager(host hostutils.IHost) (*SStorageManager, error) {
|
||||
var (
|
||||
ret = &SStorageManager{
|
||||
host: host,
|
||||
@@ -276,7 +270,7 @@ func Manager() *SStorageManager {
|
||||
return storageManager
|
||||
}
|
||||
|
||||
func Init(host IHost) error {
|
||||
func Init(host hostutils.IHost) error {
|
||||
var (
|
||||
err error
|
||||
zone = host.GetZone()
|
||||
|
||||
@@ -14,32 +14,31 @@ import (
|
||||
type IDisk interface {
|
||||
GetId() string
|
||||
Probe() error
|
||||
|
||||
GetPath() string
|
||||
GetSnapshotDir() string
|
||||
GetDiskDesc() jsonutils.JSONObject
|
||||
GetDiskSetupScripts(idx int) string
|
||||
|
||||
// TODO
|
||||
// DeleteAllSnapshot() error
|
||||
// TODO DeleteAllSnapshot() error
|
||||
Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error)
|
||||
Resize(ctx context.Context, params interface{}) (jsonutils.JSONObject, error)
|
||||
|
||||
GetPath() string
|
||||
GetSnapshotDir() string
|
||||
PrepareSaveToGlance(ctx context.Context, params interface{}) (jsonutils.JSONObject, error)
|
||||
ResetFromSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error)
|
||||
CleanupSnapshots(ctx context.Context, params interface{}) (jsonutils.JSONObject, error)
|
||||
|
||||
CreateFromUrl(context.Context, string) error
|
||||
// CreateFromSnapshot
|
||||
// TODO CreateFromSnapshot
|
||||
CreateFromTemplate(context.Context, string, string, int64) (jsonutils.JSONObject, error)
|
||||
CreateFromImageFuse(context.Context, string) error
|
||||
CreateRaw(ctx context.Context, sizeMb int, diskFromat string, fsFormat string,
|
||||
encryption bool, diskId string, back string) (jsonutils.JSONObject, error)
|
||||
PostCreateFromImageFuse()
|
||||
|
||||
CreateSnapshot(snapshotId string) error
|
||||
DeleteSnapshot(snapshotId string) error
|
||||
DeleteSnapshot(snapshotId, convertSnapshot string, pendingDelete bool) error
|
||||
|
||||
// @params: diskPath, guestDesc, deployInfo
|
||||
DeployGuestFs(string, *jsonutils.JSONDict, *guestfs.SDeployInfo) (jsonutils.JSONObject, error)
|
||||
|
||||
PostCreateFromImageFuse()
|
||||
DeployGuestFs(diskPath string, guestDesc *jsonutils.JSONDict,
|
||||
deployInfo *guestfs.SDeployInfo) (jsonutils.JSONObject, error)
|
||||
}
|
||||
|
||||
type SBaseDisk struct {
|
||||
|
||||
@@ -18,9 +18,13 @@ import (
|
||||
var (
|
||||
keyWords = []string{"disks"}
|
||||
actionFuncs = map[string]actionFunc{
|
||||
"create": diskCreate,
|
||||
"delete": diskDelete,
|
||||
"resize": diskResize,
|
||||
"create": diskCreate,
|
||||
"delete": diskDelete,
|
||||
"resize": diskResize,
|
||||
"save-prepare": diskSavePrepare,
|
||||
"reset": diskReset,
|
||||
// "snapshot": diskSnapshot,
|
||||
"cleanup-snapshots": diskCleanupSnapshots,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -151,7 +155,7 @@ func perfomrDiskActions(ctx context.Context, w http.ResponseWriter, r *http.Requ
|
||||
func diskCreate(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) {
|
||||
diskInfo, err := body.Get("disk")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Missing disk")
|
||||
return nil, httperrors.NewMissingParameterError("disk")
|
||||
}
|
||||
hostutils.DelayTask(ctx, storage.CreateDiskByDiskinfo,
|
||||
&SDiskCreateByDiskinfo{diskId, disk, diskInfo, storage})
|
||||
@@ -166,8 +170,52 @@ func diskDelete(ctx context.Context, storage IStorage, diskId string, disk IDisk
|
||||
func diskResize(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) {
|
||||
diskInfo, err := body.Get("disk")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Missing disk")
|
||||
return nil, httperrors.NewMissingParameterError("disk")
|
||||
}
|
||||
hostutils.DelayTask(ctx, disk.Resize, diskInfo)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func diskSavePrepare(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) {
|
||||
diskInfo, err := body.Get("disk")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("disk")
|
||||
}
|
||||
hostutils.DelayTask(ctx, disk.PrepareSaveToGlance, diskInfo)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func diskReset(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) {
|
||||
snapshotId, err := body.GetString("snapshot_id")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("snapshot_id")
|
||||
}
|
||||
outOfChain, err := body.Bool("out_of_chain")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("out_of_chain")
|
||||
}
|
||||
hostutils.DelayTask(ctx, disk.ResetFromSnapshot, &SDiskReset{snapshotId, outOfChain})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// func diskSnapshot(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) {
|
||||
// snapshotId, err := body.GetString("snapshot_id")
|
||||
// if err != nil {
|
||||
// return nil, httperrors.NewMissingParameterError("snapshot_id")
|
||||
// }
|
||||
// hostutils.DelayTask(ctx, disk.CreateSnapshot(snapshotId), snapshotId)
|
||||
// return nil, nil
|
||||
// }
|
||||
|
||||
func diskCleanupSnapshots(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) {
|
||||
convertSnapshots, err := body.GetArray("convert_snapshots")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("convert_snapshots")
|
||||
}
|
||||
deleteSnapshots, err := body.GetArray("delete_snapshots")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("delete_snapshots")
|
||||
}
|
||||
hostutils.DelayTask(ctx, disk.CleanupSnapshots, &SDiskCleanupSnapshots{convertSnapshots, deleteSnapshots})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/appctx"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman/remotefile"
|
||||
@@ -302,3 +303,176 @@ func (d *SLocalDisk) PostCreateFromImageFuse() {
|
||||
log.Errorln(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) CreateSnapshot(snapshotId string) error {
|
||||
snapshotDir := d.GetSnapshotDir()
|
||||
if !fileutils2.Exists(snapshotDir) {
|
||||
err := exec.Command("mkdir", "-p", snapshotDir).Run()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
snapshotPath := path.Join(snapshotDir, snapshotId)
|
||||
err := exec.Command("mv", "-f", d.getPath(), snapshotPath).Run()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
img, err := qemuimg.NewQemuImage(d.getPath())
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
exec.Command("mv", "-f", snapshotPath, d.getPath()).Run()
|
||||
return err
|
||||
}
|
||||
if err := img.CreateQcow2(0, false, snapshotPath); err != nil {
|
||||
log.Errorf("Snapshot create image error %s", err)
|
||||
exec.Command("mv", "-f", snapshotPath, d.getPath()).Run()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) DeleteSnapshot(snapshotId, convertSnapshot string, pendingDelete bool) error {
|
||||
snapshotDir := d.GetSnapshotDir()
|
||||
if len(convertSnapshot) > 0 {
|
||||
if !fileutils2.Exists(snapshotDir) {
|
||||
err := exec.Command("mkdir", "-p", snapshotDir).Run()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
convertSnapshotPath := path.Join(snapshotDir, convertSnapshot)
|
||||
output := convertSnapshotPath + ".tmp"
|
||||
if fileutils2.Exists(output) {
|
||||
exec.Command("rm", "-f", output).Run()
|
||||
}
|
||||
img, err := qemuimg.NewQemuImage(convertSnapshotPath)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
if err = img.Convert2Qcow2To(output, true); err != nil {
|
||||
log.Errorln(err)
|
||||
exec.Command("rm", "-f", output).Run()
|
||||
return err
|
||||
}
|
||||
if err = exec.Command("rm", "-f", convertSnapshotPath).Run(); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
if err = exec.Command("mv", "-f", output, convertSnapshotPath).Run(); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
if !pendingDelete {
|
||||
err = exec.Command("rm", "-f", path.Join(snapshotDir, snapshotId)).Run()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
err := exec.Command("rm", "-f", path.Join(snapshotDir, snapshotId)).Run()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) PrepareSaveToGlance(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
|
||||
diskInfo, ok := params.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return nil, hostutils.ParamsError
|
||||
}
|
||||
if err := d.Probe(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
destDir := d.Storage.GetImgsaveBackupPath()
|
||||
if err := exec.Command("mkdir", "-p", destDir).Run(); err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
backupPath := path.Join(destDir, fmt.Sprintf("%s.%s", d.Id, appctx.AppContextTaskId(ctx)))
|
||||
if err := exec.Command("cp", "--sparse=always", "-f", d.GetPath(), backupPath).Run(); err != nil {
|
||||
log.Errorln(err)
|
||||
exec.Command("rm", "-f", backupPath).Run()
|
||||
return nil, err
|
||||
}
|
||||
return jsonutils.NewDict(jsonutils.NewPair("backup", jsonutils.NewString(backupPath))), nil
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) ResetFromSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
|
||||
resetParams, ok := params.(*SDiskReset)
|
||||
if !ok {
|
||||
return nil, hostutils.ParamsError
|
||||
}
|
||||
|
||||
snapshotDir := d.GetSnapshotDir()
|
||||
snapshotPath := path.Join(snapshotDir, resetParams.SnapshotId)
|
||||
diskTmpPath := d.GetPath() + "_reset.tmp"
|
||||
if err := exec.Command("mv", "-f", d.GetPath(), diskTmpPath).Run(); err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
if !resetParams.OutOfChain {
|
||||
img, err := qemuimg.NewQemuImage(d.GetPath())
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
exec.Command("mv", "-f", diskTmpPath, d.GetPath()).Run()
|
||||
return nil, err
|
||||
}
|
||||
if err := img.CreateQcow2(0, false, snapshotPath); err != nil {
|
||||
log.Errorln(err)
|
||||
exec.Command("mv", "-f", diskTmpPath, d.GetPath()).Run()
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if err := exec.Command("cp", "-f", snapshotPath, d.GetPath()).Run(); err != nil {
|
||||
log.Errorln(err)
|
||||
exec.Command("mv", "-f", diskTmpPath, d.GetPath()).Run()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, exec.Command("rm", "-f", diskTmpPath).Run()
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) CleanupSnapshots(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
|
||||
cleanupParams, ok := params.(*SDiskCleanupSnapshots)
|
||||
if !ok {
|
||||
return nil, hostutils.ParamsError
|
||||
}
|
||||
snapshotDir := d.GetSnapshotDir()
|
||||
for _, snapshotId := range cleanupParams.ConvertSnapshots {
|
||||
snapId, _ := snapshotId.GetString()
|
||||
snapshotPath := path.Join(snapshotDir, snapId)
|
||||
output := snapshotPath + "_convert.tmp"
|
||||
img, err := qemuimg.NewQemuImage(snapshotPath)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
if err = img.Convert2Qcow2To(output, true); err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
if exec.Command("mv", "-f", output, snapshotPath).Run(); err != nil {
|
||||
exec.Command("rm", "-f", output).Run()
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, snapshotId := range cleanupParams.DeleteSnapshots {
|
||||
snapId, _ := snapshotId.GetString()
|
||||
if err := exec.Command("rm", "-f", path.Join(snapshotDir, snapId)).Run(); err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ type IStorage interface {
|
||||
DeleteDiskfile(diskPath string) error
|
||||
GetFuseTmpPath() string
|
||||
GetFuseMountPath() string
|
||||
GetImgsaveBackupPath() string
|
||||
}
|
||||
|
||||
type SBaseStorage struct {
|
||||
@@ -219,3 +220,7 @@ func (s *SBaseStorage) CreateDiskFromSnpashot(ctx context.Context, disk IDisk, c
|
||||
}
|
||||
return disk.GetDiskDesc(), nil
|
||||
}
|
||||
|
||||
func (s *SLocalStorage) GetImgsaveBackupPath() string {
|
||||
return s.getSubdirPath(_IMGSAVE_BACKUPS_)
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ func storageUpdate(ctx context.Context, body jsonutils.JSONObject) (interface{},
|
||||
storage := storageManager.GetStorage(storageId)
|
||||
ret, err := modules.Hoststorages.Get(hostutils.GetComputeSession(context.Background()),
|
||||
storageManager.GetHostId(), storageId,
|
||||
jsonutils.NewDict(jsonutils.JSONPair{"details", jsonutils.JSONTrue}))
|
||||
jsonutils.NewDict(jsonutils.NewPair("details", jsonutils.JSONTrue)))
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
|
||||
@@ -9,3 +9,13 @@ type SDiskCreateByDiskinfo struct {
|
||||
|
||||
Storage IStorage
|
||||
}
|
||||
|
||||
type SDiskReset struct {
|
||||
SnapshotId string
|
||||
OutOfChain bool
|
||||
}
|
||||
|
||||
type SDiskCleanupSnapshots struct {
|
||||
ConvertSnapshots []jsonutils.JSONObject
|
||||
DeleteSnapshots []jsonutils.JSONObject
|
||||
}
|
||||
|
||||
+4
@@ -14,6 +14,10 @@ type JSONPair struct {
|
||||
val JSONObject
|
||||
}
|
||||
|
||||
func NewPair(key string, val JSONObject) JSONPair {
|
||||
return JSONPair{key, val}
|
||||
}
|
||||
|
||||
func NewDict(objs ...JSONPair) *JSONDict {
|
||||
dict := JSONDict{data: make(map[string]JSONObject)}
|
||||
for _, o := range objs {
|
||||
|
||||
Reference in New Issue
Block a user