mirror of https://github.com/apache/cloudstack.git
- 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
This commit is contained in:
parent
4481c9925a
commit
239ee80a88
|
|
@ -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);
|
||||
|
|
@ -6973,6 +7076,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
return _name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultScriptsDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -248,6 +248,19 @@ def createFileInDomr(session, args):
|
|||
txt = 'fail#' + txt
|
||||
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})
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue