/* 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.Text.RegularExpressions; using System.Threading; using XenAdmin; using XenAdmin.Core; using XenAdmin.Network; namespace XenAPI { partial class PBD { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static bool WaitForPlug(Session session, string pbdOpaqueRef) { int timeout = 120; //Wait 2 min for PBD to plug while (timeout > 0) { if (PBD.get_currently_attached(session, pbdOpaqueRef)) return true; Thread.Sleep(1000); timeout--; } return false; } public static void CheckPlugPBDsForVMs(IXenConnection connection, List> vmRefs, bool ignoreFailure = false) { var pbds = new List(); foreach (XenRef vmRef in vmRefs) { VM vm = connection.TryResolveWithTimeout(vmRef); foreach (var vbdRef in vm.VBDs) { var vbd = connection.Resolve(vbdRef); if (vbd == null) continue; VDI vdi = connection.Resolve(vbd.VDI); if (vdi == null) continue; SR sr = connection.Resolve(vdi.SR); if (sr == null) continue; foreach (var pbdRef in sr.PBDs) { var pbd = connection.Resolve(pbdRef); if (pbd != null && !pbds.Contains(pbd)) pbds.Add(pbd); } } } foreach (PBD pbd in pbds) { Session session = pbd.Connection.DuplicateSession(); log.DebugFormat("Waiting for PBDs {0} to become plugged", pbd.Name()); // Wait 2 min for PBD to become plugged if (WaitForPlug(session, pbd.opaque_ref)) continue; // if it's still unplugged, try plugging it - this will probably // fail, but at least we'll get a better error message. try { log.DebugFormat("Plugging PBD {0}", pbd.Name()); plug(session, pbd.opaque_ref); } catch (Exception e) { log.Debug(string.Format("Error plugging PBD {0}", pbd.Name()), e); if (!ignoreFailure) throw; } } } public bool MultipathActive() { return BoolKey(other_config, "multipathed"); } /// /// The number of iSCSI sessions in use, as advertised by the SR backend, or -1 if the value is missing. /// public int ISCSISessions() { return IntKey(other_config, "iscsi_sessions", -1); } private static readonly Regex multipathCountRegex = new Regex(@"\[(\d+)L?,\s(\d+)L?"); public static bool ParsePathCounts(String input, out int currentPaths, out int maxPaths) { currentPaths = 0; maxPaths = 0; Match match = multipathCountRegex.Match(input); return match.Success && match.Groups.Count == 3 && int.TryParse(match.Groups[1].Value, out currentPaths) && int.TryParse(match.Groups[2].Value, out maxPaths); } /// /// The status of the PBD as a friendly string (unplugged, host down, connected) /// public string StatusString() { if (!currently_attached) return Messages.REPAIR_SR_DIALOG_UNPLUGGED; Host h = Connection.Resolve(host); if (h == null) return Messages.REPAIR_SR_DIALOG_UNPLUGGED; if (!h.IsLive()) return Messages.HOST_NOT_LIVE; return Messages.CONNECTED; } public StorageLinkCredentials GetStorageLinkCredentials() { var deviceConfig = new Dictionary(device_config); SR sr = Connection.Resolve(SR); if (sr != null && sr.type == "cslg") { string host, username, passwordSecret; deviceConfig.TryGetValue("target", out host); deviceConfig.TryGetValue("username", out username); deviceConfig.TryGetValue("password_secret", out passwordSecret); return new StorageLinkCredentials(Connection, host, username, null, passwordSecret); } return null; } } }