Automatic merge from release/2.1.0 -> release/2.2.0

* commit 'ab8d120580317d802d6a1150c86b91bd0641a341':
  server create disk
  minor fix
  attach detach isolate device
  server attach detach network, change bandwidth, some bug fix
  guest desc, guest sendkey, fix disk delete
This commit is contained in:
邱剑
2018-09-14 17:04:39 +08:00
10 changed files with 422 additions and 37 deletions

View File

@@ -955,10 +955,6 @@ func objectPerformAction(dispatcher *DBModelDispatcher, modelValue reflect.Value
}
func updateItem(manager IModelManager, item IModel, ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if !item.AllowUpdateItem(ctx, userCred) {
return nil, httperrors.NewForbiddenError(fmt.Sprintf("Not allow to update item"))
}
var err error
err = item.ValidateUpdateCondition(ctx)
@@ -1030,6 +1026,10 @@ func (dispatcher *DBModelDispatcher) Update(ctx context.Context, idStr string, q
return nil, httperrors.NewGeneralError(err)
}
if !model.AllowUpdateItem(ctx, userCred) {
return nil, httperrors.NewForbiddenError(fmt.Sprintf("Not allow to update item"))
}
lockman.LockObject(ctx, model)
defer lockman.ReleaseObject(ctx, model)

View File

@@ -136,7 +136,7 @@ func (dispatcher *DBJointModelDispatcher) Get(ctx context.Context, id1 string, i
} else if err != nil {
return nil, httperrors.NewGeneralError(err)
}
if !item.AllowGetDetails(ctx, userCred, query) {
if !item.AllowGetJointDetails(ctx, userCred, query, item) {
return nil, httperrors.NewForbiddenError("Not allow to get details")
}
return getItemDetails(dispatcher.JointModelManager(), item, ctx, userCred, query)
@@ -200,6 +200,11 @@ func (dispatcher *DBJointModelDispatcher) Update(ctx context.Context, id1 string
} else if err != nil {
return nil, httperrors.NewGeneralError(err)
}
if !item.AllowUpdateJointItem(ctx, userCred, item) {
return nil, httperrors.NewForbiddenError(fmt.Sprintf("Not allow to update item"))
}
lockman.LockJointObject(ctx, master, slave)
defer lockman.ReleaseJointObject(ctx, master, slave)
return updateItem(dispatcher.JointModelManager(), item, ctx, userCred, query, data)

View File

@@ -131,6 +131,8 @@ type IJointModel interface {
Slave() IStandaloneModel
Detach(ctx context.Context, userCred mcclient.TokenCredential) error
AllowGetJointDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, item IJointModel) bool
AllowUpdateJointItem(ctx context.Context, userCred mcclient.TokenCredential, item IJointModel) bool
}
type IStandaloneModelManager interface {

View File

@@ -179,6 +179,16 @@ func (joint *SJointResourceBase) Slave() IStandaloneModel {
return nil
}
func (self *SJointResourceBase) AllowGetJointDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, item IJointModel) bool {
masterVirtual := item.Master().(IVirtualModel)
return masterVirtual.IsOwner(userCred)
}
func (self *SJointResourceBase) AllowUpdateJointItem(ctx context.Context, userCred mcclient.TokenCredential, item IJointModel) bool {
masterVirtual := item.Master().(IVirtualModel)
return masterVirtual.IsOwner(userCred)
}
/*
func (joint *SJointResourceBase) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := joint.SResourceBase.GetCustomizeColumns(ctx, userCred, query)

View File

@@ -266,21 +266,18 @@ func (self *SKVMGuestDriver) RequestDeleteDetachedDisk(ctx context.Context, disk
}
func (self *SKVMGuestDriver) RequestSyncConfigOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
if guest.Status == models.VM_RUNNING {
desc := guest.GetDriver().GetJsonDescAtHost(ctx, guest, host)
body := jsonutils.NewDict()
body.Add(desc, "desc")
if fw_only, _ := task.GetParams().Bool("fw_only"); fw_only {
body.Add(jsonutils.JSONTrue, "fw_only")
}
url := fmt.Sprintf("/servers/%s/sync", guest.Id)
header := http.Header{}
header.Add("X-Task-Id", task.GetTaskId())
header.Add("X-Region-Version", "v2")
_, err := host.Request(task.GetUserCred(), "POST", url, header, body)
return err
desc := guest.GetDriver().GetJsonDescAtHost(ctx, guest, host)
body := jsonutils.NewDict()
body.Add(desc, "desc")
if fw_only, _ := task.GetParams().Bool("fw_only"); fw_only {
body.Add(jsonutils.JSONTrue, "fw_only")
}
return nil
url := fmt.Sprintf("/servers/%s/sync", guest.Id)
header := http.Header{}
header.Add("X-Task-Id", task.GetTaskId())
header.Add("X-Region-Version", "v2")
_, err := host.Request(task.GetUserCred(), "POST", url, header, body)
return err
}
func (self *SKVMGuestDriver) RqeuestSuspendOnHost(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {

View File

@@ -4,6 +4,7 @@ import (
"context"
"crypto/md5"
"crypto/rand"
"database/sql"
"fmt"
"io"
"regexp"
@@ -19,7 +20,6 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/compute/options"
"database/sql"
)
const (
@@ -292,9 +292,11 @@ func (self *SGuestnetwork) ValidateUpdateData(ctx context.Context, userCred mccl
if err != nil {
return nil, fmt.Errorf("fail to fetch index %s", err)
}
q := GuestnetworkManager.Query().Equals("guest_id", self.GuestId)
q = q.NotEquals("network_id", self.NetworkId).Equals("idnex", index)
if q.Count() > 0 {
q := GuestnetworkManager.Query().SubQuery()
count := q.Query().Filter(sqlchemy.Equals(q.Field("guest_id"), self.GuestId)).
Filter(sqlchemy.NotEquals(q.Field("network_id"), self.NetworkId)).
Filter(sqlchemy.Equals(q.Field("index"), index)).Count()
if count > 0 {
return nil, fmt.Errorf("NIC Index %d has been occupied", index)
}
}

View File

@@ -35,6 +35,7 @@ import (
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/logclient"
)
const (
@@ -513,6 +514,16 @@ func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.To
if err != nil {
return nil, err
}
if vmemSize > 0 || vcpuCount > 0 {
if !utils.IsInStringArray(self.Status, []string{VM_READY}) {
return nil, httperrors.NewInvalidStatusError("Cannot modify Memory and CPU in status %s", self.Status)
}
if self.GetHypervisor() == HYPERVISOR_BAREMETAL {
return nil, httperrors.NewInputParameterError("Cannot modify memory for baremetal")
}
}
if vmemSize > 0 {
data.Add(jsonutils.NewInt(int64(vmemSize)), "vmem_size")
}
@@ -530,14 +541,6 @@ func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.To
return nil, httperrors.NewInputParameterError("name is to short")
}
}
/* if self.GetHypervisor() == HYPERVISOR_BAREMETAL {
return nil, httperrors.NewInputParameterError("Cannot modify memory for baremetal")
}
if ! utils.IsInStringArray(self.Status, []string {VM_READY}) {
return nil, httperrors.NewInvalidStatusError("Cannot modify Memory and CPU in status %s", self.Status)
}*/
// return nil, httperrors.NewInputParameterError("cannot update guest vmem_size")
//}
return self.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data)
}
@@ -2109,7 +2112,7 @@ func (self *SGuest) attachIsolatedDevice(userCred mcclient.TokenCredential, dev
if dev.HostId != self.HostId {
return fmt.Errorf("Isolated device and guest are not located in the same host")
}
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
_, err := IsolatedDeviceManager.TableSpec().Update(dev, func() error {
dev.GuestId = self.Id
return nil
})
@@ -2182,6 +2185,9 @@ func (self *SGuest) CategorizeNics() SGuestNicCategory {
func (self *SGuest) StartGuestDeployTask(ctx context.Context, userCred mcclient.TokenCredential, kwargs *jsonutils.JSONDict, action string, parentTaskId string) error {
self.SetStatus(userCred, VM_START_DEPLOY, "")
if kwargs == nil {
kwargs = jsonutils.NewDict()
}
kwargs.Add(jsonutils.NewString(action), "deploy_action")
task, err := taskman.TaskManager.NewTask(ctx, "GuestDeployTask", self, userCred, kwargs, parentTaskId, "", nil)
if err != nil {
@@ -2462,6 +2468,74 @@ func (self *SGuest) DetachDisk(ctx context.Context, disk *SDisk, userCred mcclie
}
}
func (self *SGuest) AllowPerformCreatedisk(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred)
}
func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
var diskIdx, diskSize = 0, 0
disksConf := jsonutils.NewDict()
diskSizes := make(map[string]int, 0)
diskSeq := fmt.Sprintf("disk.%d", diskIdx)
for data.Contains(diskSeq) {
diskDef, _ := data.Get(diskSeq)
diskInfo, err := parseDiskInfo(ctx, userCred, diskDef)
if err != nil {
logclient.AddActionLog(self, logclient.ACT_CREATE, err.Error(), userCred, false)
return nil, httperrors.NewBadRequestError(err.Error())
}
disksConf.Set(diskSeq, jsonutils.Marshal(diskInfo))
if _, ok := diskSizes[diskInfo.Backend]; !ok {
diskSizes[diskInfo.Backend] = diskInfo.Size
} else {
diskSizes[diskInfo.Backend] += diskInfo.Size
}
diskSize += diskInfo.Size
diskIdx += 1
diskSeq = fmt.Sprintf("disk.%d", diskIdx)
}
if diskIdx == 0 {
logclient.AddActionLog(self, logclient.ACT_CREATE, "No Disk Info Provided", userCred, false)
return nil, httperrors.NewBadRequestError("No Disk Info Provided")
}
host := self.GetHost()
if host == nil {
logclient.AddActionLog(self, logclient.ACT_CREATE, "No valid host", userCred, false)
return nil, httperrors.NewBadRequestError("No valid host")
}
for backend, size := range diskSizes {
storage := host.GetLeastUsedStorage(backend)
if storage == nil {
logclient.AddActionLog(self, logclient.ACT_CREATE, "No valid storage on current host", userCred, false)
return nil, httperrors.NewBadRequestError("No valid storage on current host")
}
if storage.GetCapacity() < size {
logclient.AddActionLog(self, logclient.ACT_CREATE, "Not eough storage space on current host", userCred, false)
return nil, httperrors.NewBadRequestError("Not eough storage space on current host")
}
}
pendingUsage := &SQuota{
Storage: diskSize,
}
err := QuotaManager.CheckSetPendingQuota(ctx, userCred, self.ProjectId, pendingUsage)
if err != nil {
logclient.AddActionLog(self, logclient.ACT_CREATE, err.Error(), userCred, false)
return nil, httperrors.NewBadRequestError(err.Error())
}
lockman.LockObject(ctx, host)
defer lockman.ReleaseObject(ctx, host)
err = self.CreateDisksOnHost(ctx, userCred, host, disksConf, pendingUsage)
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, self.ProjectId, nil, pendingUsage)
logclient.AddActionLog(self, logclient.ACT_CREATE, err.Error(), userCred, false)
return nil, httperrors.NewBadRequestError(err.Error())
}
err = self.StartGuestCreateDiskTask(ctx, userCred, disksConf, "")
return nil, err
}
func (self *SGuest) AllowPerformDetachdisk(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred)
}
@@ -2508,6 +2582,196 @@ func (self *SGuest) PerformDetachdisk(ctx context.Context, userCred mcclient.Tok
return nil, httperrors.NewResourceNotFoundError("Disk %s not found", diskId)
}
func (self *SGuest) AllowPerformDetachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return userCred.IsSystemAdmin()
}
func (self *SGuest) PerformDetachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if self.Hypervisor != HYPERVISOR_KVM {
return nil, httperrors.NewNotAcceptableError("Not allow for hypervisor %s", self.Hypervisor)
}
if self.Status != VM_READY {
msg := "Only allowed to attach isolated device when guest is ready"
logclient.AddActionLog(self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
return nil, httperrors.NewInvalidStatusError(msg)
}
device, err := data.GetString("device")
if err != nil {
msg := "Missing isolated device"
logclient.AddActionLog(self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
return nil, httperrors.NewBadRequestError(msg)
}
iDev, err := IsolatedDeviceManager.FetchByIdOrName(userCred.GetProjectId(), device)
if err != nil {
msg := fmt.Sprintf("Isolated device %s not found", device)
logclient.AddActionLog(self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
return nil, httperrors.NewBadRequestError(msg)
}
dev := iDev.(*SIsolatedDevice)
host := self.GetHost()
lockman.LockObject(ctx, host)
defer lockman.ReleaseObject(ctx, host)
err = self.detachIsolateDevice(userCred, dev)
return nil, err
}
func (self *SGuest) detachIsolateDevice(userCred mcclient.TokenCredential, dev *SIsolatedDevice) error {
if dev.GuestId != self.Id {
msg := "Isolated device is not attached to this guest"
logclient.AddActionLog(self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
return httperrors.NewBadRequestError(msg)
}
_, err := self.GetModelManager().TableSpec().Update(dev, func() error {
dev.GuestId = ""
return nil
})
if err != nil {
return err
}
db.OpsLog.LogEvent(self, db.ACT_GUEST_DETACH_ISOLATED_DEVICE, dev.GetShortDesc(), userCred)
return nil
}
func (self *SGuest) AllowPerformAttachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return userCred.IsSystemAdmin()
}
func (self *SGuest) PerformAttachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if self.Hypervisor != HYPERVISOR_KVM {
return nil, httperrors.NewNotAcceptableError("Not allow for hypervisor %s", self.Hypervisor)
}
if self.Status != VM_READY {
msg := "Only allowed to attach isolated device when guest is ready"
logclient.AddActionLog(self, logclient.ACT_GUEST_ATTACH_ISOLATED_DEVICE, msg, userCred, false)
return nil, httperrors.NewInvalidStatusError(msg)
}
device, err := data.GetString("device")
if err != nil {
msg := "Missing isolated device"
logclient.AddActionLog(self, logclient.ACT_GUEST_ATTACH_ISOLATED_DEVICE, msg, userCred, false)
return nil, httperrors.NewBadRequestError(msg)
}
iDev, err := IsolatedDeviceManager.FetchByIdOrName(userCred.GetProjectId(), device)
if err != nil {
msg := fmt.Sprintf("Isolated device %s not found", device)
logclient.AddActionLog(self, logclient.ACT_GUEST_ATTACH_ISOLATED_DEVICE, msg, userCred, false)
return nil, httperrors.NewBadRequestError(msg)
}
dev := iDev.(*SIsolatedDevice)
host := self.GetHost()
lockman.LockObject(ctx, host)
defer lockman.ReleaseObject(ctx, host)
err = self.attachIsolatedDevice(userCred, dev)
var msg string
if err != nil {
msg = err.Error()
}
logclient.AddActionLog(self, logclient.ACT_GUEST_ATTACH_ISOLATED_DEVICE, msg, userCred, err == nil)
return nil, err
}
func (self *SGuest) AllowPerformDetachnetwork(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred)
}
func (self *SGuest) PerformDetachnetwork(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if self.Status != VM_READY {
return nil, httperrors.NewInvalidStatusError("Cannot detach network in status %s", self.Status)
}
reserve := jsonutils.QueryBoolean(data, "reserve", false)
netId, err := data.GetString("net_id")
if err != nil {
return nil, httperrors.NewBadRequestError(err.Error())
}
iNetwork, err := NetworkManager.FetchById(netId)
if err != nil {
return nil, httperrors.NewNotFoundError("Network %s not found", netId)
}
network := iNetwork.(*SNetwork)
err = self.detachNetwork(ctx, userCred, network, reserve, true)
return nil, err
}
func (self *SGuest) AllowPerformAttachnetwork(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred)
}
func (self *SGuest) PerformAttachnetwork(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if self.Status == VM_READY {
// owner_cred = self.get_owner_user_cred() >.<
netDesc, err := data.Get("net_desc")
if err != nil {
return nil, httperrors.NewBadRequestError(err.Error())
}
conf, err := parseNetworkInfo(userCred, netDesc)
if err != nil {
return nil, err
}
err = isValidNetworkInfo(userCred, conf)
if err != nil {
return nil, httperrors.NewBadRequestError(err.Error())
}
var inicCnt, enicCnt, ibw, ebw int
if isExitNetworkInfo(conf) {
enicCnt = 1
ebw = conf.BwLimit
} else {
inicCnt = 1
ibw = conf.BwLimit
}
pendingUsage := &SQuota{
Port: inicCnt,
Eport: enicCnt,
Bw: ibw,
Ebw: ebw,
}
projectId := self.GetOwnerProjectId()
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, projectId, pendingUsage)
if err != nil {
return nil, httperrors.NewOutOfQuotaError(err.Error())
}
host := self.GetHost()
err = self.attach2NetworkDesc(ctx, userCred, host, conf, pendingUsage)
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, projectId, nil, pendingUsage)
return nil, httperrors.NewBadRequestError(err.Error())
}
host.ClearSchedDescCache()
err = self.StartGuestDeployTask(ctx, userCred, nil, "deploy", "")
return nil, err
}
return nil, httperrors.NewBadRequestError("Cannot attach network in status %s", self.Status)
}
func (self *SGuest) AllowPerformChangeBandwidth(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || userCred.IsSystemAdmin()
}
func (self *SGuest) PerformChangeBandwidth(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING}) {
guestnics := self.GetNetworks()
index, err := data.Int("index")
if err != nil || index > int64(len(guestnics)) {
return nil, httperrors.NewBadRequestError("Index Not fount or out of NIC index")
}
bandwidth, err := data.Int("bandwidth")
if err != nil || bandwidth <= 0 {
return nil, httperrors.NewBadRequestError("Bandwidth must be larger than 0")
}
guestnic := &guestnics[index]
if guestnic.BwLimit != int(bandwidth) {
GuestnetworkManager.TableSpec().Update(guestnic, func() error {
guestnic.BwLimit = int(bandwidth)
return nil
})
err := self.StartSyncTask(ctx, userCred, false, "")
return nil, err
}
return nil, nil
}
return nil, httperrors.NewBadRequestError("Cannot change bandwidth in status %s", self.Status)
}
func (self *SGuest) AllowPerformChangeConfig(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || self.IsAdmin(userCred)
}
@@ -3548,6 +3812,78 @@ func (self *SGuest) GetDetailsMonitor(ctx context.Context, userCred mcclient.Tok
return nil, httperrors.NewInvalidStatusError("Cannot send command in status %s", self.Status)
}
func (self *SGuest) AllowGetDetailsDesc(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return self.IsOwner(userCred)
}
func (self *SGuest) GetDetailsDesc(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
host := self.GetHost()
if host == nil {
return nil, httperrors.NewInvalidStatusError("No host for server")
}
desc := self.GetDriver().GetJsonDescAtHost(ctx, self, host)
return desc, nil
}
func (self *SGuest) AllowPerformSendkeys(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred)
}
func (self *SGuest) PerformSendkeys(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if self.Hypervisor != HYPERVISOR_KVM {
return nil, httperrors.NewUnsupportOperationError("Not allow for hypervisor %s", self.Hypervisor)
}
if self.Status != VM_RUNNING {
return nil, httperrors.NewInvalidStatusError("Cannot send keys in status %s", self.Status)
}
keys, err := data.GetString("keys")
if err != nil {
return nil, err
}
err = self.VerifySendKeys(keys)
if err != nil {
return nil, httperrors.NewBadRequestError(err.Error())
}
cmd := fmt.Sprintf("sendkey %s", keys)
duration, err := data.Int("duration")
if err == nil {
cmd = fmt.Sprintf("%s %d", cmd, duration)
}
_, err = self.SendMonitorCommand(ctx, userCred, cmd)
return nil, err
}
func (self *SGuest) VerifySendKeys(keyStr string) error {
keys := strings.Split(keyStr, "-")
for _, key := range keys {
if !self.IsLegalKey(key) {
return fmt.Errorf("Unknown key '%s'", key)
}
}
return nil
}
func (self *SGuest) IsLegalKey(key string) bool {
singleKeys := "1234567890abcdefghijklmnopqrstuvwxyz"
legalKeys := []string{"ctrl", "ctrl_r", "alt", "alt_r", "shift", "shift_r",
"delete", "esc", "insert", "print", "spc",
"f1", "f2", "f3", "f4", "f5", "f6",
"f7", "f8", "f9", "f10", "f11", "f12",
"home", "pgup", "pgdn", "end",
"up", "down", "left", "right",
"tab", "minus", "equal", "backspace", "backslash",
"bracket_left", "bracket_right", "backslash",
"semicolon", "apostrophe", "grave_accent", "ret",
"comma", "dot", "slash",
"caps_lock", "num_lock", "scroll_lock"}
if len(key) > 1 && !utils.IsInStringArray(key, legalKeys) {
return false
} else if len(key) == 1 && !strings.Contains(singleKeys, key) {
return false
}
return true
}
func (self *SGuest) SendMonitorCommand(ctx context.Context, userCred mcclient.TokenCredential, cmd string) (jsonutils.JSONObject, error) {
host := self.GetHost()
url := fmt.Sprintf("%s/servers/%s/monitor", host.ManagerUri, self.Id)

View File

@@ -452,10 +452,40 @@ func (self *SIsolatedDevice) GetCustomizeColumns(ctx context.Context, userCred m
return extra
}
func (self *SIsolatedDevice) ClearSchedDescCache() error {
if len(self.HostId) == 0 {
return nil
}
host := self.getHost()
return host.ClearSchedDescCache()
}
func (self *SIsolatedDevice) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
err := self.SStandaloneResourceBase.Delete(ctx, userCred)
if err != nil {
return err
}
return self.ClearSchedDescCache()
}
func (self *SIsolatedDevice) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
if len(self.GuestId) > 0 {
if !jsonutils.QueryBoolean(data, "purge", false) {
return httperrors.NewBadRequestError("Isolated device used by server: %s", self.GuestId)
}
iGuest, err := GuestManager.FetchById(self.GuestId)
if err != nil {
return err
}
guest := iGuest.(*SGuest)
err = guest.detachIsolateDevice(userCred, self)
if err != nil {
return err
}
}
host := self.getHost()
if host != nil {
db.OpsLog.LogEvent(host, db.ACT_HOST_DETACH_ISOLATED_DEVICE, self.GetShortDesc(), userCred)
}
return nil
return self.RealDelete(ctx, userCred)
}

View File

@@ -21,6 +21,10 @@ const (
DEFAULT_API_VERSION = "v1"
)
var (
MutilVersionService = []string{"compute"}
)
type ClientSession struct {
client *Client
region string
@@ -72,7 +76,7 @@ func (this *ClientSession) GetServiceURL(service, endpointType string) (string,
// session specific endpoint type should override the input endpointType, which is supplied by manager
endpointType = this.endpointType
}
if len(this.apiVersion) > 0 && this.apiVersion != DEFAULT_API_VERSION {
if utils.IsInStringArray(service, MutilVersionService) && len(this.apiVersion) > 0 && this.apiVersion != DEFAULT_API_VERSION {
service = fmt.Sprintf("%s_%s", service, this.apiVersion)
}
url, err := this.token.GetServiceURL(service, this.region, this.zone, endpointType)
@@ -87,7 +91,7 @@ func (this *ClientSession) GetServiceURLs(service, endpointType string) ([]strin
// session specific endpoint type should override the input endpointType, which is supplied by manager
endpointType = this.endpointType
}
if len(this.apiVersion) > 0 && this.apiVersion != DEFAULT_API_VERSION {
if utils.IsInStringArray(service, MutilVersionService) && len(this.apiVersion) > 0 && this.apiVersion != DEFAULT_API_VERSION {
service = fmt.Sprintf("%s_%s", service, this.apiVersion)
}
urls, err := this.token.GetServiceURLs(service, this.region, this.zone, endpointType)

View File

@@ -3,12 +3,12 @@ package logclient
import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/stringutils"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/pkg/util/stringutils"
)
const (
@@ -102,7 +102,6 @@ func AddActionLog(model IObject, action string, iNotes interface{}, userCred mcc
}
logentry.Add(jsonutils.NewString(notes), "notes")
logclientWorkerMan.Run(func() {
s := auth.GetSession(userCred, "", "")
_, err := modules.Actions.Create(s, logentry)