Skip to content

Commit 9eb9940

Browse files
committed
wip: prepare updates VM in a generic way
Signed-off-by: Abhishek Kumar <[email protected]>
1 parent 28b1b34 commit 9eb9940

File tree

6 files changed

+132
-76
lines changed

6 files changed

+132
-76
lines changed

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ public class ApiConstants {
428428
public static final String POST_URL = "postURL";
429429
public static final String POWER_STATE = "powerstate";
430430
public static final String PRECEDENCE = "precedence";
431+
public static final String PREPARE_VM = "preparevm";
431432
public static final String PRIVATE_INTERFACE = "privateinterface";
432433
public static final String PRIVATE_IP = "privateip";
433434
public static final String PRIVATE_PORT = "privateport";

core/src/main/java/com/cloud/agent/api/PrepareExternalProvisioningAnswer.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,21 @@
2020

2121
import java.util.Map;
2222

23+
import com.cloud.agent.api.to.VirtualMachineTO;
24+
2325
public class PrepareExternalProvisioningAnswer extends Answer {
2426

2527
Map<String, String> serverDetails;
28+
VirtualMachineTO virtualMachineTO;
2629

2730
public PrepareExternalProvisioningAnswer() {
2831
super();
2932
}
3033

31-
public PrepareExternalProvisioningAnswer(PrepareExternalProvisioningCommand cmd, Map<String, String> serverDetails, String details) {
34+
public PrepareExternalProvisioningAnswer(PrepareExternalProvisioningCommand cmd, Map<String, String> externalDetails, VirtualMachineTO virtualMachineTO, String details) {
3235
super(cmd, true, details);
33-
this.serverDetails = serverDetails;
36+
this.serverDetails = externalDetails;
37+
this.virtualMachineTO = virtualMachineTO;
3438
}
3539

3640
public PrepareExternalProvisioningAnswer(PrepareExternalProvisioningCommand cmd, boolean success, String details) {
@@ -40,4 +44,8 @@ public PrepareExternalProvisioningAnswer(PrepareExternalProvisioningCommand cmd,
4044
public Map<String, String> getServerDetails() {
4145
return serverDetails;
4246
}
47+
48+
public VirtualMachineTO getVirtualMachineTO() {
49+
return virtualMachineTO;
50+
}
4351
}

core/src/main/java/com/cloud/agent/api/PrepareExternalProvisioningCommand.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,14 @@ public class PrepareExternalProvisioningCommand extends Command {
2828
Long clusterId;
2929
Map<String, Object> externalDetails;
3030

31-
public PrepareExternalProvisioningCommand(VirtualMachineTO vmUUID, Long clusterId) {
32-
this.virtualMachineTO = vmUUID;
33-
this.clusterId = clusterId;
31+
public PrepareExternalProvisioningCommand(VirtualMachineTO vmTO) {
32+
this.virtualMachineTO = vmTO;
3433
}
3534

3635
public VirtualMachineTO getVirtualMachineTO() {
3736
return virtualMachineTO;
3837
}
3938

40-
public Long getClusterId() {
41-
return clusterId;
42-
}
43-
4439
public Map<String, Object> getExternalDetails() {
4540
return externalDetails;
4641
}

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@
124124
import com.cloud.agent.api.PingRoutingCommand;
125125
import com.cloud.agent.api.PlugNicAnswer;
126126
import com.cloud.agent.api.PlugNicCommand;
127+
import com.cloud.agent.api.PrepareExternalProvisioningAnswer;
128+
import com.cloud.agent.api.PrepareExternalProvisioningCommand;
127129
import com.cloud.agent.api.PrepareForMigrationAnswer;
128130
import com.cloud.agent.api.PrepareForMigrationCommand;
129131
import com.cloud.agent.api.RebootAnswer;
@@ -1161,6 +1163,62 @@ protected void updateVmMetadataManufacturerAndProduct(VirtualMachineTO vmTO, VMI
11611163
vmTO.setMetadataProductName(metadataProduct);
11621164
}
11631165

1166+
protected void updateExternalVm(VirtualMachineTO vmTO, VirtualMachineTO updatedTO) {
1167+
if (updatedTO == null) {
1168+
return;
1169+
}
1170+
for (NicTO nicTO : updatedTO.getNics()) {
1171+
if (StringUtils.isNotBlank(nicTO.getMac())) {
1172+
NicVO nicVO = _nicsDao.findByUuid(nicTO.getUuid());
1173+
if (nicVO == null || Objects.equals(nicVO.getMacAddress(), nicTO.getMac())) {
1174+
continue;
1175+
}
1176+
nicVO.setMacAddress(nicTO.getMac());
1177+
_nicsDao.update(nicVO.getId(), nicVO);
1178+
}
1179+
}
1180+
}
1181+
1182+
@SuppressWarnings("unchecked")
1183+
protected void processPrepareExternalProvisioning(Host host, VirtualMachineTO virtualMachineTO) {
1184+
if (host == null || !HypervisorType.External.equals(host.getHypervisorType()) || host.getName() != null) {
1185+
return;
1186+
}
1187+
Map<String, String> vmDetails = virtualMachineTO.getExternalDetails();
1188+
Map<String, Object> externalDetails = extensionsManager.getExternalAccessDetails(host,
1189+
vmDetails);
1190+
Map<String, String> extensionDetails = (Map<String, String>)externalDetails.get(ApiConstants.EXTENSION);
1191+
Map<String, String> resourceMapDetails = (Map<String, String>)externalDetails.get(ApiConstants.RESOURCE_MAP);
1192+
Map<String, String> hostDetails = (Map<String, String>)externalDetails.get(ApiConstants.EXTENSION);
1193+
boolean shouldPrepareVm =
1194+
Boolean.parseBoolean(extensionDetails.get(ApiConstants.PREPARE_VM)) ||
1195+
Boolean.parseBoolean(resourceMapDetails.get(ApiConstants.PREPARE_VM)) ||
1196+
Boolean.parseBoolean(hostDetails.get(ApiConstants.PREPARE_VM));
1197+
if (!shouldPrepareVm) {
1198+
return;
1199+
}
1200+
PrepareExternalProvisioningCommand cmd = new PrepareExternalProvisioningCommand(virtualMachineTO);
1201+
cmd.setExternalDetails(externalDetails);
1202+
Answer answer = null;
1203+
try {
1204+
answer = _agentMgr.send(host.getId(), cmd);
1205+
} catch (AgentUnavailableException | OperationTimedoutException e) {
1206+
logger.error("Failed PrepareExternalProvisioningCommand due to : {}", e.getMessage(), e);
1207+
return;
1208+
}
1209+
if (answer == null) {
1210+
logger.error("Invalid answer received for PrepareExternalProvisioningCommand");
1211+
return;
1212+
}
1213+
if (!(answer instanceof PrepareExternalProvisioningAnswer)) {
1214+
logger.error("Unexpected answer received for PrepareExternalProvisioningCommand: [result: {}, details: {}]",
1215+
answer.getResult(), answer.getDetails());
1216+
return;
1217+
}
1218+
PrepareExternalProvisioningAnswer prepareAnswer = (PrepareExternalProvisioningAnswer)answer;
1219+
updateExternalVm(virtualMachineTO, prepareAnswer.getVirtualMachineTO());
1220+
}
1221+
11641222
@Override
11651223
public void orchestrateStart(final String vmUuid, final Map<VirtualMachineProfile.Param, Object> params, final DeploymentPlan planToDeploy, final DeploymentPlanner planner)
11661224
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
@@ -1334,6 +1392,7 @@ public void orchestrateStart(final String vmUuid, final Map<VirtualMachineProfil
13341392
handlePath(vmTO.getDisks(), vm.getHypervisorType());
13351393
setVmNetworkDetails(vm, vmTO);
13361394

1395+
processPrepareExternalProvisioning(dest.getHost(), vmTO);
13371396

13381397
Commands cmds = new Commands(Command.OnError.Stop);
13391398
final Map<String, String> sshAccessDetails = _networkMgr.getSystemVMAccessDetails(vm);

engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java

Lines changed: 59 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import javax.naming.ConfigurationException;
4242

4343
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
44-
import org.apache.cloudstack.agent.manager.ExternalAgentManagerImpl;
4544
import org.apache.cloudstack.annotation.AnnotationService;
4645
import org.apache.cloudstack.annotation.dao.AnnotationDao;
4746
import org.apache.cloudstack.api.ApiConstants;
@@ -60,7 +59,6 @@
6059
import org.apache.cloudstack.network.RoutedIpv4Manager;
6160
import org.apache.cloudstack.network.dao.NetworkPermissionDao;
6261
import org.apache.commons.collections.CollectionUtils;
63-
import org.apache.commons.collections.MapUtils;
6462
import org.apache.commons.lang3.BooleanUtils;
6563
import org.apache.commons.lang3.ObjectUtils;
6664
import org.apache.commons.lang3.StringUtils;
@@ -76,15 +74,12 @@
7674
import com.cloud.agent.api.CleanupPersistentNetworkResourceAnswer;
7775
import com.cloud.agent.api.CleanupPersistentNetworkResourceCommand;
7876
import com.cloud.agent.api.Command;
79-
import com.cloud.agent.api.PrepareExternalProvisioningAnswer;
80-
import com.cloud.agent.api.PrepareExternalProvisioningCommand;
8177
import com.cloud.agent.api.SetupPersistentNetworkAnswer;
8278
import com.cloud.agent.api.SetupPersistentNetworkCommand;
8379
import com.cloud.agent.api.StartupCommand;
8480
import com.cloud.agent.api.StartupRoutingCommand;
8581
import com.cloud.agent.api.routing.NetworkElementCommand;
8682
import com.cloud.agent.api.to.NicTO;
87-
import com.cloud.agent.api.to.VirtualMachineTO;
8883
import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
8984
import com.cloud.alert.AlertManager;
9085
import com.cloud.api.query.dao.DomainRouterJoinDao;
@@ -132,9 +127,7 @@
132127
import com.cloud.host.Status;
133128
import com.cloud.host.dao.HostDao;
134129
import com.cloud.host.dao.HostDetailsDao;
135-
import com.cloud.hypervisor.Hypervisor;
136130
import com.cloud.hypervisor.Hypervisor.HypervisorType;
137-
import com.cloud.hypervisor.HypervisorGuru;
138131
import com.cloud.hypervisor.HypervisorGuruManager;
139132
import com.cloud.network.IpAddress;
140133
import com.cloud.network.IpAddressManager;
@@ -264,7 +257,6 @@
264257
import com.cloud.vm.VirtualMachine.Type;
265258
import com.cloud.vm.VirtualMachineManager;
266259
import com.cloud.vm.VirtualMachineProfile;
267-
import com.cloud.vm.VmDetailConstants;
268260
import com.cloud.vm.dao.DomainRouterDao;
269261
import com.cloud.vm.dao.NicDao;
270262
import com.cloud.vm.dao.NicExtraDhcpOptionDao;
@@ -2239,64 +2231,65 @@ public NicProfile prepareNic(final VirtualMachineProfile vmProfile, final Deploy
22392231
}
22402232

22412233
private void prepareNicIfExternalProvisionerInvolved(VirtualMachineProfile vmProfile, DeployDestination dest, long nicId) {
2242-
if (!Hypervisor.HypervisorType.External.equals(vmProfile.getHypervisorType())) {
2243-
return;
2244-
}
2245-
if (userVmDetailsDao.findDetail(vmProfile.getId(), VmDetailConstants.DEPLOY_VM) == null) {
2246-
return;
2247-
}
2248-
HypervisorGuru hvGuru = hvGuruMgr.getGuru(vmProfile.getHypervisorType());
2249-
VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
2250-
2251-
HostVO host = _hostDao.findById(dest.getHost().getId());
2252-
PrepareExternalProvisioningCommand command = new PrepareExternalProvisioningCommand(vmTO, host.getClusterId());
2253-
Map<String, Object> externalDetails = extensionsManager.getExternalAccessDetails(host, vmTO.getExternalDetails());
2254-
command.setExternalDetails(externalDetails);
2255-
final PrepareExternalProvisioningAnswer prepareExternalProvisioningAnswer;
2256-
try {
2257-
Long hostID = dest.getHost().getId();
2258-
final Answer answer = _agentMgr.send(hostID, command);
2259-
2260-
if (!(answer instanceof PrepareExternalProvisioningAnswer)) {
2261-
String errorMsg = String.format("Trying to prepare the instance on external hypervisor for the CloudStack instance %s failed: %s", vmProfile.getUuid(), answer.getDetails());
2262-
logger.debug(errorMsg);
2263-
throw new CloudRuntimeException(errorMsg);
2264-
}
2265-
2266-
prepareExternalProvisioningAnswer = (PrepareExternalProvisioningAnswer) answer;
2267-
} catch (AgentUnavailableException | OperationTimedoutException e) {
2268-
String errorMsg = String.format("Trying to prepare the instance on external hypervisor for the CloudStack instance %s failed: %s", vmProfile.getUuid(), e);
2269-
logger.debug(errorMsg);
2270-
throw new CloudRuntimeException(errorMsg);
2271-
}
2272-
2273-
if (prepareExternalProvisioningAnswer == null || !prepareExternalProvisioningAnswer.getResult()) {
2274-
if (prepareExternalProvisioningAnswer != null && StringUtils.isNotBlank(prepareExternalProvisioningAnswer.getDetails())) {
2275-
throw new CloudRuntimeException(String.format("Unable to prepare the instance on external system due to %s", prepareExternalProvisioningAnswer.getDetails()));
2276-
} else {
2277-
throw new CloudRuntimeException("Unable to prepare the instance on external system, please check the access details");
2278-
}
2279-
}
2280-
2281-
Map<String, String> serverDetails = prepareExternalProvisioningAnswer.getServerDetails();
2282-
if (ExternalAgentManagerImpl.expectMacAddressFromExternalProvisioner.valueIn(host.getClusterId())) {
2283-
String macAddress = serverDetails.get(VmDetailConstants.MAC_ADDRESS);
2284-
if (StringUtils.isEmpty(macAddress)) {
2285-
throw new CloudRuntimeException("Unable to fetch macaddress from the external provisioner while preparing the instance");
2286-
}
2287-
final NicVO nic = _nicDao.findById(nicId);
2288-
nic.setMacAddress(macAddress);
2289-
_nicDao.update(nicId, nic);
2290-
}
2291-
2292-
if (MapUtils.isNotEmpty(serverDetails)) {
2293-
UserVmVO userVm = _userVmDao.findById(vmProfile.getId());
2294-
_userVmDao.loadDetails(userVm);
2295-
Map<String, String> details = userVm.getDetails();
2296-
details.putAll(serverDetails);
2297-
userVm.setDetails(details);
2298-
_userVmDao.saveDetails(userVm);
2299-
}
2234+
logger.debug("SimpleEx {}, {}, {}", vmProfile.getId(), dest, nicId);
2235+
// if (!Hypervisor.HypervisorType.External.equals(vmProfile.getHypervisorType())) {
2236+
// return;
2237+
// }
2238+
// if (userVmDetailsDao.findDetail(vmProfile.getId(), VmDetailConstants.DEPLOY_VM) == null) {
2239+
// return;
2240+
// }
2241+
// HypervisorGuru hvGuru = hvGuruMgr.getGuru(vmProfile.getHypervisorType());
2242+
// VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
2243+
//
2244+
// HostVO host = _hostDao.findById(dest.getHost().getId());
2245+
// PrepareExternalProvisioningCommand command = new PrepareExternalProvisioningCommand(vmTO, host.getClusterId());
2246+
// Map<String, Object> externalDetails = extensionsManager.getExternalAccessDetails(host, vmTO.getExternalDetails());
2247+
// command.setExternalDetails(externalDetails);
2248+
// final PrepareExternalProvisioningAnswer prepareExternalProvisioningAnswer;
2249+
// try {
2250+
// Long hostID = dest.getHost().getId();
2251+
// final Answer answer = _agentMgr.send(hostID, command);
2252+
//
2253+
// if (!(answer instanceof PrepareExternalProvisioningAnswer)) {
2254+
// String errorMsg = String.format("Trying to prepare the instance on external hypervisor for the CloudStack instance %s failed: %s", vmProfile.getUuid(), answer.getDetails());
2255+
// logger.debug(errorMsg);
2256+
// throw new CloudRuntimeException(errorMsg);
2257+
// }
2258+
//
2259+
// prepareExternalProvisioningAnswer = (PrepareExternalProvisioningAnswer) answer;
2260+
// } catch (AgentUnavailableException | OperationTimedoutException e) {
2261+
// String errorMsg = String.format("Trying to prepare the instance on external hypervisor for the CloudStack instance %s failed: %s", vmProfile.getUuid(), e);
2262+
// logger.debug(errorMsg);
2263+
// throw new CloudRuntimeException(errorMsg);
2264+
// }
2265+
//
2266+
// if (prepareExternalProvisioningAnswer == null || !prepareExternalProvisioningAnswer.getResult()) {
2267+
// if (prepareExternalProvisioningAnswer != null && StringUtils.isNotBlank(prepareExternalProvisioningAnswer.getDetails())) {
2268+
// throw new CloudRuntimeException(String.format("Unable to prepare the instance on external system due to %s", prepareExternalProvisioningAnswer.getDetails()));
2269+
// } else {
2270+
// throw new CloudRuntimeException("Unable to prepare the instance on external system, please check the access details");
2271+
// }
2272+
// }
2273+
//
2274+
// Map<String, String> serverDetails = prepareExternalProvisioningAnswer.getServerDetails();
2275+
// if (ExternalAgentManagerImpl.expectMacAddressFromExternalProvisioner.valueIn(host.getClusterId())) {
2276+
// String macAddress = serverDetails.get(VmDetailConstants.MAC_ADDRESS);
2277+
// if (StringUtils.isEmpty(macAddress)) {
2278+
// throw new CloudRuntimeException("Unable to fetch macaddress from the external provisioner while preparing the instance");
2279+
// }
2280+
// final NicVO nic = _nicDao.findById(nicId);
2281+
// nic.setMacAddress(macAddress);
2282+
// _nicDao.update(nicId, nic);
2283+
// }
2284+
//
2285+
// if (MapUtils.isNotEmpty(serverDetails)) {
2286+
// UserVmVO userVm = _userVmDao.findById(vmProfile.getId());
2287+
// _userVmDao.loadDetails(userVm);
2288+
// Map<String, String> details = userVm.getDetails();
2289+
// details.putAll(serverDetails);
2290+
// userVm.setDetails(details);
2291+
// _userVmDao.saveDetails(userVm);
2292+
// }
23002293
}
23012294

23022295
@Override

plugins/hypervisors/external/src/main/java/org/apache/cloudstack/hypervisor/external/provisioner/simpleprovisioner/SimpleExternalProvisioner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ public PrepareExternalProvisioningAnswer prepareExternalProvisioning(String host
275275
} catch (CloudRuntimeException e) {
276276
logger.warn("Failed to parse the output from preparing external provisioning operation as part of VM deployment");
277277
}
278-
return new PrepareExternalProvisioningAnswer(cmd, resultMap, null);
278+
return new PrepareExternalProvisioningAnswer(cmd, resultMap, null, null);
279279
}
280280

281281
@Override

0 commit comments

Comments
 (0)