/* Copyright (c) Citrix Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ using System; using System.Collections.Generic; using System.Linq; using XenAdmin.Core; using XenAdmin.Mappings; using XenAdmin.Network; using XenAPI; namespace XenAdmin.Wizards.GenericPages { public class SummaryDetails { public SummaryDetails(string key, string value, bool errors) { Key = key; Value = value; Errors = errors; } public SummaryDetails(string key, string value) : this(key, value, false) { } public string Key { get; private set; } public string Value { get; private set; } public bool Errors { get; private set; } } /// /// Concrete component class for decorators /// public class VMMappingSummary : MappingSummary { public override List Details { get { return new List(); } } } #region Decorator classes to convert VM Mappings to a summary public abstract class TitleSummary : MappingSummaryDecorator { private readonly VmMapping mapping; public TitleSummary(MappingSummary summary, VmMapping mapping) : base(summary) { this.mapping = mapping; } public override List Details { get { List decoratedSummary = summary.Details; decoratedSummary.Add(new SummaryDetails(SummaryKeyText, mapping.VmNameLabel)); return decoratedSummary; } } protected abstract string SummaryKeyText { get; } } public class VmTitleSummary : TitleSummary { public VmTitleSummary(MappingSummary summary, VmMapping mapping) : base(summary, mapping) { } protected override string SummaryKeyText { get { return Messages.CPM_SUMMARY_KEY_MIGRATE_VM; } } } public class TemplateTitleSummary : TitleSummary { public TemplateTitleSummary(MappingSummary summary, VmMapping mapping) : base(summary, mapping) { } protected override string SummaryKeyText { get { return Messages.CPM_SUMMARY_KEY_MIGRATE_TEMPLATE; } } } public class DestinationPoolSummary : MappingSummaryDecorator { private readonly VmMapping mapping; private readonly IXenConnection connection; public DestinationPoolSummary(MappingSummary summary, VmMapping mapping, IXenConnection connection) : base(summary) { this.mapping = mapping; this.connection = connection; } public override List Details { get { List decoratedSummary = summary.Details; decoratedSummary.Add(new SummaryDetails(Messages.CPM_SUMMARY_KEY_DESTINATION, ResolveLabel())); return decoratedSummary; } } private string ResolveLabel() { if (mapping.XenRef is XenRef) { Host targetHost = connection.Resolve(mapping.XenRef as XenRef); if(targetHost == null) { return Messages.UNKNOWN; } Pool targetPool = Helpers.GetPool(targetHost.Connection); if (targetPool != null) { return targetPool.Name(); } return mapping.TargetName; } return mapping.TargetName; } } public class TargetServerSummary : MappingSummaryDecorator { private readonly VmMapping mapping; private readonly IXenConnection connection; public TargetServerSummary(MappingSummary summary, VmMapping mapping, IXenConnection connection) : base(summary) { this.mapping = mapping; this.connection = connection; } public override List Details { get { List decoratedSummary = summary.Details; decoratedSummary.Add(new SummaryDetails(Messages.CPM_SUMMARY_KEY_TARGET_SERVER, ResolveLabel())); return decoratedSummary; } } private string ResolveLabel() { if (mapping.XenRef is XenRef) { Host targetHost = connection.Resolve(mapping.XenRef as XenRef); if (targetHost == null) { return Messages.UNKNOWN; } return mapping.TargetName; } return Messages.CPM_SUMMARY_UNSET; } } public class StorageSummary : MappingSummaryDecorator { private readonly VmMapping mapping; private readonly IXenConnection connection; private const string separatorText = " -> "; public StorageSummary(MappingSummary summary, VmMapping mapping, IXenConnection connection) : base(summary) { this.mapping = mapping; this.connection = connection; } public override List Details { get { List decoratedSummary = summary.Details; AddStorageMappings(ref decoratedSummary); return decoratedSummary; } } private void AddStorageMappings(ref List decoratedSummary) { bool firstItem = true; foreach (var pair in mapping.Storage) { VDI vdi = connection.Resolve(new XenRef(pair.Key)); if (vdi == null || vdi.is_a_snapshot) // don't display the storage mappings for the shapshots continue; string valueToAdd = vdi.Name() + separatorText + pair.Value.Name(); if (firstItem) { decoratedSummary.Add(new SummaryDetails(Messages.CPM_SUMMARY_KEY_STORAGE, valueToAdd)); firstItem = false; } else { decoratedSummary.Add(new SummaryDetails(String.Empty, valueToAdd)); } } } } public class NetworkSummary : MappingSummaryDecorator { private readonly VmMapping mapping; private readonly IXenConnection connection; private const string separatorText = " -> "; public NetworkSummary(MappingSummary summary, VmMapping mapping, IXenConnection connection) : base(summary) { this.mapping = mapping; this.connection = connection; } public override List Details { get { List decoratedSummary = summary.Details; AddStorageMappings(ref decoratedSummary); return decoratedSummary; } } private void AddStorageMappings(ref List decoratedSummary) { bool addSummaryKey = true; foreach (var pair in mapping.Networks) { XenAPI.Network net = connection.Resolve(new XenRef(pair.Key)); bool networkNotFound = net == null; string valueToAdd = networkNotFound ? Messages.CPM_SUMMARY_NETWORK_NOT_FOUND : net.Name(); valueToAdd += separatorText + pair.Value.Name(); decoratedSummary.Add(addSummaryKey ? new SummaryDetails(Messages.CPM_SUMMARY_KEY_NETWORK, valueToAdd, networkNotFound) : new SummaryDetails(String.Empty, valueToAdd, networkNotFound)); addSummaryKey = false; } } } /// /// Decorator class adding a splitter to the formatting /// public class SummarySplitter : MappingSummaryDecorator { public SummarySplitter(MappingSummary summary) : base(summary) { } public override List Details { get { List decoratedSummary = summary.Details; decoratedSummary.Add(new SummaryDetails(String.Empty, String.Empty)); return decoratedSummary; } } } /// /// Decorator class adding a splitter to the formatting /// public class TransferNetworkSummary : MappingSummaryDecorator { private readonly string networkName; public TransferNetworkSummary(MappingSummary summary, string networkName) : base(summary) { this.networkName = networkName; } public override List Details { get { List decoratedSummary = summary.Details; if (!string.IsNullOrEmpty(networkName)) decoratedSummary.Add(new SummaryDetails(Messages.CPM_SUMMARY_KEY_TRANSFER_NETWORK, networkName)); return decoratedSummary; } } } #endregion /// /// Base class for decorator and component classes /// public abstract class MappingSummary { public abstract List Details { get; } } /// /// Base decorator class /// public abstract class MappingSummaryDecorator : MappingSummary { protected MappingSummary summary; protected MappingSummaryDecorator(MappingSummary summary) { this.summary = summary; } public override List Details { get { return summary != null ? summary.Details : new List(); } } } }