Merge pull request #696 from GaborApatiNagy/master_CA-184521

CA-184521: Fixed disk allocation-related calculations in New VM Wizard
This commit is contained in:
Mihaela Stoica 2015-10-06 17:40:37 +01:00
commit 607ff446a6
3 changed files with 60 additions and 27 deletions

View File

@ -238,10 +238,11 @@ namespace XenAdmin.Wizards.NewVMWizard
else
totalDiskSize[sr.opaque_ref] = item.Disk.virtual_size;
var initialSpace = Helpers.GetRequiredSpaceToCreateVdiOnSr(sr, item.Disk);
if (totalDiskInitialAllocation.ContainsKey(sr.opaque_ref))
totalDiskInitialAllocation[sr.opaque_ref] += item.Disk.InitialAllocation;
totalDiskInitialAllocation[sr.opaque_ref] += initialSpace;
else
totalDiskInitialAllocation[sr.opaque_ref] = item.Disk.InitialAllocation;
totalDiskInitialAllocation[sr.opaque_ref] = initialSpace;
}
DiskOverCommit overcommitedDisk = DiskOverCommit.None;
foreach (DiskGridRowItem item in DisksGridView.Rows)
@ -421,7 +422,7 @@ namespace XenAdmin.Wizards.NewVMWizard
Disk.virtual_size = long.Parse(diskNode.Attributes["size"].Value);
SR sruuid = connection.Cache.Find_By_Uuid<SR>(diskNode.Attributes["sr"].Value);
SR sr = GetBeskDiskStorage(Connection, Disk.virtual_size, affinity, sruuid == null ? null : sruuid);
SR sr = GetBeskDiskStorage(Connection, Disk, affinity, sruuid == null ? null : sruuid);
Disk.SR = new XenRef<SR>(sr != null ? sr.opaque_ref : Helper.NullOpaqueRef);
Disk.type = (vdi_type)Enum.Parse(typeof(vdi_type), diskNode.Attributes["type"].Value);
Device.userdevice = diskNode.Attributes["device"].Value;
@ -447,7 +448,7 @@ namespace XenAdmin.Wizards.NewVMWizard
Connection = connection;
Disk.virtual_size = vdi.virtual_size;
SR sr = GetBeskDiskStorage(Connection, Disk.virtual_size, affinity, Connection.Resolve(vdi.SR));
SR sr = GetBeskDiskStorage(Connection, vdi, affinity, Connection.Resolve(vdi.SR));
Disk.SR = new XenRef<SR>(sr != null ? sr.opaque_ref : Helper.NullOpaqueRef);
Disk.type = vdi.type;
Device.userdevice = vbd.userdevice;
@ -517,18 +518,20 @@ namespace XenAdmin.Wizards.NewVMWizard
}
/// <summary>
/// returns null if nothing suitable
/// Tries to find the best SR for the given VDI considering the suggestedSR which has priority over other SRs in this check.
/// SuggestedSR, default SR, other SRs are checked.
/// Returns first suitable SR or NULL.
/// </summary>
private static SR GetBeskDiskStorage(IXenConnection connection, long diskSize, Host affinity, SR suggestion)
private static SR GetBeskDiskStorage(IXenConnection connection, VDI disk, Host affinity, SR suggestedSR)
{
// try suggestion
if (suggestion != null && suggestion.FreeSpace > diskSize && suggestion.CanBeSeenFrom(affinity))
return suggestion;
if (suggestedSR != null && suggestedSR.CanBeSeenFrom(affinity) && IsSufficientFreeSpaceAvailableOnSrForVdi(suggestedSR, disk))
return suggestedSR;
// try default sr
SR def_sr = connection.Resolve(Helpers.GetPoolOfOne(connection).default_SR);
if (def_sr != null && def_sr.FreeSpace > diskSize && def_sr.CanBeSeenFrom(affinity))
return def_sr;
SR defaultSR = connection.Resolve(Helpers.GetPoolOfOne(connection).default_SR);
if (defaultSR != null && defaultSR.CanBeSeenFrom(affinity) && IsSufficientFreeSpaceAvailableOnSrForVdi(defaultSR, disk))
return defaultSR;
// pick an sr
foreach (SR sr in connection.Cache.SRs)
@ -536,12 +539,21 @@ namespace XenAdmin.Wizards.NewVMWizard
if (!sr.CanCreateVmOn())
continue;
if (sr.FreeSpace > diskSize && sr.CanBeSeenFrom(affinity))
if (sr.CanBeSeenFrom(affinity) && IsSufficientFreeSpaceAvailableOnSrForVdi(sr, disk))
return sr;
}
// there is nothing
return null;
// there has been no suitable SR found
return null;
}
/// <summary>
/// Checks whether there is enough space available on the SR to accommodate a VDI.
/// </summary>
private static bool IsSufficientFreeSpaceAvailableOnSrForVdi(SR sr, VDI disk)
{
return sr != null && !sr.IsFull && sr.FreeSpace > Helpers.GetRequiredSpaceToCreateVdiOnSr(sr, disk);
}
}

View File

@ -2113,5 +2113,38 @@ namespace XenAdmin.Core
var master = GetMaster(connection);
return CreamOrGreater(connection) && master != null && master.SuppPacks.Any(suppPack => suppPack.Name.ToLower().StartsWith("xscontainer"));
}
/// <summary>
/// This method returns the disk space required (bytes) on the provided SR for the provided VDI.
/// This method also considers thin provisioning. For thin provisioned SRs the provided sm_config in the VDI will be considered first, or it will use the values from the SR's sm_config in case the VDI does not have these set. For fully provisioned SRs the sm_config in the VDI will be ignored.
/// </summary>
/// <returns>Disk size required in bytes.</returns>
public static long GetRequiredSpaceToCreateVdiOnSr(SR sr, VDI vdi)
{
if (sr == null)
throw new ArgumentNullException("sr");
if (vdi == null)
throw new ArgumentNullException("vdi");
if (!sr.IsThinProvisioned)
return vdi.virtual_size;
long initialAllocationVdi = -1;
if (vdi.sm_config != null && vdi.sm_config.ContainsKey("initial_allocation"))
long.TryParse(vdi.sm_config["initial_allocation"], out initialAllocationVdi);
long initialAllocationSr = -1;
if (sr.sm_config != null && sr.sm_config.ContainsKey("initial_allocation"))
long.TryParse(sr.sm_config["initial_allocation"], out initialAllocationSr);
if (initialAllocationVdi > -1)
return initialAllocationVdi;
if (initialAllocationSr > -1)
return initialAllocationSr;
return vdi.virtual_size;
}
}
}

View File

@ -361,18 +361,6 @@ namespace XenAPI
NO_RO_IMAGE, // no part of the VDI is read-only => nothing to cache
SR_OVERRIDE, // the feature has been explicitly disabled for the VDI's SR
}
public long InitialAllocation
{
get
{
long initialAllocation;
if (sm_config != null && sm_config.ContainsKey("initial_allocation") && long.TryParse(sm_config["initial_allocation"], out initialAllocation))
{
return initialAllocation;
}
return virtual_size;
}
}
}
}