CA-339271: Improved action description. Also:

Added cancelling ability to MoveVM action; made some simplifications.

Signed-off-by: Konstantina Chremmou <konstantina.chremmou@citrix.com>
This commit is contained in:
Konstantina Chremmou 2020-05-06 16:43:08 +01:00
parent b09d3cb8e7
commit db041099ef
5 changed files with 104 additions and 108 deletions

View File

@ -44,7 +44,7 @@ namespace XenAdmin.Actions
private readonly VDI vdi;
public MigrateVirtualDiskAction(IXenConnection connection, VDI vdi, SR sr)
: base(connection, string.Format(Messages.ACTION_MOVING_VDI_TITLE, Helpers.GetName(vdi), Helpers.GetName(sr)))
: base(connection, string.Format(Messages.ACTION_MOVING_VDI_TO_SR, Helpers.GetName(vdi), Helpers.GetName(sr)))
{
Description = Messages.ACTION_PREPARING;
this.vdi = vdi;
@ -53,24 +53,10 @@ namespace XenAdmin.Actions
protected override void Run()
{
try
{
Title = Description = string.Format(Messages.ACTION_MOVING_VDI_STATUS, Helpers.GetName(vdi));
RelatedTask = VDI.async_pool_migrate(Session, vdi.opaque_ref, SR.opaque_ref, new Dictionary<string, string>());
PollToCompletion();
}
catch (CancelledException)
{
Description = string.Format(Messages.ACTION_VM_MIGRATE_CANCELLED, vdi.Name());
throw;
}
catch (Failure boo)
{
Description = boo.Message;
throw;
}
Description = Messages.ACTION_VM_MIGRATED;
Description = string.Format(Messages.ACTION_MOVING_VDI, Helpers.GetName(vdi));
RelatedTask = VDI.async_pool_migrate(Session, vdi.opaque_ref, SR.opaque_ref, new Dictionary<string, string>());
PollToCompletion();
Description = Messages.MOVED;
}
}
}

View File

@ -47,7 +47,7 @@ namespace XenAdmin.Actions
private VDI vdi;
public MoveVirtualDiskAction(IXenConnection connection, XenAPI.VDI vdi, SR sr)
: base(connection, string.Format(Messages.ACTION_MOVING_VDI_TITLE, Helpers.GetName(vdi), Helpers.GetName(sr)))
: base(connection, string.Format(Messages.ACTION_MOVING_VDI_TO_SR, Helpers.GetName(vdi), Helpers.GetName(sr)))
{
this.vdi = vdi;
SR = sr;
@ -63,7 +63,7 @@ namespace XenAdmin.Actions
protected override void Run()
{
Description = string.Format(Messages.ACTION_MOVING_VDI_STATUS, Helpers.GetName(vdi));
Description = string.Format(Messages.ACTION_MOVING_VDI, Helpers.GetName(vdi));
PercentComplete = 10;
log.DebugFormat("Moving VDI '{0}'", Helpers.GetName(vdi));
RelatedTask = VDI.async_copy(Session, vdi.opaque_ref, SR.opaque_ref);
@ -126,7 +126,7 @@ namespace XenAdmin.Actions
Connection.WaitForCache(VBD.create(Session, newVbd));
PercentComplete = 100;
Description = Messages.COMPLETED;
Description = Messages.MOVED;
log.DebugFormat("Moved VDI '{0}'", Helpers.GetName(vdi));
}

View File

@ -40,20 +40,21 @@ namespace XenAdmin.Actions.VMActions
{
public class VMMoveAction : AsyncAction
{
public Dictionary<string, SR> StorageMapping;
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private Dictionary<string, SR> _storageMapping;
public VMMoveAction(VM vm, Dictionary<string, SR> storageMapping, Host host)
: base(vm.Connection, Messages.ACTION_VM_MOVING)
: base(vm.Connection, string.Format(Messages.ACTION_VM_MOVING, vm.Name()))
{
this.Description = Messages.ACTION_PREPARING;
this.VM = vm;
this.Host = host;
this.Pool = Helpers.GetPool(vm.Connection);
if (vm.is_a_template)
this.Template = vm;
StorageMapping = storageMapping;
SR = StorageMapping.Values.FirstOrDefault();
_storageMapping = storageMapping;
SR = _storageMapping.Values.FirstOrDefault();
PopulateApiMethodsToRoleCheck();
}
@ -61,7 +62,6 @@ namespace XenAdmin.Actions.VMActions
public VMMoveAction(VM vm, SR sr, Host host, string namelabel)
: base(vm.Connection, string.Format(Messages.ACTION_VM_MOVING_TITLE, vm.Name(), namelabel, sr.NameWithoutHost()))
{
this.Description = Messages.ACTION_PREPARING;
this.VM = vm;
this.Host = host;
this.Pool = Helpers.GetPool(vm.Connection);
@ -70,11 +70,12 @@ namespace XenAdmin.Actions.VMActions
this.Template = vm;
// create a storage map where all VDIs are mapped to the same SR
StorageMapping = new Dictionary<string, SR>();
var vbds = vm.Connection.ResolveAll(vm.VBDs);
foreach (var vbd in vbds)
_storageMapping = new Dictionary<string, SR>();
foreach (var vbdRef in vm.VBDs)
{
StorageMapping.Add(vbd.VDI.opaque_ref, sr);
var vbd = vm.Connection.Resolve(vbdRef);
if (vbd != null)
_storageMapping.Add(vbd.VDI.opaque_ref, sr);
}
PopulateApiMethodsToRoleCheck();
@ -95,68 +96,77 @@ namespace XenAdmin.Actions.VMActions
protected override void Run()
{
this.Description = Messages.ACTION_VM_MOVING;
try
Description = Messages.ACTION_PREPARING;
// move the progress bar above 0, it's more reassuring to see than a blank bar as we copy the first disk
PercentComplete += 10;
int halfstep = 90 / (VM.VBDs.Count * 2);
var exceptions = new List<Exception>();
foreach (var vbdRef in VM.VBDs)
{
var vbds = Connection.ResolveAll(VM.VBDs);
int halfstep = (int)(90/(vbds.Count * 2));
// move the progress bar above 0, it's more reassuring to see than a blank bar as we copy the first disk
PercentComplete += 10;
Exception exn = null;
if (Cancelling)
throw new CancelledException();
foreach (VBD oldVBD in vbds)
var oldVBD = Connection.Resolve(vbdRef);
if (oldVBD == null || !oldVBD.GetIsOwner())
continue;
if (_storageMapping == null ||
!_storageMapping.TryGetValue(oldVBD.VDI.opaque_ref, out SR sr) || sr == null)
continue;
var curVdi = Connection.Resolve(oldVBD.VDI);
if (curVdi == null)
continue;
if (curVdi.SR.opaque_ref == sr.opaque_ref)
continue;
Description = string.Format(Messages.ACTION_MOVING_VDI_TO_SR,
Helpers.GetName(curVdi), Helpers.GetName(sr));
RelatedTask = VDI.async_copy(Session, oldVBD.VDI.opaque_ref, sr.opaque_ref);
PollToCompletion(PercentComplete, PercentComplete + halfstep);
var newVDI = Connection.WaitForCache(new XenRef<VDI>(Result));
var newVBD = new VBD
{
if (!oldVBD.GetIsOwner())
continue;
userdevice = oldVBD.userdevice,
bootable = oldVBD.bootable,
mode = oldVBD.mode,
type = oldVBD.type,
unpluggable = oldVBD.unpluggable,
other_config = oldVBD.other_config,
VDI = new XenRef<VDI>(newVDI.opaque_ref),
VM = new XenRef<VM>(VM.opaque_ref)
};
newVBD.SetIsOwner(oldVBD.GetIsOwner());
var curVdi = Connection.Resolve(oldVBD.VDI);
if (curVdi == null)
continue;
if (StorageMapping == null || !StorageMapping.ContainsKey(oldVBD.VDI.opaque_ref))
continue;
SR sr = StorageMapping[oldVBD.VDI.opaque_ref];
if (sr == null || curVdi.SR.opaque_ref == sr.opaque_ref)
continue;
RelatedTask = XenAPI.VDI.async_copy(Session, oldVBD.VDI.opaque_ref, sr.opaque_ref);
PollToCompletion(PercentComplete, PercentComplete + halfstep);
var newVDI = Connection.WaitForCache(new XenRef<VDI>(Result));
var newVBD = new VBD
{
userdevice = oldVBD.userdevice,
bootable = oldVBD.bootable,
mode = oldVBD.mode,
type = oldVBD.type,
unpluggable = oldVBD.unpluggable,
other_config = oldVBD.other_config,
VDI = new XenRef<VDI>(newVDI.opaque_ref),
VM = new XenRef<VM>(VM.opaque_ref)
};
newVBD.SetIsOwner(oldVBD.GetIsOwner());
VBD vbd = oldVBD;
BestEffort(ref exn, () => VDI.destroy(Session, vbd.VDI.opaque_ref));
Connection.WaitForCache<VBD>(VBD.create(Session, newVBD));
PercentComplete += halfstep;
try
{
VDI.destroy(Session, oldVBD.VDI.opaque_ref);
}
catch (Exception e)
{
log.ErrorFormat("Failed to destroy old VDI {0}", oldVBD.VDI.opaque_ref);
exceptions.Add(e);
}
if (SR != null)
VM.set_suspend_SR(Session, VM.opaque_ref, SR.opaque_ref);
Connection.WaitForCache(VBD.create(Session, newVBD));
if (exn != null)
throw exn;
PercentComplete += halfstep;
}
}
catch (CancelledException)
{
this.Description = string.Format(Messages.MOVE_CANCELLED, VM.Name());
throw;
}
this.Description = Messages.MOVED;
if (SR != null)
VM.set_suspend_SR(Session, VM.opaque_ref, SR.opaque_ref);
if (exceptions.Count > 0)
throw new Exception(Messages.ACTION_VM_MOVING_VDI_DESTROY_FAILURE);
Description = Messages.MOVED;
}
}
}

View File

@ -1566,18 +1566,18 @@ namespace XenAdmin {
/// <summary>
/// Looks up a localized string similar to Moving virtual disk &apos;{0}&apos;....
/// </summary>
public static string ACTION_MOVING_VDI_STATUS {
public static string ACTION_MOVING_VDI {
get {
return ResourceManager.GetString("ACTION_MOVING_VDI_STATUS", resourceCulture);
return ResourceManager.GetString("ACTION_MOVING_VDI", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Moving Virtual Disk &apos;{0}&apos; to SR &apos;{1}&apos;.
/// </summary>
public static string ACTION_MOVING_VDI_TITLE {
public static string ACTION_MOVING_VDI_TO_SR {
get {
return ResourceManager.GetString("ACTION_MOVING_VDI_TITLE", resourceCulture);
return ResourceManager.GetString("ACTION_MOVING_VDI_TO_SR", resourceCulture);
}
}
@ -3193,7 +3193,7 @@ namespace XenAdmin {
}
/// <summary>
/// Looks up a localized string similar to Moving VM to new storage....
/// Looks up a localized string similar to Moving VM &apos;{0}&apos; to new storage.
/// </summary>
public static string ACTION_VM_MOVING {
get {
@ -3210,6 +3210,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Failed to finalize moving VM &apos;{0}&apos; to new storage. Please see logs for details..
/// </summary>
public static string ACTION_VM_MOVING_VDI_DESTROY_FAILURE {
get {
return ResourceManager.GetString("ACTION_VM_MOVING_VDI_DESTROY_FAILURE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Rebooted.
/// </summary>
@ -24523,15 +24532,6 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Moving {0} canceled.
/// </summary>
public static string MOVE_CANCELLED {
get {
return ResourceManager.GetString("MOVE_CANCELLED", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Move object &apos;{0}&apos; to folder &apos;{1}&apos;....
/// </summary>
@ -24578,7 +24578,7 @@ namespace XenAdmin {
}
/// <summary>
/// Looks up a localized string similar to Moved.
/// Looks up a localized string similar to Move completed..
/// </summary>
public static string MOVED {
get {

View File

@ -618,10 +618,10 @@
<data name="ACTION_MIGRATING_X_VDIS_STARTED" xml:space="preserve">
<value>Started migrating virtual disks</value>
</data>
<data name="ACTION_MOVING_VDI_STATUS" xml:space="preserve">
<data name="ACTION_MOVING_VDI" xml:space="preserve">
<value>Moving virtual disk '{0}'...</value>
</data>
<data name="ACTION_MOVING_VDI_TITLE" xml:space="preserve">
<data name="ACTION_MOVING_VDI_TO_SR" xml:space="preserve">
<value>Moving Virtual Disk '{0}' to SR '{1}'</value>
</data>
<data name="ACTION_MOVING_X_VDIS" xml:space="preserve">
@ -1183,11 +1183,14 @@
<value>Migrating VM '{0}'</value>
</data>
<data name="ACTION_VM_MOVING" xml:space="preserve">
<value>Moving VM to new storage...</value>
<value>Moving VM '{0}' to new storage</value>
</data>
<data name="ACTION_VM_MOVING_TITLE" xml:space="preserve">
<value>Moving VM '{0}' to '{1}' on SR '{2}'</value>
</data>
<data name="ACTION_VM_MOVING_VDI_DESTROY_FAILURE" xml:space="preserve">
<value>Failed to finalize moving VM '{0}' to new storage. Please see logs for details.</value>
</data>
<data name="ACTION_VM_REBOOTED" xml:space="preserve">
<value>Rebooted</value>
</data>
@ -8522,10 +8525,7 @@ Do you want to continue?</value>
<value>More info...</value>
</data>
<data name="MOVED" xml:space="preserve">
<value>Moved</value>
</data>
<data name="MOVE_CANCELLED" xml:space="preserve">
<value>Moving {0} canceled</value>
<value>Move completed.</value>
</data>
<data name="MOVE_OBJECTS_TO_FOLDER" xml:space="preserve">
<value>Move selected objects to folder '{0}'...</value>