You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ja...@apache.org on 2015/05/28 13:59:23 UTC
[6/9] git commit: updated refs/heads/master to b616522
CLOUDSTACK-8324: Added config drive support for xenserver
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/e4079861
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e4079861
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e4079861
Branch: refs/heads/master
Commit: e40798618393bd937722badc5f35c7317edee456
Parents: 7984ae5
Author: Jayapal <ja...@apache.org>
Authored: Tue May 26 10:05:39 2015 +0530
Committer: Jayapal <ja...@apache.org>
Committed: Thu May 28 15:51:50 2015 +0530
----------------------------------------------------------------------
.../cloud/agent/api/to/VirtualMachineTO.java | 39 +++
api/src/com/cloud/network/NetworkModel.java | 4 +
api/src/com/cloud/vm/UserVmService.java | 5 +
api/src/com/cloud/vm/VirtualMachineProfile.java | 15 +
.../com/cloud/vm/VirtualMachineProfileImpl.java | 50 +++
.../xenserver/resource/CitrixResourceBase.java | 320 +++++++++++++++++++
.../src/com/cloud/network/NetworkModelImpl.java | 55 ++++
server/src/com/cloud/vm/UserVmManagerImpl.java | 27 +-
8 files changed, 514 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e4079861/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
index 3e508ee..c367ec9 100644
--- a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
+++ b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
@@ -16,6 +16,7 @@
// under the License.
package com.cloud.agent.api.to;
+import java.util.List;
import java.util.Map;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
@@ -62,6 +63,12 @@ public class VirtualMachineTO {
NicTO[] nics;
GPUDeviceTO gpuDevice;
Integer vcpuMaxLimit;
+ List<String[]> vmData = null;
+
+ String configDriveLabel = null;
+ String configDriveIsoRootFolder = null;
+ String configDriveIsoFile = null;
+
public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader,
String os, boolean enableHA, boolean limitCpuUse, String vncPassword) {
@@ -292,4 +299,36 @@ public class VirtualMachineTO {
this.vcpuMaxLimit = vcpuMaxLimit;
}
+ public List<String[]> getVmData() {
+ return vmData;
+ }
+
+ public void setVmData(List<String[]> vmData) {
+ this.vmData = vmData;
+ }
+
+ public String getConfigDriveLabel() {
+ return configDriveLabel;
+ }
+
+ public void setConfigDriveLabel(String configDriveLabel) {
+ this.configDriveLabel = configDriveLabel;
+ }
+
+ public String getConfigDriveIsoRootFolder() {
+ return configDriveIsoRootFolder;
+ }
+
+ public void setConfigDriveIsoRootFolder(String configDriveIsoRootFolder) {
+ this.configDriveIsoRootFolder = configDriveIsoRootFolder;
+ }
+
+ public String getConfigDriveIsoFile() {
+ return configDriveIsoFile;
+ }
+
+ public void setConfigDriveIsoFile(String configDriveIsoFile) {
+ this.configDriveIsoFile = configDriveIsoFile;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e4079861/api/src/com/cloud/network/NetworkModel.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/NetworkModel.java b/api/src/com/cloud/network/NetworkModel.java
index 70132d2..780f97d 100644
--- a/api/src/com/cloud/network/NetworkModel.java
+++ b/api/src/com/cloud/network/NetworkModel.java
@@ -277,4 +277,8 @@ public interface NetworkModel {
boolean isNetworkReadyForGc(long networkId);
boolean getNetworkEgressDefaultPolicy(Long networkId);
+
+ List<String[]> generateVmData(String userData, String serviceOffering, String zoneName,
+ String vmName, long vmId, String publicKey, String password, Boolean isWindows);
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e4079861/api/src/com/cloud/vm/UserVmService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java
index c0c0335..2935815 100644
--- a/api/src/com/cloud/vm/UserVmService.java
+++ b/api/src/com/cloud/vm/UserVmService.java
@@ -55,8 +55,13 @@ import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import com.cloud.utils.exception.ExecutionException;
+import org.apache.cloudstack.framework.config.ConfigKey;
public interface UserVmService {
+
+ static final ConfigKey<String> VmConfigDriveLabel = new ConfigKey<String>("Hidden", String.class, "vm.configdrive.label", "config",
+ "The default lable name for the config drive", false);
+
/**
* Destroys one virtual machine
*
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e4079861/api/src/com/cloud/vm/VirtualMachineProfile.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/VirtualMachineProfile.java b/api/src/com/cloud/vm/VirtualMachineProfile.java
index d0fea49..c092d84 100644
--- a/api/src/com/cloud/vm/VirtualMachineProfile.java
+++ b/api/src/com/cloud/vm/VirtualMachineProfile.java
@@ -34,9 +34,24 @@ import com.cloud.user.Account;
*/
public interface VirtualMachineProfile {
+ List<String[]> getVmData();
+
+ void setVmData(List<String[]> vmData);
+
+ void setConfigDriveLabel(String configDriveLabel);
+
+ String getConfigDriveIsoRootFolder();
+
+ void setConfigDriveIsoRootFolder(String configDriveIsoRootFolder);
+
+ String getConfigDriveIsoFile();
+
+ void setConfigDriveIsoFile(String isoFile);
+
public static class Param {
public static final Param VmPassword = new Param("VmPassword");
+ public static final Param VmSshPubKey = new Param("VmSshPubKey");
public static final Param ControlNic = new Param("ControlNic");
public static final Param ReProgramGuestNetworks = new Param("RestartNetwork");
public static final Param PxeSeverType = new Param("PxeSeverType");
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e4079861/engine/components-api/src/com/cloud/vm/VirtualMachineProfileImpl.java
----------------------------------------------------------------------
diff --git a/engine/components-api/src/com/cloud/vm/VirtualMachineProfileImpl.java b/engine/components-api/src/com/cloud/vm/VirtualMachineProfileImpl.java
index 4284a21..7a0a07c 100644
--- a/engine/components-api/src/com/cloud/vm/VirtualMachineProfileImpl.java
+++ b/engine/components-api/src/com/cloud/vm/VirtualMachineProfileImpl.java
@@ -51,6 +51,13 @@ public class VirtualMachineProfileImpl implements VirtualMachineProfile {
VirtualMachine.Type _type;
+ List<String[]> vmData = null;
+
+ String configDriveLabel = null;
+ String configDriveIsoBaseLocation = "/tmp/"; //TODO: Make this location configurable.
+ String configDriveIsoRootFolder = null;
+ String configDriveIsoFile = null;
+
public VirtualMachineProfileImpl(VirtualMachine vm, VirtualMachineTemplate template, ServiceOffering offering, Account owner, Map<Param, Object> params) {
_vm = vm;
_template = template;
@@ -255,4 +262,47 @@ public class VirtualMachineProfileImpl implements VirtualMachineProfile {
public Float getMemoryOvercommitRatio() {
return memoryOvercommitRatio;
}
+
+ @Override
+ public List<String[]> getVmData() {
+ return vmData;
+ }
+
+ @Override
+ public void setVmData(List<String[]> vmData) {
+ this.vmData = vmData;
+ }
+
+ public String getConfigDriveLabel() {
+ return configDriveLabel;
+ }
+
+ @Override
+ public void setConfigDriveLabel(String configDriveLabel) {
+ this.configDriveLabel = configDriveLabel;
+ }
+
+ @Override
+ public String getConfigDriveIsoRootFolder() {
+ return configDriveIsoRootFolder;
+ }
+
+ @Override
+ public void setConfigDriveIsoRootFolder(String configDriveIsoRootFolder) {
+ this.configDriveIsoRootFolder = configDriveIsoRootFolder;
+ }
+
+ public String getConfigDriveIsoBaseLocation() {
+ return configDriveIsoBaseLocation;
+ }
+
+ @Override
+ public String getConfigDriveIsoFile() {
+ return configDriveIsoFile;
+ }
+
+ @Override
+ public void setConfigDriveIsoFile(String isoFile) {
+ this.configDriveIsoFile = isoFile;
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e4079861/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
index ef0631e..5366927 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
@@ -17,7 +17,9 @@
package com.cloud.hypervisor.xenserver.resource;
import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
@@ -48,6 +50,7 @@ import javax.xml.parsers.ParserConfigurationException;
import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
+import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcException;
import org.w3c.dom.Document;
@@ -251,6 +254,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
protected VirtualRoutingResource _vrResource;
+ protected String _configDriveIsopath = "/opt/xensource/packages/configdrive_iso/";
+ protected String _configDriveSRName = "ConfigDriveISOs";
+ protected String _attachIsoDeviceNum = "3";
+
protected int _wait;
// Hypervisor specific params with generic value, may need to be overridden
// for specific versions
@@ -4940,4 +4947,317 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
}
}
}
+
+ public boolean createAndAttachConfigDriveIsoForVM(Connection conn, VM vm, List<String[]> vmDataList, String configDriveLabel) throws XenAPIException, XmlRpcException {
+
+ String vmName = vm.getNameLabel(conn);
+
+ // create SR
+ SR sr = createLocalIsoSR(conn, _configDriveSRName+_host.getIp());
+ if (sr == null) {
+ s_logger.debug("Failed to create local SR for the config drive");
+ return false;
+ }
+
+ s_logger.debug("Creating vm data files in config drive for vm "+vmName);
+ // 1. create vm data files
+ if (!createVmdataFiles(vmName, vmDataList, configDriveLabel)) {
+ s_logger.debug("Failed to create vm data files in config drive for vm "+vmName);
+ return false;
+ }
+
+ // 2. copy config drive iso to host
+ if (!copyConfigDriveIsoToHost(conn, sr, vmName)) {
+ return false;
+ }
+
+ // 3. attachIsoToVM
+ if (!attachConfigDriveIsoToVm(conn, vm)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean createVmdataFiles(String vmName, List<String[]> vmDataList, String configDriveLabel) {
+
+ // add vm iso to the isolibrary
+ String isoPath = "/tmp/"+vmName+"/configDrive/";
+ String configDriveName = "cloudstack/";
+
+ //create folder for the VM
+ //Remove the folder before creating it.
+
+ try {
+ deleteLocalFolder("/tmp/"+isoPath);
+ } catch (IOException e) {
+ s_logger.debug("Failed to delete the exiting config drive for vm "+vmName+ " "+ e.getMessage());
+ } catch (Exception e) {
+ s_logger.debug("Failed to delete the exiting config drive for vm "+vmName+ " "+ e.getMessage());
+ }
+
+
+ if (vmDataList != null) {
+ for (String[] item : vmDataList) {
+ String dataType = item[0];
+ String fileName = item[1];
+ String content = item[2];
+
+ // create file with content in folder
+
+ if (dataType != null && !dataType.isEmpty()) {
+ //create folder
+ String folder = isoPath+configDriveName+dataType;
+ if (folder != null && !folder.isEmpty()) {
+ File dir = new File(folder);
+ boolean result = true;
+
+ try {
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+ }catch (SecurityException ex) {
+ s_logger.debug("Failed to create dir "+ ex.getMessage());
+ return false;
+ }
+
+ if (result && content != null && !content.isEmpty()) {
+ try {
+ File file = new File(folder+"/"+fileName+".txt");
+ FileWriter fw = new FileWriter(file.getAbsoluteFile());
+ BufferedWriter bw = new BufferedWriter(fw);
+ bw.write(content);
+ bw.close();
+ s_logger.debug("created file: "+ file + " in folder:"+folder);
+ } catch (IOException ex) {
+ s_logger.debug("Failed to create file "+ ex.getMessage());
+ return false;
+ }
+ }
+ }
+ }
+ }
+ s_logger.debug("Created the vm data in "+ isoPath);
+ }
+
+ String s = null;
+ try {
+
+ String cmd = "mkisofs -iso-level 3 -V "+ configDriveLabel +" -o "+ isoPath+vmName +".iso " + isoPath;
+ Process p = Runtime.getRuntime().exec(cmd);
+
+ BufferedReader stdInput = new BufferedReader(new
+ InputStreamReader(p.getInputStream()));
+
+ BufferedReader stdError = new BufferedReader(new
+ InputStreamReader(p.getErrorStream()));
+
+ // read the output from the command
+ while ((s = stdInput.readLine()) != null) {
+ s_logger.debug(s);
+ }
+
+ // read any errors from the attempted command
+ while ((s = stdError.readLine()) != null) {
+ s_logger.debug(s);
+ }
+ s_logger.debug(" Created config drive ISO using the command " + cmd +" in the host "+ _host.getIp());
+ } catch (IOException e) {
+ s_logger.debug(e.getMessage());
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean copyConfigDriveIsoToHost(Connection conn, SR sr, String vmName) {
+
+ String vmIso = "/tmp/"+vmName+"/configDrive/"+vmName+".iso";
+ //scp file into the host
+ com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22);
+
+ try {
+ sshConnection.connect(null, 60000, 60000);
+ if (!sshConnection.authenticateWithPassword(_username, _password.peek())) {
+ throw new CloudRuntimeException("Unable to authenticate");
+ }
+
+ s_logger.debug("scp config drive iso file "+vmIso +" to host " + _host.getIp() +" path "+_configDriveIsopath);
+ SCPClient scp = new SCPClient(sshConnection);
+ String p = "0755";
+
+ scp.put(vmIso, _configDriveIsopath, p);
+ sr.scan(conn);
+ s_logger.debug("copied config drive iso to host " + _host);
+ } catch (IOException e) {
+ s_logger.debug("failed to copy configdrive iso " + vmIso + " to host " + _host, e);
+ return false;
+ } catch (XmlRpcException e) {
+ s_logger.debug("Failed to scan config drive iso SR "+ _configDriveSRName+_host.getIp() + " in host "+ _host, e);
+ return false;
+ } finally {
+ sshConnection.close();
+ //clean up the config drive files
+
+ String configDir = "/tmp/"+vmName;
+ try {
+ deleteLocalFolder(configDir);
+ s_logger.debug("Successfully cleaned up config drive directory " + configDir
+ + " after copying it to host ");
+ } catch (Exception e) {
+ s_logger.debug("Failed to delete config drive folder :" + configDir + " for VM " + vmName + " "
+ + e.getMessage());
+ }
+ }
+
+ return true;
+ }
+
+ public boolean attachConfigDriveIsoToVm(Connection conn, VM vm) throws XenAPIException, XmlRpcException {
+
+ String vmName = vm.getNameLabel(conn);
+ String isoURL = _configDriveIsopath + vmName+".iso";
+ VDI srVdi;
+
+ //1. find the vdi of the iso
+ //2. find the vbd for the vdi
+ //3. attach iso to vm
+
+ try {
+ Set<VDI> vdis = VDI.getByNameLabel(conn, vmName+".iso");
+ if (vdis.isEmpty()) {
+ throw new CloudRuntimeException("Could not find ISO with URL: " + isoURL);
+ }
+ srVdi = vdis.iterator().next();
+
+ } catch (XenAPIException e) {
+ s_logger.debug("Unable to get config drive iso: " + isoURL + " due to " + e.toString());
+ return false;
+ } catch (Exception e) {
+ s_logger.debug("Unable to get config drive iso: " + isoURL + " due to " + e.toString());
+ return false;
+ }
+
+ VBD isoVBD = null;
+
+ // Find the VM's CD-ROM VBD
+ Set<VBD> vbds = vm.getVBDs(conn);
+ for (VBD vbd : vbds) {
+ Types.VbdType type = vbd.getType(conn);
+
+ VBD.Record vbdr = vbd.getRecord(conn);
+
+ // if the device exists then attach it
+ if (!vbdr.userdevice.equals(_attachIsoDeviceNum) && type == Types.VbdType.CD) {
+ isoVBD = vbd;
+ break;
+ }
+ }
+
+ if (isoVBD == null) {
+ //create vbd
+ VBD.Record cfgDriveVbdr = new VBD.Record();
+ cfgDriveVbdr.VM = vm;
+ cfgDriveVbdr.empty = true;
+ cfgDriveVbdr.bootable = false;
+ cfgDriveVbdr.userdevice = "autodetect";
+ cfgDriveVbdr.mode = Types.VbdMode.RO;
+ cfgDriveVbdr.type = Types.VbdType.CD;
+ VBD cfgDriveVBD = VBD.create(conn, cfgDriveVbdr);
+ isoVBD = cfgDriveVBD;
+
+ s_logger.debug("Created CD-ROM VBD for VM: " + vm);
+ }
+
+ if (isoVBD != null) {
+ // If an ISO is already inserted, eject it
+ if (isoVBD.getEmpty(conn) == false) {
+ isoVBD.eject(conn);
+ }
+
+ try {
+ // Insert the new ISO
+ isoVBD.insert(conn, srVdi);
+ s_logger.debug("Attached config drive iso to vm " + vmName);
+ }catch (XmlRpcException ex) {
+ s_logger.debug("Failed to attach config drive iso to vm " + vmName);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public SR createLocalIsoSR(Connection conn, String srName) throws XenAPIException, XmlRpcException {
+
+ // if config drive sr already exists then return
+ SR sr = getSRByNameLabelandHost(conn, _configDriveSRName+_host.getIp());
+
+ if (sr != null) {
+ s_logger.debug("Config drive SR already exist, returing it");
+ return sr;
+ }
+
+ try{
+ Map<String, String> deviceConfig = new HashMap<String, String>();
+
+ com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22);
+ try {
+ sshConnection.connect(null, 60000, 60000);
+ if (!sshConnection.authenticateWithPassword(_username, _password.peek())) {
+ throw new CloudRuntimeException("Unable to authenticate");
+ }
+
+ String cmd = "mkdir -p " + _configDriveIsopath;
+ if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
+ throw new CloudRuntimeException("Cannot create directory configdrive_iso on XenServer hosts");
+ }
+ } catch (IOException e) {
+ throw new CloudRuntimeException("Unable to create iso folder", e);
+ } finally {
+ sshConnection.close();
+ }
+ s_logger.debug("Created the config drive SR " + srName +" folder path "+ _configDriveIsopath);
+
+ deviceConfig.put("location", _configDriveIsopath);
+ deviceConfig.put("legacy_mode", "true");
+ Host host = Host.getByUuid(conn, _host.getUuid());
+ String type = SRType.ISO.toString();
+ sr = SR.create(conn, host, deviceConfig, new Long(0), _configDriveIsopath, "iso", type, "iso", false, new HashMap<String, String>());
+
+ sr.setNameLabel(conn, srName);
+ sr.setNameDescription(conn, deviceConfig.get("location"));
+
+ sr.scan(conn);
+ s_logger.debug("Config drive ISO SR at the path " + _configDriveIsopath +" got created in host " + _host);
+ return sr;
+ } catch (XenAPIException e) {
+ String msg = "createLocalIsoSR failed! mountpoint " + e.toString();
+ s_logger.warn(msg, e);
+ throw new CloudRuntimeException(msg, e);
+ } catch (Exception e) {
+ String msg = "createLocalIsoSR failed! mountpoint: due to " + e.getMessage();
+ s_logger.warn(msg, e);
+ throw new CloudRuntimeException(msg, e);
+ }
+
+ }
+
+
+ public void deleteLocalFolder(String directory) throws Exception {
+ if (directory == null || directory.isEmpty()) {
+ String msg = "Invalid directory path (null/empty) detected. Cannot delete specified directory.";
+ s_logger.debug(msg);
+ throw new Exception(msg);
+ }
+
+ try {
+ FileUtils.deleteDirectory(new File(directory));
+ } catch (IOException e) {
+ // IOException here means failure to delete. Not swallowing it here to
+ // let the caller handle with appropriate contextual log message.
+ throw e;
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e4079861/server/src/com/cloud/network/NetworkModelImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java
index b867b64..a49da68 100644
--- a/server/src/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/com/cloud/network/NetworkModelImpl.java
@@ -19,6 +19,8 @@ package com.cloud.network;
import java.math.BigInteger;
import java.security.InvalidParameterException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -32,6 +34,8 @@ import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
+import com.cloud.utils.StringUtils;
+import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
@@ -2281,4 +2285,55 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel {
throw ex;
}
}
+
+ @Override
+ public List<String[]> generateVmData(String userData, String serviceOffering, String zoneName,
+ String vmName, long vmId, String publicKey, String password, Boolean isWindows) {
+ final List<String[]> vmData = new ArrayList<String[]>();
+
+ if (userData != null) {
+ vmData.add(new String[]{"userdata", "user-data", new String(Base64.decodeBase64(userData.getBytes()))});
+ }
+ vmData.add(new String[]{"metadata", "service-offering", StringUtils.unicodeEscape(serviceOffering)});
+ vmData.add(new String[]{"metadata", "availability-zone", StringUtils.unicodeEscape(zoneName)});
+ vmData.add(new String[]{"metadata", "local-hostname", StringUtils.unicodeEscape(vmName)});
+ vmData.add(new String[]{"metadata", "instance-id", vmName});
+ vmData.add(new String[]{"metadata", "vm-id", String.valueOf(vmId)});
+ vmData.add(new String[]{"metadata", "public-keys", publicKey});
+
+ String cloudIdentifier = _configDao.getValue("cloud.identifier");
+ if (cloudIdentifier == null) {
+ cloudIdentifier = "";
+ } else {
+ cloudIdentifier = "CloudStack-{" + cloudIdentifier + "}";
+ }
+ vmData.add(new String[]{"metadata", "cloud-identifier", cloudIdentifier});
+
+ if (password != null && !password.isEmpty() && !password.equals("saved_password")) {
+
+ // Here we are calculating MD5 checksum to reduce the over head of calculating MD5 checksum
+ // in windows VM in password reset script.
+
+ if (isWindows) {
+ MessageDigest md5 = null;
+ try {
+ md5 = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ s_logger.error("Unexpected exception " + e.getMessage(), e);
+ throw new CloudRuntimeException("Unable to get MD5 MessageDigest", e);
+ }
+ md5.reset();
+ md5.update(password.getBytes());
+ byte[] digest = md5.digest();
+ BigInteger bigInt = new BigInteger(1, digest);
+ String hashtext = bigInt.toString(16);
+
+ vmData.add(new String[]{"password", "vm-password-md5checksum", hashtext});
+ }
+
+ vmData.add(new String[]{"password", "vm-password", password});
+ }
+
+ return vmData;
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e4079861/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 1661390..3364655 100644
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -3501,6 +3501,31 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
UserVmVO vm = _vmDao.findById(profile.getId());
Map<String, String> details = _vmDetailsDao.listDetailsKeyPairs(vm.getId());
vm.setDetails(details);
+
+
+ // add userdata info into vm profile
+ Nic defaultNic = _networkModel.getDefaultNic(vm.getId());
+ if(defaultNic != null) {
+ Network network = _networkModel.getNetwork(defaultNic.getNetworkId());
+ if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
+ final String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText();
+ final String zoneName = _dcDao.findById(vm.getDataCenterId()).getName();
+ boolean isWindows = _guestOSCategoryDao.findById(_guestOSDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
+
+ List<String[]> vmData = _networkModel.generateVmData(vm.getUserData(), serviceOffering, zoneName, vm.getInstanceName(), vm.getId(),
+ (String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
+ String vmName = vm.getInstanceName();
+ String configDriveIsoRootFolder = "/tmp";
+ String isoFile = configDriveIsoRootFolder + "/" + vmName + "/configDrive/" + vmName + ".iso";
+ profile.setVmData(vmData);
+ profile.setConfigDriveLabel(VmConfigDriveLabel.value());
+ profile.setConfigDriveIsoRootFolder(configDriveIsoRootFolder);
+ profile.setConfigDriveIsoFile(isoFile);
+ }
+ }
+
+
+
_templateMgr.prepareIsoForVmProfile(profile);
return true;
}
@@ -5268,7 +5293,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
@Override
public ConfigKey<?>[] getConfigKeys() {
- return new ConfigKey<?>[] {EnableDynamicallyScaleVm, VmIpFetchWaitInterval, VmIpFetchTrialMax, VmIpFetchThreadPoolMax};
+ return new ConfigKey<?>[] {EnableDynamicallyScaleVm, VmIpFetchWaitInterval, VmIpFetchTrialMax, VmIpFetchThreadPoolMax, VmConfigDriveLabel};
}
@Override