Azure Virtual Machine 之 如何利用Management Class Libraries 创建VM
之前发的blog简单的介绍了如何使用Management Class Libraries 来控制Azure platform。
但由于官方并没有提供文档,所以我们只能够通过自己研究来摸索使用该类库的方法。
在使用过程中我发现可以再抽象出一层中间层,从而让该类库的使用更趋近于Management REST API。
下面以创建一个Virtual Machine 为例让我们来了解如何使用该类库来操作Virtual Machine
首先我们要知道,在Azure Platform中,任何一个VM Instance都要运行在一个HostedService 里面的Deployment下面的。
所以在使用过程中我们需要首先创建一个Hosted Service。
我们可以通过以下两个方法来进行创建:
public static void createCloudServiceByLocation(string cloudServiceName, string location) { ComputeManagementClient client = new ComputeManagementClient(getCredentials()); HostedServiceCreateParameters hostedServiceCreateParams = new HostedServiceCreateParameters { ServiceName = cloudServiceName, Location = location, Label = EncodeToBase64(cloudServiceName), }; try { client.HostedServices.Create(hostedServiceCreateParams); } catch (CloudException e) { throw e; } } public static void createCloudServiceByAffinityGroup(string cloudServiceName, string affinityGroupName) { ComputeManagementClient client = new ComputeManagementClient(getCredentials()); HostedServiceCreateParameters hostedServiceCreateParams = new HostedServiceCreateParameters { ServiceName = cloudServiceName, AffinityGroup = affinityGroupName, Label = EncodeToBase64(cloudServiceName), }; try { client.HostedServices.Create(hostedServiceCreateParams); } catch (CloudException e) { throw e; } }
在有了HostedService之后,我们可以通过两种方式来创建VM。
第一种:首先创建一个Deployment,然后再通过添加角色来向这个Deployment中添加Virtual Machine,这样需要与Azure平台交互两次。
第二种:直接调用创建虚拟机部署,这样将在一个Request中创建一个虚拟机的Deployment并且将添加1或多个Virtual Machine到该Deployment下面。
我们可以通过创建自己的Extension Class Library来使得操作更趋向于REST API,一下是我抽象层的代码:
public static class MyVirtualMachineExtension { /// <summary> /// Instantiation a new VM Role /// </summary> public static Role CreateVMRole(this IVirtualMachineOperations client, string cloudServiceName, string roleName, VirtualMachineRoleSize roleSize, string userName, string password, OSVirtualHardDisk osVHD) { Role vmRole = new Role { RoleType = VirtualMachineRoleType.PersistentVMRole.ToString(), RoleName = roleName, Label = roleName, RoleSize = roleSize, ConfigurationSets = new List<ConfigurationSet>(), OSVirtualHardDisk = osVHD }; ConfigurationSet configSet = new ConfigurationSet { ConfigurationSetType = ConfigurationSetTypes.WindowsProvisioningConfiguration, EnableAutomaticUpdates = true, ResetPasswordOnFirstLogon = false, ComputerName = roleName, AdminUserName = userName, AdminPassword = password, InputEndpoints = new BindingList<InputEndpoint> { new InputEndpoint { LocalPort = 3389, Name = "RDP", Protocol = "tcp" }, new InputEndpoint { LocalPort = 80, Port = 80, Name = "web", Protocol = "tcp" } } }; vmRole.ConfigurationSets.Add(configSet); return vmRole; } public static OSVirtualHardDisk CreateOSVHD(this IVirtualMachineImageOperations operation, string cloudserviceName, string vmName, string storageAccount, string imageFamiliyName) { try { var osVHD = new OSVirtualHardDisk { MediaLink = GetVhdUri(string.Format("{0}.blob.core.windows.net/vhds", storageAccount), cloudserviceName, vmName), SourceImageName = GetSourceImageNameByFamliyName(operation, imageFamiliyName) }; return osVHD; } catch (CloudException e) { throw e; } } private static string GetSourceImageNameByFamliyName(this IVirtualMachineImageOperations operation, string imageFamliyName) { var disk = operation.List().Where(o => o.ImageFamily == imageFamliyName).FirstOrDefault(); if (disk != null) { return disk.Name; } else { throw new CloudException(string.Format("Can't find {0} OS image in current subscription")); } } private static Uri GetVhdUri(string blobcontainerAddress, string cloudServiceName, string vmName, bool cacheDisk = false, bool https = false) { var now = DateTime.UtcNow; string dateString = now.Year + "-" + now.Month + "-" + now.Day; var address = string.Format("http{0}://{1}/{2}-{3}-{4}-{5}-650.vhd", https ? "s" : string.Empty, blobcontainerAddress, cloudServiceName, vmName, cacheDisk ? "-CacheDisk" : string.Empty, dateString); return new Uri(address); } public static void CreateVMDeployment(this IVirtualMachineOperations operations, string cloudServiceName, string deploymentName, List<Role> roleList, DeploymentSlot slot = DeploymentSlot.Production) { try { VirtualMachineCreateDeploymentParameters createDeploymentParams = new VirtualMachineCreateDeploymentParameters { Name = deploymentName, Label = cloudServiceName, Roles = roleList, DeploymentSlot = slot }; operations.CreateDeployment(cloudServiceName, createDeploymentParams); } catch (CloudException e) { throw e; } } public static void AddRole(this IVirtualMachineOperations operations, string cloudServiceName, string deploymentName, Role role, DeploymentSlot slot = DeploymentSlot.Production) { try { VirtualMachineCreateParameters createParams = new VirtualMachineCreateParameters { RoleName = role.Label, RoleSize = role.RoleSize, OSVirtualHardDisk = role.OSVirtualHardDisk, ConfigurationSets = role.ConfigurationSets, AvailabilitySetName = role.AvailabilitySetName, DataVirtualHardDisks = role.DataVirtualHardDisks }; operations.Create(cloudServiceName, deploymentName, createParams); } catch (CloudException e) { throw e; } } }
整体programe代码如下:
class Program { public const string base64EncodedCertificate = ""; public const string subscriptionId = ""; public static string vmName = "Azure111"; public static string location = "East Asia"; public static string storageAccountName = "superdino"; public static string userName = "Dino"; public static string password = "PassWord1!"; public static string imageFamiliyName = "Windows Server 2012 Datacenter"; static void Main(string[] args) { ComputeManagementClient client = new ComputeManagementClient(getCredentials()); //You need a hosted service host VM. try { client.HostedServices.Get(vmName); } catch (CloudException e) { createCloudServiceByLocation(vmName, location); } var OSVHD = client.VirtualMachineImages.CreateOSVHD(vmName, vmName, storageAccountName, imageFamiliyName); var VMROle = client.VirtualMachines.CreateVMRole(vmName, vmName, VirtualMachineRoleSize.Small, userName, password, OSVHD); List<Role> roleList = new List<Role>{ VMROle }; client.VirtualMachines.CreateVMDeployment(vmName, vmName, roleList); Console.WriteLine("Create VM success"); client.VirtualMachines.AddRole("CloudServiceName", "ExsitDeploymentName", VMROle); Console.ReadLine(); } public static void createCloudServiceByLocation(string cloudServiceName, string location) { ComputeManagementClient client = new ComputeManagementClient(getCredentials()); HostedServiceCreateParameters hostedServiceCreateParams = new HostedServiceCreateParameters { ServiceName = cloudServiceName, Location = location, Label = EncodeToBase64(cloudServiceName), }; try { client.HostedServices.Create(hostedServiceCreateParams); } catch (CloudException e) { throw e; } } public static void createCloudServiceByAffinityGroup(string cloudServiceName, string affinityGroupName) { ComputeManagementClient client = new ComputeManagementClient(getCredentials()); HostedServiceCreateParameters hostedServiceCreateParams = new HostedServiceCreateParameters { ServiceName = cloudServiceName, AffinityGroup = affinityGroupName, Label = EncodeToBase64(cloudServiceName), }; try { client.HostedServices.Create(hostedServiceCreateParams); } catch (CloudException e) { throw e; } } public static string EncodeToBase64(string toEncode) { byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode); string returnValue = System.Convert.ToBase64String(toEncodeAsBytes); return returnValue; } public static SubscriptionCloudCredentials getCredentials() { return new CertificateCloudCredentials(subscriptionId, new X509Certificate2(Convert.FromBase64String(base64EncodedCertificate))); } }