Example #1
0
        /// <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);
            }
        }
Example #2
0
        /// <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;
        }
Example #3
0
 /// <inheritdoc/>
 public override (string Address, int Port) GetSshEndpoint(string nodeName)
 {
     return(Address : cluster.GetNode(nodeName).PrivateAddress.ToString(), Port : NetworkPorts.SSH);
 }
Example #4
0
        /// <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;
                }
            }
        }