diff --git a/cmd/climc/shell/compute/isolatedevices.go b/cmd/climc/shell/compute/isolatedevices.go index d9b2997a9b..be798a44e6 100644 --- a/cmd/climc/shell/compute/isolatedevices.go +++ b/cmd/climc/shell/compute/isolatedevices.go @@ -26,4 +26,5 @@ func init() { cmd.Update(&compute.DeviceUpdateOptions{}) cmd.Show(&compute.DeviceShowOptions{}) cmd.BatchDelete(&compute.DeviceDeleteOptions{}) + cmd.BatchPerform("purge", &compute.DevicePurgeOptions{}) } diff --git a/pkg/apis/compute/isolated_device.go b/pkg/apis/compute/isolated_device.go index 094bc03935..b1fc99c350 100644 --- a/pkg/apis/compute/isolated_device.go +++ b/pkg/apis/compute/isolated_device.go @@ -23,6 +23,10 @@ import ( "yunion.io/x/onecloud/pkg/apis" ) +const ( + ErrMsgIsolatedDeviceUsedByServer = "Isolated device used by server" +) + type IsolateDeviceDetails struct { apis.StandaloneResourceDetails HostResourceInfo diff --git a/pkg/compute/models/isolated_devices.go b/pkg/compute/models/isolated_devices.go index 2f5bea14b3..90d0513dba 100644 --- a/pkg/compute/models/isolated_devices.go +++ b/pkg/compute/models/isolated_devices.go @@ -948,7 +948,7 @@ func (self *SIsolatedDevice) PerformPurge(ctx context.Context, userCred mcclient 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) + return httperrors.NewBadRequestError("%s: %s", api.ErrMsgIsolatedDeviceUsedByServer, self.GuestId) } iGuest, err := GuestManager.FetchById(self.GuestId) if err != nil { diff --git a/pkg/hostman/isolated_device/isolated_device.go b/pkg/hostman/isolated_device/isolated_device.go index e4dc210681..6d12df3e6f 100644 --- a/pkg/hostman/isolated_device/isolated_device.go +++ b/pkg/hostman/isolated_device/isolated_device.go @@ -402,11 +402,15 @@ func (man *isolatedDeviceManager) StartDetachTask() { log.Infof("Start delete cloud device %s", jsonutils.Marshal(dev)) if _, err := modules.IsolatedDevices.PerformAction(man.getSession(), dev.Id, "purge", jsonutils.Marshal(map[string]interface{}{ - "purge": true, + //"purge": true, })); err != nil { if errors.Cause(err) == httperrors.ErrResourceNotFound { break } + if strings.Contains(err.Error(), api.ErrMsgIsolatedDeviceUsedByServer) { + log.Warningf("Purge isolated device %s failed: %v", jsonutils.Marshal(dev), err) + break + } log.Errorf("Detach device %s failed: %v, try again later", dev.Id, err) time.Sleep(30 * time.Second) continue diff --git a/pkg/mcclient/options/compute/isolated_devices.go b/pkg/mcclient/options/compute/isolated_devices.go index 29a7df2a55..dfb181b98c 100644 --- a/pkg/mcclient/options/compute/isolated_devices.go +++ b/pkg/mcclient/options/compute/isolated_devices.go @@ -61,3 +61,14 @@ type DeviceUpdateOptions struct { func (o *DeviceUpdateOptions) Params() (jsonutils.JSONObject, error) { return jsonutils.Marshal(o), nil } + +type DevicePurgeOptions struct { + options.BaseIdsOptions + Purge bool `help:"purge devices when attached to guest"` +} + +func (o *DevicePurgeOptions) Params() (jsonutils.JSONObject, error) { + return jsonutils.Marshal(map[string]interface{}{ + "purge": o.Purge, + }), nil +}