public static VolumeGroupDetails CreateVolumeGroup(AzureNetAppFilesManagementClient netAppMgmtClient, string volumeGroupName = volumeGroupName1, string poolName = poolName1, string accountName = accountName1, string resourceGroup = resourceGroup, string location = vgLocation, List <string> protocolTypes = null, IDictionary <string, string> tags = default(IDictionary <string, string>), VolumePropertiesExportPolicy exportPolicy = null, string vnet = vgVnet, bool volumeGroupOnly = false, string snapshotId = null, string snapshotPolicyId = null, string backupVnetLocation = "", long poolSize = 4398046511104) { CapacityPool pool = null; if (!volumeGroupOnly) { pool = CreatePool(netAppMgmtClient, poolName, accountName, resourceGroup: resourceGroup, location: location, poolSize: poolSize, qosType: QosType.Manual); } var defaultProtocolType = new List <string>() { "NFSv4.1" }; var volumeProtocolTypes = protocolTypes == null ? defaultProtocolType : protocolTypes; if (exportPolicy == null) { exportPolicy = new VolumePropertiesExportPolicy { Rules = new List <ExportPolicyRule>() { new ExportPolicyRule { Nfsv3 = false, Nfsv41 = true, RuleIndex = 1, AllowedClients = "0.0.0.0/0" }, new ExportPolicyRule { Nfsv3 = false, Nfsv41 = true, RuleIndex = 2, AllowedClients = "0.0.0.0/0" } } }; } var volumeGroupVolumeProperties = new List <VolumeGroupVolumeProperties> { new VolumeGroupVolumeProperties { Name = $"{volumeGroupName}-log-1", VolumeSpecName = "log", CapacityPoolResourceId = pool.Id, ProximityPlacementGroup = proximityPlacementGroup, UsageThreshold = 100 * gibibyte, ThroughputMibps = 6, ProtocolTypes = volumeProtocolTypes, CreationToken = $"{volumeGroupName}-log-1", SubnetId = "/subscriptions/" + netAppMgmtClient.SubscriptionId + "/resourceGroups/" + resourceGroup + "/providers/Microsoft.Network/virtualNetworks/" + vnet + "/subnets/default", Tags = tags, ExportPolicy = exportPolicy }, new VolumeGroupVolumeProperties { Name = $"{volumeGroupName}-DataBackup-2", VolumeSpecName = "data-backup", CapacityPoolResourceId = pool.Id, ProximityPlacementGroup = proximityPlacementGroup, ThroughputMibps = 6, UsageThreshold = 100 * gibibyte, ProtocolTypes = volumeProtocolTypes, CreationToken = $"{volumeGroupName}-DataBackup-2", SubnetId = "/subscriptions/" + netAppMgmtClient.SubscriptionId + "/resourceGroups/" + resourceGroup + "/providers/Microsoft.Network/virtualNetworks/" + vnet + "/subnets/default", Tags = tags, ExportPolicy = exportPolicy }, new VolumeGroupVolumeProperties { Name = $"{volumeGroupName}-DataVol-3", VolumeSpecName = "data", ProximityPlacementGroup = proximityPlacementGroup, CapacityPoolResourceId = pool.Id, ThroughputMibps = 6, UsageThreshold = 100 * gibibyte, ProtocolTypes = volumeProtocolTypes, CreationToken = $"{volumeGroupName}-DataVol-3", SubnetId = "/subscriptions/" + netAppMgmtClient.SubscriptionId + "/resourceGroups/" + resourceGroup + "/providers/Microsoft.Network/virtualNetworks/" + vnet + "/subnets/default", Tags = tags, ExportPolicy = exportPolicy } }; var volumeGroup = new VolumeGroupDetails() { Location = location, Tags = tags, GroupMetaData = new VolumeGroupMetaData() { ApplicationType = ApplicationType.SAPHANA, ApplicationIdentifier = "SH1", GlobalPlacementRules = new List <PlacementKeyValuePairs> { new PlacementKeyValuePairs { Key = "Key1", Value = "value1" } }, DeploymentSpecId = SAPHANAOnGENPOPDeploymentSpecID, GroupDescription = "group description" }, Volumes = volumeGroupVolumeProperties }; var resource = netAppMgmtClient.VolumeGroups.Create(volumeGroup, resourceGroup, accountName, volumeGroupName); Assert.Equal(accountName + '/' + volumeGroupName, resource.Name); if (Environment.GetEnvironmentVariable("AZURE_TEST_MODE") == "Record") { Thread.Sleep(delay); // some robustness against ARM caching } return(resource); }
private VolumeGroupDetails CreateHostVolumeGroup(string name, string sid, string poolResourceId, IDictionary <string, string> tagPairs, string[] volumeBackupProtocolTypes, VolumePropertiesExportPolicy volumeExportPolicy, int startingHostId, int hostCount) { var dataUsageThreshold = this.DataSize ?? CalulateUsageThreshold(NodeMemory, CapacityOverhead, this.HostCount, null, null, SapVolumeType.Data); var logUsageThreshold = this.LogSize ?? CalulateUsageThreshold(NodeMemory, CapacityOverhead, this.HostCount, null, null, SapVolumeType.Log); var sharedUsageThreshold = this.SharedSize ?? CalulateUsageThreshold(NodeMemory, CapacityOverhead, this.HostCount, dataUsageThreshold, logUsageThreshold, SapVolumeType.Shared); var logBackupdUsageThreshold = this.LogBackupSize ?? CalulateUsageThreshold(NodeMemory, CapacityOverhead, this.HostCount, dataUsageThreshold, logUsageThreshold, SapVolumeType.LogBackup); var dataBackupUsageThreshold = this.DataBackupSize ?? CalulateUsageThreshold(NodeMemory, CapacityOverhead, this.HostCount, dataUsageThreshold, logUsageThreshold, SapVolumeType.DataBackup); var dataThroughput = this.DataPerformance ?? CalculateThroughput(NodeMemory, SapVolumeType.Data); var logThroughput = this.LogPerformance ?? CalculateThroughput(NodeMemory, SapVolumeType.Log); var sharedThroughput = this.SharedPerformance ?? CalculateThroughput(NodeMemory, SapVolumeType.Shared); var logBackupThroughput = this.LogBackupPerformance ?? CalculateThroughput(NodeMemory, SapVolumeType.LogBackup); var dataBackupThroughput = this.DataBackupPerformance ?? CalculateThroughput(NodeMemory, SapVolumeType.DataBackup); List <VolumeGroupVolumeProperties> volumesInGroup = new List <VolumeGroupVolumeProperties>(); for (int i = 0; i < hostCount; i++) { int currentHostCount = i + 1; string dataVolumeName = GenerateVolumeName(ApplicationIdentifier, SapVolumeType.Data, currentHostCount, SystemRole, Prefix); string logVolumeName = GenerateVolumeName(ApplicationIdentifier, SapVolumeType.Log, currentHostCount, SystemRole, Prefix); string sharedVolumeName = GenerateVolumeName(ApplicationIdentifier, SapVolumeType.Shared, currentHostCount, SystemRole, Prefix); string logBackupVolumeName = GenerateVolumeName(ApplicationIdentifier, SapVolumeType.LogBackup, currentHostCount, SystemRole, Prefix); string dataBackupVolumeName = GenerateVolumeName(ApplicationIdentifier, SapVolumeType.DataBackup, currentHostCount, SystemRole, Prefix); var dataVolume = new VolumeGroupVolumeProperties { Name = dataVolumeName, VolumeSpecName = SapVolumeType.Data, CapacityPoolResourceId = poolResourceId, ProximityPlacementGroup = ProximityPlacementGroup, UsageThreshold = dataUsageThreshold, ThroughputMibps = dataThroughput, ProtocolTypes = DefaultProtocoTypes, CreationToken = dataVolumeName, SubnetId = SubnetId, Tags = tagPairs, ExportPolicy = volumeExportPolicy }; volumesInGroup.Add(dataVolume); var logVolume = new VolumeGroupVolumeProperties { Name = logVolumeName, VolumeSpecName = SapVolumeType.Log, CapacityPoolResourceId = poolResourceId, ProximityPlacementGroup = ProximityPlacementGroup, ThroughputMibps = logThroughput, UsageThreshold = logUsageThreshold, ProtocolTypes = DefaultProtocoTypes, CreationToken = logVolumeName, SubnetId = SubnetId, Tags = tagPairs, ExportPolicy = volumeExportPolicy }; volumesInGroup.Add(logVolume); //Shared, Log backup and Data backup only created for HostID==1. if (currentHostCount == 1) { var sharedVolume = new VolumeGroupVolumeProperties { Name = sharedVolumeName, VolumeSpecName = SapVolumeType.Shared, CapacityPoolResourceId = poolResourceId, ProximityPlacementGroup = ProximityPlacementGroup, ThroughputMibps = sharedThroughput, UsageThreshold = sharedUsageThreshold, ProtocolTypes = DefaultProtocoTypes, CreationToken = sharedVolumeName, SubnetId = SubnetId, Tags = tagPairs, ExportPolicy = volumeExportPolicy }; volumesInGroup.Add(sharedVolume); var logBackupVolume = new VolumeGroupVolumeProperties { Name = logBackupVolumeName, VolumeSpecName = SapVolumeType.LogBackup, CapacityPoolResourceId = poolResourceId, ProximityPlacementGroup = ProximityPlacementGroup, ThroughputMibps = logBackupThroughput, UsageThreshold = logBackupdUsageThreshold, ProtocolTypes = volumeBackupProtocolTypes, CreationToken = logBackupVolumeName, SubnetId = SubnetId, Tags = tagPairs, ExportPolicy = volumeExportPolicy }; volumesInGroup.Add(logBackupVolume); var dataBackupVolume = new VolumeGroupVolumeProperties { Name = dataBackupVolumeName, VolumeSpecName = SapVolumeType.DataBackup, CapacityPoolResourceId = poolResourceId, ProximityPlacementGroup = ProximityPlacementGroup, ThroughputMibps = dataBackupThroughput, UsageThreshold = dataBackupUsageThreshold, ProtocolTypes = volumeBackupProtocolTypes, CreationToken = dataBackupVolumeName, SubnetId = SubnetId, Tags = tagPairs, ExportPolicy = volumeExportPolicy }; volumesInGroup.Add(dataBackupVolume); } } var volumeGroup = new VolumeGroupDetails() { Location = Location, GroupMetaData = new VolumeGroupMetaData() { ApplicationType = ApplicationType, ApplicationIdentifier = ApplicationIdentifier, GlobalPlacementRules = GlobalPlacementRule, DeploymentSpecId = SAPHANAOnGENPOPDeploymentSpecID, GroupDescription = GroupDescription }, Volumes = volumesInGroup }; return(volumeGroup); }
/// <summary> /// Create the specified volume group and volumes. Creating volume group will /// create all the volumes specified in request body implicitly. Once volumes /// are created using volume group, those will be treated as regular volumes /// thereafter. /// </summary> /// <remarks> /// Create a volume group along with specified volumes /// </remarks> /// <param name='operations'> /// The operations group for this extension method. /// </param> /// <param name='body'> /// Volume Group object supplied in the body of the operation. /// </param> /// <param name='resourceGroupName'> /// The name of the resource group. /// </param> /// <param name='accountName'> /// The name of the NetApp account /// </param> /// <param name='volumeGroupName'> /// The name of the volumeGroup /// </param> /// <param name='cancellationToken'> /// The cancellation token. /// </param> public static async Task <VolumeGroupDetails> BeginCreateAsync(this IVolumeGroupsOperations operations, VolumeGroupDetails body, string resourceGroupName, string accountName, string volumeGroupName, CancellationToken cancellationToken = default(CancellationToken)) { using (var _result = await operations.BeginCreateWithHttpMessagesAsync(body, resourceGroupName, accountName, volumeGroupName, null, cancellationToken).ConfigureAwait(false)) { return(_result.Body); } }
/// <summary> /// Create the specified volume group and volumes. Creating volume group will /// create all the volumes specified in request body implicitly. Once volumes /// are created using volume group, those will be treated as regular volumes /// thereafter. /// </summary> /// <remarks> /// Create a volume group along with specified volumes /// </remarks> /// <param name='operations'> /// The operations group for this extension method. /// </param> /// <param name='body'> /// Volume Group object supplied in the body of the operation. /// </param> /// <param name='resourceGroupName'> /// The name of the resource group. /// </param> /// <param name='accountName'> /// The name of the NetApp account /// </param> /// <param name='volumeGroupName'> /// The name of the volumeGroup /// </param> public static VolumeGroupDetails BeginCreate(this IVolumeGroupsOperations operations, VolumeGroupDetails body, string resourceGroupName, string accountName, string volumeGroupName) { return(operations.BeginCreateAsync(body, resourceGroupName, accountName, volumeGroupName).GetAwaiter().GetResult()); }
/// <summary> /// Create the specified volume group and volumes. Creating volume group will /// create all the volumes specified in request body implicitly. Once volumes /// are created using volume group, those will be treated as regular volumes /// thereafter. /// </summary> /// <remarks> /// Create a volume group along with specified volumes /// </remarks> /// <param name='body'> /// Volume Group object supplied in the body of the operation. /// </param> /// <param name='resourceGroupName'> /// The name of the resource group. /// </param> /// <param name='accountName'> /// The name of the NetApp account /// </param> /// <param name='volumeGroupName'> /// The name of the volumeGroup /// </param> /// <param name='customHeaders'> /// Headers that will be added to request. /// </param> /// <param name='cancellationToken'> /// The cancellation token. /// </param> /// <exception cref="CloudException"> /// Thrown when the operation returned an invalid status code /// </exception> /// <exception cref="SerializationException"> /// Thrown when unable to deserialize the response /// </exception> /// <exception cref="ValidationException"> /// Thrown when a required parameter is null /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown when a required parameter is null /// </exception> /// <return> /// A response object containing the response body and response headers. /// </return> public async Task <AzureOperationResponse <VolumeGroupDetails> > BeginCreateWithHttpMessagesAsync(VolumeGroupDetails body, string resourceGroupName, string accountName, string volumeGroupName, Dictionary <string, List <string> > customHeaders = null, CancellationToken cancellationToken = default(CancellationToken)) { if (body == null) { throw new ValidationException(ValidationRules.CannotBeNull, "body"); } if (Client.SubscriptionId == null) { throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.SubscriptionId"); } if (resourceGroupName == null) { throw new ValidationException(ValidationRules.CannotBeNull, "resourceGroupName"); } if (resourceGroupName != null) { if (resourceGroupName.Length > 90) { throw new ValidationException(ValidationRules.MaxLength, "resourceGroupName", 90); } if (resourceGroupName.Length < 1) { throw new ValidationException(ValidationRules.MinLength, "resourceGroupName", 1); } if (!System.Text.RegularExpressions.Regex.IsMatch(resourceGroupName, "^[-\\w\\._\\(\\)]+$")) { throw new ValidationException(ValidationRules.Pattern, "resourceGroupName", "^[-\\w\\._\\(\\)]+$"); } } if (accountName == null) { throw new ValidationException(ValidationRules.CannotBeNull, "accountName"); } if (volumeGroupName == null) { throw new ValidationException(ValidationRules.CannotBeNull, "volumeGroupName"); } if (volumeGroupName != null) { if (volumeGroupName.Length > 64) { throw new ValidationException(ValidationRules.MaxLength, "volumeGroupName", 64); } if (volumeGroupName.Length < 1) { throw new ValidationException(ValidationRules.MinLength, "volumeGroupName", 1); } if (!System.Text.RegularExpressions.Regex.IsMatch(volumeGroupName, "^[a-zA-Z0-9][a-zA-Z0-9\\-_]{0,63}$")) { throw new ValidationException(ValidationRules.Pattern, "volumeGroupName", "^[a-zA-Z0-9][a-zA-Z0-9\\-_]{0,63}$"); } } if (Client.ApiVersion == null) { throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.ApiVersion"); } if (Client.ApiVersion != null) { if (Client.ApiVersion.Length < 1) { throw new ValidationException(ValidationRules.MinLength, "Client.ApiVersion", 1); } } // Tracing bool _shouldTrace = ServiceClientTracing.IsEnabled; string _invocationId = null; if (_shouldTrace) { _invocationId = ServiceClientTracing.NextInvocationId.ToString(); Dictionary <string, object> tracingParameters = new Dictionary <string, object>(); tracingParameters.Add("body", body); tracingParameters.Add("resourceGroupName", resourceGroupName); tracingParameters.Add("accountName", accountName); tracingParameters.Add("volumeGroupName", volumeGroupName); tracingParameters.Add("cancellationToken", cancellationToken); ServiceClientTracing.Enter(_invocationId, this, "BeginCreate", tracingParameters); } // Construct URL var _baseUrl = Client.BaseUri.AbsoluteUri; var _url = new System.Uri(new System.Uri(_baseUrl + (_baseUrl.EndsWith("/") ? "" : "/")), "subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.NetApp/netAppAccounts/{accountName}/volumeGroups/{volumeGroupName}").ToString(); _url = _url.Replace("{subscriptionId}", System.Uri.EscapeDataString(Client.SubscriptionId)); _url = _url.Replace("{resourceGroupName}", System.Uri.EscapeDataString(resourceGroupName)); _url = _url.Replace("{accountName}", System.Uri.EscapeDataString(accountName)); _url = _url.Replace("{volumeGroupName}", System.Uri.EscapeDataString(volumeGroupName)); List <string> _queryParameters = new List <string>(); if (Client.ApiVersion != null) { _queryParameters.Add(string.Format("api-version={0}", System.Uri.EscapeDataString(Client.ApiVersion))); } if (_queryParameters.Count > 0) { _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters); } // Create HTTP transport objects var _httpRequest = new HttpRequestMessage(); HttpResponseMessage _httpResponse = null; _httpRequest.Method = new HttpMethod("PUT"); _httpRequest.RequestUri = new System.Uri(_url); // Set Headers if (Client.GenerateClientRequestId != null && Client.GenerateClientRequestId.Value) { _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString()); } if (Client.AcceptLanguage != null) { if (_httpRequest.Headers.Contains("accept-language")) { _httpRequest.Headers.Remove("accept-language"); } _httpRequest.Headers.TryAddWithoutValidation("accept-language", Client.AcceptLanguage); } if (customHeaders != null) { foreach (var _header in customHeaders) { if (_httpRequest.Headers.Contains(_header.Key)) { _httpRequest.Headers.Remove(_header.Key); } _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value); } } // Serialize Request string _requestContent = null; if (body != null) { _requestContent = Rest.Serialization.SafeJsonConvert.SerializeObject(body, Client.SerializationSettings); _httpRequest.Content = new StringContent(_requestContent, System.Text.Encoding.UTF8); _httpRequest.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json; charset=utf-8"); } // Set Credentials if (Client.Credentials != null) { cancellationToken.ThrowIfCancellationRequested(); await Client.Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false); } // Send Request if (_shouldTrace) { ServiceClientTracing.SendRequest(_invocationId, _httpRequest); } cancellationToken.ThrowIfCancellationRequested(); _httpResponse = await Client.HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false); if (_shouldTrace) { ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse); } HttpStatusCode _statusCode = _httpResponse.StatusCode; cancellationToken.ThrowIfCancellationRequested(); string _responseContent = null; if ((int)_statusCode != 201) { var ex = new CloudException(string.Format("Operation returned an invalid status code '{0}'", _statusCode)); try { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); CloudError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject <CloudError>(_responseContent, Client.DeserializationSettings); if (_errorBody != null) { ex = new CloudException(_errorBody.Message); ex.Body = _errorBody; } } catch (JsonException) { // Ignore the exception } ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent); ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent); if (_httpResponse.Headers.Contains("x-ms-request-id")) { ex.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault(); } if (_shouldTrace) { ServiceClientTracing.Error(_invocationId, ex); } _httpRequest.Dispose(); if (_httpResponse != null) { _httpResponse.Dispose(); } throw ex; } // Create Result var _result = new AzureOperationResponse <VolumeGroupDetails>(); _result.Request = _httpRequest; _result.Response = _httpResponse; if (_httpResponse.Headers.Contains("x-ms-request-id")) { _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault(); } // Deserialize Response if ((int)_statusCode == 201) { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); try { _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject <VolumeGroupDetails>(_responseContent, Client.DeserializationSettings); } catch (JsonException ex) { _httpRequest.Dispose(); if (_httpResponse != null) { _httpResponse.Dispose(); } throw new SerializationException("Unable to deserialize the response.", _responseContent, ex); } } if (_shouldTrace) { ServiceClientTracing.Exit(_invocationId, _result); } return(_result); }
/// <summary> /// Create the specified volume group and volumes. Creating volume group will /// create all the volumes specified in request body implicitly. Once volumes /// are created using volume group, those will be treated as regular volumes /// thereafter. /// </summary> /// <remarks> /// Create a volume group along with specified volumes /// </remarks> /// <param name='body'> /// Volume Group object supplied in the body of the operation. /// </param> /// <param name='resourceGroupName'> /// The name of the resource group. /// </param> /// <param name='accountName'> /// The name of the NetApp account /// </param> /// <param name='volumeGroupName'> /// The name of the volumeGroup /// </param> /// <param name='customHeaders'> /// The headers that will be added to request. /// </param> /// <param name='cancellationToken'> /// The cancellation token. /// </param> public async Task <AzureOperationResponse <VolumeGroupDetails> > CreateWithHttpMessagesAsync(VolumeGroupDetails body, string resourceGroupName, string accountName, string volumeGroupName, Dictionary <string, List <string> > customHeaders = null, CancellationToken cancellationToken = default(CancellationToken)) { // Send Request AzureOperationResponse <VolumeGroupDetails> _response = await BeginCreateWithHttpMessagesAsync(body, resourceGroupName, accountName, volumeGroupName, customHeaders, cancellationToken).ConfigureAwait(false); return(await Client.GetPutOrPatchOperationResultAsync(_response, customHeaders, cancellationToken).ConfigureAwait(false)); }