This is an automated email from the ASF dual-hosted git repository. pearl11594 pushed a commit to branch test-opt in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit 239ee80a888756c988c2ea45295273a397e9e0a2 Author: Pearl Dsilva <[email protected]> AuthorDate: Tue Dec 14 18:25:07 2021 +0530 - Support to patch SystemVMs - VMWare - Remove attaching systemvm.iso to systemVMs - Modify / Refactor VMware start command to copy patch related files to the systemvms - cleanup --- .../hypervisor/vmware/resource/VmwareResource.java | 114 ++++++++++++++++++++- .../xenbase/CitrixPatchSystemVmCommandWrapper.java | 19 ++-- scripts/vm/hypervisor/xenserver/vmops | 16 ++- .../main/java/com/cloud/vm/UserVmManagerImpl.java | 2 +- 4 files changed, 136 insertions(+), 15 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index ed37391..669ae08 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -48,6 +48,10 @@ import java.util.stream.Collectors; import javax.naming.ConfigurationException; import javax.xml.datatype.XMLGregorianCalendar; +import com.cloud.agent.api.PatchSystemVmAnswer; +import com.cloud.agent.api.PatchSystemVmCommand; +import com.cloud.resource.ServerResourceBase; +import com.cloud.utils.FileUtil; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; @@ -362,9 +366,10 @@ import com.vmware.vim25.VmConfigSpec; import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec; import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec; -public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer { +public class VmwareResource extends ServerResourceBase implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer { private static final Logger s_logger = Logger.getLogger(VmwareResource.class); public static final String VMDK_EXTENSION = ".vmdk"; + public static final String BASEPATH = "/usr/share/cloudstack-common/vms/"; private static final Random RANDOM = new Random(System.nanoTime()); @@ -594,7 +599,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa answer = execute((SetupPersistentNetworkCommand) cmd); } else if (clz == GetVmVncTicketCommand.class) { answer = execute((GetVmVncTicketCommand) cmd); - } else { + } else if (clz == PatchSystemVmCommand.class) { + answer = execute((PatchSystemVmCommand) cmd); + } else { answer = Answer.createUnsupportedCommandAnswer(cmd); } @@ -634,6 +641,68 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return answer; } + private ExecutionResult getSystemVmVersionAndChecksum(String controlIp) { + ExecutionResult result; + try { + result = executeInVR(controlIp, VRScripts.VERSION, null); + if (!result.isSuccess()) { + String errMsg = String.format("GetSystemVMVersionCmd on %s failed, message %s", controlIp, result.getDetails()); + s_logger.error(errMsg); + throw new CloudRuntimeException(errMsg); + } + } catch (final Exception e) { + final String msg = "GetSystemVMVersionCmd failed due to " + e; + s_logger.error(msg, e); + throw new CloudRuntimeException(msg, e); + } + return result; + } + + private Answer execute(PatchSystemVmCommand cmd) { + String controlIp = getRouterSshControlIp(cmd); + String sysVMName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + String homeDir = System.getProperty("user.home"); + File pemFile = new File(homeDir + "/.ssh/id_rsa"); + + ExecutionResult result = getSystemVmVersionAndChecksum(controlIp); + try { + FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, newSrcFiles, BASEPATH); + } catch (CloudRuntimeException e) { + return new PatchSystemVmAnswer(cmd, e.getMessage()); + } + + final String[] lines = result.getDetails().split("&"); + // TODO: do we fail, or patch anyway?? + if (lines.length != 2) { + return new PatchSystemVmAnswer(cmd, result.getDetails()); + } + + String scriptChecksum = lines[1].trim(); + String checksum = calculateCurrentChecksum(sysVMName).trim(); + + if (!org.apache.commons.lang3.StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { + if (!cmd.isForced()) { + String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); + s_logger.info(msg); + return new PatchSystemVmAnswer(cmd, msg, lines[0], lines[1]); + } + } + + Pair<Boolean, String> patchResult = null; + try { + patchResult = SshHelper.sshExecute(controlIp, DefaultDomRSshPort, "root", + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + } catch (Exception e) { + return new PatchSystemVmAnswer(cmd, e.getMessage()); + } + + if (patchResult.first()) { + return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + } + return new PatchSystemVmAnswer(cmd, patchResult.second()); + + } + private Answer execute(SetupPersistentNetworkCommand cmd) { VmwareHypervisorHost host = getHyperHost(getServiceContext()); String hostname = null; @@ -2100,7 +2169,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, - String.format("[%s] systemvm/%s", secDsMo.getName(), mgr.getSystemVMIsoFileNameOnDatastore()), secDsMo.getMor(), true, true, ideUnitNumber++, i + 1); + null, secDsMo.getMor(), true, true, ideUnitNumber++, i + 1); deviceConfigSpecArray[i].setDevice(isoInfo.first()); if (isoInfo.second()) { if (s_logger.isDebugEnabled()) @@ -2485,6 +2554,29 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa startAnswer.setIqnToData(iqnToData); + if (vmSpec.getType() != VirtualMachine.Type.User) { + String controlIp = getControlIp(nics); + // check if the router is up? + for (int count = 0; count < 60; count++) { + final boolean result = _vrResource.connect(controlIp, 1, 5000); + if (result) { + break; + } + } + + try { + String homeDir = System.getProperty("user.home"); + File pemFile = new File(homeDir + "/.ssh/id_rsa"); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, newSrcFiles, BASEPATH); + // TODO: May want to remove this when cert patching logic is moved + Thread.sleep(10000); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; + s_logger.error(errMsg, e); + return new StartAnswer(cmd, String.format("%s due to: %s", errMsg, e.getMessage())); + } + } + // Since VM was successfully powered-on, if there was an existing VM in a different cluster that was unregistered, delete all the files associated with it. if (existingVmName != null && existingVmFileLayout != null) { List<String> vmDatastoreNames = new ArrayList<String>(); @@ -3886,6 +3978,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } + private String getControlIp(NicTO[] nicTOs) { + String controlIpAddress = null; + for (NicTO nic : nicTOs) { + if ((TrafficType.Management == nic.getType() || TrafficType.Control == nic.getType()) && nic.getIp() != null) { + controlIpAddress = nic.getIp(); + break; + } + } + return controlIpAddress; + } + private VirtualMachineMO takeVmFromOtherHyperHost(VmwareHypervisorHost hyperHost, String vmName) throws Exception { VirtualMachineMO vmMo = hyperHost.findVmOnPeerHyperHost(vmName); @@ -6974,6 +7077,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } @Override + protected String getDefaultScriptsDir() { + return null; + } + + @Override public boolean start() { return true; } diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java index e27381e..a6b183f 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -25,10 +25,8 @@ import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; import com.cloud.utils.ExecutionResult; -import com.cloud.utils.FileUtil; -import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.ssh.SshHelper; +import com.xensource.xenapi.Connection; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; @@ -44,12 +42,13 @@ public class CitrixPatchSystemVmCommandWrapper extends CommandWrapper<PatchSyste public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverResource) { final String controlIp = command.getAccessDetail(NetworkElementCommand.ROUTER_IP); final String sysVMName = command.getAccessDetail(NetworkElementCommand.ROUTER_NAME); - + final Connection conn = serverResource.getConnection(); ExecutionResult result; try { result = getSystemVmVersionAndChecksum(serverResource, controlIp); - FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, CitrixResourceBase.BASEPATH); + serverResource.copyPatchFilesToVR(controlIp, "/home/cloud"); + //FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, CitrixResourceBase.BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(command, e.getMessage()); } @@ -70,18 +69,18 @@ public class CitrixPatchSystemVmCommandWrapper extends CommandWrapper<PatchSyste return new PatchSystemVmAnswer(command, msg, lines[0], lines[1]); } } - Pair<Boolean, String> patchResult = null; + String patchResult = null; try { - patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", - pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + patchResult = serverResource.callHostPlugin(conn, "vmops", "runPatchScriptInDomr", "domrip", controlIp); } catch (Exception e) { return new PatchSystemVmAnswer(command, e.getMessage()); } - if (patchResult.first()) { + + if (patchResult.startsWith("succ#")) { return new PatchSystemVmAnswer(command, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); } - return new PatchSystemVmAnswer(command, patchResult.second()); + return new PatchSystemVmAnswer(command, patchResult.substring(5)); } diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index e5c7e1a..cea47cc 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -249,6 +249,19 @@ def createFileInDomr(session, args): return txt @echo +def runPatchScriptInDomr(session, args): + domrip = args['domrip'] + txt="" + try: + target = "root@" + domrip + txt = util.pread2(['ssh','-p','3922','-i','/root/.ssh/id_rsa.cloud', target, "/bin/bash","/home/cloud/patch-sysvms.sh"]) + txt = 'succ#' + txt + except: + logging.debug("failed to run patch script in systemVM with IP: " + domrip) + txt = 'fail#' + txt + return txt + +@echo def deleteFile(session, args): file_path = args["filepath"] @@ -1590,4 +1603,5 @@ if __name__ == "__main__": "cleanup_rules":cleanup_rules, "createFileInDomr":createFileInDomr, "kill_copy_process":kill_copy_process, - "secureCopyToHost":secureCopyToHost}) + "secureCopyToHost":secureCopyToHost, + "runPatchScriptInDomr": runPatchScriptInDomr}) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index d7c90b3..a3b7c47 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -4874,7 +4874,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { UserVmVO vm = _vmDao.findById(profile.getId()); Answer[] answersToCmds = cmds.getAnswers();
