/* 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.Windows.Forms;
using XenAPI;
using XenAdmin.Actions;
using XenAdmin.Network;
using XenAdmin.Core;
using System.Threading;
using XenAdmin.Controls;
using XenAdmin.Dialogs;
using System.Drawing;
using System.Linq;
using XenAdmin.Utils;
namespace XenAdmin.Wizards.NewSRWizard_Pages.Frontends
{
public partial class LVMoISCSI : XenTabPage
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
///
/// If an SR already exists on this LUN, this will point to the SR info which indicates that
/// the SR should be reattached.
///
/// If this is null, indicates the LUN should be formatted into a new SR.
///
private SR.SRInfo _srToIntroduce;
private ISCSIPopulateLunsAction IscsiPopulateLunsAction;
private ISCSIPopulateIQNsAction IscsiPopulateIqnsAction;
private readonly Dictionary LunMap = new Dictionary();
private readonly ToolTip TargetIqnToolTip = new ToolTip();
private const string TARGET = "target";
private const string PORT = "port";
private const string TARGETIQN = "targetIQN";
private const string LUNSERIAL = "LUNSerial";
private const string SCSIID = "SCSIid";
private const string CHAPUSER = "chapuser";
private const string CHAPPASSWORD = "chappassword";
private const string URI = "uri";
private const string URIFORMAT = "iscsi://{0}{1}:{2}/{3}/{4}"; // uri= iscsi://[[%]@][:]//
private const string CHAPFORMAT = "{0}%{1}@"; // % ErrorIcons
{
get { return new Control[] {errorIconAtCHAPPassword, errorIconAtHostOrIP, errorIconAtTargetLUN }; }
}
private IEnumerable ErrorLabels
{
get { return new Control[] { errorLabelAtHostname, errorLabelAtCHAPPassword, errorLabelAtTargetLUN }; }
}
private IEnumerable SpinnerControls
{
get { return new Control[] { spinnerIconAtScanTargetHostButton, spinnerIconAtTargetIqn, spinnerIconAtTargetLun }; }
}
private IEnumerable UserInputControls
{
get
{
return new Control[]
{
textBoxIscsiHost, textBoxIscsiPort, IscsiUseChapCheckBox, IScsiChapUserTextBox,
IScsiChapSecretTextBox, scanTargetHostButton, comboBoxIscsiIqns, comboBoxIscsiLuns
};
}
}
private readonly TemporaryDisablerForControls controlDisabler = new TemporaryDisablerForControls();
public LVMoISCSI()
{
InitializeComponent();
}
#region XentabPage overrides
public override string PageTitle { get { return Messages.NEWSR_PATH_ISCSI; } }
public override string Text { get { return Messages.NEWSR_LOCATION; } }
public override string HelpID { get { return "Location_ISCSI"; } }
public override void PageLoaded(PageLoadedDirection direction)
{
base.PageLoaded(direction);
HelpersGUI.PerformIQNCheck();
if (direction == PageLoadedDirection.Forward)
HelpersGUI.FocusFirstControl(Controls);
}
public override void PageLeave(PageLoadedDirection direction, ref bool cancel)
{
if (direction == PageLoadedDirection.Back)
return;
// For Miami hosts we need to ensure an SR.probe()
// has been performed, and that the user has made a decision. Show the iSCSI choices dialog until
// they click something other than 'Cancel'. For earlier host versions, warn that data loss may
// occur.
Host master = Helpers.GetMaster(Connection);
if (master == null)
{
cancel = true;
return;
}
Dictionary dconf = GetDeviceConfig(SR.SRTypes.lvmoiscsi); // TODO: use SRType
if (dconf == null)
{
cancel = true;
return;
}
// Start probe
SrProbeAction IscsiProbeAction = new SrProbeAction(Connection, master, SR.SRTypes.lvmoiscsi, dconf); // TODO: use SRType
using (var dialog = new ActionProgressDialog(IscsiProbeAction, ProgressBarStyle.Marquee))
{
dialog.ShowCancel = true;
dialog.ShowDialog(this);
}
// Probe has been performed. Now ask the user if they want to Reattach/Format/Cancel.
// Will return false on cancel
cancel = !ExamineIscsiProbeResults(IscsiProbeAction);
iscsiProbeError = cancel;
base.PageLeave(direction, ref cancel);
}
bool iscsiProbeError = false;
public override bool EnableNext()
{
UInt16 i;
bool portValid = UInt16.TryParse(textBoxIscsiPort.Text, out i);
return !String.IsNullOrEmpty(getIscsiHost())
&& portValid
&& !(IscsiUseChapCheckBox.Checked && String.IsNullOrEmpty(IScsiChapUserTextBox.Text))
&& comboBoxIscsiLuns.SelectedItem != null && comboBoxIscsiLuns.SelectedItem as string != Messages.SELECT_TARGET_LUN
&& !iscsiProbeError && !IsLunInUse();
}
public override bool EnablePrevious()
{
if (SrWizardType.DisasterRecoveryTask && SrWizardType.SrToReattach == null)
return false;
return true;
}
public override void PopulatePage()
{
HideAllErrorIconsAndLabels();
// Enable IQN scanning
comboBoxIscsiIqns.Visible = true;
// IQN's can be very long, so we will show the value as a mouse over tooltip.
// Initialize the tooltip here.
TargetIqnToolTip.Active = true;
TargetIqnToolTip.AutomaticDelay = 0;
TargetIqnToolTip.AutoPopDelay = 50000;
TargetIqnToolTip.InitialDelay = 50;
TargetIqnToolTip.ReshowDelay = 50;
TargetIqnToolTip.ShowAlways = true;
}
#endregion
private void UpdateButtons()
{
UInt16 i;
bool portValid = UInt16.TryParse(textBoxIscsiPort.Text, out i);
scanTargetHostButton.Enabled =
!String.IsNullOrEmpty(getIscsiHost())
&& portValid;
// Cause wizards next etc to update
OnPageUpdated();
}
private void textBoxIscsiHost_TextChanged(object sender, EventArgs e)
{
HideAllErrorIconsAndLabels();
HideAllSpinnerIcons();
IScsiParams_TextChanged(null, null);
}
///
/// Called when any of the iSCSI filer params change: resets the IQNs/LUNs.
/// Must be called on the event thread.
///
private void IScsiParams_TextChanged(object sender, EventArgs e)
{
Program.AssertOnEventThread();
spinnerIconAtScanTargetHostButton.Visible = false;
// User has changed filer hostname/username/password - clear IQN/LUN boxes
comboBoxIscsiIqns.Items.Clear();
comboBoxIscsiIqns.Enabled = false;
labelIscsiIQN.Enabled = false;
iSCSITargetGroupBox.Enabled = false;
// Cancel pending IQN/LUN scans
if (IscsiPopulateIqnsAction != null)
{
IscsiPopulateIqnsAction.Cancel();
}
ChapSettings_Changed(null, null);
}
private bool IsLunInUse()
{
SR sr = UniquenessCheck();
// LUN is not in use iff sr != null
if (sr == null)
{
HideAllErrorIconsAndLabels();
return false;
}
spinnerIconAtTargetLun.Visible = false;
Pool pool = Helpers.GetPool(sr.Connection);
if (pool != null)
{
errorIconAtTargetLUN.Visible = true;
errorLabelAtTargetLUN.Visible = true;
errorLabelAtTargetLUN.Text = String.Format(Messages.NEWSR_LUN_IN_USE_ON_POOL, sr.Name(), pool.Name());
return true;
}
Host master = Helpers.GetMaster(sr.Connection);
if (master != null)
{
errorIconAtTargetLUN.Visible = true;
errorLabelAtTargetLUN.Visible = true;
errorLabelAtTargetLUN.Text = String.Format(Messages.NEWSR_LUN_IN_USE_ON_SERVER, sr.Name(), master.Name());
return true;
}
errorIconAtTargetLUN.Visible = true;
errorLabelAtTargetLUN.Visible = true;
errorLabelAtTargetLUN.Text = Messages.NEWSR_LUN_IN_USE;
return true;
}
private void comboBoxIscsiLuns_SelectedIndexChanged(object sender, EventArgs e)
{
iscsiProbeError = false;
if (comboBoxIscsiLuns.SelectedItem as string != Messages.SELECT_TARGET_LUN)
{
spinnerIconAtTargetLun.DisplaySucceededImage();
}
else
{
spinnerIconAtTargetLun.Visible = false;
HideAllErrorIconsAndLabels();
}
UpdateButtons();
}
private void ChapSettings_Changed(object sender, EventArgs e)
{
comboBoxIscsiLuns.Items.Clear();
comboBoxIscsiLuns.Text = "";
comboBoxIscsiLuns.Enabled = false;
targetLunLabel.Enabled = false;
if (IscsiPopulateLunsAction != null)
{
IscsiPopulateLunsAction.Cancel();
}
UpdateButtons();
}
///
/// Check the current config of the iSCSI sr in the wizard is unique across
/// all active connections.
///
/// SR that uses this config if not unique, null if unique
private SR UniquenessCheck()
{
// Check currently selected lun is unique amongst other connected hosts.
foreach (IXenConnection connection in ConnectionsManager.XenConnectionsCopy)
{
foreach (SR sr in connection.Cache.SRs)
{
if (sr.GetSRType(false) != SR.SRTypes.lvmoiscsi) // TODO: use SRType
continue;
if (sr.PBDs.Count < 1)
continue;
PBD pbd = connection.Resolve(sr.PBDs[0]);
if (pbd == null)
continue;
if (UniquenessCheckMiami(connection, pbd))
return sr;
}
}
return null;
}
///
/// Check currently LUN against miami host
///
///
///
///
private bool UniquenessCheckMiami(IXenConnection connection, PBD pbd)
{
if (!pbd.device_config.ContainsKey(SCSIID))
return false;
String scsiID = pbd.device_config[SCSIID];
String myLUN = getIscsiLUN();
if (!LunMap.ContainsKey(myLUN))
return false;
ISCSIInfo info = LunMap[myLUN];
return info.ScsiID == scsiID;
}
private String getIscsiHost()
{
// If the user has selected an IQN, use the host from that IQN (due to multi-homing,
// this may differ from the host they first entered). Otherwise use the host
// they first entered,
ToStringWrapper wrapper = comboBoxIscsiIqns.SelectedItem as ToStringWrapper;
if (wrapper != null)
return wrapper.item.IpAddress;
return textBoxIscsiHost.Text.Trim();
}
private UInt16 getIscsiPort()
{
ToStringWrapper wrapper = comboBoxIscsiIqns.SelectedItem as ToStringWrapper;
if (wrapper != null)
return wrapper.item.Port;
// No combobox item was selected
UInt16 port;
if (UInt16.TryParse(textBoxIscsiPort.Text, out port))
{
return port;
}
else
{
return Util.DEFAULT_ISCSI_PORT;
}
}
private String getIscsiIQN()
{
ToStringWrapper wrapper = comboBoxIscsiIqns.SelectedItem as ToStringWrapper;
if (wrapper == null)
return "";
else
return wrapper.item.TargetIQN;
}
private void IScsiTargetIqnComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
ToStringWrapper wrapper = comboBoxIscsiIqns.SelectedItem as ToStringWrapper;
ClearLunMapAndCombo();
HideAllErrorIconsAndLabels();
if (wrapper != null)
{
TargetIqnToolTip.SetToolTip(comboBoxIscsiIqns, wrapper.ToString());
IscsiPopulateLUNs();
}
else
{
TargetIqnToolTip.SetToolTip(comboBoxIscsiIqns, Messages.SELECT_TARGET_IQN);
}
}
private String getIscsiLUN()
{
return comboBoxIscsiLuns.Text;
}
private void IscsiUseChapCheckBox_CheckedChanged(object sender, EventArgs e)
{
bool enabled = IscsiUseChapCheckBox.Checked;
IScsiChapUserTextBox.Enabled = enabled;
IScsiChapSecretTextBox.Enabled = enabled;
labelCHAPuser.Enabled = enabled;
IScsiChapSecretLabel.Enabled = enabled;
HideAllErrorIconsAndLabels();
ChapSettings_Changed(null, null);
}
private void scanTargetHostButton_Click(object sender, EventArgs e)
{
HideAllErrorIconsAndLabels();
spinnerIconAtTargetIqn.Visible = false;
spinnerIconAtTargetLun.Visible = false;
spinnerIconAtScanTargetHostButton.StartSpinning();
scanTargetHostButton.Enabled = false;
// For this button to be enabled, we must be Miami or newer
comboBoxIscsiIqns.Items.Clear();
// Clear LUNs as they may no longer be valid
ClearLunMapAndCombo();
// Cancel any LUN scan in progress, as it is no longer meaningful
if (IscsiPopulateLunsAction != null)
{
IscsiPopulateLunsAction.Cancel();
}
UpdateButtons();
if (IscsiUseChapCheckBox.Checked)
{
IscsiPopulateIqnsAction = new ISCSIPopulateIQNsAction(Connection,
getIscsiHost(), getIscsiPort(), IScsiChapUserTextBox.Text, IScsiChapSecretTextBox.Text);
}
else
{
IscsiPopulateIqnsAction = new ISCSIPopulateIQNsAction(Connection,
getIscsiHost(), getIscsiPort(), null, null);
}
IscsiPopulateIqnsAction.Completed += IscsiPopulateIqnsAction_Completed;
controlDisabler.Reset();
controlDisabler.SaveOrUpdateEnabledStates(UserInputControls);
controlDisabler.DisableAllControls();
scanTargetHostButton.Enabled = false;
IscsiPopulateIqnsAction.RunAsync();
}
private void ClearLunMapAndCombo()
{
// Clear LUNs as they may no longer be valid
comboBoxIscsiLuns.Items.Clear();
comboBoxIscsiLuns.Text = "";
comboBoxIscsiLuns.Enabled = false;
targetLunLabel.Enabled = false;
LunMap.Clear();
spinnerIconAtTargetIqn.Visible = false;
spinnerIconAtTargetLun.Visible = false;
UpdateButtons();
}
private void IscsiPopulateIqnsAction_Completed(ActionBase sender)
{
Program.Invoke(this, (System.Threading.WaitCallback)IscsiPopulateIqnsAction_Completed_, sender);
}
private void IscsiPopulateIqnsAction_Completed_(object o)
{
Program.AssertOnEventThread();
ISCSIPopulateIQNsAction action = (ISCSIPopulateIQNsAction)o;
controlDisabler.RestoreEnabledOnAllControls();
if (action.Succeeded)
{
if (action.IQNs.Length == 0)
{
// Do nothing: ActionProgressDialog will show Messages.NEWSR_NO_IQNS_FOUND
}
else
{
int width = comboBoxIscsiIqns.Width;
comboBoxIscsiIqns.Items.Add(Messages.SELECT_TARGET_IQN);
foreach (Actions.IScsiIqnInfo iqnInfo in action.IQNs)
{
if (!String.IsNullOrEmpty(iqnInfo.TargetIQN))
{
String toString = String.Format("{0} ({1}:{2})", iqnInfo.TargetIQN, iqnInfo.IpAddress, iqnInfo.Port);
comboBoxIscsiIqns.Items.Add(new ToStringWrapper(iqnInfo, toString));
width = Math.Max(width, Drawing.MeasureText(toString, comboBoxIscsiIqns.Font).Width);
}
}
// Set the combo box dropdown width to accommodate the widest item (within reason)
comboBoxIscsiIqns.DropDownWidth = Math.Min(width, Int16.MaxValue);
if (comboBoxIscsiIqns.Items.Count > 0)
{
comboBoxIscsiIqns.SelectedItem = Messages.SELECT_TARGET_IQN;
comboBoxIscsiIqns.Enabled = true;
labelIscsiIQN.Enabled = true;
iSCSITargetGroupBox.Enabled = true;
}
spinnerIconAtScanTargetHostButton.DisplaySucceededImage();
comboBoxIscsiIqns.Focus();
}
}
else
{
spinnerIconAtScanTargetHostButton.Visible = false;
Failure failure = action.Exception as Failure;
if (failure != null && failure.ErrorDescription[0] == "SR_BACKEND_FAILURE_140")
{
errorIconAtHostOrIP.Visible = true;
errorLabelAtHostname.Text = Messages.INVALID_HOST;
errorLabelAtHostname.Visible = true;
textBoxIscsiHost.Focus();
}
else if (failure != null && failure.ErrorDescription[0] == "SR_BACKEND_FAILURE_141")
{
errorIconAtHostOrIP.Visible = true;
errorLabelAtHostname.Text = Messages.SR_UNABLE_TO_CONNECT_TO_SCSI_TARGET;
errorLabelAtHostname.Visible = true;
textBoxIscsiHost.Focus();
}
else if (failure != null && failure.ErrorDescription[0] == "SR_BACKEND_FAILURE_68")
{
errorIconAtHostOrIP.Visible = true;
errorLabelAtHostname.Text = Messages.LOGGING_IN_TO_THE_ISCSI_TARGET_FAILED;
errorLabelAtHostname.Visible = true;
textBoxIscsiHost.Focus();
}
else
{
errorIconAtHostOrIP.Visible = true;
errorLabelAtHostname.Text = failure.ErrorDescription.Count > 2 ? failure.ErrorDescription[2] : failure.ErrorDescription[0];
errorLabelAtHostname.Visible = true;
textBoxIscsiHost.Focus();
}
}
scanTargetHostButton.Enabled = true;
}
private void IscsiPopulateLUNs()
{
spinnerIconAtTargetIqn.StartSpinning();
comboBoxIscsiLuns.Items.Clear();
LunMap.Clear();
if (IscsiUseChapCheckBox.Checked)
{
IscsiPopulateLunsAction = new Actions.ISCSIPopulateLunsAction(Connection,
getIscsiHost(), getIscsiPort(), getIscsiIQN(), IScsiChapUserTextBox.Text, IScsiChapSecretTextBox.Text);
}
else
{
IscsiPopulateLunsAction = new Actions.ISCSIPopulateLunsAction(Connection,
getIscsiHost(), getIscsiPort(), getIscsiIQN(), null, null);
}
IscsiPopulateLunsAction.Completed += IscsiPopulateLunsAction_Completed;
controlDisabler.Reset();
controlDisabler.SaveOrUpdateEnabledStates(UserInputControls);
controlDisabler.DisableAllControls();
IscsiPopulateLunsAction.RunAsync();
}
private void IscsiPopulateLunsAction_Completed(ActionBase sender)
{
Program.Invoke(this, (WaitCallback)IscsiPopulateLunsAction_Completed_, sender);
}
private void IscsiPopulateLunsAction_Completed_(object o)
{
Program.AssertOnEventThread();
controlDisabler.RestoreEnabledOnAllControls();
ISCSIPopulateLunsAction action = (ISCSIPopulateLunsAction)o;
if (!action.Succeeded)
{
spinnerIconAtTargetIqn.Visible = false;
Failure failure = action.Exception as Failure;
if (failure != null && failure.ErrorDescription != null && failure.ErrorDescription.Count > 0)
{
if (failure.ErrorDescription[0] == "SR_BACKEND_FAILURE_140")
{
errorIconAtHostOrIP.Visible = true;
errorLabelAtHostname.Text = Messages.INVALID_HOST;
errorLabelAtHostname.Visible = true;
textBoxIscsiHost.Focus();
}
else if (failure.ErrorDescription[0] == "SR_BACKEND_FAILURE_68")
{
errorIconAtCHAPPassword.Visible = true;
errorLabelAtCHAPPassword.Text = Messages.LOGGING_IN_TO_THE_ISCSI_TARGET_FAILED;
errorLabelAtCHAPPassword.Visible = true;
IScsiChapUserTextBox.Focus();
}
else
{
errorIconAtTargetLUN.Visible = true;
errorIconAtTargetLUN.Text = failure.ErrorDescription.Count > 2 ? failure.ErrorDescription[2] : failure.ErrorDescription[0];
errorIconAtTargetLUN.Visible = true;
textBoxIscsiHost.Focus();
}
}
return;
}
if (action.LUNs.Length == 0)
{
// Do nothing: ActionProgressDialog will show Messages.NEWSR_NO_LUNS_FOUND
}
else
{
comboBoxIscsiLuns.Items.Add(Messages.SELECT_TARGET_LUN);
foreach (Actions.ISCSIInfo i in action.LUNs)
{
String label = "LUN";
if (i.LunID != -1)
label += String.Format(" {0}", i.LunID);
if (i.Serial != "")
label += String.Format(": {0}", i.Serial);
if (i.Size >= 0)
label += String.Format(": {0}", Util.DiskSizeString(i.Size));
if (i.Vendor != "")
label += String.Format(" ({0})", i.Vendor);
comboBoxIscsiLuns.Items.Add(label);
LunMap.Add(label, i);
}
comboBoxIscsiLuns.SelectedItem = comboBoxIscsiLuns.Items.Count == 2 ? comboBoxIscsiLuns.Items[1] : Messages.SELECT_TARGET_LUN; //if there is only one choice, select that one by default
comboBoxIscsiLuns.Enabled = true;
targetLunLabel.Enabled = true;
comboBoxIscsiLuns.Focus();
spinnerIconAtTargetIqn.DisplaySucceededImage();
}
comboBoxIscsiLuns.Enabled = true;
comboBoxIscsiIqns.Enabled = true;
UpdateButtons();
}
///
/// Called with the results of an iSCSI SR.probe(), either immediately after the scan, or after the
/// user has performed a scan, clicked 'cancel' on a dialog, and then clicked 'next' again (this
/// avoids duplicate probing if none of the settings have changed).
///
///
/// Whether to continue or not - wheter to format or not is stored in
/// iScsiFormatLUN.
///
private bool ExamineIscsiProbeResults(SrProbeAction action)
{
_srToIntroduce = null;
if (!action.Succeeded)
{
Exception exn = action.Exception;
log.Warn(exn, exn);
Failure failure = exn as Failure;
if (failure != null && failure.ErrorDescription[0] == "SR_BACKEND_FAILURE_140")
{
errorIconAtHostOrIP.Visible = true;
errorLabelAtHostname.Visible = true;
errorLabelAtHostname.Text = Messages.INVALID_HOST;
textBoxIscsiHost.Focus();
}
else if (failure != null)
{
errorIconAtHostOrIP.Visible = true;
errorLabelAtHostname.Visible = true;
errorLabelAtHostname.Text = failure.ErrorDescription.Count > 2 ? failure.ErrorDescription[2] : failure.ErrorDescription[0];
textBoxIscsiHost.Focus();
}
return false;
}
try
{
List SRs = SR.ParseSRListXML(action.Result);
if (!String.IsNullOrEmpty(SrWizardType.UUID))
{
// Check LUN contains correct SR
if (SRs.Count == 1 && SRs[0].UUID == SrWizardType.UUID)
{
_srToIntroduce = SRs[0];
return true;
}
errorIconAtTargetLUN.Visible = true;
errorLabelAtTargetLUN.Visible = true;
errorLabelAtTargetLUN.Text = String.Format(Messages.INCORRECT_LUN_FOR_SR, SrWizardType.SrName);
return false;
}
else if (SRs.Count == 0)
{
// No existing SRs were found on this LUN. If allowed to create new SR, ask the user if they want to proceed and format.
if (!SrWizardType.AllowToCreateNewSr)
{
using (var dlg = new ThreeButtonDialog(
new ThreeButtonDialog.Details(SystemIcons.Error, Messages.NEWSR_LUN_HAS_NO_SRS, Messages.XENCENTER)))
{
dlg.ShowDialog(this);
}
return false;
}
DialogResult result = DialogResult.Yes;
if (!Program.RunInAutomatedTestMode)
{
using (var dlg = new ThreeButtonDialog(
new ThreeButtonDialog.Details(SystemIcons.Warning, Messages.NEWSR_ISCSI_FORMAT_WARNING, this.Text),
ThreeButtonDialog.ButtonYes,
new ThreeButtonDialog.TBDButton(Messages.NO_BUTTON_CAPTION, DialogResult.No, ThreeButtonDialog.ButtonType.CANCEL, true)))
{
result = dlg.ShowDialog(this);
}
}
return result == DialogResult.Yes;
}
else
{
// There should be 0 or 1 SRs on the LUN
System.Diagnostics.Trace.Assert(SRs.Count == 1);
// CA-17230
// Check this isn't a detached SR
SR.SRInfo info = SRs[0];
SR sr = SrWizardHelpers.SrInUse(info.UUID);
if (sr != null)
{
DialogResult res;
using (var d = new ThreeButtonDialog(
new ThreeButtonDialog.Details(null, string.Format(Messages.DETACHED_ISCI_DETECTED, Helpers.GetName(sr.Connection))),
new ThreeButtonDialog.TBDButton(Messages.ATTACH_SR, DialogResult.OK),
ThreeButtonDialog.ButtonCancel))
{
res = d.ShowDialog(Program.MainWindow);
}
if (res == DialogResult.Cancel)
return false;
_srToIntroduce = info;
return true;
}
// An SR exists on this LUN. Ask the user if they want to attach it, format it and
// create a new SR, or cancel.
DialogResult result = Program.RunInAutomatedTestMode ? DialogResult.Yes :
new IscsiChoicesDialog(Connection, info).ShowDialog(this);
switch (result)
{
case DialogResult.Yes:
// Reattach
_srToIntroduce = SRs[0];
return true;
case DialogResult.No:
// Format - SrToIntroduce is already null
return true;
default:
return false;
}
}
}
catch
{
// We really want to prevent the user getting to the next step if there is any kind of
// exception here, since clicking 'finish' might destroy data: require another probe.
return false;
}
}
private void HideAllErrorIconsAndLabels()
{
foreach (var c in ErrorIcons.Concat(ErrorLabels))
c.Visible = false;
}
private void HideAllSpinnerIcons()
{
foreach (var c in SpinnerControls)
c.Visible = false;
}
private Dictionary GetDeviceConfig(SR.SRTypes srType)
{
Dictionary dconf = new Dictionary();
ToStringWrapper iqn = comboBoxIscsiIqns.SelectedItem as ToStringWrapper;
if (iqn == null || !LunMap.ContainsKey(getIscsiLUN()))
return null;
if (srType == SR.SRTypes.gfs2)
{
// build the uri for gfs2
//uri=iscsi://[[%]@][:]//
var chap = "";
if (IscsiUseChapCheckBox.Checked)
{
chap = string.Format(CHAPFORMAT, IScsiChapUserTextBox.Text, IScsiChapSecretTextBox.Text);
}
dconf[URI] = string.Format(URIFORMAT, chap, iqn.item.IpAddress, iqn.item.Port.ToString(), getIscsiIQN(), LunMap[getIscsiLUN()].ScsiID);
return dconf;
}
// Reset target IP address to home address specified in IQN scan.
// Allows multi-homing - see CA-11607
dconf[TARGET] = iqn.item.IpAddress;
dconf[PORT] = iqn.item.Port.ToString();
dconf[TARGETIQN] = getIscsiIQN();
ISCSIInfo info = LunMap[getIscsiLUN()];
if (info.LunID == -1)
{
dconf[LUNSERIAL] = info.Serial;
}
else
{
dconf[SCSIID] = info.ScsiID;
}
if (IscsiUseChapCheckBox.Checked)
{
dconf[CHAPUSER] = IScsiChapUserTextBox.Text;
dconf[CHAPPASSWORD] = IScsiChapSecretTextBox.Text;
}
return dconf;
}
#region Accessors
public SrWizardType SrWizardType { private get; set; }
public string UUID { get { return _srToIntroduce == null ? null : _srToIntroduce.UUID; } }
public long SRSize
{
get
{
ISCSIInfo info = LunMap[getIscsiLUN()];
return info.Size;
}
}
public Dictionary DeviceConfig
{
get
{
return GetDeviceConfig(SRType);
}
}
public string SrDescription
{
get
{
ToStringWrapper iqn = comboBoxIscsiIqns.SelectedItem as ToStringWrapper;
return iqn == null ? null : string.Format(Messages.NEWSR_ISCSI_DESCRIPTION, iqn.item.IpAddress, getIscsiIQN(), getIscsiLUN());
}
}
public SR.SRTypes SRType
{
get
{
return srProvisioningMethod.Lvm ? SR.SRTypes.lvmoiscsi : SR.SRTypes.gfs2;
}
}
#endregion
}
}