diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
index f4d25ecfb6c..eb20d7fd082 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
@@ -406,7 +406,9 @@ namespace HypervResource
public class DiskTO
{
public string type;
+ public string diskSequence = null;
public TemplateObjectTO templateObjectTO = null;
+ public VolumeObjectTO volumeObjectTO = null;
public static DiskTO ParseJson(dynamic json)
{
@@ -416,7 +418,9 @@ namespace HypervResource
result = new DiskTO()
{
templateObjectTO = TemplateObjectTO.ParseJson(json.data),
+ volumeObjectTO = VolumeObjectTO.ParseJson(json.data),
type = (string)json.type,
+ diskSequence = json.diskSeq
};
}
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
index b283d976c51..51a27bfdcd2 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
@@ -215,18 +215,29 @@ namespace HypervResource
{
string vmName = (string)cmd.vmName;
DiskTO disk = DiskTO.ParseJson(cmd.disk);
- TemplateObjectTO dataStore = disk.templateObjectTO;
- if (dataStore.nfsDataStoreTO != null)
+ if (disk.type.Equals("ISO"))
{
+ TemplateObjectTO dataStore = disk.templateObjectTO;
NFSTO share = dataStore.nfsDataStoreTO;
Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
-
- // The share is mapped, now attach the iso
- string isoPath = Utils.NormalizePath(Path.Combine(share.UncPath, dataStore.path));
- wmiCallsV2.AttachIso(vmName, isoPath);
+ 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;
+ 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)
{
@@ -238,6 +249,7 @@ namespace HypervResource
{
result = result,
details = details,
+ disk = cmd.disk,
contextMap = contextMap
};
@@ -261,16 +273,27 @@ namespace HypervResource
{
string vmName = (string)cmd.vmName;
DiskTO disk = DiskTO.ParseJson(cmd.disk);
- TemplateObjectTO dataStore = disk.templateObjectTO;
- if (dataStore.nfsDataStoreTO != null)
+ if (disk.type.Equals("ISO"))
{
+ TemplateObjectTO dataStore = disk.templateObjectTO;
NFSTO share = dataStore.nfsDataStoreTO;
- // The share is mapped, now attach the iso
- string isoPath = Utils.NormalizePath(Path.Combine(share.UncPath, dataStore.path));
- wmiCallsV2.DetachDisk(vmName, isoPath);
+ 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)
{
@@ -1649,6 +1672,14 @@ namespace HypervResource
strtRouteCmd.hypervisorVersion = System.Environment.OSVersion.Version.ToString();
strtRouteCmd.caps = "hvm";
+ dynamic details = strtRouteCmd.hostDetails;
+ if (details != null)
+ {
+ string productVersion = System.Environment.OSVersion.Version.Major.ToString() + "." +
+ System.Environment.OSVersion.Version.Minor.ToString();
+ details.Add("product_version", productVersion);
+ }
+
// Detect CPUs, speed, memory
uint cores;
uint mhz;
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
index 99ce35276b7..35cdec00373 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
@@ -27,9 +27,10 @@ namespace HypervResource
{
public interface IWmiCallsV2
{
- System.Management.ManagementPath AddDiskDriveToVm(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType);
+ 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);
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
index c89f837a7a6..b7ae6656bca 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
@@ -207,14 +207,14 @@ namespace HypervResource
return new SyntheticEthernetPortSettingData(newResourcePaths[0]);
}
- public const string IDE_HARDDISK_CONTROLLER = "Microsoft:Hyper-V:Emulated IDE Controller";
+ 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 IDE_HARDDISK_DRIVE = "Microsoft:Hyper-V:Synthetic Disk Drive";
- public const string IDE_ISO_DRIVE = "Microsoft:Hyper-V:Synthetic DVD Drive";
+ 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 IDE_ISO_DISK = "Microsoft:Hyper-V:Virtual CD/DVD Disk"; // For IDE_ISO_DRIVE
- public const string IDE_HARDDISK_DISK = "Microsoft:Hyper-V:Virtual Hard Disk"; // For IDE_HARDDISK_DRIVE
+ 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
///
/// Create new VM. By default we start it.
@@ -280,7 +280,7 @@ namespace HypervResource
var newVm = CreateVM(vmName, memSize, vcpus);
// Add a SCSI controller for attaching/detaching data volumes.
- AddScsiControllerToVm(newVm);
+ AddScsiController(newVm);
foreach (var diskDrive in diskDrives)
{
@@ -345,11 +345,11 @@ namespace HypervResource
switch (driveType) {
case "ROOT":
ideCtrllr = "0";
- driveResourceType = IDE_HARDDISK_DRIVE;
+ driveResourceType = HARDDISK_DRIVE;
break;
case "ISO":
ideCtrllr = "1";
- driveResourceType = IDE_ISO_DRIVE;
+ driveResourceType = ISO_DRIVE;
break;
default:
// TODO: double check exception type
@@ -362,7 +362,7 @@ namespace HypervResource
}
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 );
- AddDiskDriveToVm(newVm, vhdFile, ideCtrllr, driveResourceType);
+ AddDiskDriveToIdeController(newVm, vhdFile, ideCtrllr, driveResourceType);
if (isoPath != null)
{
AttachIso(vmName, isoPath);
@@ -566,16 +566,32 @@ namespace HypervResource
public void patchSystemVmIso(String vmName, String systemVmIso)
{
ComputerSystem vmObject = GetComputerSystem(vmName);
- AddDiskDriveToVm(vmObject, "", "1", IDE_ISO_DRIVE);
+ 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 = AttachDiskDriveToScsiController(vm, addressOnController);
+ InsertDiskImage(vm, diskPath, HARDDISK_DISK, newDrivePath);
+ }
+ }
///
///
///
/// IDE_HARDDISK_DRIVE or IDE_ISO_DRIVE
- public ManagementPath AddDiskDriveToVm(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType)
+ 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,
@@ -585,11 +601,11 @@ namespace HypervResource
// Determine disk type for drive and assert drive type valid
string diskResourceSubType = null;
switch(driveResourceType) {
- case IDE_HARDDISK_DRIVE:
- diskResourceSubType = IDE_HARDDISK_DISK;
+ case HARDDISK_DRIVE:
+ diskResourceSubType = HARDDISK_DISK;
break;
- case IDE_ISO_DRIVE:
- diskResourceSubType = IDE_ISO_DISK;
+ case ISO_DRIVE:
+ diskResourceSubType = ISO_DISK;
break;
default:
var errMsg = string.Format(
@@ -602,7 +618,7 @@ namespace HypervResource
throw ex;
}
- ManagementPath newDrivePath = AttachNewDriveToVm(vm, cntrllerAddr, driveResourceType);
+ ManagementPath newDrivePath = AttachNewDrive(vm, cntrllerAddr, driveResourceType);
// If there's not disk to insert, we are done.
if (String.IsNullOrEmpty(vhdfile))
@@ -629,7 +645,7 @@ namespace HypervResource
}
else
{
- RemoveStorageImageFromVm(vm, diskFileName);
+ RemoveStorageImage(vm, diskFileName);
}
}
@@ -638,7 +654,7 @@ namespace HypervResource
///
///
///
- private void RemoveStorageImageFromVm(ComputerSystem vm, string diskFileName)
+ private void RemoveStorageImage(ComputerSystem vm, string diskFileName)
{
// Obtain StorageAllocationSettingData for disk
StorageAllocationSettingData.StorageAllocationSettingDataCollection storageSettingsObjs = StorageAllocationSettingData.GetInstances();
@@ -674,13 +690,13 @@ namespace HypervResource
RemoveStorageResource(imageToRemove.Path, vm);
- logger.InfoFormat("REmoved disk image {0} from VM {1} (GUID {2}): the disk image is not attached.",
+ logger.InfoFormat("Removed disk image {0} from VM {1} (GUID {2}): the disk image is not attached.",
diskFileName,
vm.ElementName,
vm.Name);
}
- private ManagementPath AttachNewDriveToVm(ComputerSystem vm, string cntrllerAddr, string driveType)
+ 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);
@@ -722,7 +738,7 @@ namespace HypervResource
return newDrivePaths[0];
}
- private ManagementPath AddScsiControllerToVm(ComputerSystem vm)
+ 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);
@@ -754,6 +770,55 @@ namespace HypervResource
return newResourcePaths[0];
}
+ private ManagementPath GetDiskDriveToScsiController(ComputerSystem vm, string addrOnController)
+ {
+ VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+ var ctrller = GetScsiControllerSettings(vmSettings);
+ 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)
{
@@ -795,16 +860,14 @@ namespace HypervResource
/// Create Msvm_StorageAllocationSettingData corresponding to the ISO image, and
/// associate this with the VM's DVD drive.
///
- private void AttachIsoToVm(ComputerSystem vm, string isoPath)
+ 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, IDE_ISO_DISK, driveWmiObj.Path);
+ InsertDiskImage(vm, isoPath, ISO_DISK, driveWmiObj.Path);
}
-
-
private static ResourceAllocationSettingData CloneResourceAllocationSetting(string wmiQuery)
{
var defaultDiskDriveSettingsObjs = ResourceAllocationSettingData.GetInstances(wmiQuery);
@@ -834,7 +897,7 @@ namespace HypervResource
}
else
{
- AttachIsoToVm(vm, iso);
+ AttachIso(vm, iso);
}
}
@@ -1827,7 +1890,7 @@ namespace HypervResource
foreach (ResourceAllocationSettingData wmiObj in wmiObjCollection)
{
- if (wmiObj.ResourceSubType == IDE_HARDDISK_CONTROLLER && wmiObj.Address == cntrllerAddr)
+ if (wmiObj.ResourceSubType == IDE_CONTROLLER && wmiObj.Address == cntrllerAddr)
{
return wmiObj;
}
@@ -1842,6 +1905,26 @@ namespace HypervResource
throw ex;
}
+ public ResourceAllocationSettingData GetScsiControllerSettings(VirtualSystemSettingData vmSettings)
+ {
+ var wmiObjCollection = GetResourceAllocationSettings(vmSettings);
+
+ foreach (ResourceAllocationSettingData wmiObj in wmiObjCollection)
+ {
+ if (wmiObj.ResourceSubType == SCSI_CONTROLLER)
+ {
+ return wmiObj;
+ }
+ }
+
+ var errMsg = string.Format(
+ "Cannot find the Microsoft Synthetic SCSI Controller in VirtualSystemSettingData {1}",
+ vmSettings.Path.Path);
+ var ex = new WmiException(errMsg);
+ logger.Error(errMsg, ex);
+ throw ex;
+ }
+
///
/// VM resources, typically hardware a described by a generic MSVM_ResourceAllocationSettingData object. The hardware type being
/// described is identified in two ways: in general terms using an enum in the ResourceType field, and in terms of the implementation