/// <summary> /// Creates a virtual machine in Azure. /// Creates all the required resources before creating VM. /// </summary> /// <param name="subscriptionId">Subscription Id</param> /// <param name="credentialName">Internet name/address used to identify entry in Credential Manager</param> /// <param name="appId">appid that is registered for this application in Azure Active Directory (AAD)</param> /// <param name="customerTenantId">Id or Domain of the customer Azure tenant</param> private static void CreateAzureVirtualMachine(string appId, string credentialName, string customerTenantId, string subscriptionId) { // Get Azure Authentication Token string azureToken = Reseller.GetAzureAuthTokenForCustomerTenant(appId, credentialName, customerTenantId); // Correlation Id to be used for this scenaario var correlationId = Guid.NewGuid().ToString(); var resourceGroupName = Guid.NewGuid().ToString(); // Appending suffix to resource group name to build names of other resources // Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only. // So removing hyphen and truncating. var storageAccountName = String.Format("{0}sa", resourceGroupName.Replace("-", "").Remove(20)); var networkSecurityGroupName = String.Format("{0}_nsg", resourceGroupName); var networkSecurityGroupId = String.Format( "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Network/networkSecurityGroups/{2}", subscriptionId, resourceGroupName, networkSecurityGroupName); var virtualNetworkName = String.Format("{0}_vn", resourceGroupName); var subnetName = String.Format("{0}_sn", resourceGroupName); var subNetId = String.Format( "/subscriptions/{0}/resourceGroups/{1}/providers/microsoft.network/virtualNetworks/{2}/subnets/{3}", subscriptionId, resourceGroupName, virtualNetworkName, subnetName); var publicIpName = String.Format("{0}_pip", resourceGroupName); var publicIpId = String.Format( "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Network/publicIPAddresses/{2}", subscriptionId, resourceGroupName, publicIpName); var networkInterfaceName = String.Format("{0}_nic", resourceGroupName); var networkInterfaceId = String.Format( "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Network/networkInterfaces/{2}", subscriptionId, resourceGroupName, networkInterfaceName); var ipName = String.Format("{0}_ip", resourceGroupName); var vitualMachineName = String.Format("{0}_vm", resourceGroupName); // Waiting Time (in seconds) For Resource to be Provisioned var retryAfter = 5; // Retry attempts for resource provisioning errors var retryAttempts = 5; var attempts = 0; // The following resources are to be created in order before creating a virtual machine. // #1 Create Resource Group do { var createResourceGroupResponse = AzureResourceManager.CreateResourceGroup(subscriptionId, resourceGroupName, azureToken, correlationId); if (createResourceGroupResponse == null) { attempts++; } else { attempts = retryAttempts + 1; // Waiting for the resource group to be created, if the request is just Accepted and the creation is still pending. if ((int)(createResourceGroupResponse.StatusCode) == (int)HttpStatusCode.Accepted) { AzureResourceManager.WaitForResourceGroupProvisioning(subscriptionId, resourceGroupName, retryAfter, azureToken, correlationId); } } } while (attempts < retryAttempts); // #2 Create Storage Account // Register the subscription with Storage Resource Provider, for creating Storage Account // Storage Resource Provider const string storageProviderName = "Microsoft.Storage"; AzureResourceManager.RegisterProvider(subscriptionId, storageProviderName, azureToken, correlationId); attempts = 0; do { var storageAccountResponse = AzureResourceManager.CreateStorageAccount(subscriptionId, resourceGroupName, storageAccountName, azureToken, correlationId); if (storageAccountResponse == null) { attempts++; } else { attempts = retryAttempts + 1; // Waiting for the storage account to be created, if the request is just Accepted and the creation is still pending. if ((int)(storageAccountResponse.StatusCode) == (int)HttpStatusCode.Accepted) { var location = storageAccountResponse.Headers.Get("Location"); retryAfter = Int32.Parse(storageAccountResponse.Headers.Get("Retry-After")); AzureResourceManager.WaitForStorageAccountProvisioning(location, resourceGroupName, retryAfter, azureToken, correlationId); } } } while (attempts < retryAttempts); // Register the subscription with Network Resource Provider for creating Network Resources - Netowrk Securtiy Group, Virtual Network, Subnet, Public IP and Network Interface // Network Resource Provider const string networkProviderName = "Microsoft.Network"; AzureResourceManager.RegisterProvider(subscriptionId, networkProviderName, azureToken, correlationId); // #3 Create Network Security Group attempts = 0; do { var networkSecurityGroupResponse = AzureResourceManager.CreateNetworkSecurityGroup(subscriptionId, resourceGroupName, networkSecurityGroupName, azureToken, correlationId); if (networkSecurityGroupResponse == null) { attempts++; } else { attempts = retryAttempts + 1; // Waiting for the network security group to be created, if the request is just Accepted and the creation is still pending. if ((int)(networkSecurityGroupResponse.StatusCode) == (int)HttpStatusCode.Accepted) { AzureResourceManager.WaitForNetworkSecurityGroupProvisioning(subscriptionId, resourceGroupName, networkSecurityGroupName, retryAfter, azureToken, correlationId); } } } while (attempts < retryAttempts); // #4 Create Virtual Network attempts = 0; do { var virtualNetworkResponse = AzureResourceManager.CreateVirtualNetwork(subscriptionId, resourceGroupName, virtualNetworkName, azureToken, correlationId); if (virtualNetworkResponse == null) { attempts++; } else { attempts = retryAttempts + 1; // Waiting for the virtual network to be created, if the request is just Accepted and the creation is still pending. if ((int)(virtualNetworkResponse.StatusCode) == (int)HttpStatusCode.Accepted) { AzureResourceManager.WaitForVirtualNetworkProvisioning(subscriptionId, resourceGroupName, virtualNetworkName, retryAfter, azureToken, correlationId); } } } while (attempts < retryAttempts); // #5 Create Subnet attempts = 0; do { var subNetResponse = AzureResourceManager.CreateSubNet(subscriptionId, resourceGroupName, virtualNetworkName, networkSecurityGroupId, subnetName, azureToken, correlationId); if (subNetResponse == null) { attempts++; } else { attempts = retryAttempts + 1; // Waiting for the subnet to be created, if the request is just Accepted and the creation is still pending. if ((int)(subNetResponse.StatusCode) == (int)HttpStatusCode.Accepted) { AzureResourceManager.WaitForSubNetProvisioning(subscriptionId, resourceGroupName, virtualNetworkName, subnetName, retryAfter, azureToken, correlationId); } } } while (attempts < retryAttempts); // #6 Create Public IP Address attempts = 0; do { var publicIpResponse = AzureResourceManager.CreatePublicIpAddress(subscriptionId, resourceGroupName, publicIpName, azureToken, correlationId); if (publicIpResponse == null) { attempts++; } else { attempts = retryAttempts + 1; // Waiting for the public IP to be created, if the request is just Accepted and the creation is still pending. if ((int)(publicIpResponse.StatusCode) == (int)HttpStatusCode.Accepted) { AzureResourceManager.WaitForPublicIpProvisioning(subscriptionId, resourceGroupName, publicIpName, retryAfter, azureToken, correlationId); } } } while (attempts < retryAttempts); // #7 Create Network Interface attempts = 0; do { var networkInterfaceResponse = AzureResourceManager.CreateNetworkInterface(subscriptionId, resourceGroupName, networkInterfaceName, networkSecurityGroupId, ipName, publicIpId, subNetId, azureToken, correlationId); if (networkInterfaceResponse == null) { attempts++; } else { attempts = retryAttempts + 1; // Waiting for the network interface to be created, if the request is just Accepted and the creation is still pending. if ((int)(networkInterfaceResponse.StatusCode) == (int)HttpStatusCode.Accepted) { AzureResourceManager.WaitForNetworkInterfaceProvisioning(subscriptionId, resourceGroupName, networkInterfaceName, retryAfter, azureToken, correlationId); } } } while (attempts < retryAttempts); // #8 Create Azure Virtual Machine // Compute Resource Provider const string computeProviderName = "Microsoft.Compute"; AzureResourceManager.RegisterProvider(subscriptionId, computeProviderName, azureToken, correlationId); var virtualMachineResponse = AzureResourceManager.CreateVirtualMachine(subscriptionId, resourceGroupName, networkInterfaceId, storageAccountName, vitualMachineName, azureToken, correlationId); if (virtualMachineResponse == null) { return; } // #9 Create a New User var newUserInfo = User.PopulateUserFromConsole(); var newUser = AzureResourceManager.CreateUser(newUserInfo.displayName, newUserInfo.mailNickname, newUserInfo.userPrincipalName, newUserInfo.password, azureToken, correlationId); // #10 Add user to Owner role // Register the subscription with Authorization Provider const string authorizationProviderName = "Microsoft.Authorization"; var registrationResult = AzureResourceManager.RegisterProvider(subscriptionId, authorizationProviderName, azureToken, correlationId); // Role Id for Role 'Owner' const string roleIdForOwner = "8e3af657-a8ff-443c-a75c-2fe8c4bcb635"; var scope = String.Format("/subscriptions/{0}", subscriptionId); // Assigning 'Owner' role to the new user var roleAssignment = AzureResourceManager.CreateRoleAssignment(azureToken, scope, newUser.objectId, roleIdForOwner, correlationId); }