C++調用C#管理Azure虛擬機

    爲了使用自己寫的C++程序管理Azure虛擬機,查了好幾天資料,開始的思路是使用cmd命令調用powershell來管理,寫了幾天腳本後發現cmd下只能運行一些簡單的powershell命令,一套腳本在powershell下運行沒有問題,但是在cmd下使用powershell ./script.p1 就會報一大堆錯,跟微軟的工程師溝通後瞭解到沒有支持C++的SDK,只能使用python、.net等語言進行管理,結合我自身的情況我在python和c#中進行選擇,考慮後決定使用C++調用C#來進行管理,在官方文檔中找到了一套流程,是使用properties文件進行認證加載,但是在運行過程中會報錯,結合微軟工程師給我的文檔,我將我所需求的功能總結出來,全部正常運行後,做成以下內容:

一、設置身份驗證:
1、登錄到powershell,記下有關用戶和訂閱的信息:
Login-AzureRmAccount -Environment "AzureChinaCloud"
2、在powershell中創建服務主體,會返回ApplicationId,注意記錄下來:
# Create the service principal (use a strong password) //自己寫DisplayName和Password的值
$sp = New-AzureRmADServicePrincipal -DisplayName "AzureDotNetTest" -Password "password"
# Give it the permissions it needs...
New-AzureRmRoleAssignment -ServicePrincipalName $sp.ApplicationId -RoleDefinitionName Contributor
# Display the Application ID, because we'll need it later.
$sp | Select DisplayName, ApplicationId
3、記錄所需數據:
subscription:使用運行 Login-AzureRmAccount 後返回的 SubscriptionId 值。
client:使用服務主體輸出中的 ApplicationId 值。
key:使用運行 New-AzureRmADServicePrincipal(不帶引號)時分配的 -Password 參數。
tenant:使用運行 Login-AzureRmAccount 後返回的 TenantId 值。

二、創建新項目
1、創建新的控制檯應用程序項目。 爲此,請在 Visual Studio 中依次單擊“文件”、“新建”、“項目...”。在 Visual C# 模板下選擇“控制檯應用(.NET Core)”,爲項目命名,並單擊“確定”。
創建新的控制檯應用後,依次單擊“工具”、“NuGet 包管理器”、“包管理器控制檯”打開包管理器控制檯。 在控制檯中,執行以下三個命令來獲取所需的包,第一個就足夠我本次對虛擬機的管理了:
# Azure Management Libraries for .NET (Fluent)
Install-Package Microsoft.Azure.Management.Fluent
# Azure Store client libraries
Install-Package WindowsAzure.Storage
# SQL Database client libraries
Install-Package System.Data.SqlClient
2、編輯應用程序的 Program.cs 文件。如果要在新創建的程序中使用,必須加入所需引用,程序如下(我新建立的,將以下程序做成dll由c++調用):

using Microsoft.Azure.Management.Compute.Fluent.Models;
using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpUtil
{
    public class AzureUtil
    {
        public static string subscriptionId = "6fdc7495";
        public static string clientId = "de579e8f";
        public static string clientSecret = "Passw0rd";
        public static string tenantId = "9fc092f5";

        static string groupName = "YangGangRS";
        static string Location = "ChinaEast";
        static string AvSetName = "YangGangAS";
        static string publicIpDnsLabel = "YangGangPublicIP";
        static string networkName = "YangGangVN";
        static string WindowsUserName = "YGAdmin";
        static string WindowsPassword = "Passw0rd1234";
        static string subNetName = "YangGangSubnet";

        static string imageName = "YangGangCSVM-Image";
	//設置各個參數的函數
        public static bool InitializeAzureData(string gName = "YangGangRS", string location = "ChinaEast", string avSetName = "YangGangAS", string pipDnsLabel = "YangGangPublicIP"
            , string networkname = "YangGangVN", string username = "YGAdmin", string passw0rd = "Passw0rd1234", string subnetName = "YangGangSubnet", string iName = "YangGangCSVM-Image")
        {
            try
            {
                groupName = gName;
                Location = location;
                AvSetName = avSetName;
                publicIpDnsLabel = pipDnsLabel;
                networkName = networkname;
                WindowsUserName = username;
                WindowsPassword = passw0rd;
                subNetName = subnetName;

                imageName = iName;
            }
            catch (Exception e)
            {
                return false;
            }
            return true;
        }
	//創建新資源組和第一臺虛擬機
        public static bool CreateNewReourceAndNetworkAndVM(string vmName, string ipAddress)
        {
            try
            {
                string nicName = vmName + "-Nic";

                var credential = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureChinaCloud);
                var azure = Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic).Authenticate(credential).WithDefaultSubscription();

                Console.WriteLine("Creating resource group...");
                var resourceGroup = azure.ResourceGroups.Define(groupName).WithRegion(Location).Create();

                Console.WriteLine("Creating availability set...");
                var availabilitySet = azure.AvailabilitySets.Define(AvSetName).WithRegion(Location).WithExistingResourceGroup(groupName)
                    .WithSku(AvailabilitySetSkuTypes.Managed).Create();

                Console.WriteLine("Creating public IP address...");
                var publicIPAddress = azure.PublicIPAddresses.Define(publicIpDnsLabel).WithRegion(Location).WithExistingResourceGroup(groupName).WithStaticIP().Create();

                Console.WriteLine("Creating virtual network...");
                var network = azure.Networks.Define(networkName).WithRegion(Location).WithExistingResourceGroup(groupName)
                    .WithAddressSpace("10.1.0.0/16").WithSubnet(subNetName, "10.1.1.0/24").Create();

                Console.WriteLine("Creating  network interface ...");
                var networkInterFace = azure.NetworkInterfaces.Define(nicName).WithRegion(Location).WithExistingResourceGroup(groupName).WithExistingPrimaryNetwork(network)
                    .WithSubnet(subNetName)
                    .WithPrimaryPrivateIPAddressStatic(ipAddress)
                    .WithExistingPrimaryPublicIPAddress(publicIPAddress).Create();

                Console.WriteLine("Creating VM...");
                var windowsVM = azure.VirtualMachines.Define(vmName).WithRegion(Location).WithExistingResourceGroup(groupName)
                    .WithExistingPrimaryNetworkInterface(networkInterFace).WithLatestWindowsImage("MicrosoftWindowsServer", "WindowsServer", "2012-R2-Datacenter-zhcn")
                    .WithAdminUsername(WindowsUserName).WithAdminPassword(WindowsPassword).WithComputerName(vmName).WithExistingAvailabilitySet(availabilitySet)
                    .WithSize(VirtualMachineSizeTypes.StandardD2).Create();

                Console.WriteLine("Press enter to continue...");
            }
            catch (Exception e)
            {
                Console.WriteLine("over");
                return false;
            }

            Console.WriteLine("CreateNewReourceAndNetworkAndVM success");
            return true;

        }
	//創建自定義鏡像的虛擬機
        public static bool CreateNextSelfImageVM(string vmName, string ipAddress)
        {
            try
            {
                Console.WriteLine("start");
                string nicName = vmName + "-Nic";
                var credential = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureChinaCloud);
                var azure = Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic).Authenticate(credential).WithDefaultSubscription();

                Console.WriteLine("Creating  network interface ...");
                var network = azure.Networks.GetByResourceGroup(groupName, networkName);
                var networkInterFace = azure.NetworkInterfaces.Define(nicName).WithRegion(Location).WithExistingResourceGroup(groupName).WithExistingPrimaryNetwork(network)
                    .WithSubnet(subNetName)
                    .WithPrimaryPrivateIPAddressStatic(ipAddress)
                    .Create();

                var myImageName = azure.VirtualMachineCustomImages.GetByResourceGroup(groupName, imageName).Id;
                Console.WriteLine("Creating VM...");
                var availabilitySet = azure.AvailabilitySets.GetByResourceGroup(groupName, AvSetName);
                var windowsVM = azure.VirtualMachines.Define(vmName).WithRegion(Location).WithExistingResourceGroup(groupName)
                    .WithExistingPrimaryNetworkInterface(networkInterFace).WithWindowsCustomImage(myImageName)
                    .WithAdminUsername(WindowsUserName).WithAdminPassword(WindowsPassword).WithComputerName(vmName).WithExistingAvailabilitySet(availabilitySet)
                    .WithSize(VirtualMachineSizeTypes.StandardD2V2).Create();
            }
            catch (Exception e)
            {
                Console.WriteLine("over");
                return false;
            }

            Console.WriteLine("CreateNextSelfImageVM success");
            return true;
        }
	//創建官方鏡像虛擬機
        public static bool CreateNextWindowsVM(string vmName, string ipAddress)
        {
            try
            {
                string nicName = vmName + "-Nic";
                var credential = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureChinaCloud);
                var azure = Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic).Authenticate(credential).WithDefaultSubscription();

                Console.WriteLine("Creating  network interface ...");
                var network = azure.Networks.GetByResourceGroup(groupName, networkName);
                var networkInterFace = azure.NetworkInterfaces.Define(nicName).WithRegion(Location).WithExistingResourceGroup(groupName).WithExistingPrimaryNetwork(network)
                    .WithSubnet(subNetName)
                    .WithPrimaryPrivateIPAddressStatic(ipAddress)
                    .Create();

                Console.WriteLine("Creating VM...");
                var availabilitySet = azure.AvailabilitySets.GetByResourceGroup(groupName, AvSetName);
                var windowsVM = azure.VirtualMachines.Define(vmName).WithRegion(Location).WithExistingResourceGroup(groupName)
                    .WithExistingPrimaryNetworkInterface(networkInterFace).WithLatestWindowsImage("MicrosoftWindowsServer", "WindowsServer", "2012-R2-Datacenter-zhcn")
                    .WithAdminUsername(WindowsUserName).WithAdminPassword(WindowsPassword).WithComputerName(vmName).WithExistingAvailabilitySet(availabilitySet)
                    .WithSize(VirtualMachineSizeTypes.StandardD2).Create();
            }
            catch (Exception e)
            {
                Console.WriteLine("over");
                return false;
            }

            Console.WriteLine("CreateNextWindowsVM success");
            return true;
        }
	//停止一臺虛擬機並解除分配
        public static bool StopAzureVM(string vmName)
        {
            try
            {
                var credential = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureChinaCloud);
                var azure = Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic).Authenticate(credential).WithDefaultSubscription();
                var vm = azure.VirtualMachines.GetByResourceGroup(groupName, vmName);
                Console.WriteLine("Stoping vm...");
                vm.Deallocate();
            }
            catch (Exception e)
            {
                Console.WriteLine("over");
                return false;
            }

            Console.WriteLine("StopAzureVM success");
            return true;
        }
	//開啓一臺虛擬機
        public static bool StartAzureVM(string vmName)
        {
            try
            {
                var credential = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureChinaCloud);
                var azure = Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic).Authenticate(credential).WithDefaultSubscription();

                var vm = azure.VirtualMachines.GetByResourceGroup(groupName, vmName);
                Console.WriteLine("Starting vm...");
                vm.Start();
            }
            catch (Exception e)
            {
                Console.WriteLine("over");
                return false;
            }
            Console.WriteLine("StartAzureVM success");
            return true;
        }
	//改變虛擬機大小
        public static bool ChangeVMSize(string vmName)
        {
            try
            {
                var credential = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureChinaCloud);
                var azure = Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic).Authenticate(credential).WithDefaultSubscription();

                var vm = azure.VirtualMachines.GetByResourceGroup(groupName, vmName);
                Console.WriteLine("Starting change vm size...");
                vm.Update().WithSize(VirtualMachineSizeTypes.StandardD2).Apply();
            }
            catch (Exception e)
            {
                Console.WriteLine("over");
                return false;
            }
            Console.WriteLine("ChangeVMSize success");
            return true;
        }

        public static void Main(string[] args)
        {
            //CreateNewReourceAndNetworkAndVM(vmName, ipAddress);
            string vmName = "YangGangCSVM1";
            string ipAddress = "10.1.1.11";
            CreateNextSelfImageVM(vmName, ipAddress);
        }

    }
}
    上方的幾個命令基本可以滿足我的虛擬機管理需求,還有更多的功能可以點出來,針對虛擬機,鏡像和其他資源的操作。

    在C++程序中,我使用以下方法使用這些函數,這裏只舉了一個例子,其他類似:

#using "..\\apps\\x64\\Debug\\CSharpUtil.dll"
using namespace CSharpUtil;
using namespace System;
using namespace std;

DLL_API bool CreateNextSelfImageVM(const wchar_t *wcvmName,const wchar_t *wcipAddress){
	AzureUtil ^azureUtil=gcnew AzureUtil;
	String ^wstrvmName=gcnew String(wcvmName);
	String ^wstripAddress=gcnew String(wcipAddress);
	return azureUtil->CreateNextSelfImageVM(wstrvmName,wstripAddress);
}
    所有函數均以bool值返回,如果創建失敗會catch到出錯,返回false。沒有事物的概念,可能網卡創建成功,但是虛擬機創建失敗,這些我都是進行手動管理的,在利用redis管理虛擬機信息後,只要保證數據不出錯且網絡不中斷,基本上不會出錯。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章