xenadmin/XenAdmin/Wizards/NewSRWizard_Pages/Frontends/CSLG.cs

475 lines
19 KiB
C#
Raw Normal View History

/* 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.Collections.ObjectModel;
using System.Windows.Forms;
using XenAdmin.Actions;
using XenAdmin.Commands;
using XenAdmin.Controls;
using XenAdmin.Core;
using XenAdmin.Dialogs;
using XenAdmin.Network;
using XenAdmin.Network.StorageLink;
using XenAdmin.StorageLinkAPI;
using XenAPI;
using System.Threading;
using System.Diagnostics;
using System.Drawing;
using XenAdmin.Properties;
namespace XenAdmin.Wizards.NewSRWizard_Pages.Frontends
{
public partial class CSLG : XenTabPage
{
#region Private fields
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private IStorageLinkObject _storageLinkObject;
private ReadOnlyCollection<CslgSystemStorage> _storages;
private SR _srToReattach;
private bool _disasterRecoveryTask;
private int _storageSystemComboLastSelectedIndex = -1;
private const string ADAPTER_ID = "adapterid";
private const string STORAGE_SYSTEM_ID = "storageSystemId";
#endregion
public CSLG()
{
InitializeComponent();
}
#region Accessors
public StorageLinkAdapterBoston SelectedStorageAdapter { get { return comboBoxStorageSystem.SelectedItem as StorageLinkAdapterBoston; } }
public CslgSystemStorage SelectedStorageSystem { get { return comboBoxStorageSystem.SelectedItem as CslgSystemStorage; } }
public ReadOnlyCollection<CslgStoragePool> StoragePools { get; private set; }
public bool NetAppSelected
{
get
{
var item = comboBoxStorageSystem.SelectedItem as string;
return item != null && item == Messages.CSLG_NETAPP_DIRECT;
}
}
public bool DellSelected
{
get
{
var item = comboBoxStorageSystem.SelectedItem as string;
return item != null && item == Messages.CSLG_DELL_DIRECT;
}
}
public Dictionary<string, string> DeviceConfigParts
{
get
{
var dconf = new Dictionary<string, string>();
2015-10-26 17:01:55 +01:00
var adapter = comboBoxStorageSystem.SelectedItem as StorageLinkAdapterBoston;
if (adapter != null)
dconf[ADAPTER_ID] = adapter.Id;
return dconf;
}
}
public SrWizardType SrWizardType
{
set
{
_srToReattach = value.SrToReattach;
_disasterRecoveryTask = value.DisasterRecoveryTask;
}
}
#endregion
private static List<StorageLinkCredentials> GetAllValidStorageLinkCreds()
{
var credsList = new List<StorageLinkCredentials>();
2015-10-26 17:01:55 +01:00
foreach (IXenConnection c in ConnectionsManager.XenConnectionsCopy.FindAll(c => c.IsConnected && !Helpers.FeatureForbidden(c, Host.RestrictStorageChoices)))
{
var p = Helpers.GetPoolOfOne(c);
credsList.Add(p.GetStorageLinkCredentials());
credsList.AddRange(Array.ConvertAll(p.Connection.Cache.PBDs, pbd => pbd.GetStorageLinkCredentials()));
}
credsList.RemoveAll(cc => cc == null || !cc.IsValid);
return credsList;
}
public void SetStorageLinkObject(IStorageLinkObject storageLinkObject)
{
_storageLinkObject = storageLinkObject;
}
/// <summary>
/// Performs a scan of the CSLG host specified in the textboxes.
/// </summary>
/// <returns>True, if the scan succeeded, otherwise False.</returns>
public bool PerformStorageSystemScan()
{
var items = new List<object>();
2015-10-26 17:01:55 +01:00
if (_storageLinkObject != null || (Connection.IsConnected && !Helpers.FeatureForbidden(Connection, Host.RestrictStorageChoices)))
{
if (_srToReattach == null || _srToReattach.type == "cslg")
{
2015-10-26 17:01:55 +01:00
var action = new SrCslgAdaptersScanAction(Connection);
var dialog = new ActionProgressDialog(action, ProgressBarStyle.Marquee);
// never show the error message if it fails.
action.Completed += s =>
{
2015-10-26 17:01:55 +01:00
if (!action.Succeeded)
{
2015-10-26 17:01:55 +01:00
Program.Invoke(dialog, dialog.Close);
}
2015-10-26 17:01:55 +01:00
};
2015-10-26 17:01:55 +01:00
dialog.ShowDialog(this);
if (action.Succeeded)
{
var adapters = action.GetAdapters();
items.AddRange(Util.PopulateList<object>(adapters));
items.Sort((x, y) => x.ToString().CompareTo(y.ToString()));
}
2015-10-26 17:01:55 +01:00
else
return false;
}
}
bool bostonHasDell = false;
bool bostonHasNetapp = false;
2015-10-26 17:01:55 +01:00
if (items != null)
{
bostonHasDell = (items.Find(item => ((StorageLinkAdapterBoston)item).Id == "DELL_EQUALLOGIC") != null);
bostonHasNetapp = (items.Find(item => ((StorageLinkAdapterBoston)item).Id == "NETAPP") != null);
}
comboBoxStorageSystem.Items.Clear();
if (_storageLinkObject != null)
{
2015-10-26 17:01:55 +01:00
;
}
else if (_srToReattach != null)
{
if (_srToReattach.type == "equal")
{
// a direct-connect Equallogic is being reattached. Only add this item.
comboBoxStorageSystem.Items.Add(Messages.CSLG_DELL_DIRECT);
}
else if (_srToReattach.type == "netapp")
{
// a direct-connect NetApp is being reattached. Only add this item.
comboBoxStorageSystem.Items.Add(Messages.CSLG_NETAPP_DIRECT);
}
}
else
{
// a pool or host was selected in the mainwindow tree when the wizard was launched.
2015-10-26 17:01:55 +01:00
if (!bostonHasDell || !bostonHasNetapp)
comboBoxStorageSystem.Items.Add(new NonSelectableComboBoxItem(Messages.CSLG_DIRECT_CONNECTION, true));
if (!bostonHasDell)
comboBoxStorageSystem.Items.Add(Messages.CSLG_DELL_DIRECT);
if (!bostonHasNetapp)
comboBoxStorageSystem.Items.Add(Messages.CSLG_NETAPP_DIRECT);
}
2015-10-26 17:01:55 +01:00
if (items != null && items.Count > 0)
{
if (!bostonHasDell || !bostonHasNetapp)
comboBoxStorageSystem.Items.Add(new NonSelectableComboBoxItem(Messages.CSLG_STORAGELINK_ADAPTERS, true));
comboBoxStorageSystem.Items.AddRange(items.ToArray());
}
if (comboBoxStorageSystem.SelectedIndex < 0 && comboBoxStorageSystem.Items.Count > 0)
{
// select the first selectable item if nothing's already been selected.
comboBoxStorageSystem.SelectedItem = Util.PopulateList<object>(comboBoxStorageSystem.Items).Find(s => !(s is NonSelectableComboBoxItem));
2015-10-26 17:01:55 +01:00
if (_srToReattach != null && _srToReattach.type == "cslg")
{
comboBoxStorageSystem.SelectedItem =
Util.PopulateList<object>(comboBoxStorageSystem.Items).Find(s =>
{
var bostonadapter = s as StorageLinkAdapterBoston;
if (bostonadapter != null)
{
// sm_config["md_svid"] looks like "DELL__EQUALLOGIC__{GUID}"
// bostonadapter.Id looks like "DELL_EQUALLOGIC"
// Additionally, EMC__CLARIION is always SMI-S (CA-72968)
if (_srToReattach.sm_config.ContainsKey("md_svid"))
{
var svid = _srToReattach.sm_config["md_svid"];
if (svid.Replace("__", "_").StartsWith(bostonadapter.Id))
return true;
if (bostonadapter.Id == "SMIS_STORAGE_SYSTEM" && svid.StartsWith("EMC__CLARIION"))
return true;
return false;
}
}
return false;
});
}
}
return true;
}
private bool PerformStoragePoolScan()
{
2015-10-26 17:01:55 +01:00
StorageLinkCredentials credentials = null;
var scanAction = new SrCslgStoragePoolScanAction(Connection, Program.StorageLinkConnections.GetCopy(), credentials.Host,
credentials.Username, credentials.PasswordSecret, SelectedStorageSystem.StorageSystemId);
ActionProgressDialog dialog = new ActionProgressDialog(scanAction, ProgressBarStyle.Marquee);
dialog.ShowDialog(this);
if (scanAction.Succeeded)
StoragePools = scanAction.CslgStoragePools;
return scanAction.Succeeded;
}
#region XenTabPage overrides
public override void PageLeave(PageLoadedDirection direction, ref bool cancel)
{
if (direction == PageLoadedDirection.Forward && SelectedStorageSystem != null)
cancel = !PerformStoragePoolScan();
base.PageLeave(direction, ref cancel);
}
public override void PopulatePage()
{
2015-10-26 17:01:55 +01:00
linkLabelGotoStorageLinkProperties.Visible = _storageLinkObject == null;
labelStorageLinkPropertiesLinkBlurb.Visible = linkLabelGotoStorageLinkProperties.Visible;
2015-10-26 17:01:55 +01:00
labelAdapter.Visible = true;
labelSystem.Visible = flowLayoutPanel1.Visible = false;
labelStorageSystem.Text = Messages.CSLG_STORAGEADAPTER;
}
public override string Text
{
2015-10-26 17:01:55 +01:00
get { return Messages.STORAGE_ADAPTER; }
}
public override string PageTitle
{
2015-10-26 17:01:55 +01:00
get { return Messages.NEWSR_CSLG_ADAPTER_PAGE_TITLE; }
}
public override string HelpID
{
2015-10-26 17:01:55 +01:00
get { return "SL_System"; }
}
public override bool EnableNext()
{
return comboBoxStorageSystem.SelectedItem != null &&
!(comboBoxStorageSystem.SelectedItem is NonSelectableComboBoxItem);
}
public override bool EnablePrevious()
{
if (_disasterRecoveryTask && _srToReattach == null)
return false;
return true;
}
#endregion
#region NonSelectableComboBoxItem class
private class NonSelectableComboBoxItem
{
public string Text { get; private set; }
public bool Bold { get; private set; }
public NonSelectableComboBoxItem(string text, bool bold)
{
Text = text;
Bold = bold;
}
public override string ToString()
{
return Text;
}
}
#endregion
#region Event handlers
private void comboBoxStorageSystem_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBoxStorageSystem.SelectedItem is NonSelectableComboBoxItem)
{
2015-10-26 17:01:55 +01:00
if (comboBoxStorageSystem.SelectedIndex < comboBoxStorageSystem.Items.Count - 1 &&
(_storageSystemComboLastSelectedIndex < comboBoxStorageSystem.SelectedIndex || comboBoxStorageSystem.SelectedIndex == 0))
{
_storageSystemComboLastSelectedIndex = comboBoxStorageSystem.SelectedIndex;
comboBoxStorageSystem.SelectedIndex++;
}
else
{
_storageSystemComboLastSelectedIndex = comboBoxStorageSystem.SelectedIndex;
comboBoxStorageSystem.SelectedIndex--;
}
}
else
{
_storageSystemComboLastSelectedIndex = comboBoxStorageSystem.SelectedIndex;
}
OnPageUpdated();
if (comboBoxStorageSystem.SelectedIndex >= 0)
{
if (_storageLinkObject != null)
{
// The user has changed which SL object to use using the storage-system combo-box so update that here.
if (_storageLinkObject is StorageLinkServer || _storageLinkObject is StorageLinkSystem)
{
_storageLinkObject = ((CslgSystemStorage)comboBoxStorageSystem.SelectedItem).StorageLinkSystem;
}
else
{
StorageLinkPool storageLinkPool = (StorageLinkPool)_storageLinkObject;
if (storageLinkPool.StorageLinkSystem != ((CslgSystemStorage)comboBoxStorageSystem.SelectedItem).StorageLinkSystem)
{
_storageLinkObject = ((CslgSystemStorage)comboBoxStorageSystem.SelectedItem).StorageLinkSystem;
}
}
}
}
}
private void comboBoxStorageSystem_DrawItem(object sender, DrawItemEventArgs e)
{
ComboBox comboBox = (ComboBox)sender;
if (e.Index > -1)
{
var item = comboBox.Items[e.Index];
var storageSystem = item as CslgSystemStorage;
var nonSelectable = item as NonSelectableComboBoxItem;
bool edit = (e.State & DrawItemState.ComboBoxEdit) != 0;
const int imageWidth = 16;
int indent = edit ? 0 : (imageWidth / 2);
e.DrawBackground();
var textRect = new Rectangle(e.Bounds.X + indent + imageWidth, e.Bounds.Y, e.Bounds.Width - imageWidth - indent, e.Bounds.Height);
if (storageSystem != null)
{
e.Graphics.DrawImageUnscaled(Resources.sl_system_16, new Point(e.Bounds.X + indent, e.Bounds.Y + 1));
Drawing.DrawText(e.Graphics, item.ToString(), e.Font, textRect, e.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
}
else if (nonSelectable != null)
{
// bold headings
Drawing.DrawText(e.Graphics, item.ToString(), new Font(e.Font, FontStyle.Bold), e.Bounds, e.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
}
else
{
// dell and netapp direction connection.
textRect = new Rectangle(e.Bounds.X + indent, e.Bounds.Y, e.Bounds.Width - indent, e.Bounds.Height);
Drawing.DrawText(e.Graphics, item.ToString(), e.Font, textRect, e.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
}
if ((e.State & DrawItemState.NoFocusRect) == 0)
{
e.DrawFocusRectangle();
}
}
}
private void linkLabelGotoStorageLinkProperties_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
IXenObject o = Helpers.GetPool(Connection);
if (o == null)
{
var hosts = Connection.Cache.Hosts;
if (hosts.Length > 0)
{
o = hosts[0];
}
}
if (o != null)
{
var dialog = new PropertiesDialog(o);
dialog.Load += (s, ee) => dialog.SelectStorageLinkPage();
dialog.FormClosing += (s, ee) =>
{
if (dialog.DialogResult == DialogResult.Yes && ee.Action != null)
{
ee.StartAction = false;
ee.Action.Completed += ss =>
{
if (ee.Action.Succeeded)
{
Program.Invoke(Program.MainWindow, () =>
{
int comboBoxItemCount = comboBoxStorageSystem.Items.Count;
PerformStorageSystemScan();
comboBoxStorageSystem.DroppedDown = comboBoxStorageSystem.Items.Count > comboBoxItemCount;
});
}
};
new ActionProgressDialog(ee.Action, ProgressBarStyle.Marquee).ShowDialog(this);
}
};
dialog.Show(this);
}
}
#endregion
}
}