Skip to content

Commit 70b07c9

Browse files
committed
Enable unmanaging guest VMs
1 parent 38298d1 commit 70b07c9

File tree

33 files changed

+934
-38
lines changed

33 files changed

+934
-38
lines changed

api/src/main/java/com/cloud/event/EventTypes.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ public class EventTypes {
102102
public static final String EVENT_VM_RESTORE = "VM.RESTORE";
103103
public static final String EVENT_VM_EXPUNGE = "VM.EXPUNGE";
104104
public static final String EVENT_VM_IMPORT = "VM.IMPORT";
105+
public static final String EVENT_VM_UNMANAGE = "VM.UNMANAGE";
105106

106107
// Domain Router
107108
public static final String EVENT_ROUTER_CREATE = "ROUTER.CREATE";
@@ -623,6 +624,7 @@ public class EventTypes {
623624
entityEventDetails.put(EVENT_VM_RESTORE, VirtualMachine.class);
624625
entityEventDetails.put(EVENT_VM_EXPUNGE, VirtualMachine.class);
625626
entityEventDetails.put(EVENT_VM_IMPORT, VirtualMachine.class);
627+
entityEventDetails.put(EVENT_VM_UNMANAGE, VirtualMachine.class);
626628

627629
entityEventDetails.put(EVENT_ROUTER_CREATE, VirtualRouter.class);
628630
entityEventDetails.put(EVENT_ROUTER_DESTROY, VirtualRouter.class);

api/src/main/java/com/cloud/vm/UserVmService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,4 +517,5 @@ UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemp
517517
final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKey,
518518
final String hostName, final HypervisorType hypervisorType, final Map<String, String> customParameters, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException;
519519

520+
boolean unmanageUserVM(Long vmId);
520521
}

api/src/main/java/com/cloud/vm/VirtualMachineProfile.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public static class Param {
6363
public static final Param UefiFlag = new Param("UefiFlag");
6464
public static final Param BootMode = new Param("BootMode");
6565
public static final Param BootType = new Param("BootType");
66+
public static final Param PreserveNics = new Param("PreserveNics");
6667

6768
private String name;
6869

api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.apache.cloudstack.context.CallContext;
4040
import org.apache.cloudstack.vm.VmImportService;
4141
import org.apache.commons.collections.MapUtils;
42+
import org.apache.commons.lang.BooleanUtils;
4243
import org.apache.log4j.Logger;
4344

4445
import com.cloud.event.EventTypes;
@@ -152,6 +153,11 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd {
152153
description = "vm and its volumes are allowed to migrate to different host/pool when offerings passed are incompatible with current host/pool")
153154
private Boolean migrateAllowed;
154155

156+
@Parameter(name = ApiConstants.FORCED,
157+
type = CommandType.BOOLEAN,
158+
description = "VM is imported despite some of its NIC's MAC addresses are already present")
159+
private Boolean forced;
160+
155161
/////////////////////////////////////////////////////
156162
/////////////////// Accessors ///////////////////////
157163
/////////////////////////////////////////////////////
@@ -268,6 +274,10 @@ public String getEventDescription() {
268274
return "Importing unmanaged VM";
269275
}
270276

277+
public boolean isForced() {
278+
return BooleanUtils.isTrue(forced);
279+
}
280+
271281
/////////////////////////////////////////////////////
272282
/////////////// API Implementation///////////////////
273283
/////////////////////////////////////////////////////
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//
2+
// Licensed to the Apache Software Foundation (ASF) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The ASF licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
//
19+
20+
package org.apache.cloudstack.api.command.admin.vm;
21+
22+
import com.cloud.event.EventTypes;
23+
import com.cloud.exception.ConcurrentOperationException;
24+
import com.cloud.exception.InsufficientCapacityException;
25+
import com.cloud.exception.NetworkRuleConflictException;
26+
import com.cloud.exception.ResourceAllocationException;
27+
import com.cloud.exception.ResourceUnavailableException;
28+
import com.cloud.user.Account;
29+
import com.cloud.uservm.UserVm;
30+
import org.apache.cloudstack.acl.RoleType;
31+
import org.apache.cloudstack.api.APICommand;
32+
import org.apache.cloudstack.api.ApiConstants;
33+
import org.apache.cloudstack.api.BaseAsyncCmd;
34+
import org.apache.cloudstack.api.Parameter;
35+
import org.apache.cloudstack.api.ResponseObject;
36+
import org.apache.cloudstack.api.ServerApiException;
37+
import org.apache.cloudstack.api.response.UnmanageVMInstanceResponse;
38+
import org.apache.cloudstack.api.response.UserVmResponse;
39+
import org.apache.cloudstack.context.CallContext;
40+
import org.apache.cloudstack.vm.UnmanageVMManager;
41+
import org.apache.log4j.Logger;
42+
43+
import javax.inject.Inject;
44+
45+
@APICommand(name = UnmanageVMInstanceCmd.API_NAME,
46+
description = "Unmanage a virtual machine from a given cluster.",
47+
responseObject = UnmanageVMInstanceResponse.class,
48+
responseView = ResponseObject.ResponseView.Full,
49+
requestHasSensitiveInfo = false,
50+
authorized = {RoleType.Admin},
51+
since = "4.14.0")
52+
public class UnmanageVMInstanceCmd extends BaseAsyncCmd {
53+
54+
public static final Logger LOGGER = Logger.getLogger(UnmanageVMInstanceCmd.class);
55+
public static final String API_NAME = "unmanageVirtualMachine";
56+
57+
@Inject
58+
private UnmanageVMManager unmanageVMManager;
59+
60+
/////////////////////////////////////////////////////
61+
//////////////// API parameters /////////////////////
62+
/////////////////////////////////////////////////////
63+
64+
@Parameter(name = ApiConstants.ID, type = CommandType.UUID,
65+
entityType = UserVmResponse.class, required = true,
66+
description = "The ID of the virtual machine to unmanage")
67+
private Long vmId;
68+
69+
/////////////////////////////////////////////////////
70+
/////////////////// Accessors ///////////////////////
71+
/////////////////////////////////////////////////////
72+
73+
public Long getVmId() {
74+
return vmId;
75+
}
76+
77+
@Override
78+
public String getEventType() {
79+
return EventTypes.EVENT_VM_UNMANAGE;
80+
}
81+
82+
@Override
83+
public String getEventDescription() {
84+
return "unmanaging VM. VM ID = " + vmId;
85+
}
86+
87+
/////////////////////////////////////////////////////
88+
/////////////// API Implementation///////////////////
89+
/////////////////////////////////////////////////////
90+
91+
@Override
92+
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
93+
ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
94+
UnmanageVMInstanceResponse response = new UnmanageVMInstanceResponse();
95+
try {
96+
CallContext.current().setEventDetails("VM ID = " + vmId);
97+
unmanageVMManager.unmanageVMInstance(vmId);
98+
response.setSuccess(true);
99+
} catch (Exception e) {
100+
response.setSuccess(false);
101+
response.setDetails(e.getMessage());
102+
}
103+
response.setResponseName(getCommandName());
104+
setResponseObject(response);
105+
}
106+
107+
@Override
108+
public String getCommandName() {
109+
return API_NAME.toLowerCase() + BaseAsyncCmd.RESPONSE_SUFFIX;
110+
}
111+
112+
@Override
113+
public long getEntityOwnerId() {
114+
UserVm vm = _responseGenerator.findUserVmById(vmId);
115+
if (vm != null) {
116+
return vm.getAccountId();
117+
}
118+
return Account.ACCOUNT_ID_SYSTEM;
119+
}
120+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.apache.cloudstack.api.response;
19+
20+
import com.cloud.serializer.Param;
21+
import com.google.gson.annotations.SerializedName;
22+
import org.apache.cloudstack.api.ApiConstants;
23+
import org.apache.cloudstack.api.BaseResponse;
24+
25+
public class UnmanageVMInstanceResponse extends BaseResponse {
26+
27+
@SerializedName(ApiConstants.RESULT)
28+
@Param(description = "result of the unmanage VM operation")
29+
private boolean success;
30+
31+
@SerializedName(ApiConstants.DETAILS)
32+
@Param(description = "details of the unmanage VM operation")
33+
private String details;
34+
35+
public UnmanageVMInstanceResponse() {
36+
}
37+
38+
public UnmanageVMInstanceResponse(boolean success, String details) {
39+
this.success = success;
40+
this.details = details;
41+
}
42+
43+
public boolean isSuccess() {
44+
return success;
45+
}
46+
47+
public void setSuccess(boolean success) {
48+
this.success = success;
49+
}
50+
51+
public String getDetails() {
52+
return details;
53+
}
54+
55+
public void setDetails(String details) {
56+
this.details = details;
57+
}
58+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.apache.cloudstack.vm;
19+
20+
import com.cloud.utils.component.PluggableService;
21+
import org.apache.cloudstack.framework.config.ConfigKey;
22+
import org.apache.cloudstack.framework.config.Configurable;
23+
24+
public interface UnmanageVMManager extends VmImportService, UnmanageVMService, PluggableService, Configurable {
25+
26+
ConfigKey<Boolean> UnmanageVMPreserveNic = new ConfigKey<>("Advanced", Boolean.class, "unmanage.vm.preserve.nics", "false",
27+
"If set to true, preserve nics (and its MAC addresses) when unmanaging a VM. " +
28+
"Otherwise, nics are removed and MAC addresses can be reassigned", true, ConfigKey.Scope.Zone);
29+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.apache.cloudstack.vm;
19+
20+
public interface UnmanageVMService {
21+
22+
/**
23+
* Unmanage a VM instance from CloudStack
24+
*/
25+
boolean unmanageVMInstance(long vmId);
26+
}

api/src/main/java/org/apache/cloudstack/vm/VmImportService.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@
2323
import org.apache.cloudstack.api.response.UnmanagedInstanceResponse;
2424
import org.apache.cloudstack.api.response.UserVmResponse;
2525

26-
import com.cloud.utils.component.PluggableService;
27-
28-
public interface VmImportService extends PluggableService {
26+
public interface VmImportService {
2927
ListResponse<UnmanagedInstanceResponse> listUnmanagedInstances(ListUnmanagedInstancesCmd cmd);
3028
UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd);
3129
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.agent.api;
18+
19+
public class PrepareUnmanageVMInstanceAnswer extends Answer {
20+
21+
public PrepareUnmanageVMInstanceAnswer() {
22+
}
23+
24+
public PrepareUnmanageVMInstanceAnswer(PrepareUnmanageVMInstanceCommand cmd, boolean result, String details) {
25+
super(cmd, result, details);
26+
}
27+
}

0 commit comments

Comments
 (0)