/* 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 XenAdmin.Core; using XenAPI; namespace XenAdmin.Actions { public class AddHostToPoolAction : PoolAbstractAction { private readonly List _hostsToRelicense; private readonly List _hostsToCpuMask; private readonly List _hostsToAdConfigure; public AddHostToPoolAction(Pool poolToJoin, Host joiningHost, Func getAdCredentials, Func acceptNTolChanges, Action, string> doOnLicensingFailure) : base(joiningHost.Connection, string.Format(Messages.ADDING_SERVER_TO_POOL, joiningHost.Name, poolToJoin.Name), getAdCredentials, acceptNTolChanges, doOnLicensingFailure) { this.Pool = poolToJoin; this.Host = joiningHost; Host master = Helpers.GetMaster(poolToJoin); _hostsToRelicense = new List(); _hostsToCpuMask = new List(); _hostsToAdConfigure = new List(); if (PoolJoinRules.FreeHostPaidMaster(joiningHost, master, false)) _hostsToRelicense.Add(joiningHost); if (!PoolJoinRules.CompatibleCPUs(joiningHost, master, false)) _hostsToCpuMask.Add(joiningHost); if (!PoolJoinRules.CompatibleAdConfig(joiningHost, master, false)) _hostsToAdConfigure.Add(joiningHost); this.Description = Messages.WAITING; AddCommonAPIMethodsToRoleCheck(); // SaveChanges in the ClearNonSharedSrs ApiMethodsToRoleCheck.Add("pool.set_name_label"); ApiMethodsToRoleCheck.Add("pool.set_name_description"); ApiMethodsToRoleCheck.Add("pool.set_other_config"); ApiMethodsToRoleCheck.Add("pool.add_to_other_config"); ApiMethodsToRoleCheck.Add("pool.set_gui_config"); ApiMethodsToRoleCheck.Add("pool.add_to_gui_config"); ApiMethodsToRoleCheck.Add("pool.set_default_SR"); ApiMethodsToRoleCheck.Add("pool.set_suspend_image_SR"); ApiMethodsToRoleCheck.Add("pool.set_crash_dump_SR"); ApiMethodsToRoleCheck.Add("pool.remove_from_other_config"); ApiMethodsToRoleCheck.Add("pool.remove_tags"); ApiMethodsToRoleCheck.Add("pool.set_wlb_enabled"); ApiMethodsToRoleCheck.Add("pool.set_wlb_verify_cert"); ApiMethodsToRoleCheck.Add("pool.join"); } protected override void Run() { this.Description = Messages.POOLCREATE_ADDING; // Use a try catch here for RBAC errors as they are a special case compared to other actions try { FixLicensing(Pool, _hostsToRelicense, DoOnLicensingFailure); FixAd(Pool, _hostsToAdConfigure, GetAdCredentials); bool fixedCpus = FixCpus(Pool, _hostsToCpuMask, AcceptNTolChanges); if (fixedCpus) Session = NewSession(); // We've rebooted the server, so we need to grab the new session RelatedTask = XenAPI.Pool.async_join(Session, Pool.Connection.Hostname, Pool.Connection.Username, Pool.Connection.Password); PollToCompletion(0, 90); } catch (Exception e) { Failure f = e as Failure; // I think we shouldn't trigger this any more, because it's now checked in PoolJoinRules. // But let's leave it here in case. SRET. if (f != null && f.ErrorDescription[0] == Failure.RBAC_PERMISSION_DENIED) { Session[] sessions = new Session[] { Session, Pool.Connection.Session }; // Special parse to cope with multiple connections. Failure.ParseRBACFailure(f, sessions); // Will not get RBAC parsed again after the throw as we have altered the error description in ParseRBACFailure throw f; } throw; } // We need a master session for ClearNonSharedSrs. // No need to log out the slave session, because the server is going to reset its database anyway. Session = NewSession(Pool.Connection); ClearNonSharedSrs(Pool); this.Description = Messages.POOLCREATE_ADDED; } protected override void OnCompleted() { if (Succeeded) { ConnectionsManager.ClearCacheAndRemoveConnection(Host.Connection); } ClearAllDelegates(); base.OnCompleted(); } } }