|
71 | 71 | import org.apache.cloudstack.framework.ca.Certificate; |
72 | 72 | import org.apache.cloudstack.framework.config.ConfigKey; |
73 | 73 | import org.apache.cloudstack.framework.config.Configurable; |
| 74 | +import org.apache.cloudstack.framework.extensions.dao.ExtensionDetailsDao; |
74 | 75 | import org.apache.cloudstack.framework.extensions.manager.ExtensionsManager; |
| 76 | +import org.apache.cloudstack.framework.extensions.vo.ExtensionDetailsVO; |
75 | 77 | import org.apache.cloudstack.framework.jobs.AsyncJob; |
76 | 78 | import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext; |
77 | 79 | import org.apache.cloudstack.framework.jobs.AsyncJobManager; |
@@ -442,6 +444,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac |
442 | 444 | private VolumeDataFactory volumeDataFactory; |
443 | 445 | @Inject |
444 | 446 | ExtensionsManager extensionsManager; |
| 447 | + @Inject |
| 448 | + ExtensionDetailsDao extensionDetailsDao; |
445 | 449 |
|
446 | 450 |
|
447 | 451 | VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this); |
@@ -1163,68 +1167,125 @@ protected void updateVmMetadataManufacturerAndProduct(VirtualMachineTO vmTO, VMI |
1163 | 1167 | vmTO.setMetadataProductName(metadataProduct); |
1164 | 1168 | } |
1165 | 1169 |
|
1166 | | - protected void updateExternalVmPrepareAnswer(VirtualMachineTO vmTO, VirtualMachineTO updatedTO) { |
1167 | | - if (updatedTO == null) { |
| 1170 | + protected void updateExternalVmDetailsFromPrepareAnswer(VirtualMachineTO vmTO, UserVmVO userVmVO, |
| 1171 | + Map<String, String> newDetails) { |
| 1172 | + if (newDetails != null || newDetails.equals(vmTO.getDetails())) { |
| 1173 | + return; |
| 1174 | + } |
| 1175 | + vmTO.setDetails(newDetails); |
| 1176 | + userVmVO.setDetails(newDetails); |
| 1177 | + _userVmDao.saveDetails(userVmVO); |
| 1178 | + } |
| 1179 | + |
| 1180 | + protected void updateExternalVmDataFromPrepareAnswer(VirtualMachineTO vmTO, VirtualMachineTO updatedTO) { |
| 1181 | + final String vncPassword = updatedTO.getVncPassword(); |
| 1182 | + final Map<String, String> details = updatedTO.getDetails(); |
| 1183 | + if ((vncPassword == null || vncPassword.equals(vmTO.getVncPassword())) && |
| 1184 | + (details == null || details.equals(vmTO.getDetails()))) { |
| 1185 | + return; |
| 1186 | + } |
| 1187 | + UserVmVO userVmVO = _userVmDao.findById(vmTO.getId()); |
| 1188 | + if (userVmVO == null) { |
| 1189 | + return; |
| 1190 | + } |
| 1191 | + if (vncPassword != null && !vncPassword.equals(userVmVO.getPassword())) { |
| 1192 | + userVmVO.setVncPassword(vncPassword); |
| 1193 | + vmTO.setVncPassword(vncPassword); |
| 1194 | + } |
| 1195 | + updateExternalVmDetailsFromPrepareAnswer(vmTO, userVmVO, updatedTO.getDetails()); |
| 1196 | + } |
| 1197 | + |
| 1198 | + protected void updateExternalVmNicsFromPrepareAnswer(VirtualMachineTO vmTO, VirtualMachineTO updatedTO) { |
| 1199 | + if (ObjectUtils.anyNull(vmTO.getNics(), updatedTO.getNics())) { |
1168 | 1200 | return; |
1169 | 1201 | } |
1170 | 1202 | Map<String, NicTO> originalNicsByUuid = new HashMap<>(); |
1171 | 1203 | for (NicTO nic : vmTO.getNics()) { |
1172 | | - originalNicsByUuid.put(nic.getUuid(), nic); |
| 1204 | + originalNicsByUuid.put(nic.getNicUuid(), nic); |
1173 | 1205 | } |
1174 | 1206 | for (NicTO updatedNicTO : updatedTO.getNics()) { |
1175 | | - if (StringUtils.isNotBlank(updatedNicTO.getMac())) { |
1176 | | - NicVO nicVO = _nicsDao.findByUuid(updatedNicTO.getUuid()); |
1177 | | - if (nicVO == null || Objects.equals(nicVO.getMacAddress(), updatedNicTO.getMac())) { |
1178 | | - continue; |
1179 | | - } |
1180 | | - nicVO.setMacAddress(updatedNicTO.getMac()); |
1181 | | - _nicsDao.update(nicVO.getId(), nicVO); |
1182 | | - NicTO originalNicTO = originalNicsByUuid.get(updatedNicTO.getUuid()); |
1183 | | - if (originalNicTO != null) { |
1184 | | - originalNicTO.setMac(updatedNicTO.getMac()); |
1185 | | - } |
| 1207 | + final String nicUuid = updatedNicTO.getNicUuid(); |
| 1208 | + NicTO originalNicTO = originalNicsByUuid.get(nicUuid); |
| 1209 | + if (originalNicTO == null) { |
| 1210 | + continue; |
1186 | 1211 | } |
| 1212 | + final String mac = updatedNicTO.getMac(); |
| 1213 | + final String ip4 = updatedNicTO.getIp(); |
| 1214 | + final String ip6 = updatedNicTO.getIp6Address(); |
| 1215 | + if (Objects.equals(mac, originalNicTO.getMac()) && |
| 1216 | + Objects.equals(ip4, originalNicTO.getIp()) && |
| 1217 | + Objects.equals(ip6, originalNicTO.getIp6Address())) { |
| 1218 | + continue; |
| 1219 | + } |
| 1220 | + NicVO nicVO = _nicsDao.findByUuid(nicUuid); |
| 1221 | + if (nicVO == null) { |
| 1222 | + continue; |
| 1223 | + } |
| 1224 | + logger.debug("Updating {} during External VM preparation", nicVO); |
| 1225 | + if (ip4 != null && !ip4.equals(nicVO.getIPv4Address())) { |
| 1226 | + nicVO.setIPv4Address(ip4); |
| 1227 | + originalNicTO.setIp(ip4); |
| 1228 | + } |
| 1229 | + if (ip6 != null && !ip6.equals(nicVO.getIPv6Address())) { |
| 1230 | + nicVO.setIPv6Address(ip6); |
| 1231 | + originalNicTO.setIp6Address(ip6); |
| 1232 | + } |
| 1233 | + if (mac != null && !mac.equals(nicVO.getMacAddress())) { |
| 1234 | + nicVO.setMacAddress(mac); |
| 1235 | + originalNicTO.setMac(mac); |
| 1236 | + } |
| 1237 | + _nicsDao.update(nicVO.getId(), nicVO); |
| 1238 | + } |
| 1239 | + } |
| 1240 | + |
| 1241 | + protected void updateExternalVmFromPrepareAnswer(VirtualMachineTO vmTO, VirtualMachineTO updatedTO) { |
| 1242 | + if (updatedTO == null) { |
| 1243 | + return; |
1187 | 1244 | } |
| 1245 | + updateExternalVmDataFromPrepareAnswer(vmTO, updatedTO); |
| 1246 | + updateExternalVmNicsFromPrepareAnswer(vmTO, updatedTO); |
1188 | 1247 | } |
1189 | 1248 |
|
1190 | | - @SuppressWarnings("unchecked") |
1191 | | - protected void processPrepareExternalProvisioning(Host host, VirtualMachineTO virtualMachineTO) { |
1192 | | - if (host == null || !HypervisorType.External.equals(host.getHypervisorType()) || host.getName() != null) { |
| 1249 | + protected void processPrepareExternalProvisioning(Host host, VirtualMachineTO virtualMachineTO, |
| 1250 | + VirtualMachineTemplate template) { |
| 1251 | + if (host == null || !HypervisorType.External.equals(host.getHypervisorType()) || |
| 1252 | + template.getExtensionId() == null) { |
| 1253 | + return; |
| 1254 | + } |
| 1255 | + ExtensionDetailsVO detailsVO = extensionDetailsDao.findDetail(template.getExtensionId(), |
| 1256 | + ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM); |
| 1257 | + if (detailsVO == null || !Boolean.parseBoolean(detailsVO.getValue())) { |
1193 | 1258 | return; |
1194 | 1259 | } |
1195 | 1260 | Map<String, String> vmDetails = virtualMachineTO.getExternalDetails(); |
1196 | 1261 | Map<String, Object> externalDetails = extensionsManager.getExternalAccessDetails(host, |
1197 | 1262 | vmDetails); |
1198 | | - Map<String, String> extensionDetails = (Map<String, String>)externalDetails.get(ApiConstants.EXTENSION); |
1199 | | - Map<String, String> resourceMapDetails = (Map<String, String>)externalDetails.get(ApiConstants.RESOURCE_MAP); |
1200 | | - Map<String, String> hostDetails = (Map<String, String>)externalDetails.get(ApiConstants.EXTENSION); |
1201 | | - boolean shouldPrepareVm = |
1202 | | - Boolean.parseBoolean(extensionDetails.get(ApiConstants.PREPARE_VM)) || |
1203 | | - Boolean.parseBoolean(resourceMapDetails.get(ApiConstants.PREPARE_VM)) || |
1204 | | - Boolean.parseBoolean(hostDetails.get(ApiConstants.PREPARE_VM)); |
1205 | | - if (!shouldPrepareVm) { |
1206 | | - return; |
1207 | | - } |
1208 | 1263 | PrepareExternalProvisioningCommand cmd = new PrepareExternalProvisioningCommand(virtualMachineTO); |
1209 | 1264 | cmd.setExternalDetails(externalDetails); |
1210 | 1265 | Answer answer = null; |
| 1266 | + CloudRuntimeException cre = new CloudRuntimeException("Failed to prepare VM"); |
1211 | 1267 | try { |
1212 | 1268 | answer = _agentMgr.send(host.getId(), cmd); |
1213 | 1269 | } catch (AgentUnavailableException | OperationTimedoutException e) { |
1214 | 1270 | logger.error("Failed PrepareExternalProvisioningCommand due to : {}", e.getMessage(), e); |
1215 | | - return; |
| 1271 | + throw cre; |
1216 | 1272 | } |
1217 | 1273 | if (answer == null) { |
1218 | 1274 | logger.error("Invalid answer received for PrepareExternalProvisioningCommand"); |
1219 | | - return; |
| 1275 | + throw cre; |
1220 | 1276 | } |
1221 | 1277 | if (!(answer instanceof PrepareExternalProvisioningAnswer)) { |
1222 | 1278 | logger.error("Unexpected answer received for PrepareExternalProvisioningCommand: [result: {}, details: {}]", |
1223 | 1279 | answer.getResult(), answer.getDetails()); |
1224 | | - return; |
| 1280 | + throw cre; |
1225 | 1281 | } |
1226 | 1282 | PrepareExternalProvisioningAnswer prepareAnswer = (PrepareExternalProvisioningAnswer)answer; |
1227 | | - updateExternalVmPrepareAnswer(virtualMachineTO, prepareAnswer.getVirtualMachineTO()); |
| 1283 | + if (!prepareAnswer.getResult()) { |
| 1284 | + logger.error("Unexpected answer received for PrepareExternalProvisioningCommand: [result: {}, details: {}]", |
| 1285 | + answer.getResult(), answer.getDetails()); |
| 1286 | + throw cre; |
| 1287 | + } |
| 1288 | + updateExternalVmFromPrepareAnswer(virtualMachineTO, prepareAnswer.getVirtualMachineTO()); |
1228 | 1289 | } |
1229 | 1290 |
|
1230 | 1291 | @Override |
@@ -1400,7 +1461,7 @@ public void orchestrateStart(final String vmUuid, final Map<VirtualMachineProfil |
1400 | 1461 | handlePath(vmTO.getDisks(), vm.getHypervisorType()); |
1401 | 1462 | setVmNetworkDetails(vm, vmTO); |
1402 | 1463 |
|
1403 | | - processPrepareExternalProvisioning(dest.getHost(), vmTO); |
| 1464 | + processPrepareExternalProvisioning(dest.getHost(), vmTO, template); |
1404 | 1465 |
|
1405 | 1466 | Commands cmds = new Commands(Command.OnError.Stop); |
1406 | 1467 | final Map<String, String> sshAccessDetails = _networkMgr.getSystemVMAccessDetails(vm); |
|
0 commit comments