You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ra...@apache.org on 2014/05/12 10:06:02 UTC
[1/5] CLOUDSTACK-6518 [Hyper-V] Efficient way of finding the empty
nic in VR/VpcVR to configure VPC entities fixed windows line ending issues
Repository: cloudstack
Updated Branches:
refs/heads/hyper_vpc_patches [created] 4cb6c66f7
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4cb6c66f/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java
index 12fc39d..7888e43 100644
--- a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java
+++ b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java
@@ -177,7 +177,6 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
protected final int _retry = 24;
protected final int _sleep = 10000;
protected static final int DEFAULT_DOMR_SSHPORT = 3922;
- private final int maxid = 4094;
private String _clusterGuid;
// Used by initialize to assert object configured before
@@ -535,11 +534,15 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
}
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int publicNicInfo = -1;
- publicNicInfo = getVmNics(vmName, maxid);
+ publicNicInfo = getVmFreeNicIndex(vmName);
if (publicNicInfo > 0) {
- modifyNicVlan(vmName, vlanId, publicNicInfo);
+ modifyNicVlan(vmName, vlanId, publicNicInfo, true, cmd.getNic().getName());
+ return new PlugNicAnswer(cmd, true, "success");
}
- return new PlugNicAnswer(cmd, true, "success");
+ String msg = " Plug Nic failed for the vm as it has reached max limit of NICs to be added";
+ s_logger.warn(msg);
+ return new PlugNicAnswer(cmd, false, msg);
+
} catch (Exception e) {
s_logger.error("Unexpected exception: ", e);
return new PlugNicAnswer(cmd, false, "Unable to execute PlugNicCommand due to " + e.toString());
@@ -563,7 +566,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
int publicNicInfo = -1;
publicNicInfo = getVmNics(vmName, vlanId);
if (publicNicInfo > 0) {
- modifyNicVlan(vmName, maxid, publicNicInfo);
+ modifyNicVlan(vmName, 2, publicNicInfo, false, "");
}
return new UnPlugNicAnswer(cmd, true, "success");
} catch (Exception e) {
@@ -1765,6 +1768,37 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
return new IpAssocAnswer(cmd, results);
}
+
+ protected int getVmFreeNicIndex(String vmName) {
+ GetVmConfigCommand vmConfig = new GetVmConfigCommand(vmName);
+ URI agentUri = null;
+ int nicposition = -1;
+ try {
+ String cmdName = GetVmConfigCommand.class.getName();
+ agentUri =
+ new URI("https", null, _agentIp, _port,
+ "/api/HypervResource/" + cmdName, null, null);
+ } catch (URISyntaxException e) {
+ String errMsg = "Could not generate URI for Hyper-V agent";
+ s_logger.error(errMsg, e);
+ }
+ String ansStr = postHttpRequest(s_gson.toJson(vmConfig), agentUri);
+ Answer[] result = s_gson.fromJson(ansStr, Answer[].class);
+ s_logger.debug("GetVmConfigCommand response received "
+ + s_gson.toJson(result));
+ if (result.length > 0) {
+ GetVmConfigAnswer ans = ((GetVmConfigAnswer)result[0]);
+ List<NicDetails> nics = ans.getNics();
+ for (NicDetails nic : nics) {
+ if (nic.getState() == false) {
+ nicposition = nics.indexOf(nic);
+ break;
+ }
+ }
+ }
+ return nicposition;
+ }
+
protected int getVmNics(String vmName, int vlanid) {
GetVmConfigCommand vmConfig = new GetVmConfigCommand(vmName);
URI agentUri = null;
@@ -1816,8 +1850,9 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
}
}
- protected void modifyNicVlan(String vmName, int vlanId, int pos) {
- ModifyVmNicConfigCommand modifynic = new ModifyVmNicConfigCommand(vmName, vlanId, pos);
+ protected void modifyNicVlan(String vmName, int vlanId, int pos, boolean enable, String switchLabelName) {
+ ModifyVmNicConfigCommand modifyNic = new ModifyVmNicConfigCommand(vmName, vlanId, pos, enable);
+ modifyNic.setSwitchLableName(switchLabelName);
URI agentUri = null;
try {
String cmdName = ModifyVmNicConfigCommand.class.getName();
@@ -1828,7 +1863,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
String errMsg = "Could not generate URI for Hyper-V agent";
s_logger.error(errMsg, e);
}
- String ansStr = postHttpRequest(s_gson.toJson(modifynic), agentUri);
+ String ansStr = postHttpRequest(s_gson.toJson(modifyNic), agentUri);
Answer[] result = s_gson.fromJson(ansStr, Answer[].class);
s_logger.debug("executeRequest received response "
+ s_gson.toJson(result));
[5/5] git commit: updated refs/heads/hyper_vpc_patches to 4cb6c66
Posted by ra...@apache.org.
CLOUDSTACK-6518 [Hyper-V] Efficient way of finding the empty nic in VR/VpcVR to configure VPC entities fixed windows line ending issues
Conflicts:
plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/4cb6c66f
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/4cb6c66f
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/4cb6c66f
Branch: refs/heads/hyper_vpc_patches
Commit: 4cb6c66f7568013586d0e66691aa10f9d34233ee
Parents: 3943e0b
Author: Rajesh Battala <ra...@citrix.com>
Authored: Mon May 5 12:55:59 2014 +0530
Committer: Rajesh Battala <ra...@citrix.com>
Committed: Mon May 12 12:54:16 2014 +0530
----------------------------------------------------------------------
.../com/cloud/agent/api/GetVmConfigAnswer.java | 7 +-
.../agent/api/ModifyVmNicConfigCommand.java | 17 +
.../HypervResource/CloudStackTypes.cs | 13 +-
.../HypervResource/HypervResourceController.cs | 4690 +++++++--------
.../HypervResource/IWmiCallsV2.cs | 150 +-
.../ServerResource/HypervResource/WmiCallsV2.cs | 5498 +++++++++---------
.../resource/HypervDirectConnectResource.java | 51 +-
7 files changed, 5348 insertions(+), 5078 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4cb6c66f/core/src/com/cloud/agent/api/GetVmConfigAnswer.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/GetVmConfigAnswer.java b/core/src/com/cloud/agent/api/GetVmConfigAnswer.java
index 46e003e..e0d1536 100644
--- a/core/src/com/cloud/agent/api/GetVmConfigAnswer.java
+++ b/core/src/com/cloud/agent/api/GetVmConfigAnswer.java
@@ -42,13 +42,15 @@ public class GetVmConfigAnswer extends Answer {
public class NicDetails {
String macAddress;
int vlanid;
+ boolean state;
public NicDetails() {
}
- public NicDetails(String macAddress, int vlanid) {
+ public NicDetails(String macAddress, int vlanid, boolean state) {
this.macAddress = macAddress;
this.vlanid = vlanid;
+ this.state = state;
}
public String getMacAddress() {
@@ -59,6 +61,9 @@ public class GetVmConfigAnswer extends Answer {
return vlanid;
}
+ public boolean getState() {
+ return state;
+ }
}
@Override
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4cb6c66f/core/src/com/cloud/agent/api/ModifyVmNicConfigCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/ModifyVmNicConfigCommand.java b/core/src/com/cloud/agent/api/ModifyVmNicConfigCommand.java
index 5f4f0e1..54c0eb0 100644
--- a/core/src/com/cloud/agent/api/ModifyVmNicConfigCommand.java
+++ b/core/src/com/cloud/agent/api/ModifyVmNicConfigCommand.java
@@ -22,6 +22,9 @@ public class ModifyVmNicConfigCommand extends Command {
int vlan;
String macAddress;
int index;
+ boolean enable;
+ String switchLableName;
+
protected ModifyVmNicConfigCommand() {
}
@@ -37,10 +40,24 @@ public class ModifyVmNicConfigCommand extends Command {
this.index = position;
}
+ public ModifyVmNicConfigCommand(String vmName, int vlan, int position, boolean enable) {
+ this.vmName = vmName;
+ this.vlan = vlan;
+ this.index = position;
+ this.enable = enable;
+ }
+
public String getVmName() {
return vmName;
}
+ public String getSwitchLableName() {
+ return switchLableName;
+ }
+
+ public void setSwitchLableName(String switchlableName) {
+ this.switchLableName = switchlableName;
+ }
@Override
public boolean executeInSequence() {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4cb6c66f/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
index c222102..ef24c79 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
@@ -711,11 +711,22 @@ namespace HypervResource
public string macaddress;
[JsonProperty("vlanid")]
public int vlanid;
+ [JsonProperty("state")]
+ public bool state;
public NicDetails() { }
- public NicDetails(String macaddress, int vlanid)
+ public NicDetails(String macaddress, int vlanid, int enabledState)
{
this.macaddress = macaddress;
this.vlanid = vlanid;
+ if (enabledState == 2)
+ {
+ this.state = true;
+ }
+ else
+ {
+ this.state = false;
+ }
+
}
}
[4/5] CLOUDSTACK-6518 [Hyper-V] Efficient way of finding the empty
nic in VR/VpcVR to configure VPC entities fixed windows line ending issues
Posted by ra...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4cb6c66f/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
index 0f084db..67c367d 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
@@ -1,112 +1,112 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-using Amazon;
-using Amazon.S3;
-using Amazon.S3.Model;
-using log4net;
-using Microsoft.CSharp.RuntimeBinder;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections;
-using System.Collections.Specialized;
-using System.Collections.Generic;
-using System.Configuration;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Text;
-using System.Security.Cryptography;
-using System.Security.Principal;
-using System.Web.Http;
-using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
-
-namespace HypervResource
-{
-
- public struct HypervResourceControllerConfig
- {
- private string privateIpAddress;
- private static ILog logger = LogManager.GetLogger(typeof(HypervResourceControllerConfig));
-
- public string PrivateIpAddress
- {
- get
- {
- return privateIpAddress;
- }
- set
- {
- ValidateIpAddress(value);
- privateIpAddress = value;
- System.Net.NetworkInformation.NetworkInterface nic = HypervResourceController.GetNicInfoFromIpAddress(privateIpAddress, out PrivateNetmask);
- PrivateMacAddress = nic.GetPhysicalAddress().ToString();
- }
- }
-
- private static void ValidateIpAddress(string value)
- {
- // Convert to IP address
- IPAddress ipAddress;
- if (!IPAddress.TryParse(value, out ipAddress))
- {
- String errMsg = "Invalid PrivateIpAddress: " + value;
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
- }
- public string GatewayIpAddress;
- public string PrivateMacAddress;
- public string PrivateNetmask;
- public string StorageNetmask;
- public string StorageMacAddress;
- public string StorageIpAddress;
- public long RootDeviceReservedSpaceBytes;
- public string RootDeviceName;
- public ulong ParentPartitionMinMemoryMb;
- public string LocalSecondaryStoragePath;
- public string systemVmIso;
-
- private string getPrimaryKey(string id)
- {
- return "primary_storage_" + id;
- }
-
- public string getPrimaryStorage(string id)
- {
- NameValueCollection settings = ConfigurationManager.AppSettings;
- return settings.Get(getPrimaryKey(id));
- }
-
- public void setPrimaryStorage(string id, string path)
- {
- Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
- KeyValueConfigurationCollection settings = config.AppSettings.Settings;
- string key = getPrimaryKey(id);
- if (settings[key] != null)
- {
- settings.Remove(key);
- }
- settings.Add(key, path);
- config.Save(ConfigurationSaveMode.Modified);
- ConfigurationManager.RefreshSection("appSettings");
- }
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Amazon;
+using Amazon.S3;
+using Amazon.S3.Model;
+using log4net;
+using Microsoft.CSharp.RuntimeBinder;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Security.Cryptography;
+using System.Security.Principal;
+using System.Web.Http;
+using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
+
+namespace HypervResource
+{
+
+ public struct HypervResourceControllerConfig
+ {
+ private string privateIpAddress;
+ private static ILog logger = LogManager.GetLogger(typeof(HypervResourceControllerConfig));
+
+ public string PrivateIpAddress
+ {
+ get
+ {
+ return privateIpAddress;
+ }
+ set
+ {
+ ValidateIpAddress(value);
+ privateIpAddress = value;
+ System.Net.NetworkInformation.NetworkInterface nic = HypervResourceController.GetNicInfoFromIpAddress(privateIpAddress, out PrivateNetmask);
+ PrivateMacAddress = nic.GetPhysicalAddress().ToString();
+ }
+ }
+
+ private static void ValidateIpAddress(string value)
+ {
+ // Convert to IP address
+ IPAddress ipAddress;
+ if (!IPAddress.TryParse(value, out ipAddress))
+ {
+ String errMsg = "Invalid PrivateIpAddress: " + value;
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+ }
+ public string GatewayIpAddress;
+ public string PrivateMacAddress;
+ public string PrivateNetmask;
+ public string StorageNetmask;
+ public string StorageMacAddress;
+ public string StorageIpAddress;
+ public long RootDeviceReservedSpaceBytes;
+ public string RootDeviceName;
+ public ulong ParentPartitionMinMemoryMb;
+ public string LocalSecondaryStoragePath;
+ public string systemVmIso;
+
+ private string getPrimaryKey(string id)
+ {
+ return "primary_storage_" + id;
+ }
+
+ public string getPrimaryStorage(string id)
+ {
+ NameValueCollection settings = ConfigurationManager.AppSettings;
+ return settings.Get(getPrimaryKey(id));
+ }
+
+ public void setPrimaryStorage(string id, string path)
+ {
+ Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
+ KeyValueConfigurationCollection settings = config.AppSettings.Settings;
+ string key = getPrimaryKey(id);
+ if (settings[key] != null)
+ {
+ settings.Remove(key);
+ }
+ settings.Add(key, path);
+ config.Save(ConfigurationSaveMode.Modified);
+ ConfigurationManager.RefreshSection("appSettings");
+ }
public List<string> getAllPrimaryStorages()
{
@@ -122,2264 +122,2272 @@ namespace HypervResource
}
return poolPaths;
}
- }
-
- /// <summary>
- /// Supports one HTTP GET and multiple HTTP POST URIs
- /// </summary>
- /// <remarks>
- /// <para>
- /// POST takes dynamic to allow it to receive JSON without concern for what is the underlying object.
- /// E.g. http://stackoverflow.com/questions/14071715/passing-dynamic-json-object-to-web-api-newtonsoft-example
- /// and http://stackoverflow.com/questions/3142495/deserialize-json-into-c-sharp-dynamic-object
- /// Use ActionName attribute to allow multiple POST URLs, one for each supported command
- /// E.g. http://stackoverflow.com/a/12703423/939250
- /// Strictly speaking, this goes against the purpose of an ApiController, which is to provide one GET/POST/PUT/DELETE, etc.
- /// However, it reduces the amount of code by removing the need for a switch according to the incoming command type.
- /// http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx
- /// </para>
- /// <para>
- /// Exceptions handled on command by command basis rather than globally to allow details of the command
- /// to be reflected in the response. Default error handling is in the catch for Exception, but
- /// other exception types may be caught where the feedback would be different.
- /// NB: global alternatives discussed at
- /// http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx
- /// </para>
- /// </remarks>
- public class HypervResourceController : ApiController
- {
- public static void Configure(HypervResourceControllerConfig config)
- {
- HypervResourceController.config = config;
- wmiCallsV2 = new WmiCallsV2();
- }
-
- public static HypervResourceControllerConfig config = new HypervResourceControllerConfig();
-
- private static ILog logger = LogManager.GetLogger(typeof(HypervResourceController));
- private string systemVmIso = "";
- Dictionary<String, String> contextMap = new Dictionary<String, String>();
-
- public static void Initialize()
- {
- }
-
- public static IWmiCallsV2 wmiCallsV2 { get; set;}
-
- // GET api/HypervResource
- public string Get()
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
- return "HypervResource controller running, use POST to send JSON encoded RPCs"; ;
- }
- }
-
- /// <summary>
- /// NOP - placeholder for future setup, e.g. delete existing VMs or Network ports
- /// POST api/HypervResource/SetupCommand
- /// </summary>
- /// <param name="cmd"></param>
- /// <returns></returns>
- /// TODO: produce test
- [HttpPost]
- [ActionName(CloudStackTypes.SetupCommand)]
- public JContainer SetupCommand([FromBody]dynamic cmd)
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
+ }
+
+ /// <summary>
+ /// Supports one HTTP GET and multiple HTTP POST URIs
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// POST takes dynamic to allow it to receive JSON without concern for what is the underlying object.
+ /// E.g. http://stackoverflow.com/questions/14071715/passing-dynamic-json-object-to-web-api-newtonsoft-example
+ /// and http://stackoverflow.com/questions/3142495/deserialize-json-into-c-sharp-dynamic-object
+ /// Use ActionName attribute to allow multiple POST URLs, one for each supported command
+ /// E.g. http://stackoverflow.com/a/12703423/939250
+ /// Strictly speaking, this goes against the purpose of an ApiController, which is to provide one GET/POST/PUT/DELETE, etc.
+ /// However, it reduces the amount of code by removing the need for a switch according to the incoming command type.
+ /// http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx
+ /// </para>
+ /// <para>
+ /// Exceptions handled on command by command basis rather than globally to allow details of the command
+ /// to be reflected in the response. Default error handling is in the catch for Exception, but
+ /// other exception types may be caught where the feedback would be different.
+ /// NB: global alternatives discussed at
+ /// http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx
+ /// </para>
+ /// </remarks>
+ public class HypervResourceController : ApiController
+ {
+ public static void Configure(HypervResourceControllerConfig config)
+ {
+ HypervResourceController.config = config;
+ wmiCallsV2 = new WmiCallsV2();
+ }
+
+ public static HypervResourceControllerConfig config = new HypervResourceControllerConfig();
+
+ private static ILog logger = LogManager.GetLogger(typeof(HypervResourceController));
+ private string systemVmIso = "";
+ Dictionary<String, String> contextMap = new Dictionary<String, String>();
+
+ public static void Initialize()
+ {
+ }
+
+ public static IWmiCallsV2 wmiCallsV2 { get; set;}
+
+ // GET api/HypervResource
+ public string Get()
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ return "HypervResource controller running, use POST to send JSON encoded RPCs"; ;
+ }
+ }
+
+ /// <summary>
+ /// NOP - placeholder for future setup, e.g. delete existing VMs or Network ports
+ /// POST api/HypervResource/SetupCommand
+ /// </summary>
+ /// <param name="cmd"></param>
+ /// <returns></returns>
+ /// TODO: produce test
+ [HttpPost]
+ [ActionName(CloudStackTypes.SetupCommand)]
+ public JContainer SetupCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
logger.Info(CloudStackTypes.SetupCommand + Utils.CleanString(cmd.ToString()));
-
- string details = null;
- bool result = false;
-
- try
- {
- result = true;
- }
- catch (Exception sysEx)
- {
- details = CloudStackTypes.SetupCommand + " failed due to " + sysEx.Message;
- logger.Error(details, sysEx);
- }
-
- object ansContent = new
- {
- result = result,
- details = "success - NOP",
- _reconnect = false,
- contextMap = contextMap
- };
-
- return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.SetupAnswer);
- }
- }
-
- // POST api/HypervResource/AttachCommand
- [HttpPost]
- [ActionName(CloudStackTypes.AttachCommand)]
- public JContainer AttachCommand([FromBody]dynamic cmd)
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
- logger.Info(CloudStackTypes.AttachCommand + Utils.CleanString(cmd.ToString()));
-
- string details = null;
- bool result = false;
-
- try
- {
- string vmName = (string)cmd.vmName;
- DiskTO disk = DiskTO.ParseJson(cmd.disk);
-
- if (disk.type.Equals("ISO"))
- {
- TemplateObjectTO dataStore = disk.templateObjectTO;
- NFSTO share = dataStore.nfsDataStoreTO;
- Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
- string diskPath = Utils.NormalizePath(Path.Combine(share.UncPath, dataStore.path));
- wmiCallsV2.AttachIso(vmName, diskPath);
- result = true;
- }
- else if (disk.type.Equals("DATADISK"))
- {
- VolumeObjectTO volume = disk.volumeObjectTO;
- PrimaryDataStoreTO primary = volume.primaryDataStore;
- if (!primary.isLocal)
- {
- Utils.ConnectToRemote(primary.UncPath, primary.Domain, primary.User, primary.Password);
- }
- string diskPath = Utils.NormalizePath(volume.FullFileName);
- wmiCallsV2.AttachDisk(vmName, diskPath, disk.diskSequence);
- result = true;
- }
- else
- {
- details = "Invalid disk type to be attached to vm " + vmName;
- }
- }
- catch (Exception sysEx)
- {
- details = CloudStackTypes.AttachCommand + " failed due to " + sysEx.Message;
- logger.Error(details, sysEx);
- }
-
- object ansContent = new
- {
- result = result,
- details = details,
- disk = cmd.disk,
- contextMap = contextMap
- };
-
- return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.AttachAnswer);
- }
- }
-
- // POST api/HypervResource/DetachCommand
- [HttpPost]
- [ActionName(CloudStackTypes.DettachCommand)]
- public JContainer DetachCommand([FromBody]dynamic cmd)
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
- logger.Info(CloudStackTypes.DettachCommand + Utils.CleanString(cmd.ToString()));
-
- string details = null;
- bool result = false;
-
- try
- {
- string vmName = (string)cmd.vmName;
- DiskTO disk = DiskTO.ParseJson(cmd.disk);
-
- if (disk.type.Equals("ISO"))
- {
- TemplateObjectTO dataStore = disk.templateObjectTO;
- NFSTO share = dataStore.nfsDataStoreTO;
- string diskPath = Utils.NormalizePath(Path.Combine(share.UncPath, dataStore.path));
- wmiCallsV2.DetachDisk(vmName, diskPath);
- result = true;
- }
- else if (disk.type.Equals("DATADISK"))
- {
- VolumeObjectTO volume = disk.volumeObjectTO;
- PrimaryDataStoreTO primary = volume.primaryDataStore;
- string diskPath = Utils.NormalizePath(volume.FullFileName);
- wmiCallsV2.DetachDisk(vmName, diskPath);
- result = true;
- }
- else
- {
- details = "Invalid disk type to be dettached from vm " + vmName;
- }
- }
- catch (Exception sysEx)
- {
- details = CloudStackTypes.DettachCommand + " failed due to " + sysEx.Message;
- logger.Error(details, sysEx);
- }
-
- object ansContent = new
- {
- result = result,
- details = details,
- contextMap = contextMap
- };
-
- return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.DettachAnswer);
- }
- }
-
- // POST api/HypervResource/RebootCommand
- [HttpPost]
- [ActionName(CloudStackTypes.RebootCommand)]
- public JContainer RebootCommand([FromBody]dynamic cmd)
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
+
+ string details = null;
+ bool result = false;
+
+ try
+ {
+ result = true;
+ }
+ catch (Exception sysEx)
+ {
+ details = CloudStackTypes.SetupCommand + " failed due to " + sysEx.Message;
+ logger.Error(details, sysEx);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = "success - NOP",
+ _reconnect = false,
+ contextMap = contextMap
+ };
+
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.SetupAnswer);
+ }
+ }
+
+ // POST api/HypervResource/AttachCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.AttachCommand)]
+ public JContainer AttachCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.AttachCommand + Utils.CleanString(cmd.ToString()));
+
+ string details = null;
+ bool result = false;
+
+ try
+ {
+ string vmName = (string)cmd.vmName;
+ DiskTO disk = DiskTO.ParseJson(cmd.disk);
+
+ if (disk.type.Equals("ISO"))
+ {
+ TemplateObjectTO dataStore = disk.templateObjectTO;
+ NFSTO share = dataStore.nfsDataStoreTO;
+ Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
+ string diskPath = Utils.NormalizePath(Path.Combine(share.UncPath, dataStore.path));
+ wmiCallsV2.AttachIso(vmName, diskPath);
+ result = true;
+ }
+ else if (disk.type.Equals("DATADISK"))
+ {
+ VolumeObjectTO volume = disk.volumeObjectTO;
+ PrimaryDataStoreTO primary = volume.primaryDataStore;
+ if (!primary.isLocal)
+ {
+ Utils.ConnectToRemote(primary.UncPath, primary.Domain, primary.User, primary.Password);
+ }
+ string diskPath = Utils.NormalizePath(volume.FullFileName);
+ wmiCallsV2.AttachDisk(vmName, diskPath, disk.diskSequence);
+ result = true;
+ }
+ else
+ {
+ details = "Invalid disk type to be attached to vm " + vmName;
+ }
+ }
+ catch (Exception sysEx)
+ {
+ details = CloudStackTypes.AttachCommand + " failed due to " + sysEx.Message;
+ logger.Error(details, sysEx);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ disk = cmd.disk,
+ contextMap = contextMap
+ };
+
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.AttachAnswer);
+ }
+ }
+
+ // POST api/HypervResource/DetachCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.DettachCommand)]
+ public JContainer DetachCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.DettachCommand + Utils.CleanString(cmd.ToString()));
+
+ string details = null;
+ bool result = false;
+
+ try
+ {
+ string vmName = (string)cmd.vmName;
+ DiskTO disk = DiskTO.ParseJson(cmd.disk);
+
+ if (disk.type.Equals("ISO"))
+ {
+ TemplateObjectTO dataStore = disk.templateObjectTO;
+ NFSTO share = dataStore.nfsDataStoreTO;
+ string diskPath = Utils.NormalizePath(Path.Combine(share.UncPath, dataStore.path));
+ wmiCallsV2.DetachDisk(vmName, diskPath);
+ result = true;
+ }
+ else if (disk.type.Equals("DATADISK"))
+ {
+ VolumeObjectTO volume = disk.volumeObjectTO;
+ PrimaryDataStoreTO primary = volume.primaryDataStore;
+ string diskPath = Utils.NormalizePath(volume.FullFileName);
+ wmiCallsV2.DetachDisk(vmName, diskPath);
+ result = true;
+ }
+ else
+ {
+ details = "Invalid disk type to be dettached from vm " + vmName;
+ }
+ }
+ catch (Exception sysEx)
+ {
+ details = CloudStackTypes.DettachCommand + " failed due to " + sysEx.Message;
+ logger.Error(details, sysEx);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ contextMap = contextMap
+ };
+
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.DettachAnswer);
+ }
+ }
+
+ // POST api/HypervResource/RebootCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.RebootCommand)]
+ public JContainer RebootCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
logger.Info(CloudStackTypes.RebootCommand + Utils.CleanString(cmd.ToString()));
-
- string details = null;
- bool result = false;
-
- try
- {
- string vmName = (string)cmd.vmName;
- var sys = wmiCallsV2.GetComputerSystem(vmName);
- if (sys == null)
- {
- details = CloudStackTypes.RebootCommand + " requested unknown VM " + vmName;
- logger.Error(details);
- }
- else
- {
- wmiCallsV2.SetState(sys, RequiredState.Reset);
- result = true;
- }
- }
- catch (Exception sysEx)
- {
- details = CloudStackTypes.RebootCommand + " failed due to " + sysEx.Message;
- logger.Error(details, sysEx);
- }
-
- object ansContent = new
- {
- result = result,
- details = details,
- contextMap = contextMap
- };
-
- return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.RebootAnswer);
- }
- }
-
- // POST api/HypervResource/DestroyCommand
- [HttpPost]
- [ActionName(CloudStackTypes.DestroyCommand)]
- public JContainer DestroyCommand([FromBody]dynamic cmd)
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
+
+ string details = null;
+ bool result = false;
+
+ try
+ {
+ string vmName = (string)cmd.vmName;
+ var sys = wmiCallsV2.GetComputerSystem(vmName);
+ if (sys == null)
+ {
+ details = CloudStackTypes.RebootCommand + " requested unknown VM " + vmName;
+ logger.Error(details);
+ }
+ else
+ {
+ wmiCallsV2.SetState(sys, RequiredState.Reset);
+ result = true;
+ }
+ }
+ catch (Exception sysEx)
+ {
+ details = CloudStackTypes.RebootCommand + " failed due to " + sysEx.Message;
+ logger.Error(details, sysEx);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ contextMap = contextMap
+ };
+
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.RebootAnswer);
+ }
+ }
+
+ // POST api/HypervResource/DestroyCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.DestroyCommand)]
+ public JContainer DestroyCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
logger.Info(CloudStackTypes.DestroyCommand + Utils.CleanString(cmd.ToString()));
-
- string details = null;
- bool result = false;
-
- try
- {
- // Assert
+
+ string details = null;
+ bool result = false;
+
+ try
+ {
+ // Assert
String errMsg = "No 'volume' details in " + CloudStackTypes.DestroyCommand + " " + Utils.CleanString(cmd.ToString());
- if (cmd.volume == null)
- {
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
-
- // Assert
- errMsg = "No valide path in DestroyCommand in " + CloudStackTypes.DestroyCommand + " " + (String)cmd.ToString();
- if (cmd.volume.path == null)
- {
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
-
- String path = (string)cmd.volume.path;
- if (!File.Exists(path))
- {
- logger.Info(CloudStackTypes.DestroyCommand + ", but volume at pass already deleted " + path);
- }
-
- string vmName = (string)cmd.vmName;
- if (!string.IsNullOrEmpty(vmName) && File.Exists(path))
- {
- // Make sure that this resource is removed from the VM
- wmiCallsV2.DetachDisk(vmName, path);
- }
-
- File.Delete(path);
- result = true;
- }
- catch (Exception sysEx)
- {
- details = CloudStackTypes.DestroyCommand + " failed due to " + sysEx.Message;
- logger.Error(details, sysEx);
- }
-
- object ansContent = new
- {
- result = result,
- details = details,
- contextMap = contextMap
- };
-
- return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
- }
- }
-
- // POST api/HypervResource/DeleteCommand
- [HttpPost]
- [ActionName(CloudStackTypes.DeleteCommand)]
- public JContainer DeleteCommand([FromBody]dynamic cmd)
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
+ if (cmd.volume == null)
+ {
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+
+ // Assert
+ errMsg = "No valide path in DestroyCommand in " + CloudStackTypes.DestroyCommand + " " + (String)cmd.ToString();
+ if (cmd.volume.path == null)
+ {
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+
+ String path = (string)cmd.volume.path;
+ if (!File.Exists(path))
+ {
+ logger.Info(CloudStackTypes.DestroyCommand + ", but volume at pass already deleted " + path);
+ }
+
+ string vmName = (string)cmd.vmName;
+ if (!string.IsNullOrEmpty(vmName) && File.Exists(path))
+ {
+ // Make sure that this resource is removed from the VM
+ wmiCallsV2.DetachDisk(vmName, path);
+ }
+
+ File.Delete(path);
+ result = true;
+ }
+ catch (Exception sysEx)
+ {
+ details = CloudStackTypes.DestroyCommand + " failed due to " + sysEx.Message;
+ logger.Error(details, sysEx);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ contextMap = contextMap
+ };
+
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+ }
+ }
+
+ // POST api/HypervResource/DeleteCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.DeleteCommand)]
+ public JContainer DeleteCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
logger.Info(CloudStackTypes.DestroyCommand + Utils.CleanString(cmd.ToString()));
-
- string details = null;
- bool result = false;
-
- try
- {
- // Assert
+
+ string details = null;
+ bool result = false;
+
+ try
+ {
+ // Assert
String errMsg = "No 'volume' details in " + CloudStackTypes.DestroyCommand + " " + Utils.CleanString(cmd.ToString());
- VolumeObjectTO destVolumeObjectTO = VolumeObjectTO.ParseJson(cmd.data);
-
- if (destVolumeObjectTO.name == null)
- {
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
-
- String path = destVolumeObjectTO.FullFileName;
- if (!File.Exists(path))
- {
- logger.Info(CloudStackTypes.DestroyCommand + ", but volume at pass already deleted " + path);
- }
-
- string vmName = (string)cmd.vmName;
- if (!string.IsNullOrEmpty(vmName) && File.Exists(path))
- {
- // Make sure that this resource is removed from the VM
- wmiCallsV2.DetachDisk(vmName, path);
- }
-
- File.Delete(path);
- result = true;
- }
- catch (Exception sysEx)
- {
- details = CloudStackTypes.DestroyCommand + " failed due to " + sysEx.Message;
- logger.Error(details, sysEx);
- }
-
- object ansContent = new
- {
- result = result,
- details = details,
- contextMap = contextMap
- };
-
- return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
- }
- }
-
-
- private static JArray ReturnCloudStackTypedJArray(object ansContent, string ansType)
- {
- JObject ansObj = Utils.CreateCloudStackObject(ansType, ansContent);
- JArray answer = new JArray(ansObj);
- logger.Info(Utils.CleanString(ansObj.ToString()));
- return answer;
- }
-
- // POST api/HypervResource/CreateCommand
- [HttpPost]
- [ActionName(CloudStackTypes.CreateCommand)]
- public JContainer CreateCommand([FromBody]dynamic cmd)
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
- logger.Info(CloudStackTypes.CreateCommand + Utils.CleanString(cmd.ToString()));
-
- string details = null;
- bool result = false;
- VolumeInfo volume = new VolumeInfo();
-
- try
- {
- string diskType = cmd.diskCharacteristics.type;
- ulong disksize = cmd.diskCharacteristics.size;
- string templateUri = cmd.templateUrl;
-
- // assert: valid storagepool?
- string poolTypeStr = cmd.pool.type;
- string poolLocalPath = cmd.pool.path;
- string poolUuid = cmd.pool.uuid;
- string newVolPath = null;
- long volId = cmd.volId;
- string newVolName = null;
-
- if (ValidStoragePool(poolTypeStr, poolLocalPath, poolUuid, ref details))
- {
- // No template URI? Its a blank disk.
- if (string.IsNullOrEmpty(templateUri))
- {
- // assert
- VolumeType volType;
- if (!Enum.TryParse<VolumeType>(diskType, out volType) && volType != VolumeType.DATADISK)
- {
- details = "Cannot create volumes of type " + (string.IsNullOrEmpty(diskType) ? "NULL" : diskType);
- }
- else
- {
- newVolName = cmd.diskCharacteristics.name;
- newVolPath = Path.Combine(poolLocalPath, newVolName, diskType.ToLower());
- // TODO: make volume format and block size configurable
- wmiCallsV2.CreateDynamicVirtualHardDisk(disksize, newVolPath);
- if (File.Exists(newVolPath))
- {
- result = true;
- }
- else
- {
- details = "Failed to create DATADISK with name " + newVolName;
- }
- }
- }
- else
- {
- // TODO: Does this always work, or do I need to download template at times?
- if (templateUri.Contains("/") || templateUri.Contains("\\"))
- {
- details = "Problem with templateURL " + templateUri +
- " the URL should be volume UUID in primary storage created by previous PrimaryStorageDownloadCommand";
- logger.Error(details);
- }
- else
- {
- logger.Debug("Template's name in primary store should be " + templateUri);
- // HypervPhysicalDisk BaseVol = primaryPool.getPhysicalDisk(tmplturl);
- FileInfo srcFileInfo = new FileInfo(templateUri);
- newVolName = Guid.NewGuid() + srcFileInfo.Extension;
- newVolPath = Path.Combine(poolLocalPath, newVolName);
- logger.Debug("New volume will be at " + newVolPath);
- string oldVolPath = Path.Combine(poolLocalPath, templateUri);
- File.Copy(oldVolPath, newVolPath);
- if (File.Exists(newVolPath))
- {
- result = true;
- }
- else
- {
- details = "Failed to create DATADISK with name " + newVolName;
- }
- }
- volume = new VolumeInfo(
- volId, diskType,
- poolTypeStr, poolUuid, newVolName,
- newVolPath, newVolPath, (long)disksize, null);
- }
- }
- }
- catch (Exception sysEx)
- {
- // TODO: consider this as model for error processing in all commands
- details = CloudStackTypes.CreateCommand + " failed due to " + sysEx.Message;
- logger.Error(details, sysEx);
- }
-
- object ansContent = new
- {
- result = result,
- details = details,
- volume = volume,
- contextMap = contextMap
- };
- return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CreateAnswer);
- }
- }
-
- // POST api/HypervResource/PrimaryStorageDownloadCommand
- [HttpPost]
- [ActionName(CloudStackTypes.PrimaryStorageDownloadCommand)]
- public JContainer PrimaryStorageDownloadCommand([FromBody]dynamic cmd)
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
- logger.Info(CloudStackTypes.PrimaryStorageDownloadCommand + Utils.CleanString(cmd.ToString()));
- string details = null;
- bool result = false;
- long size = 0;
- string newCopyFileName = null;
-
- string poolLocalPath = cmd.localPath;
- string poolUuid = cmd.poolUuid;
- if (!Directory.Exists(poolLocalPath))
- {
- details = "None existent local path " + poolLocalPath;
- }
- else
- {
- // Compose name for downloaded file.
- string sourceUrl = cmd.url;
- if (sourceUrl.ToLower().EndsWith(".vhd"))
- {
- newCopyFileName = Guid.NewGuid() + ".vhd";
- }
- if (sourceUrl.ToLower().EndsWith(".vhdx"))
- {
- newCopyFileName = Guid.NewGuid() + ".vhdx";
- }
-
- // assert
- if (newCopyFileName == null)
- {
- details = CloudStackTypes.PrimaryStorageDownloadCommand + " Invalid file extension for hypervisor type in source URL " + sourceUrl;
- logger.Error(details);
- }
- else
- {
- try
- {
- FileInfo newFile;
- if (CopyURI(sourceUrl, newCopyFileName, poolLocalPath, out newFile, ref details))
- {
- size = newFile.Length;
- result = true;
- }
- }
- catch (System.Exception ex)
- {
- details = CloudStackTypes.PrimaryStorageDownloadCommand + " Cannot download source URL " + sourceUrl + " due to " + ex.Message;
- logger.Error(details, ex);
- }
- }
- }
-
- object ansContent = new
- {
- result = result,
- details = details,
- templateSize = size,
- installPath = newCopyFileName,
- contextMap = contextMap
- };
- return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.PrimaryStorageDownloadAnswer);
- }
- }
-
- private static bool ValidStoragePool(string poolTypeStr, string poolLocalPath, string poolUuid, ref string details)
- {
- StoragePoolType poolType;
- if (!Enum.TryParse<StoragePoolType>(poolTypeStr, out poolType) || poolType != StoragePoolType.Filesystem)
- {
- details = "Primary storage pool " + poolUuid + " type " + poolType + " local path " + poolLocalPath + " has invalid StoragePoolType";
- logger.Error(details);
- return false;
- }
- else if (!Directory.Exists(poolLocalPath))
- {
- details = "Primary storage pool " + poolUuid + " type " + poolType + " local path " + poolLocalPath + " has invalid local path";
- logger.Error(details);
- return false;
- }
- return true;
- }
-
- /// <summary>
- /// Exceptions to watch out for:
- /// Exceptions related to URI creation
- /// System.SystemException
- /// +-System.ArgumentNullException
- /// +-System.FormatException
- /// +-System.UriFormatException
- ///
- /// Exceptions related to NFS URIs
- /// System.SystemException
- /// +-System.NotSupportedException
- /// +-System.ArgumentException
- /// +-System.ArgumentNullException
- /// +-System.Security.SecurityException;
- /// +-System.UnauthorizedAccessException
- /// +-System.IO.IOException
- /// +-System.IO.PathTooLongException
- ///
- /// Exceptions related to HTTP URIs
- /// System.SystemException
- /// +-System.InvalidOperationException
- /// +-System.Net.WebException
- /// +-System.NotSupportedException
- /// +-System.ArgumentNullException
- /// </summary>
- /// <param name="sourceUri"></param>
- /// <param name="newCopyFileName"></param>
- /// <param name="poolLocalPath"></param>
- /// <returns></returns>
- private bool CopyURI(string sourceUri, string newCopyFileName, string poolLocalPath, out FileInfo newFile, ref string details)
- {
- Uri source = new Uri(sourceUri);
- String destFilePath = Path.Combine(poolLocalPath, newCopyFileName);
- string[] pathSegments = source.Segments;
- String templateUUIDandExtension = pathSegments[pathSegments.Length - 1];
- newFile = new FileInfo(destFilePath);
-
- // NFS URI assumed to already be mounted locally. Mount location given by settings.
- if (source.Scheme.ToLower().Equals("nfs"))
- {
- String srcDiskPath = Path.Combine(HypervResourceController.config.LocalSecondaryStoragePath, templateUUIDandExtension);
- String taskMsg = "Copy NFS url in " + sourceUri + " at " + srcDiskPath + " to pool " + poolLocalPath;
- logger.Debug(taskMsg);
- File.Copy(srcDiskPath, destFilePath);
- }
- else if (source.Scheme.ToLower().Equals("http") || source.Scheme.ToLower().Equals("https"))
- {
- System.Net.WebClient webclient = new WebClient();
- webclient.DownloadFile(source, destFilePath);
- }
- else
- {
- details = "Unsupported URI scheme " + source.Scheme.ToLower() + " in source URI " + sourceUri;
- logger.Error(details);
- return false;
- }
-
- if (!File.Exists(destFilePath))
- {
- details = "Filed to copy " + sourceUri + " to primary pool destination " + destFilePath;
- logger.Error(details);
- return false;
- }
- return true;
- }
-
- // POST api/HypervResource/CheckHealthCommand
- [HttpPost]
- [ActionName(CloudStackTypes.CheckHealthCommand)]
- public JContainer CheckHealthCommand([FromBody]dynamic cmd)
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
- logger.Info(CloudStackTypes.CheckHealthCommand + Utils.CleanString(cmd.ToString()));
- object ansContent = new
- {
- result = true,
- details = "resource is alive",
- contextMap = contextMap
- };
- return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckHealthAnswer);
- }
- }
-
- // POST api/HypervResource/CheckOnHostCommand
- [HttpPost]
- [ActionName(CloudStackTypes.CheckOnHostCommand)]
- public JContainer CheckOnHostCommand([FromBody]dynamic cmd)
- {
- using (log4net.NDC.Push(Guid.NewGuid().ToString()))
- {
- logger.Info(CloudStackTypes.CheckOnHostCommand + Utils.CleanString(cmd.ToString()));
- string details = "host is not alive";
+ VolumeObjectTO destVolumeObjectTO = VolumeObjectTO.ParseJson(cmd.data);
+
+ if (destVolumeObjectTO.name == null)
+ {
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+
+ String path = destVolumeObjectTO.FullFileName;
+ if (!File.Exists(path))
+ {
+ logger.Info(CloudStackTypes.DestroyCommand + ", but volume at pass already deleted " + path);
+ }
+
+ string vmName = (string)cmd.vmName;
+ if (!string.IsNullOrEmpty(vmName) && File.Exists(path))
+ {
+ // Make sure that this resource is removed from the VM
+ wmiCallsV2.DetachDisk(vmName, path);
+ }
+
+ File.Delete(path);
+ result = true;
+ }
+ catch (Exception sysEx)
+ {
+ details = CloudStackTypes.DestroyCommand + " failed due to " + sysEx.Message;
+ logger.Error(details, sysEx);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ contextMap = contextMap
+ };
+
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+ }
+ }
+
+
+ private static JArray ReturnCloudStackTypedJArray(object ansContent, string ansType)
+ {
+ JObject ansObj = Utils.CreateCloudStackObject(ansType, ansContent);
+ JArray answer = new JArray(ansObj);
+ logger.Info(Utils.CleanString(ansObj.ToString()));
+ return answer;
+ }
+
+ // POST api/HypervResource/CreateCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.CreateCommand)]
+ public JContainer CreateCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.CreateCommand + Utils.CleanString(cmd.ToString()));
+
+ string details = null;
+ bool result = false;
+ VolumeInfo volume = new VolumeInfo();
+
+ try
+ {
+ string diskType = cmd.diskCharacteristics.type;
+ ulong disksize = cmd.diskCharacteristics.size;
+ string templateUri = cmd.templateUrl;
+
+ // assert: valid storagepool?
+ string poolTypeStr = cmd.pool.type;
+ string poolLocalPath = cmd.pool.path;
+ string poolUuid = cmd.pool.uuid;
+ string newVolPath = null;
+ long volId = cmd.volId;
+ string newVolName = null;
+
+ if (ValidStoragePool(poolTypeStr, poolLocalPath, poolUuid, ref details))
+ {
+ // No template URI? Its a blank disk.
+ if (string.IsNullOrEmpty(templateUri))
+ {
+ // assert
+ VolumeType volType;
+ if (!Enum.TryParse<VolumeType>(diskType, out volType) && volType != VolumeType.DATADISK)
+ {
+ details = "Cannot create volumes of type " + (string.IsNullOrEmpty(diskType) ? "NULL" : diskType);
+ }
+ else
+ {
+ newVolName = cmd.diskCharacteristics.name;
+ newVolPath = Path.Combine(poolLocalPath, newVolName, diskType.ToLower());
+ // TODO: make volume format and block size configurable
+ wmiCallsV2.CreateDynamicVirtualHardDisk(disksize, newVolPath);
+ if (File.Exists(newVolPath))
+ {
+ result = true;
+ }
+ else
+ {
+ details = "Failed to create DATADISK with name " + newVolName;
+ }
+ }
+ }
+ else
+ {
+ // TODO: Does this always work, or do I need to download template at times?
+ if (templateUri.Contains("/") || templateUri.Contains("\\"))
+ {
+ details = "Problem with templateURL " + templateUri +
+ " the URL should be volume UUID in primary storage created by previous PrimaryStorageDownloadCommand";
+ logger.Error(details);
+ }
+ else
+ {
+ logger.Debug("Template's name in primary store should be " + templateUri);
+ // HypervPhysicalDisk BaseVol = primaryPool.getPhysicalDisk(tmplturl);
+ FileInfo srcFileInfo = new FileInfo(templateUri);
+ newVolName = Guid.NewGuid() + srcFileInfo.Extension;
+ newVolPath = Path.Combine(poolLocalPath, newVolName);
+ logger.Debug("New volume will be at " + newVolPath);
+ string oldVolPath = Path.Combine(poolLocalPath, templateUri);
+ File.Copy(oldVolPath, newVolPath);
+ if (File.Exists(newVolPath))
+ {
+ result = true;
+ }
+ else
+ {
+ details = "Failed to create DATADISK with name " + newVolName;
+ }
+ }
+ volume = new VolumeInfo(
+ volId, diskType,
+ poolTypeStr, poolUuid, newVolName,
+ newVolPath, newVolPath, (long)disksize, null);
+ }
+ }
+ }
+ catch (Exception sysEx)
+ {
+ // TODO: consider this as model for error processing in all commands
+ details = CloudStackTypes.CreateCommand + " failed due to " + sysEx.Message;
+ logger.Error(details, sysEx);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ volume = volume,
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CreateAnswer);
+ }
+ }
+
+ // POST api/HypervResource/PrimaryStorageDownloadCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.PrimaryStorageDownloadCommand)]
+ public JContainer PrimaryStorageDownloadCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.PrimaryStorageDownloadCommand + Utils.CleanString(cmd.ToString()));
+ string details = null;
+ bool result = false;
+ long size = 0;
+ string newCopyFileName = null;
+
+ string poolLocalPath = cmd.localPath;
+ string poolUuid = cmd.poolUuid;
+ if (!Directory.Exists(poolLocalPath))
+ {
+ details = "None existent local path " + poolLocalPath;
+ }
+ else
+ {
+ // Compose name for downloaded file.
+ string sourceUrl = cmd.url;
+ if (sourceUrl.ToLower().EndsWith(".vhd"))
+ {
+ newCopyFileName = Guid.NewGuid() + ".vhd";
+ }
+ if (sourceUrl.ToLower().EndsWith(".vhdx"))
+ {
+ newCopyFileName = Guid.NewGuid() + ".vhdx";
+ }
+
+ // assert
+ if (newCopyFileName == null)
+ {
+ details = CloudStackTypes.PrimaryStorageDownloadCommand + " Invalid file extension for hypervisor type in source URL " + sourceUrl;
+ logger.Error(details);
+ }
+ else
+ {
+ try
+ {
+ FileInfo newFile;
+ if (CopyURI(sourceUrl, newCopyFileName, poolLocalPath, out newFile, ref details))
+ {
+ size = newFile.Length;
+ result = true;
+ }
+ }
+ catch (System.Exception ex)
+ {
+ details = CloudStackTypes.PrimaryStorageDownloadCommand + " Cannot download source URL " + sourceUrl + " due to " + ex.Message;
+ logger.Error(details, ex);
+ }
+ }
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ templateSize = size,
+ installPath = newCopyFileName,
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.PrimaryStorageDownloadAnswer);
+ }
+ }
+
+ private static bool ValidStoragePool(string poolTypeStr, string poolLocalPath, string poolUuid, ref string details)
+ {
+ StoragePoolType poolType;
+ if (!Enum.TryParse<StoragePoolType>(poolTypeStr, out poolType) || poolType != StoragePoolType.Filesystem)
+ {
+ details = "Primary storage pool " + poolUuid + " type " + poolType + " local path " + poolLocalPath + " has invalid StoragePoolType";
+ logger.Error(details);
+ return false;
+ }
+ else if (!Directory.Exists(poolLocalPath))
+ {
+ details = "Primary storage pool " + poolUuid + " type " + poolType + " local path " + poolLocalPath + " has invalid local path";
+ logger.Error(details);
+ return false;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Exceptions to watch out for:
+ /// Exceptions related to URI creation
+ /// System.SystemException
+ /// +-System.ArgumentNullException
+ /// +-System.FormatException
+ /// +-System.UriFormatException
+ ///
+ /// Exceptions related to NFS URIs
+ /// System.SystemException
+ /// +-System.NotSupportedException
+ /// +-System.ArgumentException
+ /// +-System.ArgumentNullException
+ /// +-System.Security.SecurityException;
+ /// +-System.UnauthorizedAccessException
+ /// +-System.IO.IOException
+ /// +-System.IO.PathTooLongException
+ ///
+ /// Exceptions related to HTTP URIs
+ /// System.SystemException
+ /// +-System.InvalidOperationException
+ /// +-System.Net.WebException
+ /// +-System.NotSupportedException
+ /// +-System.ArgumentNullException
+ /// </summary>
+ /// <param name="sourceUri"></param>
+ /// <param name="newCopyFileName"></param>
+ /// <param name="poolLocalPath"></param>
+ /// <returns></returns>
+ private bool CopyURI(string sourceUri, string newCopyFileName, string poolLocalPath, out FileInfo newFile, ref string details)
+ {
+ Uri source = new Uri(sourceUri);
+ String destFilePath = Path.Combine(poolLocalPath, newCopyFileName);
+ string[] pathSegments = source.Segments;
+ String templateUUIDandExtension = pathSegments[pathSegments.Length - 1];
+ newFile = new FileInfo(destFilePath);
+
+ // NFS URI assumed to already be mounted locally. Mount location given by settings.
+ if (source.Scheme.ToLower().Equals("nfs"))
+ {
+ String srcDiskPath = Path.Combine(HypervResourceController.config.LocalSecondaryStoragePath, templateUUIDandExtension);
+ String taskMsg = "Copy NFS url in " + sourceUri + " at " + srcDiskPath + " to pool " + poolLocalPath;
+ logger.Debug(taskMsg);
+ File.Copy(srcDiskPath, destFilePath);
+ }
+ else if (source.Scheme.ToLower().Equals("http") || source.Scheme.ToLower().Equals("https"))
+ {
+ System.Net.WebClient webclient = new WebClient();
+ webclient.DownloadFile(source, destFilePath);
+ }
+ else
+ {
+ details = "Unsupported URI scheme " + source.Scheme.ToLower() + " in source URI " + sourceUri;
+ logger.Error(details);
+ return false;
+ }
+
+ if (!File.Exists(destFilePath))
+ {
+ details = "Filed to copy " + sourceUri + " to primary pool destination " + destFilePath;
+ logger.Error(details);
+ return false;
+ }
+ return true;
+ }
+
+ // POST api/HypervResource/CheckHealthCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.CheckHealthCommand)]
+ public JContainer CheckHealthCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.CheckHealthCommand + Utils.CleanString(cmd.ToString()));
+ object ansContent = new
+ {
+ result = true,
+ details = "resource is alive",
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckHealthAnswer);
+ }
+ }
+
+ // POST api/HypervResource/CheckOnHostCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.CheckOnHostCommand)]
+ public JContainer CheckOnHostCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.CheckOnHostCommand + Utils.CleanString(cmd.ToString()));
+ string details = "host is not alive";
+ bool result = true;
+ try
+ {
+ foreach (string poolPath in config.getAllPrimaryStorages())
+ {
+ if (IsHostAlive(poolPath, (string)cmd.host.privateNetwork.ip))
+ {
+ result = false;
+ details = "host is alive";
+ break;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error("Error Occurred in " + CloudStackTypes.CheckOnHostCommand + " : " + e.Message);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckOnHostAnswer);
+ }
+ }
+
+ private bool IsHostAlive(string poolPath, string privateIp)
+ {
+ bool hostAlive = false;
+ try
+ {
+ string hbFile = Path.Combine(poolPath, "hb-" + privateIp);
+ FileInfo file = new FileInfo(hbFile);
+ using (StreamReader sr = file.OpenText())
+ {
+ string epoch = sr.ReadLine();
+ string[] dateTime = epoch.Split('@');
+ string[] date = dateTime[0].Split('-');
+ string[] time = dateTime[1].Split(':');
+ DateTime epochTime = new DateTime(Convert.ToInt32(date[0]), Convert.ToInt32(date[1]), Convert.ToInt32(date[2]), Convert.ToInt32(time[0]),
+ Convert.ToInt32(time[1]), Convert.ToInt32(time[2]), DateTimeKind.Utc);
+ DateTime currentTime = DateTime.UtcNow;
+ DateTime ThreeMinuteLaterEpoch = epochTime.AddMinutes(3);
+ if (currentTime.CompareTo(ThreeMinuteLaterEpoch) < 0)
+ {
+ hostAlive = true;
+ }
+ sr.Close();
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Info("Exception occurred in verifying host " + e.Message);
+ }
+
+ return hostAlive;
+ }
+
+ // POST api/HypervResource/CheckSshCommand
+ // TODO: create test
+ [HttpPost]
+ [ActionName(CloudStackTypes.CheckSshCommand)]
+ public JContainer CheckSshCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.CheckSshCommand + Utils.CleanString(cmd.ToString()));
+ object ansContent = new
+ {
+ result = true,
+ details = "NOP, TODO: implement properly",
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckSshAnswer);
+ }
+ }
+
+ // POST api/HypervResource/CheckVirtualMachineCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.CheckVirtualMachineCommand)]
+ public JContainer CheckVirtualMachineCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.CheckVirtualMachineCommand + Utils.CleanString(cmd.ToString()));
+ string details = null;
+ bool result = false;
+ string vmName = cmd.vmName;
+ string state = null;
+
+ // TODO: Look up the VM, convert Hyper-V state to CloudStack version.
+ var sys = wmiCallsV2.GetComputerSystem(vmName);
+ if (sys == null)
+ {
+ details = CloudStackTypes.CheckVirtualMachineCommand + " requested unknown VM " + vmName;
+ logger.Error(details);
+ }
+ else
+ {
+ state = EnabledState.ToCloudStackState(sys.EnabledState); // TODO: V2 changes?
+ result = true;
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ state = state,
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckVirtualMachineAnswer);
+ }
+ }
+
+ // POST api/HypervResource/DeleteStoragePoolCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.DeleteStoragePoolCommand)]
+ public JContainer DeleteStoragePoolCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.DeleteStoragePoolCommand + Utils.CleanString(cmd.ToString()));
+ object ansContent = new
+ {
+ result = true,
+ details = "Current implementation does not delete local path corresponding to storage pool!",
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+ }
+ }
+
+ /// <summary>
+ /// NOP - legacy command -
+ /// POST api/HypervResource/CreateStoragePoolCommand
+ /// </summary>
+ /// <param name="cmd"></param>
+ /// <returns></returns>
+ [HttpPost]
+ [ActionName(CloudStackTypes.CreateStoragePoolCommand)]
+ public JContainer CreateStoragePoolCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.CreateStoragePoolCommand + Utils.CleanString(cmd.ToString()));
+ object ansContent = new
+ {
+ result = true,
+ details = "success - NOP",
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+ }
+ }
+
+ // POST api/HypervResource/ModifyStoragePoolCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.ModifyStoragePoolCommand)]
+ public JContainer ModifyStoragePoolCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.ModifyStoragePoolCommand + Utils.CleanString(cmd.ToString()));
+ string details = null;
+ string localPath;
+ StoragePoolType poolType;
+ object ansContent;
+
+ bool result = ValidateStoragePoolCommand(cmd, out localPath, out poolType, ref details);
+ if (!result)
+ {
+ ansContent = new
+ {
+ result = result,
+ details = details,
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+ }
+
+ var tInfo = new Dictionary<string, string>();
+ long capacityBytes = 0;
+ long availableBytes = 0;
+ string hostPath = null;
+ if (poolType == StoragePoolType.Filesystem)
+ {
+ GetCapacityForLocalPath(localPath, out capacityBytes, out availableBytes);
+ hostPath = localPath;
+ }
+ else if (poolType == StoragePoolType.NetworkFilesystem ||
+ poolType == StoragePoolType.SMB)
+ {
+ NFSTO share = new NFSTO();
+ String uriStr = "cifs://" + (string)cmd.pool.host + (string)cmd.pool.path;
+ share.uri = new Uri(uriStr);
+ hostPath = Utils.NormalizePath(share.UncPath);
+
+ // Check access to share.
+ Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
+ Utils.GetShareDetails(share.UncPath, out capacityBytes, out availableBytes);
+ config.setPrimaryStorage((string)cmd.pool.uuid, hostPath);
+ }
+ else
+ {
+ result = false;
+ }
+
+ String uuid = null;
+ var poolInfo = new
+ {
+ uuid = uuid,
+ host = cmd.pool.host,
+ hostPath = cmd.pool.path,
+ localPath = hostPath,
+ poolType = cmd.pool.type,
+ capacityBytes = capacityBytes,
+ availableBytes = availableBytes
+ };
+
+ ansContent = new
+ {
+ result = result,
+ details = details,
+ localPath = hostPath,
+ templateInfo = tInfo,
+ poolInfo = poolInfo,
+ contextMap = contextMap
+ };
+
+ if (result)
+ {
+ try
+ {
+ if ((bool)cmd.add)
+ {
+ logger.Info("Adding HeartBeat Task to task scheduler for pool " + (string)cmd.pool.uuid);
+ Utils.AddHeartBeatTask((string)cmd.pool.uuid, hostPath, config.PrivateIpAddress);
+ }
+ else
+ {
+ logger.Info("Deleting HeartBeat Task from task scheduler for pool " + (string)cmd.pool.uuid);
+ Utils.RemoveHeartBeatTask(cmd.pool.uuid);
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error("Error occurred in adding/delete HeartBeat Task to/from Task Scheduler : " + e.Message);
+ }
+ }
+
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.ModifyStoragePoolAnswer);
+ }
+ }
+
+ private bool ValidateStoragePoolCommand(dynamic cmd, out string localPath, out StoragePoolType poolType, ref string details)
+ {
+ dynamic pool = cmd.pool;
+ string poolTypeStr = pool.type;
+ localPath = cmd.localPath;
+ if (!Enum.TryParse<StoragePoolType>(poolTypeStr, out poolType))
+ {
+ details = "Request to create / modify unsupported pool type: " + (poolTypeStr == null ? "NULL" : poolTypeStr) + "in cmd " + JsonConvert.SerializeObject(cmd);
+ logger.Error(details);
+ return false;
+ }
+
+ if (poolType != StoragePoolType.Filesystem &&
+ poolType != StoragePoolType.NetworkFilesystem &&
+ poolType != StoragePoolType.SMB)
+ {
+ details = "Request to create / modify unsupported pool type: " + (poolTypeStr == null ? "NULL" : poolTypeStr) + "in cmd " + JsonConvert.SerializeObject(cmd);
+ logger.Error(details);
+ return false;
+ }
+
+ return true;
+ }
+
+ // POST api/HypervResource/PlugNicCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.PlugNicCommand)]
+ public JContainer PlugNicCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.PlugNicCommand + Utils.CleanString(cmd.ToString()));
+ object ansContent = new
+ {
+ result = true,
+ details = "Hot Nic plug not supported, change any empty virtual network adapter network settings",
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.PlugNicAnswer);
+ }
+ }
+
+
+ // POST api/HypervResource/CleanupNetworkRulesCmd
+ [HttpPost]
+ [ActionName(CloudStackTypes.CleanupNetworkRulesCmd)]
+ public JContainer CleanupNetworkRulesCmd([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.CleanupNetworkRulesCmd + Utils.CleanString(cmd.ToString()));
+ object ansContent = new
+ {
+ result = false,
+ details = "nothing to cleanup in our current implementation",
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+ }
+ }
+
+ // POST api/HypervResource/CheckNetworkCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.CheckNetworkCommand)]
+ public JContainer CheckNetworkCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.CheckNetworkCommand + Utils.CleanString(cmd.ToString()));
+ object ansContent = new
+ {
+ result = true,
+ details = (string)null,
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckNetworkAnswer);
+ }
+ }
+
+ // POST api/HypervResource/ReadyCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.ReadyCommand)]
+ public JContainer ReadyCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.ReadyCommand + Utils.CleanString(cmd.ToString()));
+ object ansContent = new
+ {
+ result = true,
+ details = (string)null,
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.ReadyAnswer);
+ }
+
+ }
+
+ // POST api/HypervResource/StartCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.StartCommand)]
+ public JContainer StartCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.StartCommand + Utils.CleanString(cmd.ToString()));
+ string details = null;
+ bool result = false;
+
+ try
+ {
+ string systemVmIsoPath = systemVmIso;
+ lock (systemVmIso)
+ {
+ systemVmIsoPath = systemVmIso;
+ String uriStr = (String)cmd.secondaryStorage;
+ if (!String.IsNullOrEmpty(uriStr))
+ {
+ if (String.IsNullOrEmpty(systemVmIsoPath) || !File.Exists(systemVmIsoPath))
+ {
+ NFSTO share = new NFSTO();
+ share.uri = new Uri(uriStr);
+ string defaultDataPath = wmiCallsV2.GetDefaultDataRoot();
+
+ string secondaryPath = Utils.NormalizePath(Path.Combine(share.UncPath, "systemvm"));
+ string[] choices = choices = Directory.GetFiles(secondaryPath, "systemvm*.iso");
+ if (choices.Length != 1)
+ {
+ String errMsg = "Couldn't locate the systemvm iso on " + secondaryPath;
+ logger.Debug(errMsg);
+ }
+ else
+ {
+ systemVmIsoPath = Utils.NormalizePath(Path.Combine(defaultDataPath, Path.GetFileName(choices[0])));
+ if (!File.Exists(systemVmIsoPath))
+ {
+ Utils.DownloadCifsFileToLocalFile(choices[0], share, systemVmIsoPath);
+ }
+ systemVmIso = systemVmIsoPath;
+ }
+ }
+ }
+ }
+
+ wmiCallsV2.DeployVirtualMachine(cmd, systemVmIsoPath);
+ result = true;
+ }
+ catch (Exception wmiEx)
+ {
+ details = CloudStackTypes.StartCommand + " fail on exception" + wmiEx.Message;
+ logger.Error(details, wmiEx);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ vm = cmd.vm,
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.StartAnswer);
+ }
+ }
+
+ // POST api/HypervResource/StopCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.StopCommand)]
+ public JContainer StopCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.StopCommand + Utils.CleanString(cmd.ToString()));
+ string details = null;
+ bool result = false;
+ bool checkBeforeCleanup = cmd.checkBeforeCleanup;
+ String vmName = cmd.vmName;
+
+ if (checkBeforeCleanup == true)
+ {
+ ComputerSystem vm = wmiCallsV2.GetComputerSystem(vmName);
+ if (vm == null || vm.EnabledState == 2)
+ {
+ // VM is not available or vm in running state
+ return ReturnCloudStackTypedJArray(new { result = false, details = "VM is running on host, bailing out", vm = vmName, contextMap = contextMap }, CloudStackTypes.StopAnswer);
+ }
+ }
+ try
+ {
+ wmiCallsV2.DestroyVm(cmd);
+ result = true;
+ }
+ catch (Exception wmiEx)
+ {
+ details = CloudStackTypes.StopCommand + " fail on exception" + wmiEx.Message;
+ logger.Error(details, wmiEx);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ vm = cmd.vm,
+ contextMap = contextMap
+ };
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.StopAnswer);
+ }
+ }
+
+ // POST api/HypervResource/CreateObjectCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.CreateObjectCommand)]
+ public JContainer CreateObjectCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.CreateObjectCommand + Utils.CleanString(cmd.ToString()));
+
+ bool result = false;
+ string details = null;
+ object newData = null;
+ try
+ {
+ VolumeObjectTO volume = VolumeObjectTO.ParseJson(cmd.data);
+ PrimaryDataStoreTO primary = volume.primaryDataStore;
+ ulong volumeSize = volume.size;
+ string volumeName = volume.uuid + ".vhdx";
+ string volumePath = null;
+
+ if (primary.isLocal)
+ {
+ volumePath = Path.Combine(primary.Path, volumeName);
+ }
+ else
+ {
+ volumePath = @"\\" + primary.uri.Host + primary.uri.LocalPath + @"\" + volumeName;
+ volumePath = Utils.NormalizePath(volumePath);
+ Utils.ConnectToRemote(primary.UncPath, primary.Domain, primary.User, primary.Password);
+ }
+ volume.path = volume.uuid;
+ wmiCallsV2.CreateDynamicVirtualHardDisk(volumeSize, volumePath);
+ if (File.Exists(volumePath))
+ {
+ result = true;
+ JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.VolumeObjectTO, volume);
+ newData = ansObj;
+ }
+ else
+ {
+ details = "Failed to create disk with name " + volumePath;
+ }
+ }
+ catch (Exception ex)
+ {
+ // Test by providing wrong key
+ details = CloudStackTypes.CreateObjectCommand + " failed on exception, " + ex.Message;
+ logger.Error(details, ex);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details,
+ data = newData,
+ contextMap = contextMap
+ };
+
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CreateObjectAnswer);
+ }
+ }
+
+ // POST api/HypervResource/MaintainCommand
+ // TODO: should this be a NOP?
+ [HttpPost]
+ [ActionName(CloudStackTypes.MaintainCommand)]
+ public JContainer MaintainCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+
<TRUNCATED>
[2/5] CLOUDSTACK-6518 [Hyper-V] Efficient way of finding the empty
nic in VR/VpcVR to configure VPC entities fixed windows line ending issues
Posted by ra...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4cb6c66f/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
index 4795073..d8dd3bb 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
@@ -1,262 +1,261 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
-using log4net;
-using System.Globalization;
-using System.Management;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using CloudStack.Plugin.WmiWrappers.ROOT.CIMV2;
-using System.IO;
-using System.Net.NetworkInformation;
-using System.Net;
-
-namespace HypervResource
-{
- public class WmiCallsV2 : IWmiCallsV2
- {
- public static String CloudStackUserDataKey = "cloudstack-vm-userdata";
-
- /// <summary>
- /// Defines the migration types.
- /// </summary>
- public enum MigrationType
- {
- VirtualSystem = 32768,
- Storage = 32769,
- Staged = 32770,
- VirtualSystemAndStorage = 32771
- };
-
- /// <summary>
- /// Defines migration transport types.
- /// </summary>
- public enum TransportType
- {
- TCP = 5,
- SMB = 32768
- };
-
- public static void Initialize()
- {
- // Trigger assembly load into curren appdomain
- }
-
- private static ILog logger = LogManager.GetLogger(typeof(WmiCallsV2));
-
- /// <summary>
- /// Returns ping status of the given ip
- /// </summary>
- public static String PingHost(String ip)
- {
- return "Success";
- }
-
- /// <summary>
- /// Returns ComputerSystem lacking any NICs and VOLUMEs
- /// </summary>
- public ComputerSystem AddUserData(ComputerSystem vm, string userData)
- {
- // Obtain controller for Hyper-V virtualisation subsystem
- VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
-
- // Create object to hold the data.
- KvpExchangeDataItem kvpItem = KvpExchangeDataItem.CreateInstance();
- kvpItem.LateBoundObject["Name"] = WmiCallsV2.CloudStackUserDataKey;
- kvpItem.LateBoundObject["Data"] = userData;
- kvpItem.LateBoundObject["Source"] = 0;
- logger.Debug("VM " + vm.Name + " gets userdata " + userData);
-
- // Update the resource settings for the VM.
- System.Management.ManagementBaseObject kvpMgmtObj = kvpItem.LateBoundObject;
- System.Management.ManagementPath jobPath;
- String kvpStr = kvpMgmtObj.GetText(System.Management.TextFormat.CimDtd20);
- uint ret_val = vmMgmtSvc.AddKvpItems(new String[] { kvpStr }, vm.Path, out jobPath);
-
- // If the Job is done asynchronously
- if (ret_val == ReturnCode.Started)
- {
- JobCompleted(jobPath);
- }
- else if (ret_val != ReturnCode.Completed)
- {
- var errMsg = string.Format(
- "Failed to update VM {0} (GUID {1}) due to {2} (ModifyVirtualSystem call), existing VM not deleted",
- vm.ElementName,
- vm.Name,
- ReturnCode.ToString(ret_val));
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
-
- return vm;
- }
-
- /// <summary>
- /// Returns ComputerSystem lacking any NICs and VOLUMEs
- /// </summary>
- public ComputerSystem CreateVM(string name, long memory_mb, int vcpus)
- {
- // Obtain controller for Hyper-V virtualisation subsystem
- VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
-
- // Create VM with correct name and default resources
- ComputerSystem vm = CreateDefaultVm(vmMgmtSvc, name);
-
- // Update the resource settings for the VM.
-
- // Resource settings are referenced through the Msvm_VirtualSystemSettingData object.
- VirtualSystemSettingData vmSettings = GetVmSettings(vm);
-
- // For memory settings, there is no Dynamic Memory, so reservation, limit and quantity are identical.
- MemorySettingData memSettings = GetMemSettings(vmSettings);
- memSettings.LateBoundObject["VirtualQuantity"] = memory_mb;
- memSettings.LateBoundObject["Reservation"] = memory_mb;
- memSettings.LateBoundObject["Limit"] = memory_mb;
-
- // Update the processor settings for the VM, static assignment of 100% for CPU limit
- ProcessorSettingData procSettings = GetProcSettings(vmSettings);
- procSettings.LateBoundObject["VirtualQuantity"] = vcpus;
- procSettings.LateBoundObject["Reservation"] = vcpus;
- procSettings.LateBoundObject["Limit"] = 100000;
-
- ModifyVmResources(vmMgmtSvc, vm, new String[] {
- memSettings.LateBoundObject.GetText(TextFormat.CimDtd20),
- procSettings.LateBoundObject.GetText(TextFormat.CimDtd20)
- });
- logger.InfoFormat("VM with display name {0} has GUID {1}", vm.ElementName, vm.Name);
- logger.DebugFormat("Resources for vm {0}: {1} MB memory, {2} vcpus", name, memory_mb, vcpus);
-
- return vm;
- }
-
- /// <summary>
- /// Create a (synthetic) nic, and attach it to the vm
- /// </summary>
- /// <param name="vm"></param>
- /// <param name="mac"></param>
- /// <param name="vlan"></param>
- /// <returns></returns>
- public SyntheticEthernetPortSettingData CreateNICforVm(ComputerSystem vm, string mac)
- {
- logger.DebugFormat("Creating nic for VM {0} (GUID {1})", vm.ElementName, vm.Name);
-
- // Obtain controller for Hyper-V networking subsystem
- var vmNetMgmtSvc = GetVirtualSwitchManagementService();
-
- // Create NIC resource by cloning the default NIC
- var synthNICsSettings = SyntheticEthernetPortSettingData.GetInstances(vmNetMgmtSvc.Scope, "InstanceID LIKE \"%Default\"");
-
- // Assert
- if (synthNICsSettings.Count != 1)
- {
- var errMsg = string.Format("Internal error, coudl not find default SyntheticEthernetPort instance");
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
- var defaultSynthNICSettings = synthNICsSettings.OfType<SyntheticEthernetPortSettingData>().First();
-
- var newSynthNICSettings = new SyntheticEthernetPortSettingData((ManagementBaseObject)defaultSynthNICSettings.LateBoundObject.Clone());
-
- // Assign configuration to new NIC
- string normalisedMAC = string.Join("", (mac.Split(new char[] { ':' })));
- newSynthNICSettings.LateBoundObject["ElementName"] = vm.ElementName;
- newSynthNICSettings.LateBoundObject["Address"] = normalisedMAC;
- newSynthNICSettings.LateBoundObject["StaticMacAddress"] = "TRUE";
- newSynthNICSettings.LateBoundObject["VirtualSystemIdentifiers"] = new string[] { "{" + Guid.NewGuid().ToString() + "}" };
- newSynthNICSettings.CommitObject();
-
- // Insert NIC into vm
- string[] newResources = new string[] { newSynthNICSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20)};
- ManagementPath[] newResourcePaths = AddVirtualResource(newResources, vm );
-
- // assert
- if (newResourcePaths.Length != 1)
- {
- var errMsg = string.Format(
- "Failed to properly insert a single NIC on VM {0} (GUID {1}): number of resource created {2}",
- vm.ElementName,
- vm.Name,
- newResourcePaths.Length);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
-
- return new SyntheticEthernetPortSettingData(newResourcePaths[0]);
- }
-
- public const string IDE_CONTROLLER = "Microsoft:Hyper-V:Emulated IDE Controller";
- public const string SCSI_CONTROLLER = "Microsoft:Hyper-V:Synthetic SCSI Controller";
- public const string HARDDISK_DRIVE = "Microsoft:Hyper-V:Synthetic Disk Drive";
- public const string ISO_DRIVE = "Microsoft:Hyper-V:Synthetic DVD Drive";
-
- // TODO: names harvested from Msvm_ResourcePool, not clear how to create new instances
- public const string ISO_DISK = "Microsoft:Hyper-V:Virtual CD/DVD Disk"; // For IDE_ISO_DRIVE
- public const string HARDDISK_DISK = "Microsoft:Hyper-V:Virtual Hard Disk"; // For IDE_HARDDISK_DRIVE
-
- /// <summary>
- /// Create new VM. By default we start it.
- /// </summary>
- public ComputerSystem DeployVirtualMachine(dynamic jsonObj, string systemVmIso)
- {
- var vmInfo = jsonObj.vm;
- string vmName = vmInfo.name;
- var nicInfo = vmInfo.nics;
- int vcpus = vmInfo.cpus;
- int memSize = vmInfo.maxRam / 1048576;
- string errMsg = vmName;
- var diskDrives = vmInfo.disks;
- var bootArgs = vmInfo.bootArgs;
- string defaultvlan = "4094";
-
- // assert
- errMsg = vmName + ": missing disk information, array empty or missing, agent expects *at least* one disk for a VM";
- if (diskDrives == null)
- {
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
- // assert
- errMsg = vmName + ": missing NIC information, array empty or missing, agent expects at least an empty array.";
- if (nicInfo == null )
- {
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
-
-
- // For existing VMs, return when we spot one of this name not stopped. In the meantime, remove any existing VMs of same name.
- ComputerSystem vmWmiObj = null;
- while ((vmWmiObj = GetComputerSystem(vmName)) != null)
- {
- logger.WarnFormat("Create request for existing vm, name {0}", vmName);
- if (vmWmiObj.EnabledState == EnabledState.Disabled)
- {
- logger.InfoFormat("Deleting existing VM with name {0}, before we go on to create a VM with the same name", vmName);
- DestroyVm(vmName);
- }
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
+using log4net;
+using System.Globalization;
+using System.Management;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using CloudStack.Plugin.WmiWrappers.ROOT.CIMV2;
+using System.IO;
+using System.Net.NetworkInformation;
+using System.Net;
+
+namespace HypervResource
+{
+ public class WmiCallsV2 : IWmiCallsV2
+ {
+ public static String CloudStackUserDataKey = "cloudstack-vm-userdata";
+
+ /// <summary>
+ /// Defines the migration types.
+ /// </summary>
+ public enum MigrationType
+ {
+ VirtualSystem = 32768,
+ Storage = 32769,
+ Staged = 32770,
+ VirtualSystemAndStorage = 32771
+ };
+
+ /// <summary>
+ /// Defines migration transport types.
+ /// </summary>
+ public enum TransportType
+ {
+ TCP = 5,
+ SMB = 32768
+ };
+
+ public static void Initialize()
+ {
+ // Trigger assembly load into curren appdomain
+ }
+
+ private static ILog logger = LogManager.GetLogger(typeof(WmiCallsV2));
+
+ /// <summary>
+ /// Returns ping status of the given ip
+ /// </summary>
+ public static String PingHost(String ip)
+ {
+ return "Success";
+ }
+
+ /// <summary>
+ /// Returns ComputerSystem lacking any NICs and VOLUMEs
+ /// </summary>
+ public ComputerSystem AddUserData(ComputerSystem vm, string userData)
+ {
+ // Obtain controller for Hyper-V virtualisation subsystem
+ VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
+
+ // Create object to hold the data.
+ KvpExchangeDataItem kvpItem = KvpExchangeDataItem.CreateInstance();
+ kvpItem.LateBoundObject["Name"] = WmiCallsV2.CloudStackUserDataKey;
+ kvpItem.LateBoundObject["Data"] = userData;
+ kvpItem.LateBoundObject["Source"] = 0;
+ logger.Debug("VM " + vm.Name + " gets userdata " + userData);
+
+ // Update the resource settings for the VM.
+ System.Management.ManagementBaseObject kvpMgmtObj = kvpItem.LateBoundObject;
+ System.Management.ManagementPath jobPath;
+ String kvpStr = kvpMgmtObj.GetText(System.Management.TextFormat.CimDtd20);
+ uint ret_val = vmMgmtSvc.AddKvpItems(new String[] { kvpStr }, vm.Path, out jobPath);
+
+ // If the Job is done asynchronously
+ if (ret_val == ReturnCode.Started)
+ {
+ JobCompleted(jobPath);
+ }
+ else if (ret_val != ReturnCode.Completed)
+ {
+ var errMsg = string.Format(
+ "Failed to update VM {0} (GUID {1}) due to {2} (ModifyVirtualSystem call), existing VM not deleted",
+ vm.ElementName,
+ vm.Name,
+ ReturnCode.ToString(ret_val));
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
+ return vm;
+ }
+
+ /// <summary>
+ /// Returns ComputerSystem lacking any NICs and VOLUMEs
+ /// </summary>
+ public ComputerSystem CreateVM(string name, long memory_mb, int vcpus)
+ {
+ // Obtain controller for Hyper-V virtualisation subsystem
+ VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
+
+ // Create VM with correct name and default resources
+ ComputerSystem vm = CreateDefaultVm(vmMgmtSvc, name);
+
+ // Update the resource settings for the VM.
+
+ // Resource settings are referenced through the Msvm_VirtualSystemSettingData object.
+ VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+
+ // For memory settings, there is no Dynamic Memory, so reservation, limit and quantity are identical.
+ MemorySettingData memSettings = GetMemSettings(vmSettings);
+ memSettings.LateBoundObject["VirtualQuantity"] = memory_mb;
+ memSettings.LateBoundObject["Reservation"] = memory_mb;
+ memSettings.LateBoundObject["Limit"] = memory_mb;
+
+ // Update the processor settings for the VM, static assignment of 100% for CPU limit
+ ProcessorSettingData procSettings = GetProcSettings(vmSettings);
+ procSettings.LateBoundObject["VirtualQuantity"] = vcpus;
+ procSettings.LateBoundObject["Reservation"] = vcpus;
+ procSettings.LateBoundObject["Limit"] = 100000;
+
+ ModifyVmResources(vmMgmtSvc, vm, new String[] {
+ memSettings.LateBoundObject.GetText(TextFormat.CimDtd20),
+ procSettings.LateBoundObject.GetText(TextFormat.CimDtd20)
+ });
+ logger.InfoFormat("VM with display name {0} has GUID {1}", vm.ElementName, vm.Name);
+ logger.DebugFormat("Resources for vm {0}: {1} MB memory, {2} vcpus", name, memory_mb, vcpus);
+
+ return vm;
+ }
+
+ /// <summary>
+ /// Create a (synthetic) nic, and attach it to the vm
+ /// </summary>
+ /// <param name="vm"></param>
+ /// <param name="mac"></param>
+ /// <param name="vlan"></param>
+ /// <returns></returns>
+ public SyntheticEthernetPortSettingData CreateNICforVm(ComputerSystem vm, string mac)
+ {
+ logger.DebugFormat("Creating nic for VM {0} (GUID {1})", vm.ElementName, vm.Name);
+
+ // Obtain controller for Hyper-V networking subsystem
+ var vmNetMgmtSvc = GetVirtualSwitchManagementService();
+
+ // Create NIC resource by cloning the default NIC
+ var synthNICsSettings = SyntheticEthernetPortSettingData.GetInstances(vmNetMgmtSvc.Scope, "InstanceID LIKE \"%Default\"");
+
+ // Assert
+ if (synthNICsSettings.Count != 1)
+ {
+ var errMsg = string.Format("Internal error, coudl not find default SyntheticEthernetPort instance");
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+ var defaultSynthNICSettings = synthNICsSettings.OfType<SyntheticEthernetPortSettingData>().First();
+
+ var newSynthNICSettings = new SyntheticEthernetPortSettingData((ManagementBaseObject)defaultSynthNICSettings.LateBoundObject.Clone());
+
+ // Assign configuration to new NIC
+ string normalisedMAC = string.Join("", (mac.Split(new char[] { ':' })));
+ newSynthNICSettings.LateBoundObject["ElementName"] = vm.ElementName;
+ newSynthNICSettings.LateBoundObject["Address"] = normalisedMAC;
+ newSynthNICSettings.LateBoundObject["StaticMacAddress"] = "TRUE";
+ newSynthNICSettings.LateBoundObject["VirtualSystemIdentifiers"] = new string[] { "{" + Guid.NewGuid().ToString() + "}" };
+ newSynthNICSettings.CommitObject();
+
+ // Insert NIC into vm
+ string[] newResources = new string[] { newSynthNICSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20)};
+ ManagementPath[] newResourcePaths = AddVirtualResource(newResources, vm );
+
+ // assert
+ if (newResourcePaths.Length != 1)
+ {
+ var errMsg = string.Format(
+ "Failed to properly insert a single NIC on VM {0} (GUID {1}): number of resource created {2}",
+ vm.ElementName,
+ vm.Name,
+ newResourcePaths.Length);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
+ return new SyntheticEthernetPortSettingData(newResourcePaths[0]);
+ }
+
+ public const string IDE_CONTROLLER = "Microsoft:Hyper-V:Emulated IDE Controller";
+ public const string SCSI_CONTROLLER = "Microsoft:Hyper-V:Synthetic SCSI Controller";
+ public const string HARDDISK_DRIVE = "Microsoft:Hyper-V:Synthetic Disk Drive";
+ public const string ISO_DRIVE = "Microsoft:Hyper-V:Synthetic DVD Drive";
+
+ // TODO: names harvested from Msvm_ResourcePool, not clear how to create new instances
+ public const string ISO_DISK = "Microsoft:Hyper-V:Virtual CD/DVD Disk"; // For IDE_ISO_DRIVE
+ public const string HARDDISK_DISK = "Microsoft:Hyper-V:Virtual Hard Disk"; // For IDE_HARDDISK_DRIVE
+
+ /// <summary>
+ /// Create new VM. By default we start it.
+ /// </summary>
+ public ComputerSystem DeployVirtualMachine(dynamic jsonObj, string systemVmIso)
+ {
+ var vmInfo = jsonObj.vm;
+ string vmName = vmInfo.name;
+ var nicInfo = vmInfo.nics;
+ int vcpus = vmInfo.cpus;
+ int memSize = vmInfo.maxRam / 1048576;
+ string errMsg = vmName;
+ var diskDrives = vmInfo.disks;
+ var bootArgs = vmInfo.bootArgs;
+
+ // assert
+ errMsg = vmName + ": missing disk information, array empty or missing, agent expects *at least* one disk for a VM";
+ if (diskDrives == null)
+ {
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+ // assert
+ errMsg = vmName + ": missing NIC information, array empty or missing, agent expects at least an empty array.";
+ if (nicInfo == null )
+ {
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+
+
+ // For existing VMs, return when we spot one of this name not stopped. In the meantime, remove any existing VMs of same name.
+ ComputerSystem vmWmiObj = null;
+ while ((vmWmiObj = GetComputerSystem(vmName)) != null)
+ {
+ logger.WarnFormat("Create request for existing vm, name {0}", vmName);
+ if (vmWmiObj.EnabledState == EnabledState.Disabled)
+ {
+ logger.InfoFormat("Deleting existing VM with name {0}, before we go on to create a VM with the same name", vmName);
+ DestroyVm(vmName);
+ }
else if (vmWmiObj.EnabledState == EnabledState.Enabled)
{
string infoMsg = string.Format("Create VM discovered there exists a VM with name {0}, state {1}",
@@ -265,2231 +264,2424 @@ namespace HypervResource
logger.Info(infoMsg);
return vmWmiObj;
}
- else
- {
+ else
+ {
errMsg = string.Format("Create VM failing, because there exists a VM with name {0}, state {1}",
- vmName,
- EnabledState.ToString(vmWmiObj.EnabledState));
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
- }
-
- // Create vm carcase
- logger.DebugFormat("Going ahead with create VM {0}, {1} vcpus, {2}MB RAM", vmName, vcpus, memSize);
- var newVm = CreateVM(vmName, memSize, vcpus);
-
- // Add a SCSI controller for attaching/detaching data volumes.
- AddScsiController(newVm);
-
- foreach (var diskDrive in diskDrives)
- {
- string vhdFile = null;
- string diskName = null;
- string isoPath = null;
- VolumeObjectTO volInfo = VolumeObjectTO.ParseJson(diskDrive.data);
- TemplateObjectTO templateInfo = TemplateObjectTO.ParseJson(diskDrive.data);
-
- if (volInfo != null)
- {
- // assert
- errMsg = vmName + ": volume missing primaryDataStore for disk " + diskDrive.ToString();
- if (volInfo.primaryDataStore == null)
- {
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
- diskName = volInfo.name;
-
- // assert
- errMsg = vmName + ": can't deal with DataStore type for disk " + diskDrive.ToString();
- if (volInfo.primaryDataStore == null)
- {
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
- errMsg = vmName + ": Malformed PrimaryDataStore for disk " + diskDrive.ToString();
- if (String.IsNullOrEmpty(volInfo.primaryDataStore.Path))
- {
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
- errMsg = vmName + ": Missing folder PrimaryDataStore for disk " + diskDrive.ToString() + ", missing path: " + volInfo.primaryDataStore.Path;
- if (!Directory.Exists(volInfo.primaryDataStore.Path))
- {
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
-
- vhdFile = volInfo.FullFileName;
- if (!System.IO.File.Exists(vhdFile))
- {
- errMsg = vmName + ": non-existent volume, missing " + vhdFile + " for drive " + diskDrive.ToString();
- logger.Error(errMsg);
- throw new ArgumentException(errMsg);
- }
- logger.Debug("Going to create " + vmName + " with attached voluem " + diskName + " at " + vhdFile);
- }
- else if (templateInfo != null && templateInfo.nfsDataStoreTO != null)
- {
- NFSTO share = templateInfo.nfsDataStoreTO;
- Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
- // The share is mapped, now attach the iso
- isoPath = Utils.NormalizePath(Path.Combine(share.UncPath, templateInfo.path));
- }
-
- string driveType = diskDrive.type;
- string ideCtrllr = "0";
- string driveResourceType = null;
- switch (driveType) {
- case "ROOT":
- ideCtrllr = "0";
- driveResourceType = HARDDISK_DRIVE;
- break;
- case "ISO":
- ideCtrllr = "1";
- driveResourceType = ISO_DRIVE;
- break;
- case "DATADISK":
- break;
- default:
- // TODO: double check exception type
- errMsg = string.Format("Unknown disk type {0} for disk {1}, vm named {2}",
- string.IsNullOrEmpty(driveType) ? "NULL" : driveType,
- string.IsNullOrEmpty(diskName) ? "NULL" : diskName, vmName);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
-
- logger.DebugFormat("Create disk type {1} (Named: {0}), on vm {2} {3}", diskName, driveResourceType, vmName,
- string.IsNullOrEmpty(vhdFile) ? " no disk to insert" : ", inserting disk" + vhdFile);
- if (driveType.Equals("DATADISK"))
- {
- AttachDisk(vmName, vhdFile, (string)diskDrive.diskSeq);
- }
- else
- {
- AddDiskDriveToIdeController(newVm, vhdFile, ideCtrllr, driveResourceType);
- if (isoPath != null)
- {
- AttachIso(vmName, isoPath);
- }
- }
- }
-
- String publicIpAddress = "";
- int nicCount = 0;
- // Add the Nics to the VM in the deviceId order.
- foreach (var nc in nicInfo)
- {
- foreach (var nic in nicInfo)
- {
-
- int nicid = nic.deviceId;
+ vmName,
+ EnabledState.ToString(vmWmiObj.EnabledState));
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+ }
+
+ // Create vm carcase
+ logger.DebugFormat("Going ahead with create VM {0}, {1} vcpus, {2}MB RAM", vmName, vcpus, memSize);
+ var newVm = CreateVM(vmName, memSize, vcpus);
+
+ // Add a SCSI controller for attaching/detaching data volumes.
+ AddScsiController(newVm);
+
+ foreach (var diskDrive in diskDrives)
+ {
+ string vhdFile = null;
+ string diskName = null;
+ string isoPath = null;
+ VolumeObjectTO volInfo = VolumeObjectTO.ParseJson(diskDrive.data);
+ TemplateObjectTO templateInfo = TemplateObjectTO.ParseJson(diskDrive.data);
+
+ if (volInfo != null)
+ {
+ // assert
+ errMsg = vmName + ": volume missing primaryDataStore for disk " + diskDrive.ToString();
+ if (volInfo.primaryDataStore == null)
+ {
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+ diskName = volInfo.name;
+
+ // assert
+ errMsg = vmName + ": can't deal with DataStore type for disk " + diskDrive.ToString();
+ if (volInfo.primaryDataStore == null)
+ {
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+ errMsg = vmName + ": Malformed PrimaryDataStore for disk " + diskDrive.ToString();
+ if (String.IsNullOrEmpty(volInfo.primaryDataStore.Path))
+ {
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+ errMsg = vmName + ": Missing folder PrimaryDataStore for disk " + diskDrive.ToString() + ", missing path: " + volInfo.primaryDataStore.Path;
+ if (!Directory.Exists(volInfo.primaryDataStore.Path))
+ {
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+
+ vhdFile = volInfo.FullFileName;
+ if (!System.IO.File.Exists(vhdFile))
+ {
+ errMsg = vmName + ": non-existent volume, missing " + vhdFile + " for drive " + diskDrive.ToString();
+ logger.Error(errMsg);
+ throw new ArgumentException(errMsg);
+ }
+ logger.Debug("Going to create " + vmName + " with attached voluem " + diskName + " at " + vhdFile);
+ }
+ else if (templateInfo != null && templateInfo.nfsDataStoreTO != null)
+ {
+ NFSTO share = templateInfo.nfsDataStoreTO;
+ Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
+ // The share is mapped, now attach the iso
+ isoPath = Utils.NormalizePath(Path.Combine(share.UncPath, templateInfo.path));
+ }
+
+ string driveType = diskDrive.type;
+ string ideCtrllr = "0";
+ string driveResourceType = null;
+ switch (driveType) {
+ case "ROOT":
+ ideCtrllr = "0";
+ driveResourceType = HARDDISK_DRIVE;
+ break;
+ case "ISO":
+ ideCtrllr = "1";
+ driveResourceType = ISO_DRIVE;
+ break;
+ case "DATADISK":
+ break;
+ default:
+ // TODO: double check exception type
+ errMsg = string.Format("Unknown disk type {0} for disk {1}, vm named {2}",
+ string.IsNullOrEmpty(driveType) ? "NULL" : driveType,
+ string.IsNullOrEmpty(diskName) ? "NULL" : diskName, vmName);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
+ logger.DebugFormat("Create disk type {1} (Named: {0}), on vm {2} {3}", diskName, driveResourceType, vmName,
+ string.IsNullOrEmpty(vhdFile) ? " no disk to insert" : ", inserting disk" + vhdFile);
+ if (driveType.Equals("DATADISK"))
+ {
+ AttachDisk(vmName, vhdFile, (string)diskDrive.diskSeq);
+ }
+ else
+ {
+ AddDiskDriveToIdeController(newVm, vhdFile, ideCtrllr, driveResourceType);
+ if (isoPath != null)
+ {
+ AttachIso(vmName, isoPath);
+ }
+ }
+ }
+
+ String publicIpAddress = "";
+ int nicCount = 0;
+ int enableState = 2;
+
+ // Add the Nics to the VM in the deviceId order.
+ foreach (var nc in nicInfo)
+ {
+ foreach (var nic in nicInfo)
+ {
+
+ int nicid = nic.deviceId;
Int32 networkRateMbps = nic.networkRateMbps;
- string mac = nic.mac;
- string vlan = null;
- string isolationUri = nic.isolationUri;
- string broadcastUri = nic.broadcastUri;
+ string mac = nic.mac;
+ string vlan = null;
+ string isolationUri = nic.isolationUri;
+ string broadcastUri = nic.broadcastUri;
string nicIp = nic.ip;
string nicNetmask = nic.netmask;
- if ( (broadcastUri != null ) || (isolationUri != null && isolationUri.StartsWith("vlan://")))
- {
- if (broadcastUri != null && broadcastUri.StartsWith("storage"))
- {
- vlan = broadcastUri.Substring("storage://".Length);
- }
- else
- {
- vlan = isolationUri.Substring("vlan://".Length);
- }
- int tmp;
+ if ( (broadcastUri != null ) || (isolationUri != null && isolationUri.StartsWith("vlan://")))
+ {
+ if (broadcastUri != null && broadcastUri.StartsWith("storage"))
+ {
+ vlan = broadcastUri.Substring("storage://".Length);
+ }
+ else
+ {
+ vlan = isolationUri.Substring("vlan://".Length);
+ }
+ int tmp;
if (vlan.Equals("untagged", StringComparison.CurrentCultureIgnoreCase) ) {
// recevied vlan is untagged, don't parse for the vlan in the isolation uri
vlan = null;
}
- else if (!int.TryParse(vlan, out tmp))
- {
- // TODO: double check exception type
- errMsg = string.Format("Invalid VLAN value {0} for on vm {1} for nic uuid {2}", isolationUri, vmName, nic.uuid);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
- }
- if(nicIp.Equals("0.0.0.0") && nicNetmask.Equals("255.255.255.255") ) {
- // this is the extra nic added to VR.
- vlan = defaultvlan;
+ else if (!int.TryParse(vlan, out tmp))
+ {
+ // TODO: double check exception type
+ errMsg = string.Format("Invalid VLAN value {0} for on vm {1} for nic uuid {2}", isolationUri, vmName, nic.uuid);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
}
-
- if (nicCount == 2)
- {
- publicIpAddress = nic.ip;
- }
-
- if (nicid == nicCount)
- {
- // Create network adapter
- var newAdapter = CreateNICforVm(newVm, mac);
- String switchName ="";
- if (nic.name != null)
- {
- switchName = nic.name;
- }
-
- // connection to vswitch
- var portSettings = AttachNicToPort(newVm, newAdapter, switchName);
-
- // set vlan
- if (vlan != null)
- {
- SetPortVlan(vlan, portSettings);
- }
-
+
+ if (nicid == nicCount)
+ {
+ if (nicIp.Equals("0.0.0.0") && nicNetmask.Equals("255.255.255.255"))
+ {
+ // this is the extra nic added to VR.
+ vlan = null;
+ enableState = 3;
+ }
+
+ // Create network adapter
+ var newAdapter = CreateNICforVm(newVm, mac);
+ String switchName ="";
+ if (nic.name != null)
+ {
+ switchName = nic.name;
+ }
+ EthernetPortAllocationSettingData portSettings = null;
+ // connection to vswitch
+ portSettings = AttachNicToPort(newVm, newAdapter, switchName, enableState);
+ //reset the flag for other nics
+ enableState = 2;
+ // set vlan
+ if (vlan != null)
+ {
+ SetPortVlan(vlan, portSettings);
+ }
+
if (networkRateMbps > 0)
{
SetBandWidthLimit((ulong)networkRateMbps, portSettings);
}
- logger.DebugFormat("Created adapter {0} on port {1}, {2}",
- newAdapter.Path, portSettings.Path, (vlan == null ? "No VLAN" : "VLAN " + vlan));
- }
- }
- nicCount++;
- }
-
-
- // pass the boot args for the VM using KVP component.
- // We need to pass the boot args to system vm's to get them configured with cloudstack configuration.
- // Add new user data
- var vm = GetComputerSystem(vmName);
- if (bootArgs != null && !String.IsNullOrEmpty((string)bootArgs))
- {
-
- String bootargs = bootArgs;
- AddUserData(vm, bootargs);
-
- // Verify key added to subsystem
- //kvpInfo = GetKvpSettings(vmSettings);
-
- // HostExchangesItems are embedded objects in the sense that the object value is stored and not a reference to the object.
- //kvpProps = kvpInfo.HostExchangeItems;
-
- }
- // call patch systemvm iso only for systemvms
- if (vmName.StartsWith("r-") || vmName.StartsWith("s-") || vmName.StartsWith("v-"))
- {
- if (systemVmIso != null && systemVmIso.Length != 0)
- {
- patchSystemVmIso(vmName, systemVmIso);
- }
- }
-
- logger.DebugFormat("Starting VM {0}", vmName);
- SetState(newVm, RequiredState.Enabled);
- // Mark the VM as created by cloudstack tag
- TagVm(newVm);
-
- // we need to reboot to get the hv kvp daemon get started vr gets configured.
- if (vmName.StartsWith("r-") || vmName.StartsWith("s-") || vmName.StartsWith("v-"))
- {
- System.Threading.Thread.Sleep(90000);
- // wait for the second boot and then return with sucesss
- //if publicIPAddress is empty or null don't ping the ip
- /*if (publicIpAddress.Equals("") == true)
- {
- System.Threading.Thread.Sleep(90000);
- }
- else
- {
- pingResource(publicIpAddress);
- }*/
- }
- logger.InfoFormat("Started VM {0}", vmName);
- return newVm;
- }
-
- public static Boolean pingResource(String ip)
- {
- PingOptions pingOptions = null;
- PingReply pingReply = null;
- IPAddress ipAddress = null;
- Ping pingSender = new Ping();
- int numberOfPings = 6;
- int pingTimeout = 1000;
- int byteSize = 32;
- byte[] buffer = new byte[byteSize];
- ipAddress = IPAddress.Parse(ip);
- pingOptions = new PingOptions();
- for (int i = 0; i < numberOfPings; i++)
- {
- pingReply = pingSender.Send(ipAddress, pingTimeout, buffer, pingOptions);
- if (pingReply.Status == IPStatus.Success)
- {
- System.Threading.Thread.Sleep(30000);
- return true;
- }
- else
- {
- // wait for the second boot and then return with suces
- System.Threading.Thread.Sleep(30000);
- }
- }
- return false;
- }
-
- private EthernetPortAllocationSettingData AttachNicToPort(ComputerSystem newVm, SyntheticEthernetPortSettingData newAdapter, String vSwitchName)
- {
- // Get the virtual switch
- VirtualEthernetSwitch vSwitch = GetExternalVirtSwitch(vSwitchName);
- //check the the recevied vSwitch is the same as vSwitchName.
- if (!vSwitchName.Equals("") && !vSwitch.ElementName.Equals(vSwitchName))
- {
- var errMsg = string.Format("Internal error, coudl not find Virtual Switch with the name : " +vSwitchName);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
-
- // Create port for adapter
- var defaultEthernetPortSettings = EthernetPortAllocationSettingData.GetInstances(vSwitch.Scope, "InstanceID LIKE \"%Default\"");
-
- // assert
- if (defaultEthernetPortSettings.Count != 1)
- {
- var errMsg = string.Format("Internal error, coudl not find default EthernetPortAllocationSettingData instance");
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
-
- var defaultEthernetPortSettingsObj = defaultEthernetPortSettings.OfType<EthernetPortAllocationSettingData>().First();
- var newEthernetPortSettings = new EthernetPortAllocationSettingData((ManagementBaseObject)defaultEthernetPortSettingsObj.LateBoundObject.Clone());
- newEthernetPortSettings.LateBoundObject["Parent"] = newAdapter.Path.Path;
- newEthernetPortSettings.LateBoundObject["HostResource"] = new string[] { vSwitch.Path.Path };
-
- // Insert NIC into vm
- string[] newResources = new string[] { newEthernetPortSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
- ManagementPath[] newResourcePaths = AddVirtualResource(newResources, newVm);
-
- // assert
- if (newResourcePaths.Length != 1)
- {
- var errMsg = string.Format(
- "Failed to properly insert a single NIC on VM {0} (GUID {1}): number of resource created {2}",
- newVm.ElementName,
- newVm.Name,
- newResourcePaths.Length);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
-
- return new EthernetPortAllocationSettingData(newResourcePaths[0]);
- }
-
- /// this method is to add a dvd drive and attach the systemvm iso.
- ///
- public void patchSystemVmIso(String vmName, String systemVmIso)
- {
- ComputerSystem vmObject = GetComputerSystem(vmName);
- AddDiskDriveToIdeController(vmObject, "", "1", ISO_DRIVE);
- AttachIso(vmName, systemVmIso);
- }
-
- public void AttachDisk(string vmName, string diskPath, string addressOnController)
- {
- logger.DebugFormat("Got request to attach disk {0} to vm {1}", diskPath, vmName);
-
- ComputerSystem vm = GetComputerSystem(vmName);
- if (vm == null)
- {
- logger.DebugFormat("VM {0} not found", vmName);
- return;
- }
- else
- {
- ManagementPath newDrivePath = GetDiskDriveOnScsiController(vm, addressOnController);
- if (newDrivePath == null)
- {
- newDrivePath = AttachDiskDriveToScsiController(vm, addressOnController);
- }
- InsertDiskImage(vm, diskPath, HARDDISK_DISK, newDrivePath);
- }
- }
-
- /// </summary>
- /// <param name="vm"></param>
- /// <param name="cntrllerAddr"></param>
- /// <param name="driveResourceType">IDE_HARDDISK_DRIVE or IDE_ISO_DRIVE</param>
- public ManagementPath AddDiskDriveToIdeController(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType)
- {
- logger.DebugFormat("Creating DISK for VM {0} (GUID {1}) by attaching {2}",
- vm.ElementName,
- vm.Name,
- vhdfile);
-
- // Determine disk type for drive and assert drive type valid
- string diskResourceSubType = null;
- switch(driveResourceType) {
- case HARDDISK_DRIVE:
- diskResourceSubType = HARDDISK_DISK;
- break;
- case ISO_DRIVE:
- diskResourceSubType = ISO_DISK;
- break;
- default:
- var errMsg = string.Format(
- "Unrecognised disk drive type {0} for VM {1} (GUID {2})",
- string.IsNullOrEmpty(driveResourceType) ? "NULL": driveResourceType,
- vm.ElementName,
- vm.Name);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
-
- ManagementPath newDrivePath = AttachNewDrive(vm, cntrllerAddr, driveResourceType);
-
- // If there's not disk to insert, we are done.
- if (String.IsNullOrEmpty(vhdfile))
- {
- logger.DebugFormat("No disk to be added to drive, disk drive {0} is complete", newDrivePath.Path);
- }
- else
- {
- InsertDiskImage(vm, vhdfile, diskResourceSubType, newDrivePath);
- }
- return newDrivePath;
- }
-
-
- public void DetachDisk(string displayName, string diskFileName)
- {
- logger.DebugFormat("Got request to detach virtual disk {0} from vm {1}", diskFileName, displayName);
-
- ComputerSystem vm = GetComputerSystem(displayName);
- if (vm == null)
- {
- logger.DebugFormat("VM {0} not found", displayName);
- return;
- }
- else
- {
- RemoveStorageImage(vm, diskFileName);
- }
- }
-
- /// <summary>
- /// Removes a disk image from a drive, but does not remove the drive itself.
- /// </summary>
- /// <param name="vm"></param>
- /// <param name="diskFileName"></param>
- private void RemoveStorageImage(ComputerSystem vm, string diskFileName)
- {
- // Obtain StorageAllocationSettingData for disk
- StorageAllocationSettingData.StorageAllocationSettingDataCollection storageSettingsObjs = StorageAllocationSettingData.GetInstances();
-
- StorageAllocationSettingData imageToRemove = null;
- foreach (StorageAllocationSettingData item in storageSettingsObjs)
- {
- if (item.HostResource == null || item.HostResource.Length != 1)
- {
- continue;
- }
-
- string hostResource = item.HostResource[0];
- if (Path.Equals(hostResource, diskFileName))
- {
- imageToRemove = item;
- break;
- }
- }
-
- // assert
- if (imageToRemove == null)
- {
- var errMsg = string.Format(
- "Failed to remove disk image {0} from VM {1} (GUID {2}): the disk image is not attached.",
- diskFileName,
- vm.ElementName,
- vm.Name);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
-
- RemoveStorageResource(imageToRemove.Path, vm);
-
- logger.InfoFormat("Removed disk image {0} from VM {1} (GUID {2}): the disk image is not attached.",
- diskFileName,
- vm.ElementName,
- vm.Name);
- }
-
- private ManagementPath AttachNewDrive(ComputerSystem vm, string cntrllerAddr, string driveType)
- {
- // Disk drives are attached to a 'Parent' IDE controller. We IDE Controller's settings for the 'Path', which our new Disk drive will use to reference it.
- VirtualSystemSettingData vmSettings = GetVmSettings(vm);
- var ctrller = GetIDEControllerSettings(vmSettings, cntrllerAddr);
-
- // A description of the drive is created by modifying a clone of the default ResourceAllocationSettingData for that drive type
- string defaultDriveQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", driveType);
- var newDiskDriveSettings = CloneResourceAllocationSetting(defaultDriveQuery);
-
- // Set IDE controller and address on the controller for the new drive
- newDiskDriveSettings.LateBoundObject["Parent"] = ctrller.Path.ToString();
- newDiskDriveSettings.LateBoundObject["AddressOnParent"] = "0";
- newDiskDriveSettings.CommitObject();
-
- // Add this new disk drive to the VM
- logger.DebugFormat("Creating disk drive type {0}, parent IDE controller is {1} and address on controller is {2}",
- newDiskDriveSettings.ResourceSubType,
- newDiskDriveSettings.Parent,
- newDiskDriveSettings.AddressOnParent);
- string[] newDriveResource = new string[] { newDiskDriveSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
- ManagementPath[] newDrivePaths = AddVirtualResource(newDriveResource, vm);
-
- // assert
- if (newDrivePaths.Length != 1)
- {
- var errMsg = string.Format(
- "Failed to add disk drive type {3} to VM {0} (GUID {1}): number of resource created {2}",
- vm.ElementName,
- vm.Name,
- newDrivePaths.Length,
- driveType);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
- logger.DebugFormat("New disk drive type {0} WMI path is {1}s",
- newDiskDriveSettings.ResourceSubType,
- newDrivePaths[0].Path);
- return newDrivePaths[0];
- }
-
- private ManagementPath AddScsiController(ComputerSystem vm)
- {
- // A description of the controller is created by modifying a clone of the default ResourceAllocationSettingData for scsi controller
- string scsiQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", SCSI_CONTROLLER);
- var scsiSettings = CloneResourceAllocationSetting(scsiQuery);
-
- scsiSettings.LateBoundObject["ElementName"] = "SCSI Controller";
- scsiSettings.CommitObject();
-
- // Insert SCSI controller into vm
- string[] newResources = new string[] { scsiSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
- ManagementPath[] newResourcePaths = AddVirtualResource(newResources, vm);
-
- // assert
- if (newResourcePaths.Length != 1)
- {
- var errMsg = string.Format(
- "Failed to add scsi controller to VM {0} (GUID {1}): number of resource created {2}",
- vm.ElementName,
- vm.Name,
- newResourcePaths.Length);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
-
- logger.DebugFormat("New controller type {0} WMI path is {1}s",
- scsiSettings.ResourceSubType,
- newResourcePaths[0].Path);
- return newResourcePaths[0];
- }
-
- private ManagementPath GetDiskDriveOnScsiController(ComputerSystem vm, string addrOnController)
- {
- VirtualSystemSettingData vmSettings = GetVmSettings(vm);
- var wmiObjCollection = GetResourceAllocationSettings(vmSettings);
- foreach (ResourceAllocationSettingData wmiObj in wmiObjCollection)
- {
- if (wmiObj.ResourceSubType == HARDDISK_DRIVE)
- {
- ResourceAllocationSettingData parent = new ResourceAllocationSettingData(new ManagementObject(wmiObj.Parent));
- if (parent.ResourceSubType == SCSI_CONTROLLER && wmiObj.AddressOnParent == addrOnController)
- {
- return wmiObj.Path;
- }
- }
- }
- return null;
- }
-
- private ManagementPath AttachDiskDriveToScsiController(ComputerSystem vm, string addrOnController)
- {
- // Disk drives are attached to a 'Parent' Scsi controller.
- VirtualSystemSettingData vmSettings = GetVmSettings(vm);
- var ctrller = GetScsiControllerSettings(vmSettings);
-
- // A description of the drive is created by modifying a clone of the default ResourceAllocationSettingData for that drive type
- string defaultDriveQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", HARDDISK_DRIVE);
- var newDiskDriveSettings = CloneResourceAllocationSetting(defaultDriveQuery);
-
- // Set IDE controller and address on the controller for the new drive
- newDiskDriveSettings.LateBoundObject["Parent"] = ctrller.Path.ToString();
- newDiskDriveSettings.LateBoundObject["AddressOnParent"] = addrOnController;
- newDiskDriveSettings.CommitObject();
-
- // Add this new disk drive to the VM
- logger.DebugFormat("Creating disk drive type {0}, parent IDE controller is {1} and address on controller is {2}",
- newDiskDriveSettings.ResourceSubType,
- newDiskDriveSettings.Parent,
- newDiskDriveSettings.AddressOnParent);
- string[] newDriveResource = new string[] { newDiskDriveSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
- ManagementPath[] newDrivePaths = AddVirtualResource(newDriveResource, vm);
-
- // assert
- if (newDrivePaths.Length != 1)
- {
- var errMsg = string.Format(
- "Failed to add disk drive type {3} to VM {0} (GUID {1}): number of resource created {2}",
- vm.ElementName,
- vm.Name,
- newDrivePaths.Length,
- HARDDISK_DRIVE);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
- logger.DebugFormat("New disk drive type {0} WMI path is {1}s",
- newDiskDriveSettings.ResourceSubType,
- newDrivePaths[0].Path);
- return newDrivePaths[0];
- }
-
-
- private void InsertDiskImage(ComputerSystem vm, string diskImagePath, string diskResourceSubType, ManagementPath drivePath)
- {
- // A description of the disk is created by modifying a clone of the default ResourceAllocationSettingData for that disk type
- string defaultDiskQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", diskResourceSubType);
- var newDiskSettings = CloneStorageAllocationSetting(defaultDiskQuery);
-
- // Set file containing the disk image
- newDiskSettings.LateBoundObject["Parent"] = drivePath.Path;
-
- // V2 API uses HostResource to specify image, see http://msdn.microsoft.com/en-us/library/hh859775(v=vs.85).aspx
- newDiskSettings.LateBoundObject["HostResource"] = new string[] { diskImagePath };
- newDiskSettings.CommitObject();
-
- // Add the new Msvm_StorageAllocationSettingData object as a virtual hard disk to the vm.
- string[] newDiskResource = new string[] { newDiskSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
- ManagementPath[] newDiskPaths = AddStorageResource(newDiskResource, vm);
- // assert
- if (newDiskPaths.Length != 1)
- {
- var errMsg = string.Format(
- "Failed to add disk image type {3} to VM {0} (GUID {1}): number of resource created {2}",
- vm.ElementName,
- vm.Name,
- newDiskPaths.Length,
- diskResourceSubType);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
- logger.InfoFormat("Created disk {2} for VM {0} (GUID {1}), image {3} ",
- vm.ElementName,
- vm.Name,
- newDiskPaths[0].Path,
- diskImagePath);
- }
-
- /// <summary>
- /// Create Msvm_StorageAllocationSettingData corresponding to the ISO image, and
- /// associate this with the VM's DVD drive.
- /// </summary>
- private void AttachIso(ComputerSystem vm, string isoPath)
- {
- // Disk drives are attached to a 'Parent' IDE controller. We IDE Controller's settings for the 'Path', which our new Disk drive will use to reference it.
- VirtualSystemSettingData vmSettings = GetVmSettings(vm);
- var driveWmiObj = GetDvdDriveSettings(vmSettings);
- InsertDiskImage(vm, isoPath, ISO_DISK, driveWmiObj.Path);
- }
-
- private static ResourceAllocationSettingData CloneResourceAllocationSetting(string wmiQuery)
- {
- var defaultDiskDriveSettingsObjs = ResourceAllocationSettingData.GetInstances(wmiQuery);
-
- // assert
- if (defaultDiskDriveSettingsObjs.Count != 1)
- {
- var errMsg = string.Format("Failed to find Msvm_ResourceAllocationSettingData for the query {0}", wmiQuery);
- var ex = new WmiException(errMsg);
- logger.Error(errMsg, ex);
- throw ex;
- }
-
- ResourceAllocationSettingData defaultDiskDriveSettings = defaultDiskDriveSettingsObjs.OfType<ResourceAllocationSettingData>().First();
- return new ResourceAllocationSettingData((ManagementBaseObject)defaultDiskDriveSettings.LateBoundObject.Clone());
- }
+ logger.DebugFormat("Created adapter {0} on port {1}, {2}",
+ newAdapter.Path, portSettings.Path, (vlan == null ? "No VLAN" : "VLAN " + vlan));
+ // logger.DebugFormat("Created adapter {0} on port {1}, {2}",
+ // newAdapter.Path, portSettings.Path, (vlan == null ? "No VLAN" : "VLAN " + vlan));
+ }
+ }
+ nicCount++;
+ }
+
+
+ // pass the boot args for the VM using KVP component.
+ // We need to pass the boot args to system vm's to get them configured with cloudstack configuration.
+ // Add new user data
+ var vm = GetComputerSystem(vmName);
+ if (bootArgs != null && !String.IsNullOrEmpty((string)bootArgs))
+ {
+
+ String bootargs = bootArgs;
+ AddUserData(vm, bootargs);
+ }
+
+ // call patch systemvm iso only for systemvms
+ if (vmName.StartsWith("r-") || vmName.StartsWith("s-") || vmName.StartsWith("v-"))
+ {
+ if (systemVmIso != null && systemVmIso.Length != 0)
+ {
+ patchSystemVmIso(vmName, systemVmIso);
+ }
+ }
+
+ logger.DebugFormat("Starting VM {0}", vmName);
+ SetState(newVm, RequiredState.Enabled);
+ // Mark the VM as created by cloudstack tag
+ TagVm(newVm);
+
+ // we need to reboot to get the hv kvp daemon get started vr gets configured.
+ if (vmName.StartsWith("r-") || vmName.StartsWith("s-") || vmName.StartsWith("v-"))
+ {
+ System.Threading.Thread.Sleep(90000);
+ // wait for the second boot and then return with sucesss
+ //if publicIPAddress is empty or null don't ping the ip
+ /*if (publicIpAddress.Equals("") == true)
+ {
+ System.Threading.Thread.Sleep(90000);
+ }
+ else
+ {
+ pingResource(publicIpAddress);
+ }*/
+ }
+ logger.InfoFormat("Started VM {0}", vmName);
+ return newVm;
+ }
+
+ public static Boolean pingResource(String ip)
+ {
+ PingOptions pingOptions = null;
+ PingReply pingReply = null;
+ IPAddress ipAddress = null;
+ Ping pingSender = new Ping();
+ int numberOfPings = 6;
+ int pingTimeout = 1000;
+ int byteSize = 32;
+ byte[] buffer = new byte[byteSize];
+ ipAddress = IPAddress.Parse(ip);
+ pingOptions = new PingOptions();
+ for (int i = 0; i < numberOfPings; i++)
+ {
+ pingReply = pingSender.Send(ipAddress, pingTimeout, buffer, pingOptions);
+ if (pingReply.Status == IPStatus.Success)
+ {
+ System.Threading.Thread.Sleep(30000);
+ return true;
+ }
+ else
+ {
+ // wait for the second boot and then return with suces
+ System.Threading.Thread.Sleep(30000);
+ }
+ }
+ return false;
+ }
+
+ private EthernetPortAllocationSettingData AttachNicToPort(ComputerSystem newVm, SyntheticEthernetPortSettingData newAdapter, String vSwitchName, int enableState)
+ {
+ // Get the virtual switch
+ VirtualEthernetSwitch vSwitch = GetExternalVirtSwitch(vSwitchName);
+ //check the the recevied vSwitch is the same as vSwitchName.
+ if (!vSwitchName.Equals("") && !vSwitch.ElementName.Equals(vSwitchName))
+ {
+ var errMsg = string.Format("Internal error, coudl not find Virtual Switch with the name : " +vSwitchName);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
+ // Create port for adapter
+ var defaultEthernetPortSettings = EthernetPortAllocationSettingData.GetInstances(vSwitch.Scope, "InstanceID LIKE \"%Default\"");
+
+ // assert
+ if (defaultEthernetPortSettings.Count != 1)
+ {
+ var errMsg = string.Format("Internal error, coudl not find default EthernetPortAllocationSettingData instance");
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
+ var defaultEthernetPortSettingsObj = defaultEthernetPortSettings.OfType<EthernetPortAllocationSettingData>().First();
+ var newEthernetPortSettings = new EthernetPortAllocationSettingData((ManagementBaseObject)defaultEthernetPortSettingsObj.LateBoundObject.Clone());
+ newEthernetPortSettings.LateBoundObject["Parent"] = newAdapter.Path.Path;
+ newEthernetPortSettings.LateBoundObject["HostResource"] = new string[] { vSwitch.Path.Path };
+ newEthernetPortSettings.LateBoundObject["EnabledState"] = enableState; //3 disabled 2 Enabled
+ // Insert NIC into vm
+ string[] newResources = new string[] { newEthernetPortSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
+ ManagementPath[] newResourcePaths = AddVirtualResource(newResources, newVm);
+
+ // assert
+ if (newResourcePaths.Length != 1)
+ {
+ var errMsg = string.Format(
+ "Failed to properly insert a single NIC on VM {0} (GUID {1}): number of resource created {2}",
+ newVm.ElementName,
+ newVm.Name,
+ newResourcePaths.Length);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
+ return new EthernetPortAllocationSettingData(newResourcePaths[0]);
+ }
+
+ /// this method is to add a dvd drive and attach the systemvm iso.
+ ///
+ public void patchSystemVmIso(String vmName, String systemVmIso)
+ {
+ ComputerSystem vmObject = GetComputerSystem(vmName);
+ AddDiskDriveToIdeController(vmObject, "", "1", ISO_DRIVE);
+ AttachIso(vmName, systemVmIso);
+ }
+
+ public void AttachDisk(string vmName, string diskPath, string addressOnController)
+ {
+ logger.DebugFormat("Got request to attach disk {0} to vm {1}", diskPath, vmName);
+
+ ComputerSystem vm = GetComputerSystem(vmName);
+ if (vm == null)
+ {
+ logger.DebugFormat("VM {0} not found", vmName);
+ return;
+ }
+ else
+ {
+ ManagementPath newDrivePath = GetDiskDriveOnScsiController(vm, addressOnController);
+ if (newDrivePath == null)
+ {
+ newDrivePath = AttachDiskDriveToScsiController(vm, addressOnController);
+ }
+ InsertDiskImage(vm, diskPath, HARDDISK_DISK, newDrivePath);
+ }
+ }
+
+ /// </summary>
+ /// <param name="vm"></param>
+ /// <param name="cntrllerAddr"></param>
+ /// <param name="driveResourceType">IDE_HARDDISK_DRIVE or IDE_ISO_DRIVE</param>
+ public ManagementPath AddDiskDriveToIdeController(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType)
+ {
+ logger.DebugFormat("Creating DISK for VM {0} (GUID {1}) by attaching {2}",
+ vm.ElementName,
+ vm.Name,
+ vhdfile);
+
+ // Determine disk type for drive and assert drive type valid
+ string diskResourceSubType = null;
+ switch(driveResourceType) {
+ case HARDDISK_DRIVE:
+ diskResourceSubType = HARDDISK_DISK;
+ break;
+ case ISO_DRIVE:
+ diskResourceSubType = ISO_DISK;
+ break;
+ default:
+ var errMsg = string.Format(
+ "Unrecognised disk drive type {0} for VM {1} (GUID {2})",
+ string.IsNullOrEmpty(driveResourceType) ? "NULL": driveResourceType,
+ vm.ElementName,
+ vm.Name);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
+ ManagementPath newDrivePath = AttachNewDrive(vm, cntrllerAddr, driveResourceType);
+
+ // If there's not disk to insert, we are done.
+ if (String.IsNullOrEmpty(vhdfile))
+ {
+ logger.DebugFormat("No disk to be added to drive, disk drive {0} is complete", newDrivePath.Path);
+ }
+ else
+ {
+ InsertDiskImage(vm, vhdfile, diskResourceSubType, newDrivePath);
+ }
+ return newDrivePath;
+ }
+
+
+ public void DetachDisk(string displayName, string diskFileName)
+ {
+ logger.DebugFormat("Got request to detach virtual disk {0} from vm {1}", diskFileName, displayName);
+
+ ComputerSystem vm = GetComputerSystem(displayName);
+ if (vm == null)
+ {
+ logger.DebugFormat("VM {0} not found", displayName);
+ return;
+ }
+ else
+ {
+ RemoveStorageImage(vm, diskFileName);
+ }
+ }
+
+ /// <summary>
+ /// Removes a disk image from a drive, but does not remove the drive itself.
+ /// </summary>
+ /// <param name="vm"></param>
+ /// <param name="diskFileName"></param>
+ private void RemoveStorageImage(ComputerSystem vm, string diskFileName)
+ {
+ // Obtain StorageAllocationSettingData for disk
+ StorageAllocationSettingData.StorageAllocationSettingDataCollection storageSettingsObjs = StorageAllocationSettingData.GetInstances();
+
+ StorageAllocationSettingData imageToRemove = null;
+ foreach (StorageAllocationSettingData item in storageSettingsObjs)
+ {
+ if (item.HostResource == null || item.HostResource.Length != 1)
+ {
+ continue;
+ }
+
+ string hostResource = item.HostResource[0];
+ if (Path.Equals(hostResource, diskFileName))
+ {
+ imageToRemove = item;
+ break;
+ }
+ }
+
+ // assert
+ if (imageToRemove == null)
+ {
+ var errMsg = string.Format(
+ "Failed to remove disk image {0} from VM {1} (GUID {2}): the disk image is not attached.",
+ diskFileName,
+ vm.ElementName,
+ vm.Name);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
+ RemoveStorageResource(imageToRemove.Path, vm);
+
+ logger.InfoFormat("Removed disk image {0} from VM {1} (GUID {2}): the disk image is not attached.",
+ diskFileName,
+ vm.ElementName,
+ vm.Name);
+ }
+
+ private ManagementPath AttachNewDrive(ComputerSystem vm, string cntrllerAddr, string driveType)
+ {
+ // Disk drives are attached to a 'Parent' IDE controller. We IDE Controller's settings for the 'Path', which our new Disk drive will use to reference it.
+ VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+ var ctrller = GetIDEControllerSettings(vmSettings, cntrllerAddr);
+
+ // A description of the drive is created by modifying a clone of the default ResourceAllocationSettingData for that drive type
+ string defaultDriveQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", driveType);
+ var newDiskDriveSettings = CloneResourceAllocationSetting(defaultDriveQuery);
+
+ // Set IDE controller and address on the controller for the new drive
+ newDiskDriveSettings.LateBoundObject["Parent"] = ctrller.Path.ToString();
+ newDiskDriveSettings.LateBoundObject["AddressOnParent"] = "0";
+ newDiskDriveSettings.CommitObject();
+
+ // Add this new disk drive to the VM
+ logger.DebugFormat("Creating disk drive type {0}, parent IDE controller is {1} and address on controller is {2}",
+ newDiskDriveSettings.ResourceSubType,
+ newDiskDriveSettings.Parent,
+ newDiskDriveSettings.AddressOnParent);
+ string[] newDriveResource = new string[] { newDiskDriveSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
+ ManagementPath[] newDrivePaths = AddVirtualResource(newDriveResource, vm);
+
+ // assert
+ if (newDrivePaths.Length != 1)
+ {
+ var errMsg = string.Format(
+ "Failed to add disk drive type {3} to VM {0} (GUID {1}): number of resource created {2}",
+ vm.ElementName,
+ vm.Name,
+ newDrivePaths.Length,
+ driveType);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+ logger.DebugFormat("New disk drive type {0} WMI path is {1}s",
+ newDiskDriveSettings.ResourceSubType,
+ newDrivePaths[0].Path);
+ return newDrivePaths[0];
+ }
+
+ private ManagementPath AddScsiController(ComputerSystem vm)
+ {
+ // A description of the controller is created by modifying a clone of the default ResourceAllocationSettingData for scsi controller
+ string scsiQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", SCSI_CONTROLLER);
+ var scsiSettings = CloneResourceAllocationSetting(scsiQuery);
+
+ scsiSettings.LateBoundObject["ElementName"] = "SCSI Controller";
+ scsiSettings.CommitObject();
+
+ // Insert SCSI controller into vm
+ string[] newResources = new string[] { scsiSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
+ ManagementPath[] newResourcePaths = AddVirtualResource(newResources, vm);
+
+ // assert
+ if (newResourcePaths.Length != 1)
+ {
+ var errMsg = string.Format(
+ "Failed to add scsi controller to VM {0} (GUID {1}): number of resource created {2}",
+ vm.ElementName,
+ vm.Name,
+ newResourcePaths.Length);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
+ logger.DebugFormat("New controller type {0} WMI path is {1}s",
+ scsiSettings.ResourceSubType,
+ newResourcePaths[0].Path);
+ return newResourcePaths[0];
+ }
+
+ private ManagementPath GetDiskDriveOnScsiController(ComputerSystem vm, string addrOnController)
+ {
+ VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+ var wmiObjCollection = GetResourceAllocationSettings(vmSettings);
+ foreach (ResourceAllocationSettingData wmiObj in wmiObjCollection)
+ {
+ if (wmiObj.ResourceSubType == HARDDISK_DRIVE)
+ {
+ ResourceAllocationSettingData parent = new ResourceAllocationSettingData(new ManagementObject(wmiObj.Parent));
+ if (parent.ResourceSubType == SCSI_CONTROLLER && wmiObj.AddressOnParent == addrOnController)
+ {
+ return wmiObj.Path;
+ }
+ }
+ }
+ return null;
+ }
+
+ private ManagementPath AttachDiskDriveToScsiController(ComputerSystem vm, string addrOnController)
+ {
+ // Disk drives are attached to a 'Parent' Scsi controller.
+ VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+ var ctrller = GetScsiControllerSettings(vmSettings);
+
+ // A description of the drive is created by modifying a clone of the default ResourceAllocationSettingData for that drive type
+ string defaultDriveQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", HARDDISK_DRIVE);
+ var newDiskDriveSettings = CloneResourceAllocationSetting(defaultDriveQuery);
+
+ // Set IDE controller and address on the controller for the new drive
+ newDiskDriveSettings.LateBoundObject["Parent"] = ctrller.Path.ToString();
+ newDiskDriveSettings.LateBoundObject["AddressOnParent"] = addrOnController;
+ newDiskDriveSettings.CommitObject();
+
+ // Add this new disk drive to the VM
+ logger.DebugFormat("Creating disk drive type {0}, parent IDE controller is {1} and address on controller is {2}",
+ newDiskDriveSettings.ResourceSubType,
+ newDiskDriveSettings.Parent,
+ newDiskDriveSettings.AddressOnParent);
+ string[] newDriveResource = new string[] { newDiskDriveSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
+ ManagementPath[] newDrivePaths = AddVirtualResource(newDriveResource, vm);
+
+ // assert
+ if (newDrivePaths.Length != 1)
+ {
+ var errMsg = string.Format(
+ "Failed to add disk drive type {3} to VM {0} (GUID {1}): number of resource created {2}",
+ vm.ElementName,
+ vm.Name,
+ newDrivePaths.Length,
+ HARDDISK_DRIVE);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+ logger.DebugFormat("New disk drive type {0} WMI path is {1}s",
+ newDiskDriveSettings.ResourceSubType,
+ newDrivePaths[0].Path);
+ return newDrivePaths[0];
+ }
+
+
+ private void InsertDiskImage(ComputerSystem vm, string diskImagePath, string diskResourceSubType, ManagementPath drivePath)
+ {
+ // A description of the disk is created by modifying a clone of the default ResourceAllocationSettingData for that disk type
+ string defaultDiskQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", diskResourceSubType);
+ var newDiskSettings = CloneStorageAllocationSetting(defaultDiskQuery);
+
+ // Set file containing the disk image
+ newDiskSettings.LateBoundObject["Parent"] = drivePath.Path;
+
+ // V2 API uses HostResource to specify image, see http://msdn.microsoft.com/en-us/library/hh859775(v=vs.85).aspx
+ newDiskSettings.LateBoundObject["HostResource"] = new string[] { diskImagePath };
+ newDiskSettings.CommitObject();
+
+ // Add the new Msvm_StorageAllocationSettingData object as a virtual hard disk to the vm.
+ string[] newDiskResource = new string[] { newDiskSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
+ ManagementPath[] newDiskPaths = AddStorageResource(newDiskResource, vm);
+ // assert
+ if (newDiskPaths.Length != 1)
+ {
+ var errMsg = string.Format(
+ "Failed to add disk image type {3} to VM {0} (GUID {1}): number of resource created {2}",
+ vm.ElementName,
+ vm.Name,
+ newDiskPaths.Length,
+ diskResourceSubType);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+ logger.InfoFormat("Created disk {2} for VM {0} (GUID {1}), image {3} ",
+ vm.ElementName,
+ vm.Name,
+ newDiskPaths[0].Path,
+ diskImagePath);
+ }
+
+ /// <summary>
+ /// Create Msvm_StorageAllocationSettingData corresponding to the ISO image, and
+ /// associate this with the VM's DVD drive.
+ /// </summary>
+ private void AttachIso(ComputerSystem vm, string isoPath)
+ {
+ // Disk drives are attached to a 'Parent' IDE controller. We IDE Controller's settings for the 'Path', which our new Disk drive will use to reference it.
+ VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+ var driveWmiObj = GetDvdDriveSettings(vmSettings);
+ InsertDiskImage(vm, isoPath, ISO_DISK, driveWmiObj.Path);
+ }
+
+ private static ResourceAllocationSettingData CloneResourceAllocationSetting(string wmiQuery)
+ {
+ var defaultDiskDriveSettingsObjs = ResourceAllocationSettingData.GetInstances(wmiQuery);
+
+ // assert
+ if (defaultDiskDriveSettingsObjs.Count != 1)
+ {
+ var errMsg = string.Format("Failed to find Msvm_ResourceAllocationSettingData for the query {0}", wmiQuery);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
+ ResourceAllocationSettingData defaultDiskDriveSettings = defaultDiskDriveSettingsObjs.OfType<ResourceAllocationSettingData>().First();
+ return new ResourceAllocationSettingData((ManagementBaseObject)defaultDiskDriveSettings.LateBoundObject.Clone());
+ }
+
+ // Modify the systemvm nic's VLAN id
+ public void ModifyVmVLan(string vmName, String vlanid, String mac)
+ {
+ int enableState = 2;
+ bool enable = true;
+ ComputerSystem vm = GetComputerSystem(vmName);
+ SyntheticEthernetPortSettingData[] nicSettingsViaVm = GetEthernetPortSettings(vm);
+ // Obtain controller for Hyper-V virtualisation subsystem
+ VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
+ EthernetPortAllocationSettingData networkAdapter = null;
+ string normalisedMAC = string.Join("", (mac.Split(new char[] { ':' })));
+ int index = 0;
+ foreach (SyntheticEthernetPortSettingData item in nicSettingsViaVm)
+ {
+ if (normalisedMAC.ToLower().Equals(item.Address.ToLower()))
+ {
+ break;
+ }
+ index++;
+ }
+ String vSwitchName = "";
+ VirtualEthernetSwitch vSwitch = GetExternalVirtSwitch(vSwitchName);
+ EthernetPortAllocationSettingData[] ethernetConnections = GetEthernetConnections(vm);
+ networkAdapter = ethernetConnections[index];
+ networkAdapter.LateBoundObject["EnabledState"] = enableState; //3 disabled 2 Enabled
+ networkAdapter.LateBoundObject["HostResource"] = new string[] { vSwitch.Path.Path };
+
+ ModifyVmResources(vmMgmtSvc, vm, new String[] {
+ networkAdapter.LateBoundObject.GetText(TextFormat.CimDtd20)
+ });
+
+ EthernetSwitchPortVlanSettingData vlanSettings = GetVlanSettings(ethernetConnections[index]);
+
+ if (vlanSettings == null)
+ {
+ // when modifying nic to not connected dont create vlan
+ if (enable)
+ {
+ if (vlanid != null)
+ {
+ SetPortVlan(vlanid, networkAdapter);
+ }
+ }
+ }
+ else
+ {
+ if (enable)
+ {
+ if (vlanid != null)
+ {
+ //Assign vlan configuration to nic
+ vlanSettings.LateBoundObject["AccessVlanId"] = vlanid;
+ vlanSettings.LateBoundObject["OperationMode"] = 1;
+ ModifyFeatureVmResources(vmMgmtSvc, vm, new String[] {
+ vlanSettings.LateBoundObject.GetText(TextFormat.CimDtd20)});
+ }
+ }
+ else
+ {
+ var virtSysMgmtSvc = GetVirtualisationSystemManagementService();
+
+ // This method will remove the vlan settings present on the Nic
+ ManagementPath jobPath;
+ var ret_val = virtSysMgmtSvc.RemoveFeatureSettings(new ManagementPath[] { vlanSettings.Path },
+ out job
<TRUNCATED>
[3/5] CLOUDSTACK-6518 [Hyper-V] Efficient way of finding the empty
nic in VR/VpcVR to configure VPC entities fixed windows line ending issues
Posted by ra...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4cb6c66f/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
index c5e5bf3..0a64f4b 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
@@ -1,76 +1,78 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
-using System.Management;
-
-namespace HypervResource
-{
- public interface IWmiCallsV2
- {
- System.Management.ManagementPath AddDiskDriveToIdeController(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType);
- ComputerSystem AddUserData(ComputerSystem vm, string userData);
- void AttachIso(string displayName, string iso);
- void AttachDisk(string vmName, string diskPath, string addressOnController);
- void CreateDynamicVirtualHardDisk(ulong MaxInternalSize, string Path);
- SyntheticEthernetPortSettingData CreateNICforVm(ComputerSystem vm, string mac);
- ComputerSystem CreateVM(string name, long memory_mb, int vcpus);
- void DeleteHostKvpItem(ComputerSystem vm, string key);
- void DeleteSwitchPort(string elementName);
- ComputerSystem DeployVirtualMachine(dynamic jsonObj, string systemVmIso);
- void DestroyVm(dynamic jsonObj);
- void DestroyVm(string displayName);
- void MigrateVm(string vmName, string destination);
- void MigrateVolume(string vmName, string volume, string destination);
- void MigrateVmWithVolume(string vmName, string destination, Dictionary<string, string> volumeToPool);
- void DetachDisk(string displayName, string diskFileName);
- ComputerSystem GetComputerSystem(string displayName);
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
+using System.Management;
+
+namespace HypervResource
+{
+ public interface IWmiCallsV2
+ {
+ System.Management.ManagementPath AddDiskDriveToIdeController(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType);
+ ComputerSystem AddUserData(ComputerSystem vm, string userData);
+ void AttachIso(string displayName, string iso);
+ void AttachDisk(string vmName, string diskPath, string addressOnController);
+ void CreateDynamicVirtualHardDisk(ulong MaxInternalSize, string Path);
+ SyntheticEthernetPortSettingData CreateNICforVm(ComputerSystem vm, string mac);
+ ComputerSystem CreateVM(string name, long memory_mb, int vcpus);
+ void DeleteHostKvpItem(ComputerSystem vm, string key);
+ void DeleteSwitchPort(string elementName);
+ ComputerSystem DeployVirtualMachine(dynamic jsonObj, string systemVmIso);
+ void DestroyVm(dynamic jsonObj);
+ void DestroyVm(string displayName);
+ void MigrateVm(string vmName, string destination);
+ void MigrateVolume(string vmName, string volume, string destination);
+ void MigrateVmWithVolume(string vmName, string destination, Dictionary<string, string> volumeToPool);
+ void DetachDisk(string displayName, string diskFileName);
+ ComputerSystem GetComputerSystem(string displayName);
ComputerSystem.ComputerSystemCollection GetComputerSystemCollection();
- string GetDefaultDataRoot();
- string GetDefaultVirtualDiskFolder();
- ResourceAllocationSettingData GetDvdDriveSettings(VirtualSystemSettingData vmSettings);
- EthernetPortAllocationSettingData[] GetEthernetConnections(ComputerSystem vm);
- SyntheticEthernetPortSettingData[] GetEthernetPortSettings(ComputerSystem vm);
- ResourceAllocationSettingData GetIDEControllerSettings(VirtualSystemSettingData vmSettings, string cntrllerAddr);
- ImageManagementService GetImageManagementService();
- KvpExchangeComponentSettingData GetKvpSettings(VirtualSystemSettingData vmSettings);
- void GetMemoryResources(out ulong physicalRamKBs, out ulong freeMemoryKBs);
- MemorySettingData GetMemSettings(VirtualSystemSettingData vmSettings);
- void GetProcessorResources(out uint sockets, out uint cores, out uint mhz);
- void GetProcessorUsageInfo(out double cpuUtilization);
- ProcessorSettingData GetProcSettings(VirtualSystemSettingData vmSettings);
- ResourceAllocationSettingData.ResourceAllocationSettingDataCollection GetResourceAllocationSettings(VirtualSystemSettingData vmSettings);
- void GetSummaryInfo(System.Collections.Generic.Dictionary<string, VmStatsEntry> vmProcessorInfo, System.Collections.Generic.List<System.Management.ManagementPath> vmsToInspect);
- SyntheticEthernetPortSettingData GetSyntheticEthernetPortSettings(EthernetSwitchPort port);
- VirtualSystemManagementService GetVirtualisationSystemManagementService();
- VirtualEthernetSwitchManagementService GetVirtualSwitchManagementService();
- EthernetSwitchPortVlanSettingData GetVlanSettings(EthernetPortAllocationSettingData ethernetConnection);
- System.Collections.Generic.List<string> GetVmElementNames();
- VirtualSystemSettingData GetVmSettings(ComputerSystem vm);
- void patchSystemVmIso(string vmName, string systemVmIso);
- void SetState(ComputerSystem vm, ushort requiredState);
- Dictionary<String, VmState> GetVmSync(String privateIpAddress);
+ string GetDefaultDataRoot();
+ string GetDefaultVirtualDiskFolder();
+ ResourceAllocationSettingData GetDvdDriveSettings(VirtualSystemSettingData vmSettings);
+ EthernetPortAllocationSettingData[] GetEthernetConnections(ComputerSystem vm);
+ SyntheticEthernetPortSettingData[] GetEthernetPortSettings(ComputerSystem vm);
+ ResourceAllocationSettingData GetIDEControllerSettings(VirtualSystemSettingData vmSettings, string cntrllerAddr);
+ ImageManagementService GetImageManagementService();
+ KvpExchangeComponentSettingData GetKvpSettings(VirtualSystemSettingData vmSettings);
+ void GetMemoryResources(out ulong physicalRamKBs, out ulong freeMemoryKBs);
+ MemorySettingData GetMemSettings(VirtualSystemSettingData vmSettings);
+ void GetProcessorResources(out uint sockets, out uint cores, out uint mhz);
+ void GetProcessorUsageInfo(out double cpuUtilization);
+ ProcessorSettingData GetProcSettings(VirtualSystemSettingData vmSettings);
+ ResourceAllocationSettingData.ResourceAllocationSettingDataCollection GetResourceAllocationSettings(VirtualSystemSettingData vmSettings);
+ void GetSummaryInfo(System.Collections.Generic.Dictionary<string, VmStatsEntry> vmProcessorInfo, System.Collections.Generic.List<System.Management.ManagementPath> vmsToInspect);
+ SyntheticEthernetPortSettingData GetSyntheticEthernetPortSettings(EthernetSwitchPort port);
+ VirtualSystemManagementService GetVirtualisationSystemManagementService();
+ VirtualEthernetSwitchManagementService GetVirtualSwitchManagementService();
+ EthernetSwitchPortVlanSettingData GetVlanSettings(EthernetPortAllocationSettingData ethernetConnection);
+ System.Collections.Generic.List<string> GetVmElementNames();
+ VirtualSystemSettingData GetVmSettings(ComputerSystem vm);
+ void patchSystemVmIso(string vmName, string systemVmIso);
+ void SetState(ComputerSystem vm, ushort requiredState);
+ Dictionary<String, VmState> GetVmSync(String privateIpAddress);
string GetVmNote(System.Management.ManagementPath sysPath);
- void ModifyVmVLan(string vmName, uint vlanid, string mac);
- void ModifyVmVLan(string vmName, uint vlanid, uint pos);
- }
-}
+ void ModifyVmVLan(string vmName, String vlanid, string mac);
+ void ModifyVmVLan(string vmName, String vlanid, uint pos, bool enable, string switchLabelName);
+ void DisableVmNics();
+ void DisableNicVlan(String mac, String vmName);
+ }
+}