#region Copyright /* * Copyright © 2014-2016 NetApp, Inc. All Rights Reserved. * * CONFIDENTIALITY NOTICE: THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION OF * NETAPP, INC. USE, DISCLOSURE OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR * EXPRESS WRITTEN PERMISSION OF NETAPP, INC. */ #endregion #region Using Directives using System; using System.Collections; using System.Collections.Generic; using System.Management.Automation; using SolidFire.Core.Helpers; using System.Management.Automation.Runspaces; using SolidFire.Core; using SolidFire.Element.Api; using SolidFire.Exceptions; using ElementAccount = SolidFire.Element.Api.Account; #endregion namespace SolidFire.Volume.New { /// /// NewSFVolume is used to create a new (empty) volume on the cluster by /// wrapping the CreateVolume API method. When the volume is created /// successfully it is immediately available for use. /// /// Volumes created without specified QoS values are created with the /// default values listed in the Default QoS settings configured for a /// cluster. /// [Cmdlet(VerbsCommon.New, "SFVolume", DefaultParameterSetName = "q", ConfirmImpact = ConfirmImpact.Medium)] public class NewSFVolume : SFCmdlet { #region Private Data /// /// Member for saving the optional minimum iops setting. Implemented /// as a nullable to help decide if the setting needs to be sent /// to the api call as JSON data. /// private int? minIOPS; /// /// Member for saving the optional maximum iops setting. Implemented /// as a nullable to help decide if the setting needs to be sent /// to the api call as JSON data. /// private int? maxIOPS; /// /// Member for saving the optional burst iops setting. Implemented /// as a nullable to help decide if the setting needs to be sent /// to the api call as JSON data. /// private int? burstIOPS; private int? burstTime; private int? qosPolicyID; private long? accountID; private ElementAccount account; private bool? associateWithQoSPolicy; private List processedIDs = new List(); private Pipeline pipeline; #endregion #region Parameters /// /// Name of the volume. /// [Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, HelpMessage = "Name of the volume access group")] public String Name { get; set; } /// /// Account id for the owner of volume. /// [Parameter(Position = 1, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, HelpMessage = "Account ID for the owner of this volume")] public long AccountID { get { return accountID ?? 0; } set { accountID = value; } } /// /// Account information for the owner of the volume. /// [Parameter(Position = 2, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, HelpMessage = "Account Information for the owner of this volume")] public ElementAccount Account { get { return account; } set { if (value == null) return; account = value; } } /// /// The volume needs to have 512e emulation enabled or not. /// [Parameter(Mandatory = true, Position = 3, HelpMessage = "The volume provides 512-byte sector emulation")] public bool Enable512e { get; set; } /// /// Total size of the volume, in bytes. Size is rounded up to the nearest 1MB size. /// This value interpretation can be in GB or GiB by using the GB or GiB switch. /// [Parameter(Mandatory = true, Position = 4, HelpMessage = "Total size of the volume in GB")] public Int64 TotalSize { get; set; } /// /// Switch to specify interpreting the Total Size parameter as GiB instead of Bytes. /// [Parameter(Mandatory = false, Position = 5, HelpMessage = "Switch used to interpret total size as GB")] public SwitchParameter GB { get; set; } /// /// Switch to specify interpreting the Total Size parameter as GiB instead of Bytes. /// [Parameter(Mandatory = false, Position = 6, HelpMessage = "Switch used to interpret total size as GiB")] public SwitchParameter GiB { get; set; } /// /// Attributes to save with the volume. /// [Parameter(Mandatory = false, Position = 7, HelpMessage = "Attributes to set")] public Hashtable Attributes { get; set; } /// /// Minimum iops to set for the volume. /// [Parameter(Mandatory = false, Position = 8, HelpMessage = "The desired minimum 4KB IOPS to guarantee")] [Parameter(ParameterSetName = "q")] public int MinIOPS { get { return minIOPS ?? 100; } set { minIOPS = value; } } /// /// Maximum iops to set for the volume. /// [Parameter(Mandatory = false, Position = 9, HelpMessage = "The desired maximum 4KB IOPS to guarantee")] [Parameter(ParameterSetName = "q")] public int MaxIOPS { get { return maxIOPS ?? 15000; } set { maxIOPS = value; } } /// /// Burst iops to set for the volume. /// [Parameter(Mandatory = false, Position = 10, HelpMessage = "The maximum 4KB IOPS allowed for a short time")] [Parameter(ParameterSetName = "q")] public int BurstIOPS { get { return burstIOPS ?? 15000; } set { burstIOPS = value; } } /// /// Burst iops to set for the volume. /// [Parameter(Mandatory = false, Position = 11, HelpMessage = "The maximum 4KB IOPS allowed for a short time")] [Parameter(ParameterSetName = "q")] public int BurstTime { get { return burstTime ?? 0; } set { burstTime = value; } } [Parameter(Mandatory = false, Position = 8, HelpMessage = "The ID for the policy whose QoS settings should be applied to the specified volumes.")] [Parameter(ParameterSetName = "p")] public int QoSPolicyID { get { return qosPolicyID ?? 100; } set { qosPolicyID = value; } } [Parameter(Mandatory = false, Position = 9, HelpMessage = "Associate the volume with the specified QoSPolicyID.")] [Parameter(ParameterSetName = "p")] public bool AssociateWithQoSPolicy { get { return associateWithQoSPolicy ?? true; } set { associateWithQoSPolicy = value; } } #endregion #region Cmdlet Overrides /// /// Implementation for checking the status of the connection and /// compatibility before allowing the cmdlet to continue. /// protected override void BeginProcessing() { base.BeginProcessing(); pipeline = Runspace.DefaultRunspace.CreateNestedPipeline(); if (GB.IsPresent && GiB.IsPresent) { var errDetails = new ErrorDetails("GB and GiB are mutually exclusive switches"); var errRecord = new ErrorRecord(new ArgumentException(), errDetails.Message, ErrorCategory.InvalidArgument, this); ThrowTerminatingError(errRecord); } CheckConnection(); } protected override void EndProcessing() { base.EndProcessing(); if (processedIDs.Count > 0) { var command = new Command("Get-SFVolume"); command.Parameters.Add("VolumeID", processedIDs); if (SFConnection != null) { command.Parameters.Add("SFConnection", SFConnection); } else if (Target != null) { command.Parameters.Add("Target", Target); } pipeline.Commands.Add(command); WriteObject(pipeline.Invoke(), true); processedIDs.Clear(); } pipeline = null; } /// /// Implementation for processing the execution of the cmdlet. /// protected override void ProcessRecord() { base.ProcessRecord(); // Assemble the QOS object // Do not set default values if nothing has been set by the user // to use the cluster default settings. if (account != null) { accountID = account.AccountID; } if (account == null && AccountID == 0) { throw new ParameterException("Unable to determine AccountID. Please use -Account or -AccountID while running this CmdLet."); } var request = new CreateVolumeRequest { Name = Name, AccountID = AccountID, Enable512e = Enable512e, TotalSize = TotalSize, }; if (ParameterSetName == "q") { if (minIOPS.HasValue || maxIOPS.HasValue || burstIOPS.HasValue || burstTime.HasValue) { request.Qos = new QoS { MinIOPS = minIOPS, MaxIOPS = maxIOPS, BurstIOPS = burstIOPS, BurstTime = burstTime }; } } else { if (associateWithQoSPolicy.HasValue && !qosPolicyID.HasValue) { // no new QoSPolicyID or old QosPolicyID var message = "Missing QosPolicyID. Unable to Associate with QoS Policy because there is no QoSPolicyID to use. Please supply on."; var errRecord = new ErrorRecord(new VolumeException(message), message, ErrorCategory.InvalidData, this); SolidFireUtilities.HandleError(errRecord, this); } request.QosPolicyID = qosPolicyID; request.AssociateWithQoSPolicy = AssociateWithQoSPolicy; } if (GB.IsPresent) { request.TotalSize = request.TotalSize * Convert.ToInt64(Math.Pow(1000, 3)); } if (GiB.IsPresent) { request.TotalSize = request.TotalSize * Convert.ToInt64(Math.Pow(1024, 3)); } request.Attributes = Attributes; // Send the request to create the volume. var objsFromAPI = SendRequest("CreateVolume", request); foreach (var obj in objsFromAPI) { // If there was not an error, save off the ID for writing to the output pipeline after processing. processedIDs.Add(obj.Result.VolumeID); } } #endregion } }