/// <inheritdoc/> public override void Run(ClusterProxy cluster) { Covenant.Requires <ArgumentNullException>(cluster != null, nameof(cluster)); var node = cluster.GetNode(nodeName); if (operationName != null) { node.InvokeIdempotentAction(operationName, () => action(node)); } else { action(node); } }
/// <inheritdoc/> public override void Run(ClusterProxy cluster) { Covenant.Requires <ArgumentNullException>(cluster != null, nameof(cluster)); var node = cluster.GetNode(nodeName); var status = this.ToString(); node.UploadText(path, text, tabStop, outputEncoding); if (!string.IsNullOrEmpty(permissions)) { node.SudoCommand("chmod", permissions, path); } StatusPause(); node.Status = string.Empty; }
/// <inheritdoc/> public override (string Address, int Port) GetSshEndpoint(string nodeName) { return(Address : cluster.GetNode(nodeName).PrivateAddress.ToString(), Port : NetworkPorts.SSH); }
/// <summary> /// Provision the virtual machines on the XenServer. /// </summary> /// <param name="xenSshProxy">The XenServer SSH proxy.</param> private void ProvisionVirtualMachines(SshProxy <XenClient> xenSshProxy) { var xenHost = xenSshProxy.Metadata; foreach (var node in GetHostedNodes(xenHost)) { var vmName = GetVmName(node); var processors = node.Metadata.GetVmProcessors(cluster.Definition); var memoryBytes = node.Metadata.GetVmMemory(cluster.Definition); var diskBytes = node.Metadata.GetVmDisk(cluster.Definition); xenSshProxy.Status = FormatVmStatus(vmName, "create: virtual machine"); // We need to create a raw drive if the node hosts a Ceph OSD. var extraDrives = new List <XenVirtualDrive>(); if (node.Metadata.Labels.CephOSD) { extraDrives.Add( new XenVirtualDrive() { Size = node.Metadata.GetCephOSDDriveSize(cluster.Definition) }); } var vm = xenHost.Machine.Create(vmName, cluster.Definition.Hosting.XenServer.TemplateName, processors: processors, memoryBytes: memoryBytes, diskBytes: diskBytes, snapshot: cluster.Definition.Hosting.XenServer.Snapshot, extraDrives: extraDrives, primaryStorageRepository: cluster.Definition.Hosting.XenServer.StorageRepository, extraStorageRespository: cluster.Definition.Hosting.XenServer.OsdStorageRepository); xenSshProxy.Status = FormatVmStatus(vmName, "start: virtual machine"); xenHost.Machine.Start(vm); // We need to wait for the virtual machine to start and obtain // and IP address via DHCP. var address = string.Empty; xenSshProxy.Status = FormatVmStatus(vmName, "discover: ip address"); try { NeonHelper.WaitFor( () => { while (true) { vm = xenHost.Machine.Find(vmName); if (!string.IsNullOrEmpty(vm.Address)) { address = vm.Address; return(true); } Thread.Sleep(1000); } }, TimeSpan.FromMinutes(3)); } catch (TimeoutException) { xenSshProxy.Fault("Timeout waiting for virtual machine to start and set an IP address."); } // SSH into the VM using the DHCP address, configure the static IP // address and extend the primary partition and file system to fill // the drive and then reboot. var subnet = NetworkCidr.Parse(cluster.Definition.Network.PremiseSubnet); // We're going to temporarily set the node to the current VM address // so we can connect via SSH. var nodePrivateAddress = node.PrivateAddress; try { node.PrivateAddress = IPAddress.Parse(address); using (var nodeProxy = cluster.GetNode(node.Name)) { xenSshProxy.Status = FormatVmStatus(vmName, "connect"); nodeProxy.WaitForBoot(); // Configure the node's network stack to the static IP address // and upstream nameservers. node.Status = $"network config [IP={nodePrivateAddress}]"; var primaryInterface = node.GetNetworkInterface(node.PrivateAddress); node.ConfigureNetwork( networkInterface: primaryInterface, address: nodePrivateAddress, gateway: IPAddress.Parse(cluster.Definition.Network.Gateway), subnet: NetworkCidr.Parse(cluster.Definition.Network.PremiseSubnet), nameservers: cluster.Definition.Network.Nameservers.Select(ns => IPAddress.Parse(ns))); // Extend the primary partition and file system to fill // the virtual the drive. xenSshProxy.Status = FormatVmStatus(vmName, $"resize: primary drive"); // $hack(jeff.lill): // // I've seen a transient error here but can't reproduce it. I'm going // to assume for now that the file system might not be quite ready for // this operation directly after the VM has been rebooted, so we're going // to delay for a few seconds before performing the operations. Thread.Sleep(TimeSpan.FromSeconds(5)); nodeProxy.SudoCommand("growpart /dev/xvda 2"); nodeProxy.SudoCommand("resize2fs /dev/xvda2"); // Reboot to pick up the changes. xenSshProxy.Status = FormatVmStatus(vmName, "restarting..."); nodeProxy.Reboot(wait: false); } } finally { // Restore the node's IP address. node.PrivateAddress = nodePrivateAddress; } } }