HPOneView.310.psm1

##############################################################################
# HPE OneView PowerShell Library
##############################################################################
##############################################################################
## (C) Copyright 2013-2018 Hewlett Packard Enterprise Development LP
##############################################################################
<#
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
 
#>


<#
 Note: This library requires the following installed:
 Microsoft .NET Framework 4.6: http://go.microsoft.com/fwlink/?LinkId=528259
 Windows Management Framework (aka PowerShell) 4: https://www.microsoft.com/en-us/download/details.aspx?id=40855
#>


#Set HPOneView POSH Library Version
[Version]$ModuleVersion = '3.10.1808.1701'
New-Variable -Name PSLibraryVersion -Scope Global -Value (New-Object HPOneView.Library.Version($ModuleVersion)) -Option Constant -ErrorAction SilentlyContinue
$Global:CallStack = Get-PSCallStack
$script:ModuleVerbose = [bool]($Global:CallStack | ? { $_.Command -eq "<ScriptBlock>" }).position.text -match "-verbose"

#Check to see if another module is loaded in the console, but allow Import-Module to Process normally if user specifies the same module name
if ((get-module -name HPOneView*) -and (-not (get-module -name HPOneView* | % name -eq "HPOneView.310"))) 
{

    write-Host "CRITICAL: Another HP OneView module is already loaded: "  -ForegroundColor Yellow -BackgroundColor Black 
    Write-Host " |"  -ForegroundColor Yellow -BackgroundColor Black 
    get-module -name HPOneView* | % { write-host " |--> $($_.name) ($($_.Version))"  -ForegroundColor Yellow -BackgroundColor Black }
    write-host ""

    [System.String]$Exception                                  = 'InvalidOperationException'
    [System.String]$ErrorId                                    = 'CannotLoadMultipleLibraries'
    [System.Object]$TargetObject                               = 'Import-Module HPOneView.310'
    [System.Management.Automation.ErrorCategory]$ErrorCategory = 'ResourceExists'
    [System.String]$Message                                    = 'Another HPE OneView module is already loaded. The HPE OneView PowerShell library does not support loading multiple versions of libraries within the same console.'
    
    $_exception  = New-Object $Exception $Message
    $ErrorRecord = New-Object Management.Automation.ErrorRecord $_exception, $ErrorID, $ErrorCategory, $TargetObject
    throw $ErrorRecord

}

$debugMode = $False

#Note: Set $debugPreference to control debug logging
If ($debugmode) 
{

    $debugPreference   = "Continue"         # Display requests and responses
    $VerbosePreference = "Continue" 

}
#Else{ $debugPreference = "SilentlyContinue" } # Hide debug messages

#region URIs and Enums
[String]$script:AuthProviderSetting = "LOCAL"
${Global:ConnectedSessions}         = New-Object System.Collections.ArrayList
${Global:ResponseErrorObject}       = New-Object System.Collections.ArrayList
[TimeSpan]$script:defaultTimeout    = New-TimeSpan -Minutes 20
$script:FSOpenMode                  = [System.IO.FileMode]::Open
$script:FSRead                      = [System.IO.FileAccess]::Read
[MidpointRounding]$script:MathMode  = 'AwayFromZero' 
[String]$MinXAPIVersion             = "500"
[String]$MaxXAPIVersion             = "500"
[String]$Repository                 = "https://api.github.com/repos/HewlettPackard/POSH-HPOneView/releases"

#------------------------------------
# Appliance Configuration
#------------------------------------
[String]$script:ApplianceStartProgressUri  = '/rest/appliance/progress'
[String]$script:ApplianceVersionUri        = '/rest/appliance/nodeinfo/version'
[String]$ApplianceEulaStatusUri            = '/rest/appliance/eula/status'
[String]$ApplianceEulaSaveUri              = '/rest/appliance/eula/save'
[String]$ApplianceNetworkConfigUri         = '/rest/appliance/network-interfaces'
[String]$script:ApplianceNetworkStatusUri  = '/rest/appliance/network-interfaces/status'
[String]$ApplianceNetworkMacAddrUri        = '/rest/appliance/network-interfaces/mac-addresses'
[string]$script:ApplianceDateTimeUri       = '/rest/appliance/configuration/time-locale'
[String]$script:ApplianceGlobalSettingsUri = '/rest/global-settings'
[String]$Script:ApplianceBaselineRepoUri   = '/rest/firmware-drivers'
[String]$ApplianceRepositoriesUri          = '/rest/repositories'
[String]$ApplianceBaselineRepositoriesUri  = '/rest/firmware-repositories/defaultOneViewRepo'
[Hashtable]$RepositoryType                 = @{
    External = 'FirmwareExternalRepo';
    Internal = 'FirmwareInternalRepo'
}
[String]$script:ApplianceXApiVersionUri    = '/rest/version'
[String]$Script:ApplianceHANodesUri        = '/rest/appliance/ha-nodes'
[String]$ApplianceBackupUri                = '/rest/backups'
[String]$script:ApplianceRestoreRepoUri    = '/rest/backups/archive'
[String]$Script:ApplianceAutoBackupConfUri = '/rest/backups/config'
[String]$script:ApplianceRestoreUri        = '/rest/restores'
[String]$ApplianceProxyConfigUri           = '/rest/appliance/proxy-config'
[Hashtable]$script:progressStepEnum        = @{

    COMPLETED            = "Restore Completed";
    FAILED               = "Restore Failed";
    PREPARING_TO_RESTORE = "Preparing to Restore";
    RESTORING_DB         = "Restoring Database";
    RESTORING_FILES      = "Restoring Files";
    STARTING_SERVICES    = "Starting Services";
    UNKNOWN              = "The restore step is unknown"

}
[Hashtable]$Script:ApplianceLocaleSetEnum  = @{

    'en-US' = 'en_US.UTF-8';
    'en_US' = 'en_US.UTF-8';
    'zh_CN' = 'zh_CN.UTF-8';
    'zh-CN' = 'zh_CN.UTF-8';
    'ja_JP' = 'ja_JP.UTF-8';
    'ja-JP' = 'ja_JP.UTF-8';

}
[Hashtable]$Script:ApplianceLocaleEnum     = @{

    'en_US.UTF-8' = 'English (United States)';
    'zh_CN.UTF-8' = 'Chinese (China)';
    'ja_JP.UTF-8' = 'Japanese (Japan)';

}
[Hashtable]$Script:DayOfWeekEnum           = @{

    Sunday    = 'SU';
    SU        = 'SU';
    SUN       = 'SU';
    Monday    = 'MO';
    MO        = 'MO';
    MON       = 'MO';
    Tuesday   = 'TU';
    TU        = 'TU';
    TUE       = 'TU';
    TUES      = 'TU';
    Wednesday = 'WE';
    WE        = 'WE';
    WED       = 'WE';
    Thursday  = 'TH';
    Thur      = 'TH';
    Thurs     = 'TH';
    TH        = 'TH';
    Friday    = 'FR';
    Fri       = 'FR';
    FR        = 'FR';
    Saturday  = 'SA';
    Sat       = 'SA';
    SA        = 'SA';

}
[Hashtable]$AppliancePlatformType          = @{

    hardware = 'Composer';
    vm       = 'VMA'

}
[String]$script:applSupportDump            = "/rest/appliance/support-dumps"
[String]$script:applHealthStatus           = "/rest/appliance/health-status"
[String]$ApplianceTrustedCertStoreUri      = '/rest/certificates'
[String]$script:applRabbitmqUri            = "/rest/certificates/client/rabbitmq"
[String]$RabbitMQKeyPairUri                = "/rest/certificates/client/rabbitmq/keypair/default"
[String]$RabbitMQKeyPairCertUri            = '/rest/certificates/ca/rabbitmq_readonly'
[String]$script:applCaUri                  = "/rest/certificates/ca"
[String]$ApplianceUpdateImageUri           = "/rest/appliance/firmware/image"
[String]$ApplianceUpdatePendingUri         = "/rest/appliance/firmware/pending"
[String]$ApplianceUpdateNotificationUri    = "/rest/appliance/firmware/notification"
[String]$ApplianceUpdateMonitorUri         = "/cgi-bin/status/update-status.cgi"
[String]$script:applSnmpReadCommunity      = "/rest/appliance/device-read-community-string"
[String]$script:applianceRebootUri         = '/rest/appliance/shutdown?type=REBOOT'
[String]$script:applianceShutDownUri       = '/rest/appliance/shutdown?type=HALT'
[String]$script:applianceCsr               = '/rest/certificates/https/certificaterequest'
[String]$script:applianceSslCert           = '/rest/certificates/https'
[String]$Script:appliancePingTestUri       = '/rest/appliance/reachable'
[string]$script:applianceDebugLogSetting   = '/logs/rest/debug/'
[string]$script:RemoteSyslogUri            = '/rest/remote-syslog'
[string]$script:IPSubnetAddressPattern     = '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' +
                                             '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' +
                                             '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' +
                                             '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' +
                                             '(/0*([1-9]|[12][0-9]|3[0-2]))?$'
[String]$LabelsUri                         = '/rest/labels'
[String]$LabelsResourcesBaseUri            = '/rest/labels/resources'

#------------------------------------
# Remote Support
#------------------------------------
[String]$RemoteSupportUri                         = '/rest/support'
[String]$RemoteSupportConfigUri                   = '/rest/support/configuration'
[String]$RemoteSupportContactsUri                 = '/rest/support/contacts'
[String]$RemoteSupportSitesUri                    = '/rest/support/sites'
[String]$RemoteSupportDefaultSitesUri             = '/rest/support/sites/default'
[String]$ServerHardwareRemoteSupportSettingsUri   = '/rest/support/server-hardware'
[String]$EnclosureRemoteSupportSettingsUri        = '/rest/support/server-hardware'
[String]$RemoteSupportDataCollectionsUri          = '/rest/support/data-collections'
[String]$RemoteSupportDataCollectionsDownloadUri  = '/rest/support/data-collections/download'
[string]$InsightOnlinePortalRegistraionUri        = '/rest/support/portal-registration'
[String]$RemoteSupportChannelPartnersUri          = '/rest/support/channel-partners'
[String]$RemoteSupportChannelPartnersValidatorUri = '/rest/support/channel-partners/validator'
[String]$RemoteSupportDataCollectionScheduleUri   = '/rest/support/schedules'
[String]$RemoteSupportComputeSettingsUri          = '/rest/support/server-hardware'
[String]$RemoteSupportEnclosureSettingsUri        = '/rest/support/enclosures'
[HashTable]$RemoteSupportResourceSettingEnum      = @{
    'salesChannelPartnerUri'   = 'SalesChannelPartner';
    'supportChannelPartnerUri' = 'SupportChannelPartner';
    'primaryContactUri'        = 'PrimaryContact'; 
    'secondaryContactUri'      = 'SecondaryContact'
}
[Hashtable]$RemoteSupportCollectionEnum           = @{
    'AHS'   = 'AHS';
    'Basic' = 'Basic'
}
[Array]$RemoteSupportUris                         = @(
    $RemoteSupportUri,
    $RemoteSupportConfigUri,
    $RemoteSupportContactsUri,
    $RemoteSupportSitesUri,
    $RemoteSupportDefaultSitesUri
)
#------------------------------------
# Image Streamer (I3S) Management
#------------------------------------
[String]$DeploymentServersUri          = '/rest/deployment-servers' #Mapped to Get-HPOVOSDeploymentServer?
[String]$AvailableDeploymentServersUri = '/rest/deployment-servers/image-streamer-appliances' #Mapped to Show-HPOVImageStreamer?
[String]$DeploymentPlansUri            = '/rest/os-deployment-plans/' #Mapped to Get-HPOVOsDeploymentPlan
#------------------------------------
# Physical Resource Management
#------------------------------------
[String]$ServerHardwareUri                      = "/rest/server-hardware"
[String]$script:ServerHardwareTypesUri          = "/rest/server-hardware-types"
[String]$EnclosuresUri                          = "/rest/enclosures"
[String]$script:LogicalEnclosuresUri            = '/rest/logical-enclosures'
[String]$script:EnclosureGroupsUri              = "/rest/enclosure-groups"
[String]$script:EnclosurePreviewUri             = "/rest/enclosure-preview"
[String]$VCMigratorUri                          = "/rest/migratable-vc-domains"
[String]$script:FwUploadUri                     = "/rest/firmware-bundles"
[String]$script:FwDriversUri                    = "/rest/firmware-drivers"
[String]$script:PowerDevicesUri                 = "/rest/power-devices"
[String]$script:PowerDevicesDiscoveryUri        = "/rest/power-devices/discover"
[String]$script:PowerDevicePotentialConnections = "/rest/power-devices/potentialConnections?providerUri="
[String]$script:UnmanagedDevicesUri             = "/rest/unmanaged-devices?sort=name:asc"
[PSCustomObject]$script:MpModelTable            = @{
    ilo2 = "RI7";
    ilo3 = "RI9";
    ilo4 = "RI10"
}
[HashTable]$Script:ServerPowerControlEnum       = @{

    PressAndHold   = 'PressAndHold';
    MomentaryPress = 'MomentaryPress';
    ColdBoot       = 'ColdBoot';
    Reset          = 'Reset'

}
[string]$SyngergyEnclosureTypeUri               = '/rest/enclosure-types/SY12000'
[string]$C7000EnclosureTypeUri                  = '/rest/enclosure-types/c7000'
[Hashtable]$EnclosureGroupIpAddressModeEnum     = @{

    DHCP        = 'DHCP';
    External    = 'External';
    AddressPool = 'IpPool'

}
[Hashtable]$FramePowerModeEnum                  = @{

    RedundantPowerSupply = 'RedundantPowerSupply';
    RedundantPowerFeed   = 'RedundantPowerFeed'

}
[Hashtable]$FrameAmbientTemperatureEnum         = @{
    
    'ASHRAE_A3' = 'ASHRAE_A3';    
    'ASHRAE_A4' = 'ASHRAE_A4';
    'Standard'  = 'Standard';
    'Telco'     = 'Telco'
}
#------------------------------------
# Storage Resource Management
#------------------------------------
[String]$DriveEnclosureUri                              = '/rest/drive-enclosures'
[String]$script:SasInterconnectTypeUri                  = '/rest/sas-interconnect-types'
[String]$script:SasInterconnectsUri                     = '/rest/sas-interconnects'
[String]$SasLogicalInterconnectsUri                     = '/rest/sas-logical-interconnects'
[String]$script:SasLogicalInterconnectGroupsUri         = '/rest/sas-logical-interconnect-groups'
[String]$StorageSystemsUri                              = "/rest/storage-systems"
[String]$StorageVolumesUri                              = "/rest/storage-volumes"
[String]$StorageVolumeFromSnapshotUri                   = '/rest/storage-volumes/from-snapshot'
[String]$StoragePoolsUri                                = "/rest/storage-pools"
[String]$ReachableStoragePoolsUri                       = '/rest/storage-pools/reachable-storage-pools'
[String]$AttachableStorageVolumesUri                    = '/rest/storage-volumes/attachable-volumes'
[String]$script:StorageVolumeTemplateUri                = "/rest/storage-volume-templates"
[string]$script:ApplStorageVolumeTemplateRequiredPolicy = '/rest/global-settings/appliance/global/StorageVolumeTemplateRequired'
[String]$script:fcSanManagerProvidersUri                = "/rest/fc-sans/providers"  #list available SAN Manager plugins, and create SAN Manager
[Hashtable]$script:FcSanManagerSnmpAuthLevel            = @{
    None        = "noauthnopriv";
    AuthOnly    = "authnopriv";
    AuthAndPriv = "authpriv"
}
[Hashtable]$script:FcSanManagerSnmpPrivProtocol         = @{
    'aes-128' = "AES";
    'des56'   = "DES56";
    '3des'    = "3DES"
}
[String]$script:FcSanManagersUri                        = "/rest/fc-sans/device-managers" #created SAN Managers
[String]$script:FcManagedSansUri                        = "/rest/fc-sans/managed-sans" #Discovered managed SAN(s) that the added SAN Manager will manage
[String]$script:FcZonesUri                              = '/rest/fc-sans/zones'
[String]$Script:SanEndpoints                            = '/rest/fc-sans/Endpoints'
[RegEx]$Script:iQNPattern                               = '^(?:iqn\.[0-9]{4}-[0-9]{2}(?:\.[A-Za-z](?:[A-Za-z0-9\-]*[A-Za-z0-9])?)+(?::.*)?|eui\.[0-9A-Fa-f]{16})'
[Hashtable]$StorageVolShareableEnum                     = @{

    Private = $false;
    Shared  = $true

}
[Hashtable]$StorageSystemFamilyTypeEnum                 = @{
    StoreVirtual = 'StoreVirtual';
    StoreServ    = 'StoreServ'
}
[Hashtable]$Global:StorageSystemPortModeEnum            = @{

    AutoSelectExpectedSan = 'Auto';
    Ignore                = 'Ignore';
    Managed               = 'Managed'

}
[Hashtable]$StorageVolumeProvisioningTypeEnum           = @{
    Full = 'Full';
    Thin = 'Thin';
    TPDD = 'Thin Deduplication'
}
[Hashtable]$DataProtectionLevelEnum                     = @{
    NetworkRaid0None         = 'NetworkRaid0None';
    NetworkRaid5SingleParity = 'NetworkRaid5SingleParity';
    NetworkRaid10Mirror2Way  = 'NetworkRaid10Mirror2Way';
    NetworkRaid10Mirror3Way  = 'NetworkRaid10Mirror3Way';
    NetworkRaid10Mirror4Way  = 'NetworkRaid10Mirror4Way';
    NetworkRaid6DualParity   = 'NetworkRaid6DualParity'
}
#------------------------------------
# Network Resource Management
#------------------------------------
[String]$script:InterconnectLinkTopologies   = '/rest/interconnect-link-topologies'
[String]$script:NetworkSetsUri               = "/rest/network-sets"
[String]$script:EthNetworksUri               = "/rest/ethernet-networks"
[String]$script:FcNetworksUri                = "/rest/fc-networks"
[String]$script:FcoeNetworksUri              = "/rest/fcoe-networks"
[String]$script:ConnectionTemplatesUri       = "/rest/connection-templates"
[String]$script:LogicalInterconnectGroupsUri = "/rest/logical-interconnect-groups"
[String]$script:LogicalInterconnectsUri      = "/rest/logical-interconnects"
[String]$script:InterconnectsUri             = "/rest/interconnects"
[String]$script:InterconnectTypesUri         = '/rest/interconnect-types'
[String]$script:UplinkSetsUri                = "/rest/uplink-sets"
[String]$script:LogicalDownlinksUri          = "/rest/logical-downlinks"
[String]$SwitchTypesUri                      = '/rest/switch-types'
[String]$LogicalSwitchGroupsUri              = '/rest/logical-switch-groups'
[String]$LogicalSwitchesUri                  = '/rest/logical-switches'
[String]$SwitchesUri                         = '/rest/switches'
[Hashtable]$LogicalSwitchManagementLevelEnum = @{ 
    Managed         = 'BASIC_MANAGED'; 
    Monitored       = 'MONITORED'; 
    ManagedSnmpV3   = 'BASIC_MANAGED'; 
    MonitoredSnmpV3 = 'MONITORED'
}
[String]$script:ApplianceVmacPoolsUri        = '/rest/id-pools/vmac'
[String]$script:ApplianceVmacPoolRangesUri   = '/rest/id-pools/vmac/ranges'
[String]$script:ApplianceVwwnPoolsUri        = '/rest/id-pools/vwwn'
[String]$script:ApplianceVwwnPoolRangesUri   = '/rest/id-pools/vwwn/ranges'
[String]$script:ApplianceVsnPoolsUri         = '/rest/id-pools/vsn'
[String]$script:ApplianceVsnPoolRangesUri    = '/rest/id-pools/vsn/ranges'
[String]$script:ApplianceIPv4PoolsUri        = '/rest/id-pools/ipv4'
[String]$script:ApplianceIPv4PoolRangesUri   = '/rest/id-pools/ipv4/ranges'
[String]$script:ApplianceIPv4SubnetsUri      = '/rest/id-pools/ipv4/subnets'
[String]$script:ApplianceVmacGenerateUri     = '/rest/id-pools/vmac/generate'
[String]$script:ApplianceVwwnGenerateUri     = '/rest/id-pools/vwwn/generate'
[String]$script:ApplianceVsnPoolGenerateUri  = '/rest/id-pools/vsn/generate'
$MacAddressPattern                           = @('^([0-9a-f]{2}:){5}([0-9a-f]{2})$')
$WwnAddressPattern                           = @('^([0-9a-f]{2}:){7}([0-9a-f]{2})$')
$WwnLongAddressPattern                       = @('^([0-9a-f]{2}:){15}([0-9a-f]{2})$')
[RegEx]$script:ip4regex                      = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
[HashTable]$Global:FCNetworkFabricTypeEnum   = @{

    FA           = 'FabricAttach';
    FabricAttach = 'FabricAttach';
    DA           = 'DirectAttach';
    DirectAttach = 'DirectAttach'

}
[Hashtable]$global:GetUplinkSetPortSpeeds    = @{
    Speed0M   = "0";
    Speed100M = "100Mb";
    Speed10G  = "10Gb";
    Speed10M  = "10Mb";
    Speed1G   = "1Gb";
    Speed1M   = "1Mb";
    Speed20G  = "20Gb";
    Speed2G   = "2Gb";
    Speed2_5G = "2.5Gb";
    Speed40G  = "40Gb";
    Speed4G   = "4Gb";
    Speed8G   = "8Gb";
    Auto       = "Auto"
}
[Hashtable]$global:SetUplinkSetPortSpeeds    = @{
    '0'    = "Speed0M";
    '100M' = "Speed100M";
    '100'  = "Speed100M";
    '10G'  = "Speed10G";
    '10'   = "Speed10G";
    '10M'  = "Speed10M";
    '1G'   = "Speed1G";
    '1'    = "Speed1G";
    '1M'   = "Speed1M";
    '20G'  = "Speed20G";
    '2G'   = "Speed2G";
    '2'    = "Speed2G";
    '2.5G' = "Speed2_5G";
    '40G'  = "Speed40G";
    '4G'   = "Speed4G";
    '8G'   = "Speed8G";
    '4'    = "Speed4G";
    '8'    = "Speed8G";
    'Auto' = "Auto"
}
[Hashtable]$global:LogicalInterconnectConsistencyStatusEnum = @{

    'CONSISTENT'     = "Consistent" ;
    'NOT_CONSISTENT' = "Inconsistent with group" 

}
[Array]$IngressDscpClassMappingEnum                       = @('DSCP 18, AF21','DSCP 20, AF22','DSCP 22, AF23','DSCP 26, AF31','DSCP 28, AF32','DSCP 30, AF33','DSCP 34, AF41','DSCP 36, AF42','DSCP 38, AF43','DSCP 16, CS2','DSCP 24, CS3','DSCP 32, CS4','DSCP 10, AF11','DSCP 12, AF12','DSCP 14, AF13','DSCP 8, CS1','DSCP 0, CS0','DSCP 46, EF','DSCP 40, CS5','DSCP 48, CS6','DSCP 56, CS7')
[Hashtable]$Global:UplinkSetNetworkTypeEnum               = @{

    Ethernet      = 'Ethernet';
    FibreChannel  = 'FibreChannel';
    Untagged      = 'Ethernet';
    Tunnel        = 'Ethernet';
    ImageStreamer = 'Ethernet'

}
[Hashtable]$Global:UplinkSetEthNetworkTypeEnum            = @{

    Ethernet      = 'Tagged'
    Untagged      = 'Untagged'
    Tunnel        = 'Tunnel'
    ImageStreamer = 'ImageStreamer'

}
[Hashtable]$Global:LogicalInterconnectGroupRedundancyEnum = @{

    HighlyAvailable = 'HighlyAvailable';
    ASide           = 'NonRedundantASide';
    BSide           = 'NonRedundantBSide';
    Redundant       = 'Redundant'

}
[Array]$Script:SnmpEneTrapCategoryEnums                   = @('Other', 'PortStatus', 'PortThresholds')
[Array]$Script:SnmpFcTrapCategoryEnums                    = @('Other', 'PortStatus')
[Array]$Script:SnmpVcmTrapCategoryEnums                   = @('Legacy')
[Array]$Script:SnmpTrapSeverityEnums                      = @('Critical', 'Info', 'Major', 'Minor', 'Normal', 'Unknown', 'Warning')
[Net.IPAddress]$Script:ExcludedIPSubnetID                 = '172.30.254.0' #Synergy Specific
[Net.IPAddress]$Script:ExcludedIPSubnetEnd                = '172.30.254.254' #Synergy Specific
[Hashtable]$EthernetNetworkPurposeEnum = @{

    General        = "General";
    Management     = "Management";
    VMMigration    = "VMMigration";
    FaultTolerance = "FaultTolerance";
    ISCSI          = 'ISCSI'

}
#------------------------------------
# Profile Management
#------------------------------------
[String]$ServerProfilesUri                          = "/rest/server-profiles"
[String]$ServerProfileTemplatesUri                  = '/rest/server-profile-templates?sort=name:asc'
[String]$ServerProfileIndexListUri                  = "/rest/index/resources?sort=name:asc&category=server-profiles"
[String]$ServerProfileAvailStorageSystemsUri        = '/rest/server-profiles/available-storage-systems'
[String]$ServerProfilesAvailableNetworksUri         = '/rest/server-profiles/available-networks'
[Hashtable]$ServerProfileConnectionBootPriorityEnum = @{ 
    none           = 'NotBootable'; 
    NotBootable    = 'NotBootable'; 
    Primary        = 'Primary'; 
    Secondary      = 'Secondary'; 
    IscsiPrimary   = 'Primary'; 
    IscsiSecondary = 'Secondary'
}
[PSCustomObject]$ServerProfileSanManageOSType       = @{
    CitrixXen = "Citrix Xen Server 5.x/6.x";
    AIX       = "AIX";
    IBMVIO    = "IBM VIO Server";
    RHEL4     = "RHE Linux (Pre RHEL 5)";
    RHEL3     = "RHE Linux (Pre RHEL 5)";
    RHEL      = "RHE Linux (5.x, 6.x)";
    RHEV      = "RHE Virtualization (5.x, 6.x)";
    VMware    = "VMware (ESXi)";
    Win2k3    = "Windows 2003";
    Win2k8    = "Windows 2008/2008 R2";
    Win2k12   = "Windows 2012 / WS2012 R2";
    OpenVMS   = "OpenVMS";
    Egenera   = "Egenera";
    Exanet    = "Exanet";
    Solaris9  = "Solaris 9/10";
    Solaris10 = "Solaris 9/10";
    Solaris11 = "Solaris 11";
    ONTAP     = "NetApp/ONTAP";
    OEL       = "OE Linux UEK (5.x, 6.x)";
    HPUX11iv1 = "HP-UX (11i v1, 11i v2)"
    HPUX11iv2 = "HP-UX (11i v1, 11i v2)";
    HPUX11iv3 = "HP-UX (11i v3)";
    SUSE      = "SuSE (10.x, 11.x)";
    SUSE9     = "SuSE Linux (Pre SLES 10)";
    Inform    = "InForm"
}
[Hashtable]$ServerProfileConnectionTypeEnum         = @{

    'ethernet-networks' = 'Ethernet';
    'network-sets'      = 'Ethernet';
    'fcoe-networks'     = 'FibreChannel';
    'fc-networks'       = 'FibreChannel';
    'FC'                = 'FibreChannel';
    'FibreChannel'      = 'FibreChannel';
    'FCoE'              = 'FibreChannel';
    'Eth'               = 'Ethernet';
    'Ethernet'          = 'Ethernet';
    'iSCSI'             = 'iSCSI'

}
[Hashtable]$LogicalDiskTypeEnum                     = @{

    'Sas'     = 'SasHdd';
    'SASHDD'  = 'SasHdd';
    'Sata'    = 'SataHdd';
    'SATAHDD' = 'SataHdd';
    'Sasssd'  = 'SasSsd';
    'Satassd' = 'SataSsd';
    'Auto'    = $Null

}
[Hashtable]$ServerProfileFirmwareControlModeEnum    = @{

    FirmwareOnly            = 'FirmwareOnly';
    FirmwareAndSoftware     = 'FirmwareAndOSDrivers';
    FirmwareOffline         = 'FirmwareOnlyOfflineMode';
    FirmwareAndOSDrivers    = 'FirmwareAndOSDrivers';
    FirmwareOnlyOfflineMode = 'FirmwareOnlyOfflineMode'

}
[Hashtable]$ServerProfileFirmareActivationModeEnum  = @{
    Immediate    = 'Immediate';
    NotScheduled = 'NotScheduled';
    Scheduled    = 'Scheduled'
}
#------------------------------------
# Datacenter/Facilities
#------------------------------------
[String]$DataCentersUri     = '/rest/datacenters'
[String]$DataCenterRacksUri = '/rest/racks'
#------------------------------------
# Index Search
#------------------------------------
[String]$IndexUri                    = "/rest/index/resources" 
[String]$AssociationsUri             = "/rest/index/associations"
[String]$IndexAssociatedResourcesUri = '{0}/resources' -f $AssociationsUri
[String]$AssociationTreesUri         = "/rest/index/trees"
#------------------------------------
# Tasks
#------------------------------------
[String]$AllNonHiddenTaskUri    = "/rest/tasks?filter=hidden=$false"
[String]$TasksUri               = "/rest/tasks"
[Array]$TaskFinishedStatesEnum  = @(
    
    "Error",
    "Warning",
    "Completed",
    "Terminated",
    "Killed"
    
) 
#------------------------------------
# Alerts and Events
#------------------------------------
$AlertsUri                   = "/rest/alerts"
$script:eventsUri            = "/rest/events"
[String]$SmtpConfigUri       = "/rest/appliance/notifications/email-config"
[String]$TestNotificationUri = "/rest/appliance/notifications/send-email"
[String]$HtmlPattern         = "</?\w+((\s+\w+(\s*=\s*(?:`".*?`|'.*?'|[\^'`">\s]+))?)+\s*|\s*)/?>"
#------------------------------------
# Licenses
#------------------------------------
$script:licensesUri = "/rest/licenses"
#------------------------------------
# Security
#------------------------------------
[String]$ApplianceLoginSessionsUri  = '/rest/login-sessions'
[String]$ActiveUserSessionsUri      = '/rest/active-user-sessions'
$script:UsersUri                    = '/rest/users'
$script:UserRoleUri                 = "/rest/users/role"
[String]$AuthnProvidersUri          = '/rest/logindomains'
[String]$AuthnAllowLocalLoginUri    = '/rest/logindomains/global-settings/allow-local-login'
[String]$AuthnDefaultLoginDomainUri = '/rest/logindomains/global-settings/default-login-domain'
$script:AuthnProviderValidatorUri   = "/rest/logindomains/validator"
$script:AuthnSettingsUri            = "/rest/logindomains/global-settings"
$AuthnDirectoryGroups               = "/rest/logindomains/groups"
$Script:AuthnDirectorySearchContext = '/rest/logindomains/contexts'
$AuthnEgroupRoleMappingUri          = "/rest/logindomains/grouptorolemapping"
$script:ApplAuditLogsUri            = "/rest/audit-logs"
$script:ApplAuditLogDownloadUri     = "/rest/audit-logs/download"
$Script:ApplianceRolesUri           = '/rest/roles'
$Script:ApplianceLoginDomainDetails = '/rest/logindetails'
[String]$ScopesUri                  = '/rest/scopes'
[Hashtable]$ScopeCategoryEnum       = @{

    'enclosures'                  = 'Enclosure';
    'server-hardware'             = 'ServerHardware';
    'network-sets'                = 'NetworkSet';
    'interconnects'               = 'Interconnect';
    'logical-interconnects'       = 'LogicalInterconnect';
    'logical-interconnect-groups' = 'LogicalInterconnectGroup';
    'ethernet-networks'           = 'EthernetNetwork';
    'fc-networks'                 = 'FCNetwork';
    'fcoe-networks'               = 'FCoENetwork';
    'logical-switches'            = 'LogicalSwitch';
    'logical-switch-groups'       = 'LogicalSwitchGroup';
    'switches'                    = 'Switch'

}
$Script:OrganizationalUnitPattern   = '^(?:(?:CN|OU|DC)\=[\w\s]+,)*(?:CN|OU|DC)\=[\w\s]+$'
$Script:CommonNamePattern           = '^CN=(.+?),(?:CN|OU)=.+'
$JsonPasswordRegEx                  = New-Object System.Text.RegularExpressions.Regex ('\"password\"\:[\s]*?\"(.*?)\"', [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)

#Endregion

$WhiteListedURIs = @(

    $ApplianceLoginSessionsUri,
    $ApplianceUpdateMonitorUri,
    $ApplianceXApiVersionUri,
    "/ui-js/pages/",
    $ApplianceEulaStatusUri,
    $ApplianceEulaSaveUri,
    ($usersUri + "/changePassword"),
    "/startstop/rest/component?fields=status",
    $ApplianceStartProgressUri,
    $ApplianceLoginDomainDetails

)

#######################################################
# Resource Objects
#

function NewObject 
{

    [CmdletBinding ()]
    Param
    (

        [Object]$InputObject, 
        [switch]$AddStorageVolume,
        [switch]$AddStorageVolumeV3,
        [switch]$AddSslCertificate,
        [switch]$AlertFilter,
        [switch]$AllApiResponse,
        [switch]$ApplianceCSR,
        [switch]$ApplianceDebug,
        [switch]$ApplianceProxy,
        [switch]$ApplianceSslCertificate,
        [switch]$ApplianceTimeLocale,
        [switch]$ApplianceVersion,
        [switch]$AuthDirectory,
        [switch]$AuthDirectoryServer,
        [switch]$AuthLogin,
        [switch]$AutoBackupConfig,
        [switch]$BaseTrafficClass,
        [switch]$BulkEthernetNetworks,
        [switch]$ConvertSnapshotToVol,
        [switch]$CustomBaselineRestore,
        [switch]$DataCenter,
        [switch]$DataCenterItem,
        [switch]$DefaultBestEffortTrafficClass,
        [switch]$DefaultFCoELosslessQosTrafficClassifiers,
        [switch]$DefaultNoFCoELosslessQosTrafficClassifiers,
        [switch]$DeploymentModeSettings,
        [switch]$DirectoryGroup,
        [switch]$DirectoryGroupCredentials,
        [switch]$DownloadFileStatus,
        [switch]$EnclosureGroup,
        [switch]$EnclosureGroupPreview,
        [switch]$EnclosureGroupI3SDeploymentSettings,
        [switch]$EnclosureImport,
        [switch]$EnclosureRefresh,
        [switch]$EnclosureRefreshForceOptions,
        [switch]$EphemeralStorageVolume,
        [switch]$EthernetNetwork,
        [switch]$EulaStatus,
        [switch]$ExternalRepository,
        [switch]$FCNetwork,
        [switch]$FCoELossLessTrafficClass,
        [switch]$FCoENetwork,
        [switch]$FCAlias,
        [switch]$FCZone,
        [switch]$GlobalSetting,
        [switch]$IDPoolRange,
        [switch]$I3SAdd,
        [switch]$IloRestSession,
        [switch]$IPv4Subnet,
        [switch]$InterconnectBayMapping,
        [switch]$InterconnectMapEntryTemplate,
        [switch]$InsightOnlineRegistration,
        [switch]$IscsiBootEntry,
        [switch]$IscsiIPv4Configuration,
        [switch]$LogicalInterconnectBaseline,
        [switch]$C7kLIG,
        [switch]$SELIG,
        [switch]$SESASLIG,
        [switch]$LiUplinkSetObject,
        [switch]$LigUplinkSetObject,
        [switch]$LicenseKey,
        [switch]$LocationEntry,
        [switch]$LogicalEnclosure,
        [switch]$LogicalSwitchGroup,
        [switch]$LogicalSwitch,
        [switch]$LogicalSwitchCredentials,
        [switch]$LogicalSwitchSnmpV3Config,
        [switch]$LogialSwitchConnectionProperties,
        [switch]$LogicalSwitchConnectionProperty,
        [switch]$LoginMessageObject,
        [switch]$NetworkSet,
        [switch]$OSDeploymentSettings,
        [switch]$OSDeploymentPlanSetting,
        [switch]$PatchOperation,
        [switch]$Ping,
        [switch]$PowerDeliveryDeviceAdd,
        [switch]$Rack,
        [switch]$RackItem,
        [switch]$RabbitmqCertReq,
        [switch]$RemoteSupportConfig,
        [switch]$RemoteSupportContact,
        [switch]$RemoteSupportPartner,
        [switch]$RemoteSupportSchedule,
        [switch]$RemoteSupportSite,
        [switch]$RemoteSyslog,
        [switch]$QosConfiguration,
        [switch]$SanManager,
        [switch]$SanManagerConnectInfo,
        [switch]$ScopeCollection,
        [switch]$ScopeMemberUpdate,
        [switch]$SelfSignedCert,
        [switch]$ServerImport,
        [switch]$ServerProfile,
        [switch]$ServerProfileEthernetConnection,
        [switch]$ServerProfileFCConnection,
        [switch]$ServerProfileEthBootableConnection,
        [switch]$ServerProfileEthBootableConnectionWithTargets,
        [switch]$ServerProfileIscsiBootableConnectionWithTargets,
        [switch]$ServerProfileFcBootableConnection,
        [switch]$ServerProfileConnectionFcBootTarget,
        [switch]$ServerProfileLocalStorageController,
        [switch]$ServerProfileLocalStorageLogicalDrive,
        [switch]$ServerProfileSasLogicalJBOD,
        [switch]$ServerProfileStorageVolume,
        [switch]$ServerProfileTemplate,
        [switch]$ServerProfileTemplateLocalStorage,
        [switch]$SPTOSDeploymentSettings,
        [switch]$SmtpConfig,
        [switch]$SnmpConfig,
        [switch]$SnmpTrapDestination,
        [switch]$StoragePath,
        [switch]$StorageSystemCredentials,
        [switch]$StorageSystemManagedPort,
        [switch]$StoreServStorageVolume,
        [switch]$StoreVirtualStorageVolume,
        [switch]$StoreVirtualVolumeTemplate,
        [switch]$StoreServVolumeTemplate,
        [switch]$SwitchLogicalLocation,
        [switch]$TemporaryConnection,
        [switch]$TestSmtpConfig,
        [switch]$UpdateAlert,
        [switch]$UplinkSetLocation,
        [switch]$UplinkSetLocationEntry,
        [switch]$UplinkSetLogicalLocation,
        [switch]$UplinkSetLogicalLocationEntry,
        [switch]$UnmanagedDevice,
        [switch]$UserAccount,
        [switch]$UpdateUserPassword,
        [switch]$VcMigration,
        [switch]$VCMigratorReport,
        [switch]$VolSnapshot

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

    }

    Process
    {

        switch($PSBoundParameters.Keys)
        {
            
            'IloRestSession'
            {

                Return [PSCustomObject]@{
                    
                    RootUri        = $null;
                    "X-Auth-Token" = $null;
                    Location       = $null
                
                }

            }

            'SPTOSDeploymentSettings'
            {

                Return [PSCustomObject]@{

                    osCustomAttributes  = $null;
                    osDeploymentPlanUri = $null

                }

            }

            'ApplianceSslCertificate'
            {

                Return [PSCustomObject]@{

                    type       = "CertificateDataV2";
                    base64Data = $null

                }

            }

            'AddSslCertificate'
            {

                Return [PSCustomObject]@{

                    base64SSLCertData = $null;
                    type              = "SSLCertificateDTO"

                }

            }

            'ExternalRepository'
            {

                Return [PSCustomObject]@{

                    repositoryName = $null;
                    userName       = $null;
                    password       = $null;
                    repositoryURI  = $null;
                    repositoryType = "FirmwareExternalRepo";
                    base64Data     = $null

                }

            }

            'OSDeploymentPlanSetting'
            {

                Return [PSCustomObject]@{

                    name  = $null;
                    value = $null

                }

            }

            'OSDeploymentSettings'
            {

                Return [PSCustomObject]@{

                    osDeploymentPlanUri = $null;
                    osCustomAttributes  = New-Object System.Collections.ArrayList

                }

            }

            'DataCenter'
            {

                Return [PSCustomObject]@{

                    name                    = $null;
                    coolingCapacity         = 5;
                    costPerKilowattHour     = 0.10;
                    currency                = 'USD';
                    deratingType            = 'NaJp';
                    deratingPercentage      = 20.0;
                    defaultPowerLineVoltage = 220;
                    coolingMultiplier       = 1.5;
                    width                   = 0;
                    depth                   = 0;
                    contents                = New-Object System.Collections.ArrayList                        

                }

            }

            'Rack'
            {

                Return [PSCustomObject]@{
                    
                    name         = $null;
                    thermalLimit = $null;
                    serialNumber = $null;
                    partNumber   = $null;
                    uHeight      = 0
                    depth        = 0;
                    height       = 0;
                    width        = 0;
                    rackMounts   = New-Object System.Collections.ArrayList

                }

            }

            'DataCenterItem'
            {

                Return [PSCustomObject]@{

                    resourceUri = $null;
                    rotation    = 0;
                    x           = 0;
                    y           = 0

                }

            }

            'RackItem'
            {

                Return [PSCustomObject]@{

                    mountUri = $null;
                    location = 'CenterFront';
                    relativeOrder = -1;
                    topUSlot = 0;
                    uHeight  = 0

                }

            }

            'RemoteSupportSchedule'
            {

                Return [PSCustomObject]@{

                    type         = "Schedule";
                    taskType     = $null;
                    hourOfDay    = $null;
                    taskKey      = $null;
                    scheduleName = $null;
                    repeatOption = $null;
                    factory      = $true;
                    viewable     = $true;
                    serviceName  = $null;
                    minute       = $null;
                    dayOfMonth   = $null;
                    dayOfWeek    = $null;
                    enabled      = $true;
                    priority     = $null

                }

            }

            'RemoteSupportPartner'
            {

                Return [PSCustomObject]@{

                    type        = "ChannelPartner";
                    id          = $null;
                    default     = $false;
                    partnerType = "RESELLER"
                
                }

            }

            'ApplianceProxy'
            {

                Return [PSCustomObject] @{

                    type     = "ProxyServer";
                    server   = $null;
                    port     = $null;
                    username = $null;
                    password = $null;
                    credUri  = $null

                }

            }

            'InsightOnlineRegistration'
            {

                Return [PSCustomObject]@{
                    
                    type     = "PortalRegistration";
                    userName = "username";
                    password = "password"
                
                }

            }

            'RemoteSyslog'
            {

                Return [PSCustomObject]@{

                    type                    = "RemoteSyslog";
                    sendTestLog             = $false;
                    remoteSyslogPort        = "514";
                    remoteSyslogDestination = $null;
                    enabled                 = $true

                }

            }

            'I3SAdd'
            {

                Return [PSCustomObject]@{

                    description    = $null;
                    name           = $null;
                    mgmtNetworkUri = $null;
                    applianceUri   = $null

                }

            }

            'LogicalSwitch'
            {
                Return [PSCustomObject]@{

                    logicalSwitch = [PSCustomObject]@{
                        type = 'logical-switchV300';
                        name = $null;
                        managementLevel = $null
                        logicalSwitchGroupUri = $null;
                        switchCredentialConfiguration = New-Object System.Collections.ArrayList
                    
                    };
                    logicalSwitchCredentials = New-Object System.Collections.ArrayList

                }

            }

            'LogicalSwitchCredentials'
            {

                Return [PSCustomObject]@{

                    snmpV1Configuration = [PSCustomObject] @{communityString = $null};
                    snmpV3Configuration = NewObject -LogicalSwitchSnmpV3Config;
                    logicalSwitchManagementHost = $null;
                    snmpVersion = "SNMPv1";
                    snmpPort = 161

                }
                
            }

            'LogicalSwitchSnmpV3Config'
            {

                Return [PSCustomObject]@{

                    authorizationProtocol = $null;
                    privacyProtocol = $null;
                    securityLevel = $null

                }

            }

            'LogialSwitchConnectionProperties'
            {

                Return [PSCustomObject] @{ connectionProperties = New-Object System.Collections.ArrayList }
                
            }

            'LogicalSwitchConnectionProperty'
            {

                Return [PSCustomObject]@{
                
                    propertyName = $null;
                    value        = $null;
                    valueFormat  = 'Unknown';
                    valueType    = $null;
                
                }

            }

            'LogicalSwitchGroup'
            {

                Return [PSCustomObject]@{ 

                    type              = "logical-switch-groupV300";
                    name              = $null;
                    state             = "Active";
                    switchMapTemplate = [PSCustomObject]@{

                        switchMapEntryTemplates = New-Object System.Collections.ArrayList

                    }

                }

            }

            'SwitchLogicalLocation'
            {

                Return [PSCustomObject]@{

                    logicalLocation = [PSCustomObject]@{

                        locationEntries = New-Object System.Collections.ArrayList
                        
                    };
                    permittedSwitchTypeUri = $null
                }

            }

            'TemporaryConnection'
            {

                $_ID = 99

                While (-not($FoundID))
                {

                    if ($ConnectedSessions.ConnectionID -notcontains $_ID)
                    {

                        $FoundID = $_ID

                    }

                    $_ID--

                }

                $_TemporaryConnection = New-Object HPOneView.Appliance.Connection($_ID)

                $_TemporaryConnection.SessionID    = 'TemporaryConnection'
                $_TemporaryConnection.SslChecked   = $true

                [void]${Global:ConnectedSessions}.Add($_TemporaryConnection)

                Return $_TemporaryConnection

            }
            
            'ScopeMemberUpdate'
            {

                Return [PSCustomObject]@{

                    type                = "ScopeV2";
                    addedResourceUris   = New-Object System.Collections.ArrayList;
                    removedResourceUris = New-Object System.Collections.ArrayList
                                
                }

            }

            'EulaStatus'
            {
            
                Return [PSCustomObject]@{

                    EulaAccepted         = $false;
                    SupportAccessEnabled = $false

                }
                
            }  
            
            'EnclosureGroupPreview'
            {

                Return [PSCustomObject]@{

                    hostname = $null;
                    username = $null;
                    password = $null;
                    logicalInterconnectGroupNeeded = $true;
                    ligPrefix = $null

                }

            }

            'FCZone'
            {

                Return [PSCustomObject]@{
                
                    Name = $null;
                    State = $null;
                    Status = $null;
                    ManagedSan = $null;
                    Members = New-Object System.Collections.ArrayList;
                    Created = $null;
                    Modified = $null;
                    ApplianceConnection = $null    
                
                }

            }

            'FCAlias'
            {

                Return [PSCustomObject]@{
                
                    Name = $null;
                    WWN = $null;
                
                }

            }

            'UpdateUserPassword'
            {

                Return [PSCustomObject]@{

                    type            = 'UserAndRoles';
                    currentPassword = $null;
                    password        = $null;
                    userName        = $Null
                }

            }

            'VCMigratorReport'
            {

                Return [PSCustomObject]@{

                    apiVcMigrationReport = @{};
                    issueCount           = [int]$null;
                    migrationState       = [String]$Null;
                    VcemManaged          = [Bool]$False;
                    outReport            = New-Object System.Collections.ArrayList

                }

            }

            'EnclosureRefresh'
            {

                Return [PSCustomObject]@{ 

                    refreshState        = "RefreshPending"; 
                    refreshForceOptions = $null 
                }

            }

            'EnclosureRefreshForceOptions'
            {

                Return [PSCustomObject]@{

                    address  = $null;
                    username = $null;
                    password = $null

                }

            }

            'AutoBackupConfig'
            {

                Return [PSCustomObject]@{

                    remoteServerName      = $null;
                    remoteServerDir       = '';
                    remoteServerPublicKey = $null;
                    userName              = $null;
                    password              = $null;
                    enabled               = $true;
                    protocol              = 'SCP';
                    scheduleInterval      = 'NONE';
                    scheduleDays          = New-Object System.Collections.ArrayList
                    scheduleTime          = $null;
                    eTag                  = $null

                }     

            }

            'DirectoryGroupCredentials'
            {

                Return [PSCustomObject]@{

                    userName = $null;
                    password = $null

                }

            }

            'ApplianceTimeLocale'
            {

                Return [PSCustomObject]@{

                    type            = 'TimeAndLocale';
                    locale          = $null;
                    timezone        = 'UTC';
                    ntpServers      = New-Object System.Collections.ArrayList
                    pollingInterval = $null;

                }

            }

            'RemoteSupportConfig'
            {

                Return [PSCustomObject]@{

                    type                = 'Configuration';
                    eTag                = $null;
                    enableRemoteSupport = $false;
                    companyName         = $null;
                    marketingOptIn      = $false

                }

            }

            'RemoteSupportContact'
            {

                Return [PSCustomObject]@{

                    type           = 'Contact';
                    default        = $false;
                    alternatePhone = $null;
                    email          = $null;
                    firstName      = $null;
                    lastName       = $null;
                    language       = $null;
                    notes          = $null;
                    primaryPhone   = $null

                }

            }

            'RemoteSupportSite'
            {

                Return [PSCustomObject]@{

                    type           = 'Site';
                    name           = 'DEFAULT SITE'
                    default        = $true;
                    city           = $null;
                    postalCode     = $null;
                    provinceState  = $null;
                    streetAddress1 = $null;
                    streetAddress2 = $null;
                    countryCode    = $null;
                    timeZone       = $null

                }

            }

            'SnmpConfig'
            {

                Return [PSCustomObject]@{

                    type              = 'snmp-configuration'
                    readCommunity     = 'public';
                    enabled           = $true;
                    systemContact     = $null;
                    snmpAccess        = New-Object System.Collections.ArrayList;
                    trapDestinations  = New-Object System.Collections.ArrayList

                }
            
            }

            'SnmpTrapDestination'
            {

                Return [PSCustomObject]@{

                    trapDestination    = $null;
                    communityString    = $null;
                    trapFormat         = $null;
                    trapSeverities     = New-Object System.Collections.ArrayList;
                    vcmTrapCategories  = New-Object System.Collections.ArrayList;
                    enetTrapCategories = New-Object System.Collections.ArrayList;
                    fcTrapCategories   = New-Object System.Collections.ArrayList;

                }

            }

            'PatchOperation'
            {

                Return [PSCustomObject]@{

                    op    = $null;
                    path  = $null;
                    value = $null

                }

            }

            'IPv4Subnet'
            {

                Return [PSCustomObject]@{

                    type           = 'Subnet';
                    category       = 'id-range-IPv4-subnet';
                    name           = $null;
                    networkId      = $null;
                    subnetmask     = $null;
                    gateway        = $null;
                    domain         = $null;
                    dnsServers     = New-Object System.Collections.ArrayList;

                }

            }

            'LogicalEnclosure'
            {

                Return [PSCustomObject] @{ 
                    
                    name                 = $null;
                    enclosureUris        = New-Object System.Collections.ArrayList;
                    enclosureGroupUri    = $null;
                    firmwareBaselineUri  = $null;
                    forceInstallFirmware = $false

                }

            }

            'InterconnectMapEntryTemplate'
            {

                Return [PSCustomObject] @{
                        
                    #logicalDownlinkUri = $null;
                    permittedInterconnectTypeUri = $null;
                    enclosureIndex               = $null;
                    logicalLocation = [PSCustomObject]@{

                        locationEntries = New-Object System.Collections.ArrayList

                    }

                }

            }

            'InterconnectMapEntryTemplate'
            {

                Return [PSCustomObject] @{
                        
                    logicalDownlinkUri           = $null;
                    permittedInterconnectTypeUri = $null;
                    enclosureIndex               = $null;
                    logicalLocation = [PSCustomObject]@{

                        locationEntries = New-Object System.Collections.ArrayList

                    }

                }

            }

            'LocationEntry'
            {

                Return [PSCustomObject]@{

                    relativeValue = 1;
                    type          = $Null

                }

            }

            'LoginMessageObject'
            {

                Return [PSCustomObject]@{

                    Message             = $null;
                    Acknowledgment      = $null;
                    ApplianceConnection = $null

                }

            }

            'ConvertSnapshotToVol'
            {

                Return [PSCustomObject]@{

                    properties           = [PSCustomObject] @{

                        name             = $null;
                        description      = $null;
                        provisioningType = 'Thin';
                        storagePool      = $null;
                        snapshotPool     = $null;
                        isShareable      = $false

                    };
                    snapshotUri          = $null;
                    templateUri          = $null;
                    isPermanent          = $true;
                  
                }

            }

            'VolSnapshot'
            {

                Return [PSCustomObject]@{

                    name        = '{volumeName}_{timestamp}';
                    description = $null

                }

            }

            'LogicalInterconnectBaseline'
            {

                Return [PsCustomObject]@{ 
            
                    command                 = 'Update'; 
                    ethernetActivationType  = 'OddEven';
                    ethernetActivationDelay = 5;
                    fcActivationType        = 'OddEven';
                    fcActivationDelay       = 5;
                    sppUri                  = $null; 
                    force                   = $false
        
                }

            }

            'StoragePath'
            {

                Return [PSCustomObject]@{

                    targetSelector = "Auto";
                    targets        = New-Object System.Collections.ArrayList;
                    connectionId   = 1;
                    isEnabled      = $true

                }

            }

            'LicenseKey'
            {

                Return [PsCustomObject] @{

                    type = "LicenseV500";
                    key  = $null

                }

            }

            'UnmanagedDevice'
            {

                Return [PSCustomObject]@{ 
                
                    name           = [string]$null; 
                    model          = [string]$null; 
                    height         = [int]1; 
                    mac            = [string]$null;
                    ipv4Address    = [string]$null;
                    ipv6Address    = [string]$null;
                    maxPwrConsumed = [int]100 
                
                }

            }

            'RabbitmqCertReq'
            {

                Return [PSCustomObject] @{
        
                    commonName = 'default';
                    type       = 'RabbitMqClientCertV2'
            
                }

            }

            'AuthLogin'
            {

                Return [PSCustomObject] @{
        
                    userName        = $null;
                    password        = $null;
                    authLoginDomain = $null
            
                }

            }

            'DownloadFileStatus'
            {

                Return [PSCustomObject]@{

                    status              = $null;
                    file                = $null;
                    ApplianceConnection = $null

                }

            }

            'GlobalSetting'
            {

                Return [PSCustomObject]@{
                    
                    type  = "SettingV2"; 
                    name  = $null; 
                    value = $null
                
                }

            }

            'StoreVirtualVolumeTemplate'
            {

                Return [PSCustomObject]@{
                    
                    name            = $null;
                    description     = $null;
                    rootTemplateUri = $null;
                    properties      = @{
                        name = @{
                            title       = "Volume name";
                            description = "A volume name";
                            type        = "string";
                            default     = $null;
                            required    = $true;
                            maxLength   = 100;
                            minLength   = 1;
                            meta        = @{
                                locked = $false
                            }
                        };
                        description = @{
                            title       = "description";
                            description = "A description for the volume";
                            type        = "string";
                            default     = $null;
                            minLength   = 0;
                            maxLength   = 2000;
                            meta        = @{
                                locked = $false
                            }
                        };
                        storagePool = @{
                            title = "Storage pool";
                            description = "URI of the storage pool that the volume should be added to";
                            type = "string";
                            format = "x-uri-reference";
                            default = $null;
                            required = $true;
                            meta = @{
                                locked = $false;
                                createOnly = $true;
                                semanticType = "device-storage-pool"
                            }
                        };
                        size = @{
                            title = "Capacity";
                            description = "Capacity of the volume in bytes";
                            type = "integer";
                            minimum = 4194304;
                            default = 1073741824;
                            required = $true;
                            meta = @{
                                locked = $false;
                                semanticType = "capacity"
                            }
                        };
                        dataProtectionLevel = @{
                            title = "Data protection level";
                            description = "Indicates the number and configuration of data copies in the storage pool";
                            type = "string";
                            default = "NetworkRaid10Mirror2Way";
                            required = $true;
                            enum = @(
                                "NetworkRaid0None",
                                "NetworkRaid5SingleParity",
                                "NetworkRaid10Mirror2Way",
                                "NetworkRaid10Mirror3Way",
                                "NetworkRaid10Mirror4Way",
                                "NetworkRaid6DualParity"
                            );
                            meta = @{
                                locked = $false;
                                semanticType = "device-dataProtectionLevel"
                            }
                        };
                        provisioningType = @{
                            title = "Provisioning type";
                            description = "The provisioning type for the volume";
                            type = "string";
                            enum = @(
                                "Thin",
                                "Full"
                            )
                            default = "Thin";
                            meta = @{
                                locked = $false;
                                createOnly = $true;
                                semanticType = "device-provisioningType"
                            }
                        };
                        isAdaptiveOptimizationEnabled = @{
                            title = "Adaptive optimization";
                            description = "";
                            type = "boolean";
                            default = $true;
                            meta = @{
                                locked = $false
                            }
                        };
                        isShareable = @{
                            title = "Is shareable";
                            description = "The shareability of the volume";
                            type = "boolean";
                            default = $false;
                            meta = @{
                                locked = $false
                            }
                        
                        }

                    }

                }

            }

            'StoreServVolumeTemplate'
            {

                Return [PSCustomObject]@{
                    
                    name            = $null;
                    description     = $null;
                    rootTemplateUri = $null;
                    properties      = @{
                        name = @{
                            title       = "Volume name";
                            description = "A volume name";
                            type        = "string";
                            default     = $null;
                            required    = $true;
                            maxLength   = 100;
                            minLength   = 1;
                            meta        = @{
                                locked = $false
                            }
                        };
                        description = @{
                            title       = "description";
                            description = "A description for the volume";
                            type        = "string";
                            default     = $null;
                            minLength   = 0;
                            maxLength   = 2000;
                            meta        = @{
                                locked = $false
                            }
                        };
                        storagePool = @{
                            title = "Storage pool";
                            description = "URI of the storage pool that the volume should be added to";
                            type = "string";
                            format = "x-uri-reference";
                            default = $null;
                            required = $true;
                            meta = @{
                                locked = $false;
                                createOnly = $true;
                                semanticType = "device-storage-pool"
                            }
                        };
                        size = @{
                            title = "Capacity";
                            description = "Capacity of the volume in bytes";
                            type = "integer";
                            minimum = 268435456;
                            maximum = 17592186044416;
                            default = 1073741824;
                            required = $true;
                            meta = @{
                                locked = $false;
                                semanticType = "capacity"
                            }
                        };
                        provisioningType = @{
                            title = "Provisioning type";
                            description = "The provisioning type for the volume";
                            type = "string";
                            enum = @(
                                "Thin",
                                "Full",
                                "Thin Deduplication"
                            )
                            default = "Thin";
                            meta = @{
                                locked = $false;
                                createOnly = $true
                            }
                        };
                        isShareable = @{
                            title = "Is shareable";
                            description = "The shareability of the volume";
                            type = "boolean";
                            default = $false;
                            meta = @{
                                locked = $false
                            }
                        
                        };
                        snapshotPool = @{

                            title = "Snapshot Pool";
                            description = "A URI reference to the common provisioning group used to create snapshots";
                            type = "string";
                            format = "x-uri-reference";
                            default = $null;
                            meta = @{
                                locked = $false;
                                semanticType = "device-snapshot-storage-pool"
                            }

                        }

                    }

                }

            }

            'CustomBaselineRestore'
            {

                Return [PSCustomObject]@{

                    baselineUri        = $null;
                    hotfixUris         = New-Object System.Collections.ArrayList;
                    customBaselineName = $null

                }

            }

            'SmtpConfig'
            {

                Return [PSCustomObject]@{
        
                    type               = "EmailNotificationV2";
                    senderEmailAddress = $null;
                    password           = $null;
                    smtpServer         = $null;
                    smtpPort           = 25;
                    alertEmailDisabled = $false;
                    alertEmailFilters  = New-Object System.Collections.ArrayList
                
                }

            }

            'TestSmtpConfig'
            {

                Return [PSCustomObject]@{
        
                    type            = "Email";
                    subject         = $null;
                    htmlMessageBody = $null;
                    textMessageBody = $null;
                    toAddress       = New-Object System.Collections.ArrayList
                
                }

            }

            'UpdateAlert'
            {

                Return [PSCustomObject] @{ 
            
                    alertState     = $null;
                    assignedToUser = $null;
                    notes          = $null;
                    eTag           = $null
                
                } 

            }

            'SelfSignedCert'
            {
            
                Return [PSCustomObject]@{

                    type               = "CertificateDtoV2";
                    country            =  $null;
                    state              =  $null;
                    locality           =  $null;
                    organization       =  $null;
                    commonName         =  $null;
                    organizationalUnit =  $null;
                    alternativeName    =  $null;
                    contactPerson      =  $null;
                    email              =  $null;
                    surname            =  $null;
                    givenName          =  $null;
                    initials           =  $null;
                    dnQualifier        =  $null

                }    
            
            }

            'ApplianceCSR'
            {

                Return [PSCustomObject]@{

                    type               = "CertificateDtoV2";
                    country            =  $null;
                    state              =  $null;
                    locality           =  $null;
                    organization       =  $null;
                    commonName         =  $null;
                    organizationalUnit =  $null;
                    alternativeName    =  $null;
                    contactPerson      =  $null;
                    email              =  $null;
                    surname            =  $null;
                    givenName          =  $null;
                    initials           =  $null;
                    dnQualifier        =  $null;
                    unstructuredName   =  $null;
                    challengePassword  =  $null

                }    

            }

            'AuthDirectory'
            {

                Return [PSCustomObject]@{
                    
                    type                = 'LoginDomainConfigVersion200'
                    authProtocol        = 'AD';
                    baseDN              = $null;
                    orgUnits            = New-Object System.Collections.ArrayList
                    userNamingAttribute = 'CN';
                    name                = $null;
                    credential          = [PSCustomObject]@{
                        
                        userName = $null; 
                        password = $null
                    
                    };
                    directoryServers    = New-Object System.Collections.ArrayList;

                }

            }

            'DirectoryGroup'
            {

                Return [PSCustomObject]@{

                    type                = 'Group2RolesMappingPerGroupValidationDto';
                    group2rolesPerGroup = [PSCustomObject]@{
                    
                        type        = 'Group2RolesMappingPerGroupDto';
                        loginDomain = $null;
                        egroup      = $null;
                        roles       = New-Object System.Collections.ArrayList;

                    }
                    credentials = NewObject -DirectoryGroupCredentials

                }

            }

            'AuthDirectoryServer'
            {

                Return [PSCustomObject]@{

                    type                                 = 'LoginDomainDirectoryServerInfoDto'
                    directoryServerCertificateBase64Data = $null;
                    directoryServerIpAddress             = $null;
                    directoryServerSSLPortNumber         = "636";

                }

            }

            'IDPoolRange'
            {

                Return [PsCustomObject]@{ 

                    type          = 'Range'; 
                    rangeCategory = 'Custom';
                    name          = $null;
                    enabled       = $true;
                    startAddress  = $null; 
                    endAddress    = $null;
                    subnetUri     = $null

                }

            }

            'UserAccount'
            {

                Return [PsCustomObject]@{

                    type         = "UserAndRoles";
                    userName     = $null; 
                    fullName     = $null; 
                    password     = $null; 
                    emailAddress = $emailAddress; 
                    officePhone  = $null; 
                    mobilePhone  = $null; 
                    enabled      = $True;
                    roles        = $null

                }

            }

            'PowerDeliveryDeviceAdd'
            {

                Return [PSCustomObject]@{

                    hostname = $null;
                    username = $null;
                    password = $null;
                    force    = $null

                }

            }
            
            'ApplianceDebug'
            {

                Return [PSCustomObject]@{

                    scope      = $null;
                    loggerName = $null;
                    level      = $null

                }

            }

            'AlertFilter'
            {

                Return [PSCustomObject]@{

                    filterName      = $null;
                    disabled        = $False;
                    filter          = $null;
                    displayFilter   = $null;
                    userQueryFilter = $null;
                    emails          = $null;
                    scopeQuery      = $null 

                }

            }

            'ServerProfile'
            {

                Return [PSCustomObject]@{

                    type                  = "ServerProfileV7"; 
                    name                  = $null; 
                    description           = $null; 
                    affinity              = $null;
                    hideUnusedFlexNics    = $true;
                    bios                  = [PSCustomObject]@{

                        manageBios         = $false;
                        overriddenSettings = $null

                    }; 
                    firmware                 = [PSCustomObject]@{

                        manageFirmware         = $false;
                        firmwareBaselineUri    = $null;
                        forceInstallFirmware   = $false;
                        firmwareInstallType    = 'FirmwareAndOSDrivers';
                        firmwareActivationType = 'Immediate'
                            
                    };
                    boot           = [PSCustomObject]@{
                       
                        manageBoot = $false; 
                        order      = New-Object System.Collections.ArrayList
                           
                    };
                    bootMode                 = $null;
                    localStorage             = [PSCustomObject]@{

                        sasLogicalJBODs = New-Object System.Collections.ArrayList; 
                        controllers     = New-Object System.Collections.ArrayList

                    }
                    serialNumberType         = 'Virtual'; 
                    macType                  = 'Virtual';
                    wwnType                  = 'Virtual';
                    connections              = New-Object System.Collections.ArrayList; 
                    serialNumber             = $null;
                    iscsiInitiatorNameType   = 'AutoGenerated'
                    serverHardwareUri        = $null;
                    serverHardwareTypeUri    = $null;
                    serverProfileTemplateUri = $null;
                    enclosureBay             = $null;
                    enclosureGroupUri        = $null;
                    enclosureUri             = $null;
                    sanStorage               = $null;
                    uuid                     = $null;
                }

            }

            'ServerProfileTemplate'
            {

                Return [PSCustomObject]@{

                    type                     = "ServerProfileTemplateV3"; 
                    serverProfileDescription = $null;
                    serverHardwareTypeUri    = $null;
                    enclosureGroupUri        = $null;
                    serialNumberType         = 'Virtual'; 
                    macType                  = 'Virtual';
                    wwnType                  = 'Virtual';
                    name                     = $null; 
                    description              = $null; 
                    affinity                 = $null;
                    connectionSettings       = @{

                        connections              = New-Object System.Collections.ArrayList;
                        manageConnections        = $true

                    }
                    
                    boot                     = [PSCustomObject]@{
                               
                        manageBoot = $true; 
                        order      = New-Object System.Collections.ArrayList
                                   
                    };
                    bootMode                 = $null;
                    firmware                 = [PSCustomObject]@{

                        manageFirmware         = $false;
                        firmwareBaselineUri    = $null;
                        forceInstallFirmware   = $false;
                        firmwareInstallType    = 'FirmwareAndOSDrivers';
                        firmwareActivationType = 'Immediate'
                            
                    };
                    bios                     = [PSCustomObject]@{

                        manageBios         = $false;
                        overriddenSettings = New-Object System.Collections.ArrayList

                    }; 
                    hideUnusedFlexNics       = $true;
                    iscsiInitiatorNameType   = "AutoGenerated";
                    localStorage             = [PSCustomObject]@{

                        sasLogicalJBODs = New-Object System.Collections.ArrayList; 
                        controllers     = New-Object System.Collections.ArrayList

                    }
                    sanStorage               = $null;

                }

            } 

            'ServerProfileTemplateLocalStorage'
            {

                Return [PSCustomObject]@{

                    slotNumber          = '0';
                    managed             = $true;
                    mode                = 'RAID'
                    initialize          = $false;
                    logicalDrives       = New-Object System.Collections.ArrayList

                }

            }

            'ServerProfileLocalStorageController'
            {

                Return [PSCustomObject]@{

                    deviceSlot          = 'Embedded';
                    importConfiguration = $false;
                    mode                = 'RAID'
                    initialize          = $false;
                    logicalDrives       = New-Object System.Collections.ArrayList

                }

            }

            'ServerProfileLocalStorageLogicalDrive'
            {

                Return [PSCustomObject]@{ 

                    name              = $null;
                    bootable          = $false;
                    raidLevel         = $null;
                    numPhysicalDrives = $null;
                    driveTechnology   = $null;
                    sasLogicalJBODId  = $null
                
                }

            }

            'ServerProfileSasLogicalJBOD'
            {

                Return [PSCustomObject]@{

                    id                = 1;
                    deviceSlot        = $null;
                    name              = $null
                    numPhysicalDrives = 1;
                    driveMinSizeGB    = 0;
                    driveMaxSizeGB    = 0;
                    driveTechnology   = $null

                }

            }

            'EnclosureImport'
            {

                Return [PSCustomObject]@{

                    hostname             = $null;
                    username             = $null;
                    password             = $null;
                    licensingIntent      = 'OneView';
                    force                = $false;
                    enclosureGroupUri    = $null;
                    firmwareBaselineUri  = $null;
                    forceInstallFirmware = $false;
                    updateFirmwareOn     = $null;
                    state                = $null
                
                }

            }

            'ServerImport'
            {

                Return [PSCustomObject]@{

                    hostname             = $null;
                    username             = $null;
                    password             = $null;
                    force                = $false;
                    licensingIntent      = 'OneVeiw';
                    configurationState   = $null
                
                }

            }

            'StorageSystemCredentials'
            {

                Return [PSCustomObject]@{
                    
                    hostname = $null; 
                    username = $null; 
                    password = $null;
                    family   = $null
                
                }

            }

            'StorageSystemManagedPort'
            {

                Return [PSCustomObject]@{

                    type                = "StorageTargetPortV3"; 
                    portName            = $null; 
                    name                = $null;
                    expectedNetworkUri  = $null; 
                    expectedNetworkName = $null;
                    actualNetworkUri    = $null; 
                    actualNetworkSanUri = $null;
                    portWwn             = $null; 
                    groupName           = 'Auto'; 
                    label               = $null;
                    protocolType       = 'FC'

                }

            }

            'StoreServStorageVolume'
            {

                Return [PSCustomObject]@{

                    properties = @{
                        name             = $null;
                        description      = $null;
                        storagePool      = $null;
                        size             = 107374182400;
                        provisioningType = "Thin";
                        isShareable      = $false;
                        snapshotPool     = $null
                    };
                    templateUri = $null

                }

            }

            'StoreVirtualStorageVolume'
            {

                Return [PSCustomObject]@{

                    properties = @{
                        name                          = $null;
                        description                   = $null;
                        storagePool                   = $null;
                        size                          = 107374182400;
                        provisioningType              = "Thin";
                        isShareable                   = $false;
                        dataProtectionLevel           = $null
                        isAdaptiveOptimizationEnabled = $false
                    };
                    templateUri = $null

                }

            }

            'ServerProfileStorageVolume'
            {

                Return [PsCustomObject]@{
            
                    id                     = $null;
                    lun                    = $null;
                    volumeUri              = $null;
                    volumeStoragePoolUri   = $null;
                    volumeStorageSystemUri = $null;
                    lunType                = 'Auto';
                    storagePaths           = New-Object System.Collections.ArrayList;
                    isBootVolume           = $false;
                    ApplianceConnection    = $null;

                }   

            }

            'AddStorageVolume'
            {

                Return [PSCustomObject]@{

                    description      = $null;
                    deviceVolumeName = $null;
                    isShareable      = $false;
                    name             = $null;
                    storageSystemUri = $null;

                }

            }

            'AddStorageVolumeV3'
            {

                Return [PSCustomObject]@{

                    type                    = 'AddStorageVolumeV3';
                    name                    = $null;
                    description             = $null;
                    storageSystemUri        = $null;
                    storageSystemVolumeName = $null;
                    provisioningParameters  = [PSCustomObject]@{

                        shareable = $false
                    
                    }
                
                }

            }

            'EphemeralStorageVolume'
            {

                Return [PsCustomObject]@{
            
                    id                             = 1;
                    lun                            = $null;
                    lunType                        = 'Auto';
                    volumeStoragePoolUri           = $null;
                    volumeStorageSystemUri         = $null;
                    volumeName                     = $null;
                    volumeProvisionType            = 'Thin';
                    volumeProvisionedCapacityBytes = '10737418240';
                    isBootVolume                   = $false;
                    permanent                      = $true;
                    volumeShareable                = $false;
                    ApplianceConnection            = $null;
                    storagePaths                   = New-Object System.Collections.ArrayList

                }

            }

            'ServerProfileEthernetConnection'
            {

                Return [PSCustomObject]@{
            
                    id                  = 1;
                    functionType        = 'Ethernet';
                    name                = $null;
                    portId              = $null; 
                    networkUri          = $null; 
                    requestedMbps       = 2000; 
                    boot                = $null;
                    macType             = 'Virtual';
                    mac                    = $null;
                    requestedVFs        = '0';
                    ApplianceConnection = $null

                }

            }

            'ServerProfileFCConnection'
            {

                Return [PSCustomObject]@{
            
                    id                  = 1;
                    functionType        = 'FibreChannel';
                    name                = $null;
                    portId              = $null; 
                    networkUri          = $null; 
                    requestedMbps       = 2000; 
                    boot                = $null;
                    macType             = 'Virtual';
                    mac                    = $null;
                    wwpnType            = 'Virtual';
                    wwnn                = $null;
                    wwpn                = $null;
                    ApplianceConnection = $null

                }

            }

            'ServerProfileEthBootableConnection'
            {

                Return [PSCustomObject]@{

                    priority         = 'NotBootable';
                    ethernetBootType = "PXE";
                    iscsi            = $null

                }

            }

            'ServerProfileEthBootableConnectionWithTargets'
            {

                Return [PSCustomObject]@{

                    priority         = 'NotBootable';
                    targets          = New-Object System.Collections.ArrayList;
                    bootVolumeSource = 'AdapterBIOS';
                    ethernetBootType = "PXE";
                    iscsi            = $null

                }

            }

            'ServerProfileIscsiBootableConnectionWithTargets'
            {

                Return [PSCustomObject]@{

                    priority         = 'NotBootable';
                    targets          = New-Object System.Collections.ArrayList;
                    bootVolumeSource = 'AdapterBIOS';
                    iscsi            = $null

                }

            }

            'ServerProfileFcBootableConnection'
            {

                Return [PSCustomObject]@{

                    priority         = 'NotBootable';
                    targets          = New-Object System.Collections.ArrayList;
                    bootVolumeSource = 'AdapterBIOS'

                }

            }

            'ServerProfileConnectionFcBootTarget'
            {

                Return [PSCustomObject]@{

                    arrayWwpn = $null;
                    lun       = $null

                }

            }

            'IscsiBootEntry'
            {

                Return [PSCustomObject]@{
                        
                    initiatorNameSource  = "ProfileInitiatorName";
                    firstBootTargetIp    = $null;
                    firstBootTargetPort  = $null;
                    secondBootTargetIp   = $null;
                    secondBootTargetPort = $null;
                    chapLevel            = $null;
                    initiatorName        = $null;
                    bootTargetName       = $null;
                    bootTargetLun        = $null;
                    chapName             = $null;
                    chapSecret           = $null;
                    mutualChapName       = $null;
                    mutualChapSecret     = $null

                }

            }

            'IscsiIPv4Configuration'
            {

                Return [PSCustomObject]@{
                        
                    ipAddress       = $null;
                    subnetMask      = $null;
                    gateway         = $null;
                    ipAddressSource = 'UserDefined'

                }

            }

            'SanManager'
            {

                Return [PSCustomObject]@{
            
                    "connectionInfo" = New-Object System.Collections.ArrayList
                    
                }

            }

            'SanManagerConnectInfo'
            {

                Return [PSCustomObject]@{
                
                    name  = $null;
                    Value = $null
                
                }

            }

            'EthernetNetwork'
            {

                Return [pscustomobject]@{
                            
                    type                = "ethernet-networkV300"; 
                    vlanId              = 1; 
                    ethernetNetworkType = 'Tagged'; 
                    purpose             = 'General'; 
                    name                = $null; 
                    smartLink           = $false;
                    privateNetwork      = $false;
                    subnetUri           = $null

                }

            }

            'BulkEthernetNetworks'
            {

                Return [pscustomobject]@{

                    type           = "bulk-ethernet-network"; 
                    vlanIdRange    = $null; 
                    purpose        = 'General'; 
                    namePrefix     = $null; 
                    smartLink      = $false; 
                    privateNetwork = $false;
                    bandwidth      = [PSCustomObject]@{
                                    
                        typicalBandwidth = 1;
                        maximumBandwidth = 10000
                                    
                    }

                }

            }

            'FCNetwork'
            {

                [pscustomobject]@{

                    type                    = "fc-networkV300"; 
                    name                    = $Name; 
                    linkStabilityTime       = 30; 
                    autoLoginRedistribution = $true; 
                    fabricType              = 'FabricAttach'; 
                    connectionTemplateUri   = $null;
                    managedSanUri           = $null
                        
                }

            }

            'FCoENetwork'
            {

                Return [pscustomobject]@{
                        
                    type                  = "fcoe-networkV300"; 
                    name                  = $null; 
                    vlanId                = 1; 
                    connectionTemplateUri = $null;
                    managedSanUri         = $null

                }
                
            }

            'NetworkSet'
            {

                Return [PSCustomObject] @{

                    type             = 'network-setV300'; 
                    name             = $null; 
                    networkUris      = New-Object System.Collections.ArrayList; 
                    nativeNetworkUri = $null; 
                
                }

            }

            'EnclosureGroup'
            {

                Return [PSCustomObject]@{

                    type                        = "EnclosureGroupV400";
                    name                        = $null;
                    enclosureTypeUri            = $C7000EnclosureTypeUri; 
                    stackingMode                = 'Enclosure';
                    interconnectBayMappingCount = [int]0;
                    interconnectBayMappings     = [System.Collections.ArrayList]@();
                    configurationScript         = $null;
                    powerMode                   = 'RedundantPowerFeed';
                    ipAddressingMode            = $null;
                    ipRangeUris                 = [System.Collections.ArrayList]@();
                    enclosureCount              = 1;
                    osDeploymentSettings        = $null

                }

            }

            'DeploymentModeSettings'
            {

                Return [PSCustomObject]@{

                    deploymentModeSettings = $null;
                    manageOSDeployment     = $false

                }

            }

            'EnclosureGroupI3SDeploymentSettings'
            {

                Return [PSCustomObject]@{

                    deploymentMode       = 'None';
                    deploymentNetworkUri = $null

                }

            }

            'InterconnectBayMapping'
            {

                Return [PSCustomObject]@{
                    
                    enclosureIndex              = 1;
                    interconnectBay             = 1; 
                    logicalInterconnectGroupUri = $null
                
                }

            }

            'ApplianceVersion'
            {

                Return [PSCustomObject]@{

                    applianceName    = $null;
                    softwareVersion  = $null; 
                    major            = $null;
                    minor            = $null;
                    xapiVersion      = $null;
                    modelNumber      = $null

                }

            }

            'AllApiResponse'
            {

                Return [PSCustomObject]@{

                    type        = [string]$null;
                    nextPageUri = [string]$null;
                    start       = [int]0;
                    prevPageUri = [string]$null;
                    total       = [int]0;
                    count       = [int]0;
                    members     = New-Object System.Collections.ArrayList;
                    eTag        = [string]$null;
                    created     = [string]$null;
                    modified    = [string]$null;
                    category    = [string]$null;
                    uri         = [string]$null

                }

            }

            #Default LIG Object
            "C7KLIG"
            {
            
                Return [PSCustomObject]@{
                    name                    = $Null;
                    uplinkSets              = New-Object System.Collections.ArrayList; 
                    interconnectMapTemplate = [PSCustomObject]@{
                        
                        interconnectMapEntryTemplates = New-Object System.Collections.ArrayList};

                    internalNetworkUris     = New-Object System.Collections.ArrayList; 
                    ethernetSettings = [PSCustomObject]@{

                        type                        = "EthernetInterconnectSettingsV201";
                        enableIgmpSnooping          = $false;
                        igmpIdleTimeoutInterval     = 260; 
                        enableFastMacCacheFailover  = $true;
                        macRefreshInterval          = 5;
                        enableNetworkLoopProtection = $false;
                        enablePauseFloodProtection  = $false;
                        enableRichTLV               = $false;
                        enableTaggedLldp            = $false
                        
                    };
                    snmpConfiguration       = $Null;
                    qosConfiguration        = [PSCustomObject]@{
                        
                        type                     = "qos-aggregated-configuration";
                        activeQosConfig          = $Null;
                        inactiveFCoEQosConfig    = $null;
                        inactiveNonFCoEQosConfig = $null

                            
                    };
                    stackingMode            = "Enclosure";
                    enclosureType           = "C7000";
                    type                    = "logical-interconnect-groupV300"

                }

            }

            "SELIG"
            {
            
                Return [PSCustomObject]@{
                    type                    = "logical-interconnect-groupV300"
                    name                    = $Null;
                    uplinkSets              = New-Object System.Collections.ArrayList; 
                    interconnectMapTemplate = [PSCustomObject]@{interconnectMapEntryTemplates = New-Object System.Collections.ArrayList};
                    internalNetworkUris     = New-Object System.Collections.ArrayList; 
                    ethernetSettings = [PSCustomObject]@{

                        type                        = "EthernetInterconnectSettingsV201";
                        enableIgmpSnooping          = $false;
                        igmpIdleTimeoutInterval     = 260; 
                        enableFastMacCacheFailover  = $true;
                        macRefreshInterval          = 5;
                        enableNetworkLoopProtection = $false;
                        enablePauseFloodProtection  = $false;
                        enableRichTLV               = $false;
                        enableTaggedLldp            = $false
                        
                    };
                    snmpConfiguration       = $Null;
                    qosConfiguration        = [PSCustomObject]@{
                        
                        type                     = "qos-aggregated-configuration";
                        activeQosConfig          = $Null;
                        inactiveFCoEQosConfig    = $null;
                        inactiveNonFCoEQosConfig = $null

                            
                    };
                    enclosureType      = 'SY12000';
                    enclosureIndexes   = New-Object System.Collections.ArrayList;
                    interconnectBaySet = 1;
                    redundancyType     = 'Redundant'
                    
                }

            }

            "SESASLIG"
            {
            
                Return [PSCustomObject]@{
                    type                    = "sas-logical-interconnect-group"
                    name                    = $Null;
                    interconnectMapTemplate = [PSCustomObject]@{
                        
                        interconnectMapEntryTemplates = New-Object System.Collections.ArrayList};

                    enclosureType      = 'SY12000';
                    enclosureIndexes   = @(1);
                    interconnectBaySet = 1
                    
                }

            }
            
            #Default qosConfiguration Object for LIG
            "QosConfiguration"
            {
                
                Return [PSCustomObject]@{
                
                    type                       = "QosConfiguration";
                    configType                 = "Passthrough";
                    qosTrafficClassifiers      = [System.Collections.ArrayList]@()
                    uplinkClassificationType   = $Null; #Leave Null to support default 'Passthrough'
                    downlinkClassificationType = $Null; #Leave Null to support default 'Passthrough'
                
                }

            }

            'QosIngressClassMapping'
            {

                Return [PSCustomObject]@{
                        
                    dot1pClassMapping = New-Object System.Collections.ArrayList;
                    dscpClassMapping  = New-Object System.Collections.ArrayList
                            
                }

            }

            #Default With FCoE Lossless Traffic Classifiers Object
            "DefaultFCoELosslessQosTrafficClassifiers"
            {
            
                Return @(

                    #1
                    [PSCustomObject]@{ 
                    qosTrafficClass = [PSCustomObject]@{
            
                        maxBandwidth     = 100;
                        bandwidthShare   = "65";
                        egressDot1pValue = 0;
                        realTime         = $false;
                        className        = "Best effort";
                        enabled          = $true;
            
                    };
                            
                    qosClassificationMapping = [PSCustomObject]@{
            
                        dot1pClassMapping = [System.Collections.ArrayList]@(1,0);
                        dscpClassMapping  = [System.Collections.ArrayList]@(
            
                            "DSCP 10, AF11",
                            "DSCP 12, AF12",
                            "DSCP 14, AF13",
                            "DSCP 8, CS1",
                            "DSCP 0, CS0"
            
                        )
            
                    }
            
                },
                            
                    #2
                    [PSCustomObject]@{ 
                    qosTrafficClass = [PSCustomObject]@{
            
                        maxBandwidth     = 100;
                        bandwidthShare   = "0";
                        egressDot1pValue = 0;
                        realTime         = $false;
                        className        = "Class1";
                        enabled          = $false;
            
                    };
                                
                    qosClassificationMapping = $null
            
                },
                
                    #3
                    [PSCustomObject]@{ 
                    qosTrafficClass = [PSCustomObject]@{
            
                        maxBandwidth     = 100;
                        bandwidthShare   = "0";
                        egressDot1pValue = 0;
                        realTime         = $false;
                        className        = "Class2";
                        enabled          = $false;
            
                    };
                                
                    qosClassificationMapping = $null
            
                },
                
                    #4
                    [PSCustomObject]@{ 
                    qosTrafficClass = [PSCustomObject]@{
            
                        maxBandwidth     = 100;
                        bandwidthShare   = "0";
                        egressDot1pValue = 0;
                        realTime         = $false;
                        className        = "Class3";
                        enabled          = $false;
            
                    };
                                
                    qosClassificationMapping = $null
            
                },
                
                    #5
                    [PSCustomObject]@{ 
                    qosTrafficClass = [PSCustomObject]@{
            
                        maxBandwidth     = 100;
                        bandwidthShare   = "0";
                        egressDot1pValue = 0;
                        realTime         = $false;
                        className        = "Class4";
                        enabled          = $false;
            
                    };
                                
                    qosClassificationMapping = $null
            
                },
                
                    #6
                    [PSCustomObject]@{ 
                    qosTrafficClass = [PSCustomObject]@{
            
                        maxBandwidth     = 100;
                        bandwidthShare   = "fcoe";
                        egressDot1pValue = 3;
                        realTime         = $false;
                        className        = "FCoE lossless";
                        enabled          = $true;
            
                    };                    
                            
                    qosClassificationMapping = [PSCustomObject]@{
            
                        dot1pClassMapping = [System.Collections.ArrayList]@(3);
                        dscpClassMapping  = [System.Collections.ArrayList]@()
            
                    }
            
                },
                
                    #7
                    [PSCustomObject]@{ 
                    qosTrafficClass = [PSCustomObject]@{
            
                        maxBandwidth     = 100;
                        bandwidthShare   = "25";
                        egressDot1pValue = 2;
                        realTime         = $false;
                        className        = "Medium";
                        enabled          = $true;
            
                    };
                                
                    qosClassificationMapping = [PSCustomObject]@{
            
                        dot1pClassMapping = [System.Collections.ArrayList]@(4,3,2);
                        dscpClassMapping  = [System.Collections.ArrayList]@(
            
                            "DSCP 18, AF21",
                            "DSCP 20, AF22",
                            "DSCP 22, AF23",
                            "DSCP 26, AF31",
                            "DSCP 28, AF32",
                            "DSCP 30, AF33",
                            "DSCP 34, AF41",
                            "DSCP 36, AF42",
                            "DSCP 38, AF43",
                            "DSCP 16, CS2",
                            "DSCP 24, CS3",
                            "DSCP 32, CS4"
            
                        )
            
                    }
            
                },
                
                    #8
                    [PSCustomObject]@{ 
                    qosTrafficClass = [PSCustomObject]@{
            
                        maxBandwidth     = 10;
                        bandwidthShare   = "10";
                        egressDot1pValue = 5;
                        realTime         = $true;
                        className        = "Real time";
                        enabled          = $true;
            
                    };
                                
                    qosClassificationMapping = [PSCustomObject]@{
            
                        dot1pClassMapping = [System.Collections.ArrayList]@(5,6,7);
                        dscpClassMapping  = [System.Collections.ArrayList]@(
            
                            "DSCP 46, EF",
                            "DSCP 40, CS5",
                            "DSCP 48, CS6",
                            "DSCP 56, CS7"
            
                        )
            
                    }
            
                }
                
                )

            }

            #Default With No FCoE Lossless Traffic Classifiers Object
            "DefaultNoFCoELosslessQosTrafficClassifiers" 
            {
                
                Return @(

                    #1
                    [PSCustomObject]@{ 
                        qosTrafficClass = [PSCustomObject]@{

                            maxBandwidth     = 100;
                            bandwidthShare   = "65";
                            egressDot1pValue = 0;
                            realTime         = $false;
                            className        = "Best effort";
                            enabled          = $true;

                        };
                                
                        qosClassificationMapping = [PSCustomObject]@{

                            dot1pClassMapping = [System.Collections.ArrayList]@(1,0);
                            dscpClassMapping  = [System.Collections.ArrayList]@(

                                "DSCP 10, AF11",
                                "DSCP 12, AF12",
                                "DSCP 14, AF13",
                                "DSCP 8, CS1",
                                "DSCP 0, CS0"

                            )

                        }

                    },
                                            
                    #2
                    [PSCustomObject]@{ 
                        qosTrafficClass = [PSCustomObject]@{

                            maxBandwidth     = 100;
                            bandwidthShare   = "0";
                            egressDot1pValue = 0;
                            realTime         = $false;
                            className        = "Class1";
                            enabled          = $false;

                        };
                                    
                        qosClassificationMapping = $null

                    },
                                
                    #3
                    [PSCustomObject]@{ 
                        qosTrafficClass = [PSCustomObject]@{

                            maxBandwidth     = 100;
                            bandwidthShare   = "0";
                            egressDot1pValue = 0;
                            realTime         = $false;
                            className        = "Class2";
                            enabled          = $false;

                        };
                                    
                        qosClassificationMapping = $null

                    },
                                
                                    #4
                                    [PSCustomObject]@{ 
                        qosTrafficClass = [PSCustomObject]@{

                            maxBandwidth     = 100;
                            bandwidthShare   = "0";
                            egressDot1pValue = 0;
                            realTime         = $false;
                            className        = "Class3";
                            enabled          = $false;

                        };
                                    
                        qosClassificationMapping = $null

                    },
                                
                    #5
                    [PSCustomObject]@{ 
                        qosTrafficClass = [PSCustomObject]@{

                            maxBandwidth     = 100;
                            bandwidthShare   = "0";
                            egressDot1pValue = 0;
                            realTime         = $false;
                            className        = "Class4";
                            enabled          = $false;

                        };
                                    
                        qosClassificationMapping = $null

                    },
                                
                    #6
                    [PSCustomObject]@{ 
                        qosTrafficClass = [PSCustomObject]@{

                            maxBandwidth     = 100;
                            bandwidthShare   = "0";
                            egressDot1pValue = 0;
                            realTime         = $false;
                            className        = "Class5";
                            enabled          = $false;

                        };                    
                                
                        qosClassificationMapping = $null

                    },
                                
                    #7
                    [PSCustomObject]@{ 
                        qosTrafficClass = [PSCustomObject]@{

                            maxBandwidth     = 100;
                            bandwidthShare   = "25";
                            egressDot1pValue = 2;
                            realTime         = $false;
                            className        = "Medium";
                            enabled          = $true;

                        };
                                    
                        qosClassificationMapping = [PSCustomObject]@{

                            dot1pClassMapping = [System.Collections.ArrayList]@(4,3,2);
                            dscpClassMapping  = [System.Collections.ArrayList]@(

                                "DSCP 18, AF21",
                                "DSCP 20, AF22",
                                "DSCP 22, AF23",
                                "DSCP 26, AF31",
                                "DSCP 28, AF32",
                                "DSCP 30, AF33",
                                "DSCP 34, AF41",
                                "DSCP 36, AF42",
                                "DSCP 38, AF43",
                                "DSCP 16, CS2",
                                "DSCP 24, CS3",
                                "DSCP 32, CS4"

                            )

                        }

                    },
                                
                    #8
                    [PSCustomObject]@{ 
                        qosTrafficClass = [PSCustomObject]@{

                            maxBandwidth     = 10;
                            bandwidthShare   = "10";
                            egressDot1pValue = 5;
                            realTime         = $true;
                            className        = "Real time";
                            enabled          = $true;

                        };
                                    
                        qosClassificationMapping = [PSCustomObject]@{

                            dot1pClassMapping = [System.Collections.ArrayList]@(5,6,7);
                            dscpClassMapping  = [System.Collections.ArrayList]@(

                                "DSCP 46, EF",
                                "DSCP 40, CS5",
                                "DSCP 48, CS6",
                                "DSCP 56, CS7"

                            )

                        }

                    }
                
                )

            }

            #Default BestEffort Traffic Class
            "DefaultBestEffortTrafficClass"
            {
                
                Return [PSCustomObject]@{ 

                    qosTrafficClass = [PSCustomObject]@{

                        maxBandwidth     = 100;
                        bandwidthShare   = "65";
                        egressDot1pValue = 0;
                        realTime         = $false;
                        className        = "Best effort";
                        enabled          = $true;

                    };
                                
                    qosClassificationMapping = [PSCustomObject]@{

                        dot1pClassMapping = [System.Collections.ArrayList]@(1,0);
                        dscpClassMapping  = [System.Collections.ArrayList]@(

                            "DSCP 10, AF11",
                            "DSCP 12, AF12",
                            "DSCP 14, AF13",
                            "DSCP 8, CS1",
                            "DSCP 0, CS0"

                        )

                    }

                }

            }

            #FCoE Lossless Traffic Class
            "FCoELossLessTrafficClass"
            {

                Return [PSCustomObject]@{ 

                    qosTrafficClass = [PSCustomObject]@{
                
                        maxBandwidth     = 100;
                        bandwidthShare   = "fcoe";
                        egressDot1pValue = 3;
                        realTime         = $false;
                        className        = "FCoE lossless";
                        enabled          = $true;
                
                    };                    
                                
                    qosClassificationMapping = [PSCustomObject]@{
                
                        dot1pClassMapping = [System.Collections.ArrayList]@(3);
                        dscpClassMapping  = New-Object System.Collections.ArrayList
                
                    }
                
                }

            }
            
            #Basic, not enabled Traffic Class
            "BaseTrafficClass"
            {
                
                Return [PSCustomObject]@{ 
                    
                    qosTrafficClass = [PSCustomObject]@{
                    
                        maxBandwidth     = 100;
                        bandwidthShare   = "0";
                        egressDot1pValue = 0;
                        realTime         = $false;
                        className        = "Class";
                        enabled          = $false;
                    
                    };
                                    
                    qosClassificationMapping = [PSCustomObject]@{
                            
                        dot1pClassMapping = New-Object System.Collections.ArrayList;
                        dscpClassMapping  = New-Object System.Collections.ArrayList
                            
                    }

                }

            }

            "Ping"
            {

                Return [PSCustomObject]@{

                    type        = "PingDto";
                    address     = "example.com";
                    noOfPackets = 5

                }

            }

            "liUplinkSetObject"
            {
            
                Return [PSCustomObject]@{

                    type                           = "uplink-setV300";
                    name                           = $Name; 
                    networkUris                    = New-Object System.Collections.ArrayList;
                    portConfigInfos                = New-Object System.Collections.ArrayList;
                    networkType                    = $null; 
                    primaryPortLocation            = $null;
                    fcNetworkUris                  = New-Object System.Collections.ArrayList;
                    fcoeNetworkUris                = New-Object System.Collections.ArrayList;                
                    connectionMode                 = $null; 
                    ethernetNetworkType            = $null; 
                    lacpTimer                      = 'Short';
                    logicalInterconnectUri         = $null;
                    manualLoginRedistributionState = 'NotSupported'

                }
            
            }

            'ligUplinkSetObject'
            {

                Return [PSCustomObject]@{

                    logicalPortConfigInfos = New-Object System.Collections.ArrayList;
                    networkUris            = New-Object System.Collections.ArrayList;
                    name                   = $null; 
                    mode                   = 'Auto'; 
                    networkType            = "Ethernet";
                    primaryPort            = $null;
                    ethernetNetworkType    = $null; 
                    lacpTimer              = 'Short'

                }

            }

            'UplinkSetLogicalLocation'
            {
                
                Return [PSCustomObject]@{
                    
                    desiredSpeed    = $null;
                    logicalLocation = [PSCustomObject]@{
                                        
                        locationEntries =  New-Object System.Collections.ArrayList
                    
                    }
                    
                }

            }

            'UplinkSetLocation'
            {
                
                Return [PSCustomObject]@{

                    desiredSpeed = $null;
                    location     = [PSCustomObject]@{
                                        
                        locationEntries = New-Object System.Collections.ArrayList

                    }
                    
                }

            }

            'UplinkSetLogicalLocationEntry'
            {

                Return [PSCustomObject]@{
                                            
                    type          = $Null;
                    relativeValue = 1

                }

            }
                
            'UplinkSetLocationEntry'
            {

                Return [PSCustomObject]@{
                                            
                    type  = $Null;
                    value = 1

                }

            }

            'VcMigration'
            {

                Return [PSCustomObject]@{

                    enclosureGroupUri           = $Null;
                    iloLicenseType              = $Null;
                    credentials                 = [PSCustomObject]@{
                                            
                         oaIpAddress            = $Null;
                         oaUsername             = $Null;
                         oaPassword             = $Null;
                         vcmUsername            = $Null;
                         vcmPassword            = $Null;
                         type                   = "EnclosureCredentials"
                                            
                    };                            
                    category                    = "migratable-vc-domains";
                    type                        = "MigratableVcDomainV300"

                }

            }

        }

    }

}

#######################################################
# Basic Support functions
#

function New-ErrorRecord 
{

    <#
        .Synopsis
        Creates an custom ErrorRecord that can be used to report a terminating or non-terminating error.
         
        .Description
        Creates an custom ErrorRecord that can be used to report a terminating or non-terminating error.
         
        .Parameter Exception
        The Exception that will be associated with the ErrorRecord.
         
        .Parameter ErrorID
        A scripter-defined identifier of the error. This identifier must be a non-localized string for a specific error type.
         
        .Parameter ErrorCategory
        An ErrorCategory enumeration that defines the category of the error. The supported Category Members are (from: http://msdn.microsoft.com/en-us/library/system.management.automation.errorcategory(v=vs.85).aspx) :
             
            * AuthenticationError - An error that occurs when the user cannot be authenticated by the service. This could mean that the credentials are invalid or that the authentication system is not functioning properly.
            * CloseError - An error that occurs during closing.
            * ConnectionError - An error that occurs when a network connection that the operation depEnds on cannot be established or maintained.
            * DeadlockDetected - An error that occurs when a deadlock is detected.
            * DeviceError - An error that occurs when a device reports an error.
            * FromStdErr - An error that occurs when a non-Windows PowerShell command reports an error to its STDERR pipe.
            * InvalidArgument - An error that occurs when an argument that is not valid is specified.
            * InvalidData - An error that occurs when data that is not valid is specified.
            * InvalidOperation - An error that occurs when an operation that is not valid is requested.
            * InvalidResult - An error that occurs when a result that is not valid is returned.
            * InvalidType - An error that occurs when a .NET Framework type that is not valid is specified.
            * LimitsExceeded - An error that occurs when internal limits prevent the operation from being executed.
            * MetadataError - An error that occurs when metadata contains an error.
            * NotEnabled - An error that occurs when the operation attempts to use functionality that is currently disabled.
            * NotImplemented - An error that occurs when a referenced application programming interface (API) is not implemented.
            * NotInstalled - An error that occurs when an item is not installed.
            * NotSpecified - An unspecified error. Use only when not enough is known about the error to assign it to another error category. Avoid using this category if you have any information about the error, even if that information is incomplete.
            * ObjectNotFound - An error that occurs when an object cannot be found.
            * OpenError - An error that occurs during opening.
            * OperationStopped - An error that occurs when an operation has stopped. For example, the user interrupts the operation.
            * OperationTimeout - An error that occurs when an operation has exceeded its timeout limit.
            * ParserError - An error that occurs when a parser encounters an error.
            * PermissionDenied - An error that occurs when an operation is not permitted.
            * ProtocolError An error that occurs when the contract of a protocol is not being followed. This error should not happen with well-behaved components.
            * QuotaExceeded An error that occurs when controls on the use of traffic or resources prevent the operation from being executed.
            * ReadError An error that occurs during reading.
            * ResourceBusy An error that occurs when a resource is busy.
            * ResourceExists An error that occurs when a resource already exists.
            * ResourceUnavailable An error that occurs when a resource is unavailable.
            * SecurityError An error that occurs when a security violation occurs. This field is introduced in Windows PowerShell 2.0.
            * SyntaxError An error that occurs when a command is syntactically incorrect.
            * WriteError An error that occurs during writing.
         
        .Parameter TargetObject
        The object that was being Processed when the error took place.
         
        .Parameter Message
        Describes the Exception to the user.
         
        .Parameter InnerException
        The Exception instance that caused the Exception association with the ErrorRecord.
        .Parameter TargetType
        To customize the TargetType value, specify the appropriate Target object type. Values can be "Array", "PSObject", "HashTable", etc. Can be provided by ${ParameterName}.GetType().Name.
         
        .Example
    #>


    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory, Position = 0)]
        [System.String]$Exception,

        [Parameter (Mandatory, Position = 1)]
        [Alias ('ID')]
        [System.String]$ErrorId,

        [Parameter (Mandatory, Position = 2)]
        [Alias ('Category')]
        [ValidateSet ('AuthenticationError','ConnectionError','NotSpecified', 'OpenError', 'CloseError', 'DeviceError',
            'DeadlockDetected', 'InvalidArgument', 'InvalidData', 'InvalidOperation',
                'InvalidResult', 'InvalidType', 'MetadataError', 'NotImplemented',
                    'NotInstalled', 'ObjectNotFound', 'OperationStopped', 'OperationTimeout',
                        'SyntaxError', 'ParserError', 'PermissionDenied', 'ResourceBusy',
                            'ResourceExists', 'ResourceUnavailable', 'ReadError', 'WriteError',
                                'FromStdErr', 'SecurityError')]
        [System.Management.Automation.ErrorCategory]$ErrorCategory,

        [Parameter (Mandatory, Position = 3)]
        [System.Object]$TargetObject,

        [Parameter (Mandatory)]
        [System.String]$Message,

        [Parameter (Mandatory = $false)]
        [System.Exception]$InnerException,

        [Parameter (Mandatory = $false)]
        [System.String]$TargetType = "String"

    )

    Process 
    {

        # ...build and save the new Exception depending on present arguments, if it...
        $_exception = if ($Message -and $InnerException) {
            # ...includes a custom message and an inner exception
            New-Object $Exception $Message, $InnerException
        } elseif ($Message) {
            # ...includes a custom message only
            New-Object $Exception $Message
        } else {
            # ...is just the exception full name
            New-Object $Exception
        }

        # now build and output the new ErrorRecord
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Building ErrorRecord object"

        $record = New-Object Management.Automation.ErrorRecord $_exception, $ErrorID, $ErrorCategory, $TargetObject

        $record.CategoryInfo.TargetType = $TargetType

        Return $record
    }

}

function Enable-HPOVMSDSC 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]

    Param ()

    Begin { }

    Process 
    {

        $RegKey = "HKCU:\Software\Hewlett-Packard\HPOneView"

        if (-not(Test-Path $RegKey)) { New-Item -Path $RegKey -force | Write-Verbose }

        $UseMSDSC = [bool](Get-ItemProperty -LiteralPath $RegKey -ea silentlycontinue).'UseMSDSC'

        if (-not($UseMSDSC)) { New-ItemProperty -Path $RegKey -Name UseMSDSC -Value 1 -Type DWORD | write-verbose }

        else { Set-ItemProperty -Path $RegKey -Name UseMSDSC -Value 1 -Type DWORD | write-verbose }

    }

    End { }

}

function Disable-HPOVMSDSC 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]

    Param ()

    Begin { }

    Process 
    {

        $RegKey = "HKCU:\Software\Hewlett-Packard\HPOneView"

        if (-not(Test-Path $RegKey)) { New-Item -Path $RegKey -force | Write-Verbose }

        $UseMSDSC = [bool](Get-ItemProperty -LiteralPath $RegKey -ea silentlycontinue).'UseMSDSC'

        if (-not($UseMSDSC)) { New-ItemProperty -Path $RegKey -Name UseMSDSC -Value 0 -Type DWORD | write-verbose }

        else { Set-ItemProperty -Path $RegKey -Name UseMSDSC -Value 0 -Type DWORD | write-verbose }

    }

    End { }

}

function RestClient 
{

    <#
 
        .SYNOPSIS
        Internal Private Class for building a RestClient using [System.Net.HttpWebRequest]
 
        .DESCRIPTION
        This is a private, internal class/function to create a new [System.Net.HttpWebRequest] object with pre-defined properties of the HttpWebReqeuest connection. This class will set the following attributes, which the caller can overload the values with their own after the resource has been created:
 
            Timeout = 20000
            ContentType = "application/json"
            Accept = "application/json"
            Headers.Item("X-API-Version") = $MaxXAPIVersion
            Headers.Item("accept-language") = "en_US"
            Headers.Item("accept-encoding") = "gzip, deflate"
            Headers.Item("auth") = ${Global:ConnectedSessions}.sessionID NOTE: Only if the sessionID exists.
            AutomaticDecompression = "GZip,Deflate,None"
 
        The URI of the HttpWebRequest object will automatically include the connected (or requested if the first call is Connect-HPOVMgmt) appliance address or name ($script:HPOneViewAppliance). This value can be overloaded, but the Auth token that may be included as an HTTP header item could be invalid.
 
        .INPUTS
        None.
 
        .OUTPUTS
        New [System.Net.HttpWebRequest] object.
 
        .Parameter URI
        The URI of the request. Do not include the appaliance hostname or IP Address, only the cononical URI value (i.e. /rest/server-hardware).
 
        .Parameter Method
        Optional. Provide the HTTP method for the request. The default value is 'GET'. Only the following values are allowed:
 
            GET
            PUT
            POST
            DELETE
            PATCH
 
        .Parameter Appliance
        Provide the appliance hostname or FQDN.
 
    #>


    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $False, Position = 0)]
        [ValidateScript({if ("GET","POST","DELETE","PATCH","PUT" -match $_) {$true} else { Throw "'$_' is not a valid Method. Only GET, POST, DELETE, PATCH, or PUT are allowed." }})]
        [string]$method = "GET",

        [Parameter (Mandatory, Position = 1)]
        [ValidateScript({if ($_.startswith('/')) {$true} else {throw "-URI must being with a '/' (eg. /rest/server-hardware) in its value. Please correct the value and try again."}})]
        [string]$uri,

        [Parameter (Mandatory, Position = 2)]
        [ValidateNotNullorEmpty()]
        [string]$Appliance = $Null

    )

    Begin 
    {

        #"[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Debug

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Debug

        $url = $Appliance + $uri

        "[{0}] Building new [System.Net.HttpWebRequest] object for {1} https://{2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $method, $url | Write-Debug

    }

    Process 
    {

        "[{0}] Setting TLS only comms." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Debug

        [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12

        "[{0}] {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ([Net.ServicePointManager]::SecurityProtocol | Out-String) | Write-Debug
        
        [System.Net.ServicePointManager]::DefaultConnectionLimit = 16

        "[{0}] Building new RestClient object." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Debug

        [System.Net.HttpWebRequest]$restClient              = [System.Net.HttpWebRequest]::Create("https://$url")
        [String]$restClient.Method                          = $method
        [int]$restClient.Timeout                            = 20000
        [bool]$restClient.KeepAlive                         = $true
        [String]$restClient.UserAgent                       = "HPEOneview_PowerShell/3.10"
        [String]$restClient.ContentType                     = 'application/json'
        [String]$restClient.Accept                          = 'application/json'
        [String]$restClient.Headers.Item("X-API-Version")   = $MaxXAPIVersion
        [String]$restClient.Headers.Item("accept-language") = "en_US"
        [String]$restClient.Headers.Item("accept-encoding") = "gzip, deflate"
        [String]$restClient.AutomaticDecompression          = "GZip,Deflate,None"

        if ($method -eq 'PATCH')
        {

            $restClient.ContentType += '-patch+json'

        }

        "[{0}] RestClient Object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($RestClient | Out-String) | Write-Debug
 
        # Set the callback to check for null certificate and thumbprint matching.
        #This method is only supported in PowerShell 4 or greater
        $restClient.ServerCertificateValidationCallback = {

            $_WebRequest = [System.Net.WebRequest]$args[0]

            #Handle IPv6 Addresses, which must be encapsulated with [], e.g. [fde4:8dba:82e1::1]
            $_Hostname = $_WebRequest.Host #.Replace('[',$null).Replace(']',$null)

            [Net.IPAddress]$_HostnameIsAddress = $null

            #Need to handle IPv6 Address, as System.Net.WebRequest will expand an IPv6 address in $args[0].Host
            If ([System.Net.IPAddress]::TryParse($_Hostname,[ref]$_HostnameIsAddress) -and $_HostnameIsAddress.AddressFamily -eq 'InterNetworkV6')
            {

                $_Hostname = '[{0}]' -f $_HostnameIsAddress.IPAddressToString

            }

            if (-not(($Global:ConnectedSessions | ? Name -eq $_Hostname).SslChecked))
            {

                #Only for Pester Tests. DO NOT USE IN PRODUCTION.
                if ($Global:IgnoreCertPolicy -and $Global:PesterTest)
                {

                    Try
                    {

                        ($Global:ConnectedSessions | ? Name -eq $_Hostname).SslChecked = $true

                    }

                    Catch
                    {

                        Throw $_

                    }                
            
                    return $true

                }

                elseif ($Global:IgnoreCertPolicy)
                {

                    $Host.UI.WriteLine()
                    $Host.UI.WriteLine([System.ConsoleColor]::Yellow,[System.Console]::BackgroundColor ,'IgnoreCertPolicy Enabled ($Global:IgnoreCertPolicy = $true). The module will ignore any certificate errors, and could cause security vulnerabilities. Use at your own risk.')
                    $Host.UI.WriteLine()

                    Try
                    {

                        ($Global:ConnectedSessions | ? Name -eq $_Hostname).SslChecked = $true

                    }

                    Catch
                    {

                        Throw $_

                    }                
            
                    return $true

                }

                else
                {

                    $_certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]$args[1]

                    try 
                    { 
                    
                        $_san = ($_certificate.Extensions | Where-Object {$_.Oid.Value -eq "2.5.29.17"}).Format(0) -split ", " 
                
                    }

                    catch 
                    { 
                    
                        $_san = $null 
                
                    }

                    $_chain = New-Object Security.Cryptography.X509Certificates.X509Chain 

                    [void]$_chain.ChainPolicy.ApplicationPolicy.Add("1.3.6.1.5.5.7.3.1") #Indicates that a certificate can be used as an SSL server certificate.

                    $_status = $_chain.Build($_certificate)

                    if ($_chain.ChainStatus) { $_chainstatus = $_chain.ChainStatus | % { $_.Status.ToString() } }

                    $_certObject = New-Object HPOneView.PKI.SslCertificate(
                            $_WebRequest.ServicePoint.Certificate,
                            $_WebRequest.ServicePoint.Certificate.Issuer,
                            $_WebRequest.ServicePoint.Certificate.Subject,
                            $_san,
                            $_status,
                            $_chainstatus
                    )

                    # // Check _san as well? DnsNameList is likely not enough, and is failing cert chain validation in some cases with DCS.
                    if (($_certificate.DnsNameList -contains $_Hostname -or $_certObject.SubjectAlternativeNames -match $_Hostname) -and (-not($_status)) -and ($_chainstatus -match "UntrustedRoot"))
                    {

                        if (-not(($Global:ConnectedSessions | ? Name -eq $_Hostname).SslChecked))
                        {

                            $_backgroundcolor = [System.Console]::BackgroundColor 
                            $Host.UI.WriteLine([System.ConsoleColor]::Yellow,$_backgroundcolor,"`n$($_certObject | Out-String)")
                            $Host.UI.WriteWarningLine("The appliance SSL Certificate is UNTRUSTED. Use the Import-HPOVSSLCertificate to import the appliance Self-Signed certificate to your user accounts local Trusted Root Certification Authorities store to not display this warning when you first connect to your appliance.")
                            $Host.UI.WriteLine("")

                            ($Global:ConnectedSessions | ? Name -eq $_Hostname).SslChecked = $true

                        }
                
                        return $true
                
                    }

                    #If Cert IS valid, but cannot validate with Root CA, can validate with Subordinate CA and unable to validate revocation, display warning
                    elseif ((-not ($_status)) -and ($_certificate.ErrorInformation -match "PartialChain" -and $_certificate.ErrorInformation -match "RevocationStatusUnknown" -and $_certificate.ErrorInformation -match "OfflineRevocation")) 
                    { 

                        $Host.UI.WriteLine([System.ConsoleColor]::Yellow,$_backgroundcolor,"`n$($_certObject | Out-String)")

                        $Host.UI.WriteWarningLine("The appliance SSL Certificate is UNTRUSTED. This system does not trust the CA issuer, and is unable to verify the Certificate Authorities Revocation List (CRL) or the Revocation List Destination (CLD) is not contained within the certificate.")
                        $Host.UI.WriteLine("")
                    
                    }

                    #If Cert IS valid, but cannot validate with Root CA and unable to validate revocation, display warning
                    elseif ((-not $_status) -and ($_certificate.ErrorInformation -match "RevocationStatusUnknown" -and $_certificate.ErrorInformation -match "OfflineRevocation")) 
                    {                 
                    
                        $Host.UI.WriteLine([System.ConsoleColor]::Yellow,$_backgroundcolor,"`n$($_certObject | Out-String)")
                    
                        $Host.UI.WriteWarningLine("The appliance SSL Certificate is UNTRUSTED. This system is unable to verify the Certificate Authorities Revocation List (CRL) or the Revocation List Destination (CLD) is not contained within the certificate. If you are using an Enterprise Certificate Authority (i.e. Windows Server CA), please make sure the CRL is published as part of the issued certificate (CRL is an Extension that needs to be enabled prior to issuing certificates).")
                        $Host.UI.WriteLine("")

                    }

                    #Cert is trusted and a Global ConnectedSession exists
                    elseif ($_status -and ($Global:ConnectedSessions | ? Name -eq $_Hostname))
                    {

                        ($Global:ConnectedSessions | ? Name -eq $_Hostname).SslChecked = $true
                
                        return $_status

                    }

                    elseif ($_status)
                    {

                        #$Host.UI.WriteLine("Reached final ElseIf and cert is trusted.")
                        return $_status

                    }

                    else 
                    {

                        $Host.UI.WriteLine([System.ConsoleColor]::Red,[System.ConsoleColor]::Black,"`n$($_certObject | Out-String)")

                    }

                    return $false

                }

            }
 
            else
            {

                ($Global:ConnectedSessions | ? Name -eq $_Hostname).SslChecked

            }            

        }

    }

    End 
    {

        Return $restClient

    }

}

function RedactPassword
{

    [CmdletBinding ()]
    Param 
    (

        [Hashtable]$BoundParameters

    )

    $Caller = (Get-PSCallStack)[1].Command

    '[{0}] Redacting users Password from Verbose Output' -f $Caller | Write-Verbose 

    $_Params = @{}

    $PSBoundParameters.BoundParameters.GetEnumerator() | % {

        if ($_Params.($_.Key) -is [PSCustomObject])
        {

            $_Params.Add($_.Key,$PSBoundParameters.BoundParameters.($_.Key).PSObject.Copy())

        }

        else
        {

            $_Params.Add($_.Key,$_.Value)


        }

        #Handle Level 1
        if ($_Params.password)
        {


            $_Params.password = '[*****REDACTED******]'

        } 

        #Handle Level 2
        if ($_Params.($_.Key).password)
        {

            $_Params.($_.Key).password = '[*****REDACTED******]'

        }

    }

    "[{0}] Bound PS Parameters: {1}" -f $Caller, ($_Params | out-string) | Write-Verbose

}

function Send-HPOVRequest 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Position = 0, Mandatory)]
        [ValidateScript ({if ($_.startswith('/')) {$true} else {throw "-URI must being with a '/' (eg. /rest/server-hardware) in its value. Please correct the value and try again."}})]
        [string]$uri,

        [Parameter (Position = 1, Mandatory = $false)]
        [ValidateScript ({if ("GET","POST","DELETE","PATCH","PUT" -match $_) {$true} else { Throw "'$_' is not a valid Method. Only GET, POST, DELETE, PATCH, or PUT are allowed." }})]
        [string]$method = "GET",
        
        [Parameter (Position = 2, Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [object]$body,

        [Parameter (Position = 3, Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [int]$start = 0,

        [Parameter (Position = 4, Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [int]$count = 0,

        [Parameter (Position = 5, Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [hashtable]$AddHeader,

        [Parameter (Position = 6, Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [string]$OverrideContentType,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance','ApplianceConnection')]
        [Object]$Hostname = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    { 

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] BEGIN"

        if ($uri -eq $ApplianceLoginSessionsUri -and $Method -eq 'POST')
        {

            #RedactPassword -BoundParameters $PSBoundParameters

        }

        else
        {

            "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        }

        #Support getting the Appliance Connection Name from the object being passed within the body Param
        if ($PSBoundParameters['body'] -and $body.ApplianceConnection -and (-not($Hostname)) -and ($body -isnot [System.Collections.IEnumerable]))
        {

            "[{0}] Getting the Appliance Connection Name from the object being passed within the body Param" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $Hostname = $body.ApplianceConnection.Name

        }

        #Collection to return all responses from all specified appliance connections
        $AllResponses = New-Object System.Collections.ArrayList

    }

    Process 
    {

        $c = 1

        if (-not($PSboundParameters['Hostname']) -and (-not([bool]($Hostname | Measure-Object).count)))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoAuthSession ObjectNotFound 'Hostname' -Message "No appliance Hostname Parameter provided and no valid appliance session(s) found."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        ForEach ($ApplianceHost in $Hostname) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Process"

            "[{0}] Hostname value: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($ApplianceHost | Out-String) | Write-Verbose

            #Clear last error response for the connection we are going to make.
            if (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name)
            {

                "[{0}] Prior Global Response Error Object for '{1}' found. Clearing." -f $MyInvocation.InvocationName.ToString().ToUpper(), $ApplianceHost.Name | Write-Verbose

                $_ResponseObject = (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name)

                [void]${Global:ResponseErrorObject}.Remove($_ResponseObject)

            }
            
            #If the value is String, we assume this is the Appliance Hostname, so look up the Connection details in ${Global:ConnectedSessions}
            if ($ApplianceHost -is [String] -and (${Global:ConnectedSessions} | ? Name -eq $ApplianceHost )) 
            {

                "[{0}] Filtering for Connection Object via String: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ApplianceHost | Write-Verbose

                $ApplianceHost = ${Global:ConnectedSessions} | ? Name -eq $ApplianceHost

            }

            elseif ($ApplianceHost -isnot [HPOneView.Appliance.Connection] -and $ApplianceHost.Name)
            {

                "[{0}] Filtering for Connection Object via PSObject: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($ApplianceHost | Out-String) | Write-Verbose

                $ApplianceHost = ${Global:ConnectedSessions} | ? Name -eq $ApplianceHost.Name

            }

            "[{0}] Processing '{1}' appliance connection request. {2} of {3}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ApplianceHost.Name,$c,$Hostname.count | Write-Verbose 

            #Need to check for authenticated session when the URI passed is not value of $WhiteListedURIs
            "[{0}] Requested URI '{1}' to '{2}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $uri, ($ApplianceHost.Name -join ',') | Write-Verbose 

            if ($WhiteListedURIs -contains $uri) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] We have reached the URI Whitelist condition block. Unauth request allowed for '$uri'."

            }
                
            #Else, require authentication
            elseif (-not($ApplianceHost.SessionID)) 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoAuthSession AuthenticationError 'Send-HPOVRequest' -Message "No valid session ID found for '$($ApplianceHost.Name)'. The call to '$uri' requires authentication. Please use Connect-HPOVMgmt to connect and authenticate to an appliance."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
    
            #Pagination handling:
            $AllMembers = New-Object System.Collections.ArrayList

            #See if the caller specified a count, either in the URI or as a Param
            #(if so, we will let them handle pagination manually)
            [bool]$manualPaging = $false

            if ($uri.ToLower().Contains("count=") -or $uri.ToLower().Contains("count =")) 
            {

                $manualPaging = $true

            }

            elseif ($count -gt 0) 
            {

                $manualPaging = $true

                #add start & count params to the URI
                if (-not ($uri -contains "?")) 
                {

                    $uri += "?"    

                }

                $uri += ("start=" + $start + "&")

                $uri += ("count=" + $count)

            }

            elseif ($start -gt 0) 
            {

                #start specified, but no count -- just set the start Param & auto-page from there on:
                $manualPaging = $false

                if (-not ($uri -contains "?")) 
                {

                    $uri += "?"   
                 
                }

                $uri += ("start=" + $start)

            }

            do 
            {

                #Used to keep track of async task response
                $taskRecieved = $False

                [System.Net.HttpWebRequest]$req = RestClient $method $uri $ApplianceHost.Name

                if ($PSBoundParameters['OverrideContentType'])
                {

                    $req.ContentType = $PSBoundParameters['OverrideContentType']

                }

                #Add Auth Session token if it exists
                if ($ApplianceHost.SessionID -and $ApplianceHost.SessionID -ne 'TemporaryConnection') 
                { 
                    
                    $req.Headers.Item("auth") = $ApplianceHost.SessionID 
                
                }
                
                #Increase timeout for synchronOut call for Support Dumps to be generated as they are not an Async task.
                if ($Uri -match "support-dump" -or $Uri -match $RemoteSupportUri)
                { 
                
                    "[{0}] Increasing HttpWebRequest timeout to 200s." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
                    $req.Timeout = 200000 
                    
                }

                #Handle additional headers being passed in for updated API (storage volume removal)
                #Variable defined as a hashtable in case other API pass more than one additional header
                if($PSBoundParameters['AddHeader'])
                {

                    $AddHeader.GetEnumerator() | ForEach-Object { $req.Headers.Item($_.key) = $_.value }

                    if ($AddHeader.GetEnumerator() | ? Key -eq 'X-API-Version')
                    {

                        "[{0}] Overloading 'X-API-Version' in HttpWebRequest object to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $AddHeader.'X-API-Version' | Write-Verbose
                        $req.Headers['X-API-Version'] = $AddHeader.'X-API-Version'

                    }

                }

                #Adding due to X-API-Version 500 requirement to pass If-Match header for DELETE requests.
                if ($Method -eq 'DELETE' -and -not $req.Headers.Item('If-Match'))
                {
                    
                    "[{0}] Adding If-Match HTTP Header." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $req.Headers.Add("If-Match: *")

                }

                #Send the request with a messege
                if ($body) 
                {

                    "[{0}] Body object found. Converting to JSON." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                
                    if (('PUT','PATCH' -contains $method) -and ($null -ne $body.etag)) 
                    {

                        "[{0}] HTTP Method is $method and eTag value found $($body.etag). Setting 'If-Match' HTTP Header." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        #Handle eTags from connection manager
                        $req.Headers.Item("If-match") = $body.etag

                    }

                    #Remove any found ApplianceConnection property(ies) to not generate REST API Error
                    if ('PUT', 'PATCH', 'POST' -contains $method -and $body -isnot [System.String])
                    {

                        "[{0}] HTTP Method is $method. Removing 'ApplianceConnection' NoteProperty from object(s)." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        $body = Remove-ApplianceConnection $body

                    }

                    if ($method -eq "PATCH" -and ($body -isnot [Array]))
                    {

                        "[{0}] Patch Request and body is not an Array." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        [Array]$body = @($body)

                    }
                    
                    #Create a new stream writer to write the json to the request stream.
                    if ($body -isnot [String])
                    {

                        $js = ConvertTo-Json $body -Depth 99 -Compress

                    }

                    else
                    {

                        $js = $body

                    }

                    #Needed to remove \r character that ConvertTo-JSON adds which /rest/logindirectories does not support for the directory server SSL certificate
                    if ($body.type -eq "LoginDomainConfigVersion2Dto") 
                    { 
                        
                        $js = $js -replace "\\r",$null 
                    
                    }

                    if ($uri -eq $LoginSessionsUri -and $Method -eq 'POST')
                    {

                        '[{0}] Request Body: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), (ConvertTo-Json -InputObject $_Params.body -Depth 99 -Compress) | Write-Verbose 
                    
                    }

                    else
                    {

                        "[{0}] Request Body: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $js | Write-Verbose 

                    }

                    #Send the messege
                    try 
                    {

                        $stream = New-Object IO.StreamWriter($req.GetRequestStream())

                        $stream.AutoFlush = $True
                        $stream.WriteLine($js)
                        $stream.Flush()
                        
                    }

                    catch 
                    {                        

                        $PSCmdlet.ThrowTerminatingError($_)
                        
                    }

                    finally
                    {

                        $stream.Close()

                        if ($stream -is [System.IDisposable])
                        {

                            $stream.Dispose()

                        }

                    }                

                }

                "[{0}] Request: {1} https://{2}{3}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Method, $ApplianceHost.Name, $Uri | Write-Verbose
   
                #Write Verbose the headers if needed
                $i = 0

                foreach ($h in $req.Headers) 
                { 

                    #Remove Auth Token info from Headers
                    if ($h -eq 'auth')
                    {

                        "[{0}] Request Header {1}: {2} = [*****REDACTED******]" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($i+1), $h | Write-Verbose

                    }

                    else
                    {

                        "[{0}] Request Header {1}: {2} = {3}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($i+1), $h, $req.Headers[$i] | Write-Verbose

                    }

                    $i++ 

                }

                try 
                {

                    #Get response from appliance
                    [System.Net.WebResponse]$LastWebResponse = $req.GetResponse()

                    #Display the response status if verbose output is requested
                    "[{0}] Response Status: {1} ({2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), [int]$LastWebResponse.StatusCode, [String]$LastWebResponse.StatusDescription  | Write-Verbose

                    $i = 0

                    foreach ($h in $LastWebResponse.Headers) 
                    { 
                        
                        "[{0}] Response Header {1}: {2} = {3}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($i+1), $h, $LastWebResponse.Headers[$i] | Write-Verbose
                        
                        $i++ 
                    
                    }

                    #Read the response
                    $reader = New-Object IO.StreamReader($LastWebResponse.GetResponseStream())

                    $FinalResponse = $reader.ReadToEnd()

                    $reader.close()

                    "[{0}] FinalResponse: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $FinalResponse | Write-Verbose

                    $DuplicateiLOPattern = '\"[I|i]LO\"\:\[\"\d\.\d+\"\],'

                    if ([RegEx]::Matches($FinalResponse, $DuplicateiLOPattern, 'IgnoreCase'))
                    {

                        $FinalResponse = [Regex]::Replace($FinalResponse, $DuplicateiLOPattern, "")

                    }

                    $resp = ConvertFrom-JSON -InputObject $FinalResponse        

                    if ($resp -is [String])
                    {

                        "[{0}] Response: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $resp | Write-Verbose 

                    }

                    elseif ($resp -is [Boolean])
                    {

                        "[{0}] Bool Response: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [bool]$resp | Write-Verbose 

                    }

                    else
                    {

                        if ($resp -is [PSCustomObject])
                        {

                            if ($resp.PSobject.Properties.name -match "sessionId")
                            {

                                $_resp = $resp.PSObject.Copy()

                                $_resp.sessionId = '[*****REDACTED******]'

                                "[{0}] Response: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_resp | fl * -force | out-string) | Write-Verbose 

                            }

                        }

                        else
                        {

                            "[{0}] Response: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($resp | fl * -force | out-string) | Write-Verbose 

                        }

                    }
                    
                    "[{0}] Manual Pagination: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ManualPaging | Write-Verbose

                    #If Asyncronous (HTTP status=202), make sure we return a Task object:
                    if ([int]$LastWebResponse.StatusCode -eq 202 -and ($LastWebResponse.Headers.Item('X-Task-URI') -or $LastWebResponse.Headers.Item('Location')))
                    {

                        "[{0}] Async Task (HTTP 202) received"-f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        #AsynchronOut operation -- in some cases we get the Task object returned in the body.
                        #In other cases, we only get the Task URI in the Location header.
                        #In either case, return a Task object with as much information as we know
                        if ($LastWebResponse.Headers.Item('X-Task-URI')) 
                        {

                            [string]$TaskUri = $LastWebResponse.Headers.Item('X-Task-URI')

                        }

                        elseif ($LastWebResponse.Headers.Item('Location'))
                        {

                            [string]$TaskUri = $LastWebResponse.Headers.Item('Location')

                        }

                        if ($TaskUri)
                        {

                            "[{0}] Async Task URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $TaskUri | Write-Verbose

                            #First, make sure the task URI is relative:
                            $pos = $TaskUri.IndexOf($TasksUri)

                            if ($pos -gt 0) 
                            {

                                $TaskUri = $taskUri.SubString($pos)

                            }

                            Try
                            {

                                $resp = Send-HPOVRequest -uri $TaskUri -method GET -appliance $ApplianceHost.Name

                                "[{0}] Adding 'HPOneView.Appliance.TaskResource' to PSObject TypeNames for task object" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                                $resp | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.TaskResource') }

                            }
                            
                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)
                                
                            }

                        }

                    }

                    elseif ([int]$LastWebResponse.StatusCode -eq 202)
                    {

                        "[{0}] Return is not an Async task, but HTTP 202 was returned. Labels?" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        if ($Method -eq 'DELETE' -and $null -eq $resp)
                        {

                            "[{0}] Returning custom delete successful message." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            $resp = [PSCustomObject]@{StatusCode = [int]$LastWebResponse.StatusCode; Message = "Resource deleted successfully." }

                        }                        

                    }

                    #Handle Task Objects that have been directly accessed via task URI and not created async tasks (HTTP 202)
                    if (([int]$LastWebResponse.StatusCode -eq 200 -or [int]$LastWebResponse.StatusCode -eq 202) -and ($resp.category -eq "tasks") -and (-not($resp.PSObject.TypeNames -match "HPOneView.Appliance.TaskResource"))) 
                    {
                        
                        $resp | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.TaskResource') }

                    }

                    #User Logoff success message
                    if (([int]$LastWebResponse.StatusCode -eq 204) -and ($uri -eq $ApplianceLoginSessionsUri))
                    {

                        $resp = [PSCustomObject]@{ Message = "User logoff successful." }

                    }

                    elseif (([int]$LastWebResponse.StatusCode -eq 204 -or [int]$LastWebResponse.StatusCode -eq 200) -and $method -eq "DELETE")
                    {
                        
                        $resp = [PSCustomObject]@{StatusCode = [int]$LastWebResponse.StatusCode; Message = "Resource deleted successfully." }
                        
                    }

                    #Handle multi-page result sets
                    if ([bool]($resp | gm -Name members -ErrorAction SilentlyContinue) -and (-not($manualPaging))) 
                    {

                         "[{0}] Response members and automatic pagination" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        $resp.members | % { 
                            
                            Add-Member -InputObject $_ -NotePropertyName ApplianceConnection -NotePropertyValue (New-Object HPOneView.Library.ApplianceConnection($ApplianceHost.Name, $ApplianceHost.ConnectionId)) -Force 

                            [void]$AllMembers.Add($_) 
                        
                        }

                        "[{0}] total stored '$($AllMembers.count)'" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        "[{0}] nextPageURI: '$($AllMembers.nextPageUri)'" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        if ($resp.nextPageUri) 
                        { 

                            "[{0}] Pagination has occurred. Received $($resp.count) resources of $($resp.total)" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            $uri = $resp.nextPageUri

                        }

                        else 
                        { 

                            "[{0}] Reached End of pagination. Building AllResults" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            $_AllResults = [PsCustomObject]@{
                                
                                members     = $AllMembers; 
                                count       = $AllMembers.Count;
                                total       = $AllMembers.Count;
                                category    = $resp.category; 
                                eTag        = $resp.eTag;
                                nextPageUri = $resp.nextPageUri;
                                start        = $resp.start;
                                prevPageUri    = $resp.prevPageUri;
                                created        = $resp.created;
                                modified    = $resp.modified;
                                uri            = $resp.uri
                            
                            }

                            [void]$AllResponses.Add($_AllResults)
                            
                        }

                    }
                    
                    elseif ($resp.members -and $manualPaging )
                    {

                        "[{0}] Response members and manual paging" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        $resp.members | % { 

                            Add-Member -InputObject $_ -NotePropertyName ApplianceConnection -NotePropertyValue (New-Object HPOneView.Library.ApplianceConnection($ApplianceHost.Name, $ApplianceHost.ConnectionId)) -Force 

                        }

                        [void]$AllResponses.Add($resp)

                    }

                    elseif ($resp)
                    {

                        "[{0}] Response object, no paging needed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        Add-Member -InputObject $resp -NotePropertyName ApplianceConnection -NotePropertyValue (New-Object HPOneView.Library.ApplianceConnection($ApplianceHost.Name, $ApplianceHost.ConnectionId)) -Force 

                        [void]$AllResponses.Add($resp)

                    }

                } 
       
                catch [System.Net.WebException] 
                { 

                    "[{0}] Net.WebException Error caught" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    "[{0}] {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_.Exception.Message | write-verbose
                    
                    if ($_.Exception.InnerException -match "System.Net.WebException: Unable to connect to the remote server") 
                    { 
                    
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.NetworkConnectionException ApplianceNotResponding ResourceUnavailable 'Hostname' -Message "Unable to connect to '$($ApplianceHost.Name)' due to timeout."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }
                    
                    elseif ($_.Exception.Message -match 'The remote name could not be resolved')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.NetworkConnectionException RemoteNameLookupFailure ObjectNotFound 'Hostname' -Message "Unable to connect to the appliance. $($_.Exception.Message)."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    }

                    if ($_.Exception.InnerException) 
                    {

                        if ($_.Exception.InnerException.Response) 
                        {

                            "[{0}] InnerException" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            $LastWebResponse = $_.Exception.InnerException.Response

                        }

                        else 
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    } 
                
                    else 
                    {

                        if ($_.Exception.Response) 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Exception"

                            $LastWebResponse = $_.Exception.Response

                        }

                        else 
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                    if ($LastWebResponse) 
                    {

                        Try
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Error Response."
                        
                            $reader = New-Object IO.StreamReader($LastWebResponse.GetResponseStream())

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        $ErrorResponse = $reader.ReadToEnd() | ConvertFrom-JSON

                        $reader.Close()        

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] ERROR RESPONSE: $($ErrorResponse | ConvertTo-Json -Depth 99 | out-string)"

                        #Set Global Response Error Object
                        if (-not(${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name))
                        {
                        
                            $_NewResponseErrorObject = [PSCustomObject]@{

                                Name            = $ApplianceHost.Name
                                LastWebResponse = $LastWebResponse
                                ErrorResponse   = $ErrorResponse

                            }

                            [void]${Global:ResponseErrorObject}.Add($_NewResponseErrorObject)
                        
                        }

                        else
                        {

                            (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).LastWebResponse = $LastWebResponse
                            (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse   = $ErrorResponse

                        }                       
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response Status: HTTP $([int](${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).LastWebResponse.StatusCode) [$((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).LastWebResponse.StatusDescription)]"

                        foreach ($h in (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).LastWebResponse.Headers) 
                        { 
                            
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response Header: $($h) = $((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).LastWebResponse.Headers[$i])"
                            
                            $i++ 
                        
                        }

                        switch ([int](${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).LastWebResponse.StatusCode) 
                        {

                            #HTTP 400 errors
                            400 
                            {
                                
                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] HTTP 400 error caught."

                                if ([System.String]::IsNullOrWhiteSpace(($Global:ResponseErrorObject | ? Name -eq $ApplianceHost.Name).ErrorResponse.details))
                                {

                                    $_Message = "{0} {1} " -f ($Global:ResponseErrorObject | ? Name -eq $ApplianceHost.Name).ErrorResponse.message, ([String]::Join(' ',($global:ResponseErrorObject | ? Name -eq $ApplianceHost.Name).ErrorResponse.recommEndedActions)).trim()

                                }

                                else
                                {

                                    $_Message = "{0} {1} " -f ($Global:ResponseErrorObject | ? Name -eq $ApplianceHost.Name).ErrorResponse.details, ([String]::Join(' ',($global:ResponseErrorObject | ? Name -eq $ApplianceHost.Name).ErrorResponse.recommEndedActions)).trim()

                                }

                                switch ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorCode)
                                {

                                    #Hande initial authentication errors
                                    {"AUTHN_AUTH_DIR_FAIL","AUTHN_AUTH_FAIL" -contains $_}
                                    {
                                    
                                        "[{0}] Authentication Directory failure. Likely basd username and/or password from auth dir." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                        ${Global:ConnectedSessions}.Remove($ApplianceHost)
                                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AuthSessionException InvalidUsernameOrPassword AuthenticationError "Appliance:$($ApplianceHost.Name)" -Message $_Message
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }

                                    #Handle invalid user session
                                    "AUTHN_LOGOUT_FAILED"
                                    {

                                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User session no longer valid, likely due to session timeout. Clearing library runtime global and script variables."

                                        ${Global:ConnectedSessions}.Remove($ApplianceHost)

                                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AuthSessionException InvalidUserSession AuthenticationError "Appliance:$($ApplianceHost.Name)" -Message $_Message
                                        Throw $ErrorRecord

                                    }

                                    #Handle user not acknowledging login message
                                    "AUTHN_LOGIN_MESSAGE_ACKNOWLEDGMENT_REQUIRED"
                                    {

                                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User needed to accept the Login Message."

                                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AuthSessionException LoginMessageAcknowledgementRequired AuthenticationError "Appliance:$($ApplianceHost.Name)" -Message $_Message
                                        Throw $ErrorRecord

                                    }

                                    #Valid user, but does not belong to a group that has an assigned role
                                    'AUTHN_AUTH_FAIL_NO_ROLES'
                                    {

                                        ${Global:ConnectedSessions}.Remove($ApplianceHost)

                                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AuthSessionException NoDirectoryRoleMapping AuthenticationError "Appliance:$($ApplianceHost.Name)" -Message $_Message 
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }

                                    #Valid User, but no directory group have been added
                                    'AUTHN_LOGINDOMAIN_NO_MEMBER_GROUPS_FOUND'
                                    {

                                        ${Global:ConnectedSessions}.Remove($ApplianceHost)

                                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AuthSessionException NoDirectoryRoleMapping AuthenticationError "Appliance:$($ApplianceHost.Name)" -Message $_Message 
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }

                                    default
                                    {

                                        if ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorSource) 
                                        { 
                                        
                                            $source = (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorSource 
                                    
                                        }

                                        else 
                                        { 
                                        
                                            $source = 'Send-HPOVRequest' 
                                    
                                        }

                                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidOperation InvalidOperation $source -Message $_Message
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }

                                }

                            }

                            #User is unauthorized
                            401 
                            {

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] HTTP 401 error caught."
                                
                                if ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.details -cmatch "User not authorized for this operation" -or (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message -cmatch "insufficient privilege for operation") 
                                {

                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message) Request was '$method' at '$uri'."

                                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthPrivilegeException InsufficientPrivilege AuthenticationError 'Send-HPOVRequest' -Message ("[Send-HPOVRequest]: {0}. Request was '{1}' at '{2}'. " -f (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message, $method, $uri )
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                elseif ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorCode -eq "INSUFFICIENT_PRIVILEGES") 
                                {

                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message) Request was '$method' at '$uri'."

                                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthPrivilegeException InsufficientPrivilege AuthenticationError 'Send-HPOVRequest' -Message ("[Send-HPOVRequest]: {0}. Request was '{1}' at '{2}'. " -f (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message, $method, $uri )
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                elseif ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorCode -eq "AlertAuthorizationException") 
                                {

                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message) Request was '$method' at '$uri'."

                                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthPrivilegeException AlertAuthorizationException AuthenticationError 'Send-HPOVRequest' -Message ("[Send-HPOVRequest]: {0}. Request was '{1}' at '{2}'. " -f (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message, $method, $uri )
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                elseif ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorCode -eq "INVALID_REPOSITORY_CREDENTIALS") 
                                {

                                    "[{0}] {1} Request was '{2}' at '{3}'." -f $MyInvocation.InvocationName.ToString().ToUpper(), (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message, $method, $uri | Write-Verbose

                                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthPrivilegeException AuthorizationException AuthenticationError 'Send-HPOVRequest' -Message (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                else 
                                {

                                    [void]${Global:ConnectedSessions}.Remove($ApplianceHost)

                                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException InvalidOrTimedoutSession AuthenticationError 'Send-HPOVRequest' -Message "[Send-HPOVRequest]: Your session has timed out or is not valid. Please use Connect-HPOVMgmt to authenticate to your appliance."
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                            }

                            403 
                            {
                                
                                $resp = $Null

                                if ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorCode -eq "PASSWORD_CHANGE_REQUIRED") 
                                { 
                                    
                                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.PasswordChangeRequired PasswordExpired PermissionDenied "URI" -Message ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message + " " + (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.recommEndedActions) 
                                
                                }
                                
                                else 
                                { 
                                    
                                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ResourcePrivledgeException ResourcePrivledge PermissionDenied "URI" -Message ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message + " " + (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.recommEndedActions) 
                                
                                }

                                Throw $ErrorRecord

                            }

                            404 
                            {
                                
                                if ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorCode -eq 'CHANNEL_PARTNER_VALIDATION_FAILED')
                                {

                                    $_ExceptionMessage = (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message
                                    $ErrorRecord = New-ErrorRecord HPOneview.ResourceNotFoundException ChannelPartnerNotFound ObjectNotFound 'ID' -Message $_ExceptionMessage

                                } 
                                
                                else
                                {

                                    $ErrorRecord = New-ErrorRecord HPOneview.ResourceNotFoundException ResourceNotFound ObjectNotFound "URI" -Message ("The requested resource '$uri' could not be found. " + (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.recommendedActions)

                                }

                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }
                        
                            405 
                            {
                        
                                $ErrorRecord = New-ErrorRecord InvalidOperationException (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorCode InvalidOperation "$($Method):$($uri)" -Message ("[Send-HPOVRequest]: The requested HTTP method is not valid/supported. " + (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.details + " URI: $uri")
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                            { @(409, 412) -contains $_ } 
                            {
                        
                                $ErrorRecord = New-ErrorRecord InvalidOperationException $(${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorCode InvalidOperation 'Send-HPOVRequest' -Message ("[Send-HPOVRequest]: $((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message) $((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.recommEndedActions)")
                                Throw $ErrorRecord

                            }

                            500 
                            {

                                if ((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.details) 
                                { 
                                    
                                    $message = (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.details 
                                
                                }

                                else 
                                { 
                                    
                                    $message = (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message 
                                
                                }
                                
                                if (-not($message.SubString($message.length - 1) -eq ".")) { $message += "." }
                                
                                $ErrorRecord = New-ErrorRecord InvalidOperationException $(${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorCode InvalidOperation 'Send-HPOVRequest' -Message ("[Send-HPOVRequest]: $message $((${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.recommEndedActions)") #-InnerException $global:ResponseErrorObject
                                Throw $ErrorRecord

                            }

                            #Wait for appliance startup here by calling Wait-HPOVApplianceStart
                            { @(503, 0) -contains $_ } 
                            {
                                
                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] HTTP $([int]$LastWebResponse.StatusCode) error caught."

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Calling Wait-HPOVApplianceStart"

                                Try
                                {

                                    Wait-HPOVApplianceStart -Appliance $ApplianceHost.Name

                                }

                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }
                                

                                #appliance startup should have finished.
                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Returning caller back to: $($method.ToUpper()) $uri"

                                if ($addHeader) 
                                { 
                                    
                                    return (Send-HPOVRequest -uri $uri -method $method -body $body -addHeader $addHeader -Hostname $ApplianceHost.Name) 
                                
                                }

                                elseif ($body)
                                {

                                    return (Send-HPOVRequest -uri $uri -method $method -body $body -Hostname $ApplianceHost.Name) 

                                }

                                else 
                                { 
                                    
                                    return (Send-HPOVRequest -uri $uri -method $method -Hostname $ApplianceHost.Name) 

                                }

                            }

                            501 
                            {

                                $ErrorRecord = New-ErrorRecord InvalidOperationException (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.errorCode SyntaxError 'Send-HPOVRequest' -Message ("[Send-HPOVRequest]: " + (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.message + " " + (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.recommEndedActions) -InnerException (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.details
                                Throw $ErrorRecord

                            }
                            
                        } 

                    }

                    else 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Exception Response Object to return."

                        return $null

                    }

                }

                finally
                {

                    "[{0}] Cleaning up HttpWebRequest" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    if ($reader) { $reader.Close() }

                    if ($LastWebResponse)
                    {
                        
                        $LastWebResponse.Close()

                        if ($LastWebResponse -is [System.IDisposable])
                        {

                            $LastWebResponse.Dispose()

                        }

                    }

                    if ($req) 
                    { 

                        if ($req -is [System.IDisposable])
                        {

                            $req.Dispose()

                        }

                    }

                }

                "[{0}] Does nextPageUri member exist: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [bool]($resp | gm -Name nextPageUri -ErrorAction SilentlyContinue) | Write-Verbose
                "[{0}] Is nextPageUri Null or Empty: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [string]::IsNullOrEmpty($resp.nextPageUri) | Write-Verbose

                $_Stop = $False

                #Always stop if manual paging
                if ($ManualPaging)
                {

                    '[{0}] Stopping Do/Until loop because of manual paging' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $_Stop = $True

                }

                #If not manual paging and nextPageUri doesn't exist, stop
                elseif (-not($ManualPaging) -and -not([bool]($resp | gm -Name nextPageUri -ErrorAction SilentlyContinue)))
                {

                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Stopping Do/Until loop because nextPageUri doesn't exist and have received all objects." | Write-Verbose

                    $_Stop = $True

                }

                #If not manual paging, nextPageUri exists and it is null or empty
                elseif (-not($ManualPaging) -and ([bool]($resp | gm -Name nextPageUri -ErrorAction SilentlyContinue)) -and [string]::IsNullOrEmpty($resp.nextPageUri))
                {
                
                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Stopping Do/Until loop because nextPageUri is null/empty and have received all objects." | Write-Verbose

                    $_Stop = $True
                
                }

            } until ($_Stop)

            $c++

        } #Continue with next appliance

    }

    End 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] End"

        Return $AllResponses

    }

}

function Remove-ApplianceConnection
{
    
    [CmdletBinding ()]
    [Alias ('rac')]
    Param 
    (

        [Parameter (Mandatory = $false, ValueFromPipeline, Position = 0)]
        #[ValidateNotNullorEmpty()]
        [Object]$InputObject
    
    )

    Begin
    {

        #Write-Verbose "InputObject: $($InputObject | Out-String)"

    }

    Process
    {



        if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string] -and $InputObject -isnot [Hashtable])
        {

            Write-Verbose 'InputObject is IEnumerable'

            $Collection = New-Object System.Collections.ArrayList

            foreach ($object in $InputObject) 
            { 

                $_UpdatedObject = Remove-ApplianceConnection $object
                
                [void]$Collection.Add($_UpdatedObject)
                
            }

            Return ,$Collection

        }

        elseif ($InputObject -is [PSCustomObject])
        {

            Write-Verbose 'InputObject is [PSCustomObject]. Copying...'

            $_ClonedObject = $InputObject.PSObject.Copy()

            foreach ($property in $InputObject.PSObject.Properties)
            {

                if ($InputObject.($property.Name) -is [System.Collections.IEnumerable] -and $InputObject.($property.Name) -isnot [string] -and $InputObject.($property.Name) -isnot [Hashtable])
                {

                    Write-Verbose 'Property is IEnumerable'

                    $_SubCollection = New-Object System.Collections.ArrayList

                    foreach ($_subobject in $InputObject.($property.Name)) 
                    { 
                    
                        $_UpdatedObject = Remove-ApplianceConnection $_subobject
                        
                        [void]$_SubCollection.Add($_UpdatedObject)
                        
                    }

                    $_ClonedObject.($property.Name) = $_SubCollection

                }

                else
                {

                    if ($property.Name -eq 'ApplianceConnection')
                    {
                
                        Write-Verbose 'Found ApplianceConnection prop, removing'

                        $_ClonedObject.PSObject.Properties.Remove($property.Name)

                    }

                    elseif ($InputObject.($property.Name) -is [PSCustomObject] -and $InputObject.($property.Name) -isnot [string])
                    {

                        Write-Verbose "Nested [PSCustomObject] {$($property.Name)}, Processing..."

                        $_ClonedObject.($property.Name) = Remove-ApplianceConnection $InputObject.($property.Name)

                    }

                }

            }

            Return $_ClonedObject

        }

        else
        {

            Return $InputObject
        
        }
    
    }

}

function ConvertTo-Object
{
        
    [CmdletBinding ()]
    Param 
    (

         [Parameter (Mandatory)]
         [ValidateNotNullOrEmpty()]
         [System.Collections.ArrayList]$Objects

    )

    Begin
    {

        $NewObjects = New-Object System.Collections.ArrayList

    }

    Process
    {
        
        #Write-verbose "Objects is '$($Objects.GetType().Fullname)' type."
        
        ForEach($_obj in $Objects)
        {

            #Write-verbose "_obj is '$($_obj.GetType().Fullname)' type."

            #Write-verbose "Processing: $($_obj.name)"

            switch ($_obj.category)
            {

                "ethernet-networks"
                {
                
                    #[HPOneView.Networking.EthernetNetwork]$_newObj = $_obj

                    $_obj.PSObject.TypeNames.Insert(0,'HPOneView.Networking.EthernetNetwork')
                
                }

                "fc-networks"
                {
                
                    #[HPOneView.Networking.FibreChannelNetwork]$_newObj = $_obj
                    $_obj.PSObject.TypeNames.Insert(0,'HPOneView.Networking.FibreChannelNetwork')
                
                }

                "fcoe-networks"
                {
                
                    #[HPOneView.Networking.FCoENetwork]$_newObj = $_obj
                    $_obj.PSObject.TypeNames.Insert(0,'HPOneView.Networking.FCoENetwork')

                }

                default
                {
                
                    #$_newObj = $_obj

                }

            }


            #Write-verbose "_newObj is '$($_newObj.GetType().Fullname)' type."

            #[void]$NewObjects.Add($_newObj)
            [void]$NewObjects.Add($_obj)

        }

    }

    End
    {

        Return $NewObjects

    }

}
 
function Ping-HPOVAddress
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding ()]
    Param 
    (

        #allow via pipeline
        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [String]$Address,

        [Parameter (Mandatory = $False)]
        [ValidateNotNullOrEmpty()]
        [int]$Packets = 5,

        [Parameter (Mandatory = $False)]
        [switch]$Async,

        [Parameter (Mandatory= $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #Allow targets to be passed via pipeline
        if (-not($PSBoundParameters['Address'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            $_PingObject = NewObject -Ping

            $_PingObject.address = $Address

            if ($PSBoundParameters['Packets'])
            {

                $_PingObject.noOfPackets = $Packets

            }

            Try
            {

                $_resp = Send-HPOVRequest $appliancePingTestUri POST $_PingObject -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if (-not($PSBoundParameters['Async']))
            {

                $_resp = Wait-HPOVTaskComplete $_resp

                Write-Host " "
                $_resp.progressUpdates.statusUpdate | Out-Host
                Write-Host " "

            }
                    
            [void]$_TaskCollection.Add($_resp)

        }

    }

    End
    {

        Return $_TaskCollection

    }

}

function Wait-HPOVApplianceStart 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory)]
        [Alias ('Appliance')] 
        [ValidateNotNullOrEmpty()]
        [string]$Hostname = $null
    
    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose 

        if ($Hostname -is [String])
        {

            if (-not(${Global:ConnectedSessions}.Name -contains $Hostname) -and (-not(${Global:ConnectedSessions} | ? Name -eq $Hostname).SessionID))
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Appliance Session not found. Running FTS sequence?"

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating temporary Session object"

                $_ApplianceName = $Hostname

                [HPOneView.Appliance.Connection]$Hostname = NewObject -TemporaryConnection

                $Hostname.Name = $_ApplianceName

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($Hostname | fl * | out-string)"
            
            }

            else #if (${Global:ConnectedSessions}.Name -contains $Appliance)
            {

                "[{0}] Appliance is a string value, lookup connection in global tracker." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                [HPOneView.Appliance.Connection]$Hostname = ${Global:ConnectedSessions} | ? Name -eq $Hostname

                "[{0}] Found connection in global tracker: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Hostname | Out-String) | Write-Verbose

            }
            
        }

        elseif ($Hostname -is [HPOneView.Appliance.Connection])
        {

            "[{0}] Appliance is a Connection: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Hostname | Out-String) | Write-Verbose

        }
    
    }

    Process 
    {

        $_SW = New-Object System.Diagnostics.Stopwatch

        $_SW.Start()

        do 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Services not started. Monitoring startup progress"
            
            $waitRequest  = $Null
            $waitResponse = $Null

            [System.Net.httpWebRequest]$waitRequest = RestClient -uri $ApplianceStartProgressUri -appliance $Hostname.Name
            $waitRequest.Timeout = 10000

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] REQUEST: $($waitRequest.Method) $($waitRequest.RequestUri)"

            $i = 0

            foreach ($h in $waitRequest.Headers) 
            { 
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Request Header $($i+1): $($h) = $($waitRequest.Headers[$i])"
                
                $i++ 
            
            }

            try 
            {

                #Get response from appliance
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting response..."

                $waitResponse = $waitRequest.GetResponse()
                [int]$HttpStatusCode = $waitResponse.StatusCode

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received HTTP\$([int]$waitResponse.StatusCode) status."

                #This will trigger when the GetResponse() does not generate an HTTP Error Code and get trapped by the Catch statement below
                If ($_displayflag) 
                {

                    write-host "]"

                    #Reset flag so we don't display the Ending brace
                    $_displayflag = $False

                }

                #Read the response
                $reader = New-Object System.IO.StreamReader($waitResponse.GetResponseStream())
                $responseJson = $reader.ReadToEnd()
                $reader.Close()

                $resp = ConvertFrom-json $responseJson

                $StatusMessage = 'Step2: Start resource managers {0} of {1}, {2:##}%' -f $resp.completeComponents, $resp.totalComponents, [Math]::Round($resp.percentComplete)
                
                #Handle the call from -Verbose so Write-Progress does not get borked on display.
                if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                { 
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Skipping Write-Progress display."
                    "[{0}] {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StatusMessage | Write-Verbose

                }
                
                else 
                {

                    #Display progress-bar
                    Write-Progress -activity "Appliance services starting" -Status $StatusMessage -percentComplete ('{0:##}' -f $resp.percentComplete)

                }

                start-sleep -s 2

            }

            #Catch if we haven't received HTTP 200, as we should display a nice message stating services are still beginning to start
            catch [Net.WebException] 
            {

                if ($_.Exception.Message -match 'The remote name could not be resolved')
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($waitResponse) 
                {

                    $reader = New-Object System.IO.StreamReader($waitResponse.GetResponseStream())

                    $responseJson = $reader.ReadToEnd()

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] ERROR RESPONSE: $($responseJson | ConvertFrom-Json | out-string)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response Status: HTTP_$([int]$waitResponse.StatusCode) $($waitResponse.StatusDescription)"

                    foreach ($h in $waitResponse.Headers) 
                    { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response Header: $($h) = $($waitResponse.Headers[$i])"
                        
                        $i++ 
                    
                    }

                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] EXCEPTION CAUGHT! HTTP Status Code: $([int]$waitResponse.StatusCode)"

                #Handle WebExcpetion errors that are not HTTP Status Code 503 or 0, and throw error
                if ([int]$waitResponse.StatusCode -ne 503 -and [int]$waitResponse.StatusCode -ne 0)
                {

                    Throw $_.Exception.Message

                }

                write-verbose "$($waitResponse| Out-string)"

                #Only want to display this message once.
                if (-not($_displayflag)) 
                {

                    Write-host "Waiting for services to Begin starting [" -nonewline

                }

                if (-not ([int]$waitResponse.StatusCode -eq 200)) 
                {

                    Write-host "*" -nonewline -ForegroundColor Green

                    $_displayflag = $true

                    start-sleep -s 5

                }

            }

            finally
            {

                if ($waitResponse -is [System.IDisposable])
                {
                    
                    $waitResponse.Dispose()

                }

            }

            #Timeout after 10 minutes
            if ($_SW.Elapsed.TotalSeconds -ge 900)
            {

                $_SW.Stop()

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.NetworkConnectionException ConnectionWaitTimeoutExceeded OperationTimeout -TargetObject 'Hostname' -Message "Timeout waiting for appliance to respond after restart event. Verify the appliance is operational and reconnect to the appliance."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            '[{0}] Ending Do Loop: {1}; Percent Complete: {2}; HTTP Status Code: {3}' -f $MyInvocation.InvocationName.ToString().ToUpper(), [Bool]([int]$resp.percentComplete -eq 100 -and $HttpStatusCode -eq 200), $resp.percentComplete, $HttpStatusCode | Write-Verbose

        } until ([int]$resp.percentComplete -eq 100 -and $HttpStatusCode -eq 200)

        #Remove Temporary appliance connection
        if ((${Global:ConnectedSessions} | ? Name -eq $ApplianceConnection.Name).SessionID -eq 'TemporaryConnection')
        {

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing temporary Session object"

            [void]${Global:ConnectedSessions}.Remove($ApplianceConnection)

        }

    }

    End 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Web Services have started successfully"

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Pausing 10 seconds to let web services finish their final startup"

        start-sleep -s 10

    }

}

function Connect-HPOVMgmt 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'UsernamePassword')]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = 'UsernamePassword')]
        [Parameter (Mandatory, ParameterSetName = 'PSCredential')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance', 'Computername')]
        [string]$Hostname,

        [Parameter (Mandatory = $false, ParameterSetName = 'UsernamePassword')]
        [Parameter (Mandatory = $false, ParameterSetName = 'PSCredential')]
        [ValidateNotNullOrEmpty()]
        [Alias ('authProvider')]
        [string]$AuthLoginDomain = 'LOCAL',

        [Parameter (Mandatory, ParameterSetName = 'UsernamePassword')]
        [ValidateNotNullOrEmpty()]
        [Alias ("u",'user')]
        [string]$UserName,

        [Parameter (Mandatory = $false, ParameterSetName = 'UsernamePassword')]
        [Alias ("p")]
        [ValidateNotNullOrEmpty()]
        [Object]$Password,

        [Parameter (Mandatory, ParameterSetName = 'PSCredential')]
        [ValidateNotNullOrEmpty()]
        [Alias ('PSCredential')]
        [PSCredential]$Credential,

        [Parameter (Mandatory = $false, ParameterSetName = 'UsernamePassword')]
        [Parameter (Mandatory = $false, ParameterSetName = 'PSCredential')]
        [switch]$LoginAcknowledge 

    )

    Begin 
    {

        #Clone PSBoundParameters
        $_Params = @{}
        
        $PSBoundParameters.GetEnumerator() | % {

            $_Params.Add($_.Key,$_.Value)

        }

        $_Params['password'] = '[*****REDACTED******]'

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Bound PS Parameters: $($_Params | out-string)"
        
        #Check to see if a connection to the appliance exists
        if ((${Global:ConnectedSessions}.Name -contains $Hostname) -and ((${Global:ConnectedSessions} | ? name -eq $Hostname).SessionID)) 
        {

            Write-Warning "You are already connected to $Hostname"
            continue
                
        }

        #Create the connection object for tracking
        else 
        {

            # Look for Connection where Name exists but SessionID does not, and remove the object from $ConnectedSessions
            if ((${Global:ConnectedSessions}.Name -contains $Hostname) -and (-not(${Global:ConnectedSessions} | ? name -eq $Hostname).SessionID)) 
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found incomplete session object in $ConnectedSessions for '$Hostname'. Removing."

                #Found incomplete session connection. must remove it from the collection first.
                $_ndx = [array]::IndexOf(${Global:ConnectedSessions}, (${Global:ConnectedSessions}.Name -contains $Hostname))

                if ($_ndx -gt 0)
                {

                    [void]${Global:ConnectedSessions}.RemoveAt($_ndx)

                }

                else
                {

                    "[{0}] Index was {1}, connection doesn't exist in global tracker." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ndx | Write-Verbose

                }    
                    
            }

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating Session Container"

            $tmpConnectionId = 1

            #Figure out ConnectionId
            if (${Global:ConnectedSessions})
            {

                While (${Global:ConnectedSessions}.ConnectionId -contains $tmpConnectionId) 
                {

                    $tmpConnectionId++

                }
            
            }

            #Store the entire auth request for later deletion when issuing Disconnect-HPOVmgmt
            [HPOneView.Appliance.Connection]$ApplianceConnection = New-Object HPOneView.Appliance.Connection($tmpConnectionId, $Hostname, $UserName, $AuthLoginDomain)

            $ApplianceConnection.Default = if (-not(${Global:ConnectedSessions} | ? Default)) { $True }

            [void]${Global:ConnectedSessions}.Add($ApplianceConnection)

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(${Global:ConnectedSessions} | out-string)"
            
        }

        if (-not($PSBoundParameters['Password']) -and $PSCmdlet.ParameterSetName -eq 'UsernamePassword')
        {

            [SecureString]$password = read-host -AsSecureString "Password"
            $decryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))
            
        }

        elseif ($Password -is [SecureString] -and $PSCmdlet.ParameterSetName -eq 'UsernamePassword')
        {

            $decryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

        elseif ($PSCmdlet.ParameterSetName -eq 'UsernamePassword')
        {

            $decryptPassword = $Password

        }

        elseif ($PSCmdlet.ParameterSetName -eq 'PSCredential')
        {

            $Username = $Credential.UserName
            $decryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential.Password))

        }

        else
        {

            $Credential = Get-Credential
            $Username = $Credential.UserName
            $decryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential.Password))

        }

        #Check to make sure the appliance X-API-Version is at least the supported minimum
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Checking X-API Version"
            
        try 
        {
            
            $applianceVersion = (Send-HPOVRequest $script:ApplianceXApiVersionUri -Hostname $Hostname).currentVersion

            if ($applianceVersion -and $applianceVersion -lt $MinXAPIVersion ) 
            {

                [void] ${Global:ConnectedSessions}.Remove($ApplianceConnection)

                #Display terminating error
                $ErrorRecord = New-ErrorRecord System.NotImplementedException LibraryTooNew OperationStopped $Hostname -Message "The appliance you are connecting to supports an older version of this library. Please visit https://github.com/HewlettPackard/POSH-HPOneView for a supported version of the library."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        catch 
        {

            [void] ${Global:ConnectedSessions}.Remove($ApplianceConnection)
            
            $PSCmdlet.ThrowTerminatingError($_)

        }

    }

    Process 
    {

        $_authinfo = NewObject -AuthLogin

        $_authinfo.userName        = $UserName
        $_authinfo.password        = $decryptPassword

        if ($PSBoundParameters['LoginAcknowledge'])
        {

            $_authinfo | Add-Member -NotePropertyName loginMsgAck -NotePropertyValue $True

        }

        try 
        {

            "[{0}] Sending auth request" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_LoginDetails = Send-HPOVRequest $ApplianceLoginDomainDetails -Hostname $Hostname

            if (-not $PSBoundParameters['AuthLoginDomain'])
            {
                
                $_authinfo.authLoginDomain = $_LoginDetails.defaultLoginDomain
                (${Global:ConnectedSessions} | ? Name -EQ $Hostname).AuthLoginDomain = $_LoginDetails.defaultLoginDomain

            }

            else
            {
                
                $_authinfo.authLoginDomain = $AuthLoginDomain

            }

            Write-Host ("{0}`n" -f $_LoginDetails.loginMessage.message)
            
            $resp = Send-HPOVRequest $ApplianceLoginSessionsUri POST $_authinfo -Hostname $Hostname

        } 

        catch [HPOneView.Appliance.AuthSessionException] 
        {

            "[{0}] Authentication Exception Caught." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_ErrorId = $_.FullyQualifiedErrorId.Split(',')[0]

            $_ErrorRecord = $_

            switch ($_ErrorId)
            {

                'LoginMessageAcknowledgementRequired'
                {

                    "[{0}] Authentication Exception Caught." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    #Get LoginMessage from appliance.
                    Try
                    {

                        $caption = "Please Confirm";
                        $message = "Do you acknowledge the login message?";
                        $yes     = new-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Yes, I accept the login message.";
                        $no      = new-Object System.Management.Automation.Host.ChoiceDescription "&No","No, I do not.";
                        $choices = [System.Management.Automation.Host.ChoiceDescription[]]($yes,$no);
                        $answer  = $host.ui.PromptForChoice($caption,$message,$choices,1) 

                        switch ($answer)
                        {

                            #YES
                            0 
                            {

                                "[{0}] Submitting auth request again, with login message acknowledgement." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                            
                                $_authinfo | Add-Member -NotePropertyName loginMsgAck -NotePropertyValue $True

                                Try
                                {

                                    $resp = Send-HPOVRequest $ApplianceLoginSessionsUri POST $_authinfo -Hostname $Hostname

                                }

                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }

                            }

                            #NO
                            1
                            {

                                "[{0}] User selected 'No'." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                'You are not authenticated to {0}, as you chose not to accept the Login Message acknowledgement.' -f $Hostname | Write-Warning 

                                #Remove Connection from global tracker
                                [void] ${Global:ConnectedSessions}.Remove($ApplianceConnection)

                                Return

                            }

                        }   

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                'InvalidUsernameOrPassword'
                {

                    #Remove Connection from global tracker
                    [void] ${Global:ConnectedSessions}.Remove($ApplianceConnection)

                    $PSCmdlet.ThrowTerminatingError($_ErrorRecord)

                }

                default
                {

                    #Remove Connection from global tracker
                    [void] ${Global:ConnectedSessions}.Remove($ApplianceConnection)

                    #$ErrorRecord = New-ErrorRecord HPOneView.Appliance.AuthSessionException $_ErrorId InvalidResult 'Connect-HPOVMgmt' -Message $_.Exception.Message
                    $PSCmdlet.ThrowTerminatingError($_ErrorRecord)

                }

            }           

        }

        catch [HPOneview.Appliance.PasswordChangeRequired] 
        {

            "[{0}] Password needs to be changed. Use Set-HPOVInitialPassword if this is first time setup, or Set-HPOVUserPassword to update your own accounts password." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            [void] ${Global:ConnectedSessions}.Remove($ApplianceConnection)

            #Throw terminating error
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.PasswordChangeRequired PasswordExpired PermissionDenied 'Username' -Message "The password has expired and needs to be updated. Use Set-HPOVInitialPassword if this is first time setup, or Set-HPOVUserPassword to update your own accounts password."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)   
        
        }
            
        catch [Net.WebException] 
        {

            "[{0}] Response: $($resp)" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            [void] ${Global:ConnectedSessions}.Remove($ApplianceConnection)

            $ErrorRecord = New-ErrorRecord System.Net.WebException ApplianceNotResponding OperationStopped $Hostname -Message "The appliance at $Hostname is not responding on the network. Check for firewalls or ACL's prohibiting access to the appliance."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Something bad happened, should not leave connection in this state
        catch
        {

            [void] ${Global:ConnectedSessions}.Remove($ApplianceConnection)

            $PSCmdlet.ThrowTerminatingError($_)

        }

    }

    End 
    {

        "[{0}] Authentication Response recieved. Processing final connection object." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        #If a sessionID is returned, then the user has authenticated
        if ($resp.SessionID) 
        {

            $_RedactedResp = $resp.PSObject.Copy()

            $_RedactedResp.SessionId = '[*****REDACTED******]'
            
            "[{0}] Session received: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $($_RedactedResp | Out-String) | Write-Verbose
            
            (${Global:ConnectedSessions} | ? Name -EQ $Hostname).SessionID = $resp.sessionID
            (${Global:ConnectedSessions} | ? Name -EQ $Hostname).Username  = $UserName
    
            #Get list of supported Roles from the appliance
            "[{0}] Getting list of supported roles from appliance." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            try 
            { 
                
                $_ApplianceSecurityRoles = (Send-HPOVRequest $Script:applianceRolesUri -Hostname $Hostname).members.roleName 

                (${Global:ConnectedSessions} | ? Name -EQ $Hostname ) | Add-Member -NotePropertyName ApplianceSecurityRoles -NotePropertyValue $_ApplianceSecurityRoles  -force
            
            }

            catch [HPOneview.Appliance.AuthPrivilegeException] 
            { 
                
                (${Global:ConnectedSessions} | ? Name -EQ $Hostname ) | Add-Member -NotePropertyName ApplianceSecurityRoles -NotePropertyValue $null -force
            
            }

            #Get Appliance Type to track what Cmdlet features are available
            try 
            { 
                
                $ApplianceType = (Send-HPOVRequest $ApplianceVersionUri -Hostname $Hostname).platformType

                (${Global:ConnectedSessions} | ? Name -EQ $Hostname ).ApplianceType = $AppliancePlatformType[$ApplianceType]
            
            }

            catch
            { 
                
                $PSCmdlet.ThrowTerminatingError($_)
            
            }

            $_applianceversioninfo = NewObject -ApplianceVersion
            
            Try
            {

                $applVersionInfo = Send-HPOVRequest -Uri $ApplianceVersionUri -Hostname $Hostname

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            Try
            {

                $_applianceversioninfo = New-Object HPOneView.Appliance.Version ([Version]($applVersionInfo.softwareVersion.Replace('-',$null)), (Get-HPOVXApiVersion -ApplianceConnection $Hostname).currentVersion, $applVersionInfo.modelNumber)
                
                $PSLibraryVersion | Add-Member -NotePropertyName $Hostname -NotePropertyValue $_applianceversioninfo -Force

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            Return $ApplianceConnection

        }

        else 
        { 
                              
            Return $resp 

        }

    }

}

function Disconnect-HPOVMgmt 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding ()]
    Param
    (
    
        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance','ApplianceSession')]
        [Object]$Hostname = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose
        
        if (-not($Hostname))
        { 
        
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoAuthSession ResourceUnavailable 'Hostname' -Message "No valid logon session available. Please use Connect-HPOVMgmt to connecto to an appliance, and then use Disconnect-HPOVmgmt to terminate your session."
            $PSCmdlet.WriteError($ErrorRecord)
            
        }

    }

    Process 
    {

        if (-not($PSBoundParameters['Hostname']))
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No hostname(s) or connection(s) provided. Processing all connected sessions."

        }

        if ($Hostname -is [System.Collections.IEnumerable] -and $Hostname -isnot [System.String])
        {

            $Hostname = $Hostname.Clone()

            For ($_c = 0; $_c -lt $Hostname.Count; $_c++)
            {

                '[{0}] Processing Connection {1} of {2}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $Hostname[$_c].Name, $Hostname.Count | Write-Verbose
                
                if ($Hostname[$_c] -is [String])
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Hostname provide, looking in global connection tracker for connection."

                    [HPOneView.Appliance.Connection]$Hostname[$_c] = ${Global:ConnectedSessions} | ? Name -eq $Hostname

                }

                if ($Null -eq $Hostname[$_c] -or $Null -eq $Hostname[$_c].SessionID)
                {

                    Write-Verbose ('[{0}] User Session not found in $ConnectedSessions' -f $MyInvocation.InvocationName.ToString().ToUpper())

                    if ($Hostname[$_c] -is [HPOneView.Appliance.Connection])
                    {

                        $_ConnectionName = $Hostname[$_c].Name

                    }

                    else
                    {
                
                        $_ConnectionName  = $Hostname[$_c]
                
                    }

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException UnableToLogoff ObjectNotFound 'Hostname' -Message "User session for '$_ConnectionName' not found in library connection tracker (`${Global:ConnectedSessions}). Did you accidentially remove it, or have you not created a session to an appliance?"
                    $PSCmdlet.WriteError($ErrorRecord)

                }
           
                else
                {

                    '[{0}] Attempting to logoff user {1} from {2}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $Hostname[$_c].Username, $Hostname[$_c].Name | Write-Verbose

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending Delete Session ID request"

                    try 
                    {
                
                        $Resp = Send-HPOVRequest $ApplianceLoginSessionsUri DELETE $Hostname[$_c].SessionId -Hostname $Hostname[$_c].Name

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing connection from global connection tracker"

                        [void]$Global:ConnectedSessions.Remove($Hostname[$_c])
                    
                    }
                
                    #Need to clean up
                    catch
                    {
                
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Unable to complete logoff. Displaying error"
                        $PSCmdlet.ThrowTerminatingError($_)
                
                    }

                }

            }

        }
        
        else
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Connection: $($Hostname | fl * | Out-String)"

            #Check first if the Hostname value is a ConnectionID Integer
            [int]$_tmpValue = 0

            if ([Int]::TryParse($Hostname,[ref]$_tmpValue))
            {

                "[{0}] Hostname is ConnectionID {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_tmpValue | Write-Verbose

                [HPOneView.Appliance.Connection]$Hostname = ${Global:ConnectedSessions} | ? ConnectionID -eq $_tmpValue

                "[{0}] {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Hostname | Out-String) | Write-Verbose

            }

            if ($Hostname -is [String])
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Hostname provide, looking in global connection tracker for connection."

                [HPOneView.Appliance.Connection]$Hostname = ${Global:ConnectedSessions} | ? Name -eq $Hostname

            }

            if ($Null -eq $Hostname.SessionID)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User Session not found in '`${Global:ConnectedSessions}'"

                if ($Hostname -is [HPOneView.Appliance.Connection])
                {

                    $_ConnectionName = $Hostname.Name

                }

                else
                {
                
                    $_ConnectionName  = $Hostname
                
                }

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException UnableToLogoff ObjectNotFound 'Hostname' -Message "User session for '$_ConnectionName' not found in library connection tracker (`${Global:ConnectedSessions}). Did you accidentially remove it, or have you not created a session to an appliance?"
                $PSCmdlet.WriteError($ErrorRecord)

            }
           
            else
            {


                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Attempting to logoff user '$($Hostname.Username)' from '$($Hostname.Name)'."

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending Delete Session ID request"

                try 
                {
                
                    $Resp = Send-HPOVRequest $ApplianceLoginSessionsUri DELETE $Hostname.SessionId -Hostname $Hostname

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing connection from global connection tracker"

                    $Global:ConnectedSessions.Remove($Hostname)
                    
                }
                
                catch
                {
                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Unable to complete logoff. Displaying error"
                    $PSCmdlet.ThrowTerminatingError($_)
                
                }

            }

        }

    }

    End
    {

        if ($ConnectedSessions.Count -eq 1 -and (-not($ConnectedSessions | ? Default)))
        {

            $ConnectedSessions[0].Default = $true

        }
        
        Return $ConnectedSessions
    
    }

}

function Set-HPOVApplianceDefaultConnection
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$Connection

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #Check to see if there is only a single connection in the global tracker
        If (${Global:ConnectedSessions}.Count -eq 1)
        {

            Write-Warning 'There is only a single Appliance Connection. This Cmdlet only supports multiple Appliance Connections.'

            if (-not($Global:ConnectedSessions[0].Default))
            {

                'Appliance Connection "{0}" was not found to be the default connection. Setting as default.' -f ${Global:ConnectedSessions}[0].Name | Write-Warning 

                $Global:ConnectedSessions[0].Default = $True

            }
            
            Break

        }

        if ($Connection -is [System.String])
        {

            "[{0}] Connection Name provided. Looking in Global connection tracker variable." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Try
            {

                $Connection = ${Global:ConnectedSessions} | ? Name -eq $Connection

            }

            Catch [System.Management.Automation.ValidationMetadataException]
            {

                "[{0}] Connection was not found. Looking for matching name in Global connection tracker variable." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                Try
                {

                    $Connection = ${Global:ConnectedSessions} | ? Name -Match $Connection

                }
                
                Catch
                {

                    $_Message = "Unable to find an appliance connection with the provided Connection Name, {0}. Please provide the Connection Object or validate the Name and try again." -f $Connection
                    $ErrorRecord = New-ErrorRecord InvalidOperationException ApplianceConnectionNotFound ObjectNotFound 'Connection' -Message $_Message
                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
        }

        if ($Connection -isnot [HPOneView.Appliance.Connection])
        {

            $_Message = "An invalid connection argument value type was provided, {0}. Please provide either a [String] or [HPOneView.Appliance.Connection] object." -f $Connection
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidConnectionParameterValue InvalidArgument 'Connection' -TargetType $Connection.GetType().Name -Message $_Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

    }

    Process
    {

        #Check for existing Default Connection
        if (${Global:ConnectedSessions} | ? Default)
        {

            #Unset it
            (${Global:ConnectedSessions} | ? Default).Default = $false

        }

        "[{0}] Setting {1} as the new default Appliance Connection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Connection.Name | Write-Verbose

        (${Global:ConnectedSessions} | ? Name -eq $Connection.Name).Default = $true

    }

    End
    {

        Return ${Global:ConnectedSessions}

    }

}

function Test-HPOVAuth
{

    [CmdletBinding ()]
    Param
    (
    
        [Parameter (Mandatory = $false, ValueFromPipeline)]
        [Object] [AllowEmptyString()] $Appliance
    
    )

    Begin 
    {

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Caller: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSBoundParameters['Appliance'])
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Verify Auth for $Appliance"

        }

        else
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] -Appliance value via pipeline."
            
            $PipelineInput = $True

        }

        $_ApplianceConnections = New-Object System.Collections.ArrayList

    }

    Process
    {

        if ([string]::IsNullOrWhiteSpace($Appliance))
        {
        
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "$($Caller):$($_Appliance)" -Message 'No default active HPOV connection session found (check ${Global:ConnectedSessions} global variable.) Using this cmdlet requires either a default connection or the -ApplianceConnection parameter. Please use Connect-HPOVMgmt, if required, to establish a connection, or set a default connection and then try your command again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
        
        }

        if ($PipelineInput)
        {
    
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Verify Auth for $($Appliance.Name)"

        }
        
        if ($Appliance -is [System.Collections.IEnumerable])
        {

            ForEach ($_Appliance in $Appliance)
            {

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] `$Appliance is [{0}]"  -f $_Appliance.GetType().FullName | Write-Verbose

                Switch ($_Appliance.GetType().FullName)
                {

                    'HPOneView.Appliance.Connection'
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Recieved HPOneView.Appliance.Connection Object: $($_Appliance | Out-String)"

                        If (-not(${Global:ConnectedSessions} | ? name -eq $_Appliance.Name))
                        {

                            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "$($Caller):$($_Appliance.Name)" -Message "No Appliance connection session found for '$($_Appliance.Name)' within `${Global:ConnectedSessions} global variable. This CMDLET requires at least one active connection to an appliance. Please use Connect-HPOVMgmt to establish a connection, then try your command again."

                        }

                        if ($_Appliance.SessionID -eq 'TemporaryConnection')
                        {

                            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException InvalidApplianceConnectionState InvalidOperation "$($Caller):$($_Appliance.Name)" -Message "The ApplianceConnection provided is a Temporary Connection, which is an invlaid state your PowerShell environment has become. Plesae restart your session and try your calls again."

                        }

                        $_Appliance = $Appliance

                    }

                    'System.String'
                    {

                        if (-not(${Global:ConnectedSessions} | ? name -eq $_Appliance))
                        {

                            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "$($Caller):$($_Appliance)" -Message "No connection session found for '$($_Appliance)' within `${Global:ConnectedSessions} global variable. This CMDLET requires at least one active connection to an appliance. Please use Connect-HPOVMgmt to establish a connection, then try your command again."

                        }

                        elseif (${Global:ConnectedSessions} | ? name -eq $_Appliance)
                        {
                    
                            $_Appliance = ${Global:ConnectedSessions} | ? name -eq $_Appliance

                        }

                    }

                    'System.Management.Automation.PSCustomObject'
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Recieved PSCustomObject: $($_Appliance | Out-String)"

                        If (-not(${Global:ConnectedSessions} | ? name -eq $_Appliance.Name))
                        {

                            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "$($Caller):$($_Appliance.Name)" -Message "No Appliance connection session found for '$($_Appliance.Name)' within `${Global:ConnectedSessions} global variable. This CMDLET requires at least one active connection to an appliance. Please use Connect-HPOVMgmt to establish a connection, then try your command again."

                        }

                        $_Appliance = ${Global:ConnectedSessions} | ? name -eq $_Appliance.Name

                    }

                    default
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Unsupported ApplianceConnection object."

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NotaValidApplianceConnection AuthenticationError "$($Caller)" -Message "The provided appliance object is not valid, as it is neither an [HPOneView.Appliance.Connection] object, [String] value representing a potentially valid Appliance Connection, or a [PSCustomObject] property of a resource object obtained from an appliance. Please correct the ApplianceConnection Parameter value, and then try your command again."

                    }

                }

                If ($ErrorRecord)
                { 

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Else
                {

                    [void]$_ApplianceConnections.Add($_Appliance)

                }

            }

        }

        else
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] `$Appliance is [{0}]"  -f $Appliance.GetType().FullName | Write-Verbose

            Switch ($Appliance.GetType().FullName)
            {

                'HPOneView.Appliance.Connection'
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Recieved HPOneView.Appliance.Connection Object: $($Appliance | Out-String)"

                    If (-not(${Global:ConnectedSessions} | ? name -eq $Appliance.Name))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "$($Caller):$($_Appliance.Name)" -Message "No Appliance connection session found for '$($_Appliance.Name)' within `${Global:ConnectedSessions} global variable. This CMDLET requires at least one active connection to an appliance. Please use Connect-HPOVMgmt to establish a connection, then try your command again."

                    }

                }

                'System.String'
                {

                    if (-not(${Global:ConnectedSessions} | ? name -eq $_Appliance))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "$($Caller):$($_Appliance)" -Message "No connection session found for '$($_Appliance)' within `${Global:ConnectedSessions} global variable. This CMDLET requires at least one active connection to an appliance. Please use Connect-HPOVMgmt to establish a connection, then try your command again."

                    }

                    elseif (${Global:ConnectedSessions} | ? name -eq $_Appliance)
                    {
                    
                        $Appliance = ${Global:ConnectedSessions} | ? name -eq $Appliance

                    }

                }

                'System.Management.Automation.PSCustomObject'
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Recieved PSCustomObject: $($Appliance | Out-String)"

                    If (-not(${Global:ConnectedSessions} | ? name -eq $Appliance.Name))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "$($Caller):$($Appliance.Name)" -Message "No Appliance connection session found for '$($Appliance.Name)' within `${Global:ConnectedSessions} global variable. This CMDLET requires at least one active connection to an appliance. Please use Connect-HPOVMgmt to establish a connection, then try your command again."

                    }

                    $Appliance = ${Global:ConnectedSessions} | ? name -eq $Appliance.Name

                }

                default
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Unsupported ApplianceConnection object."

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NotaValidApplianceConnection AuthenticationError "$($Caller)" -Message "The provided appliance object is not valid, as it is neither an [HPOneView.Appliance.Connection] object, [String] value representing a potentially valid Appliance Connection, or a [PSCustomObject] property of a resource object obtained from an appliance. Please correct the ApplianceConnection Parameter value, and then try your command again."

                }

            }

            If ($ErrorRecord)
            { 

                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Else
            {

                [void]$_ApplianceConnections.Add($Appliance)

            }

        }        

    }

    End
    {
    
        Return $_ApplianceConnections

    }

}

function New-HPOVResource 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Uri,

        [Parameter (ValueFromPipeline, Mandatory)]
        [Alias('Resource')]
        [ValidateNotNullOrEmpty()]
        [object]$InputObject,

        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_NewResourceCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        Try
        {

            $_resp = Send-HPOVRequest -Uri $uri -Method POST -Body $InputObject -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        [void]$_NewResourceCollection.Add($_resp)

    }

    End
    {

        Return $_NewResourceCollection

    }

}

function Set-HPOVResource 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml
    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [Alias('Resource')]
        [ValidateNotNullOrEmpty()]
        [ValidateScript({$_.Uri})]
        [object]$InputObject,

        [Parameter (Mandatory = $false)]
        [switch]$Force,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {

        $InputObject = $InputObject.PSObject.Copy()

        if ($Force.IsPresent) 
        { 
            
            $InputObject.uri += "?force=true" 
        
        }

        Try
        {

            $_resp = Send-HPOVRequest -Uri $InputObject.uri -Method PUT -Body $InputObject -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $_resp

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVResource 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml
     
    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [Alias('Resource')]
        [ValidateNotNullorEmpty()]
        [Alias ("ro",'nameOruri','uri','name')]
        [object]$InputObject,

        [Parameter (Mandatory = $false)]
        [switch]$force,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_RemoveResourceCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
         
        switch ($InputObject.GetType().Name) 
        { 

            "PSCustomObject"  
            { 
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resource object passed."
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Name: $($InputObject.name)"
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] URI: $($InputObject.uri)"
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Type: $($InputObject.type)"

                [void]$_RemoveResourceCollection.Add($InputObject)
                
            }
         
            "String"
            {
                
                #nameOrUri value is a URI
                if ($InputObject.StartsWith("/rest"))
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resource URI passed '$($InputObject)', getting object"

                    Try
                    {

                        $_resource = Send-HPOVRequest $InputObject -Hostname $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                    [void]$_RemoveResourceCollection.Add($_resource)

                }

                #It's a string value
                else 
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resource name provided: $($InputObject)"
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Querying appliance index for resource."

                    #Use Index filtering to locate object
                    Try
                    {

                        $_resources = Send-HPOVRequest ($indexUri + "?filter=name='$InputObject'") -Hostname $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($_resources.count) resources."

                    if($_resources.members)
                    {

                        #Error should only be displayed if a Name was provided, and it wasn't globally unique on the appliance (i.e. Server Profile and Ethernet Network with the same name, which is completely valid.)
                        if($_resources.count -gt 1)
                        {
                            
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resources found: $($_resources.members | % { $_.name + " of type " + $_.category })"

                            $ErrorRecord = New-ErrorRecord InvalidOperationException ResourceNotUnique LimitsExceeded 'InputObject' -Message "'$InputObject' is not unique. Located $($_resources.count) resources with the same value."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        else 
                        { 
                        
                            [void]$_RemoveResourceCollection.Add($_resources.members)

                        }

                    }

                    else 
                    { 

                        $ErrorRecord = New-ErrorRecord InvalidOperationException ResourceNotFound ObjectNotFound 'InputObject' -Message "Resource '$InputObject' not found. Please check the resource value provided and try the call again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

            }   
              
        }

    }
    
    End
    {

        $n = 1

        ForEach ($_resource in $_RemoveResourceCollection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($_resource.name)', $n of $($_RemoveResourceCollection.Count)"

            if ([bool]$force) 
            { 
                
                $_resource.uri += "?force=true" 
            
            }

            Try
            {
                                
                Send-HPOVRequest $_resource.uri DELETE

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $n++

        }

    }

}

function ConvertFrom-HTML 
{

    [CmdletBinding ()]
    Param
    (

        [Parameter (ValueFromPipeline, Mandatory)]
        [ValidateNotNullOrEmpty()]
        [System.String] $html,

        [switch]$NoClobber
        
    )

    Begin { }

    Process 
    {
        
        # remove line breaks, replace with spaces
        if (-not ($NoClobber.ispresent)) { $html = $html -replace "(`r|`n|`t)", " " }
        
        # remove invisible content
        @('head', 'style', 'script', 'object', 'embed', 'applet', 'noframes', 'noscript', 'noembed') | % {$html = $html -replace "<$_[^>]*?>.*?</$_>", "" }
        
        # Condense extra whitespace
        $html = $html -replace "( )+", " "
        
        # Add line breaks
        @('div','p','blockquote','h[1-9]') | % { $html = $html -replace "</?$_[^>]*?>.*?</$_>", ("`n" + '$0' )} 

        # Add line breaks for self-closing tags
        @('div','p','blockquote','h[1-9]','br') | % { $html = $html -replace "<$_[^>]*?/>", ('$0' + "`n")} 
        
        #strip tags
        $html = $html -replace "<[^>]*?>", ""
         
        # replace common entities
        @(
            @("&amp;bull;", " * "),
            @("&amp;lsaquo;", "<"),
            @("&amp;rsaquo;", ">"),
            @("&amp;(rsquo|lsquo);", "'"),
            @("&amp;(quot|ldquo|rdquo);", '"'),
            @("&amp;trade;", "(tm)"),
            @("&amp;frasl;", "/"),
            @("&amp;(quot|#34|#034|#x22);", '"'),
            @('&amp;(amp|#38|#038|#x26);', "&amp;"),
            @("&amp;(lt|#60|#060|#x3c);", "<"),
            @("&amp;(gt|#62|#062|#x3e);", ">"),
            @('&amp;(copy|#169);', "(c)"),
            @("&amp;(reg|#174);", "(r)"),
            @("&amp;nbsp;", " "),
            @("&amp;(.{2,6});", ""),
            @("&nbsp;", " ")
        ) | % { $html = $html -replace $_[0], $_[1] }

    }

    End 
    {
    
        return $html

    }

}

function Start-HPOVLibraryTrace
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (
    
        [Parameter (Mandatory = $false)]
        [String]$Location = (pwd).path
    
    )

    Throw "This Cmdlet is now deprecated. Please use Get-HPOVCommandTrace instead."

}

function Stop-HPOVLibraryTrace
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    ()

    Throw "This Cmdlet is now deprecated. Please use Get-HPOVCommandTrace instead."

}

function Get-HPOVCommandTrace
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias('Command')]
        [ScriptBlock]$ScriptBlock = {},

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Location = (pwd).path

    )

    Begin 
    {

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Caller: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($Caller -eq 'Get-HPOVCommandTrace')
        {

            Throw "You cannot use the Cmdlet to trace itself. Please specify a different HPE OenView PowerShell Cmdlet."

        }

        $_TranscriptFile = $Location + '\' + (get-date -uformat %y%m%d%H%M) + '_HPOV_transcript.log'

        if ($host.name -match 'ISE' -and $PSVersionTable.PSVersion -lt '5.0')
        {

            Start-IseTranscript $_TranscriptFile | Out-Null

        }

        else
        {

            Try
            {
    
                '[{0}] Starting Transcript logging.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                '[{0}] Generating new trace file: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_TranscriptFile | Write-Verbose
                
                Start-Transcript $_TranscriptFile | Out-Null
    
            }
    
            catch
            {
    
                $PSCmdlet.ThrowTerminatingError($_)
    
            }

        }
        
        ($PSLibraryVersion | Out-String) | Write-Verbose -Verbose:$true

    }

    Process
    {

        # if ($ScriptBlock -isnot [ScriptBlock])
        # {

        # $ScriptBlock = [scriptblock]::Create("$ScriptBlock -verbose")

        # }

        # else
        # {
        
        # $ScriptBlock = [scriptblock]::Create($ScriptBlock.ToString() + ' -verbose')
        
        # }

        # '[{0}] ScritpBlock to execute: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $ScriptBlock.ToString() | Write-Verbose

        # "Executing: {0}" -f $ScriptBlock.ToString() | Write-Verbose -Verbose:$True

        # Invoke-Command -ScriptBlock $ScriptBlock -ErrorVariable CapturedError | Out-Null #.Invoke() | Out-Null

        # if ($null -ne $CaptureError)
        # {

        # $CapturedError | Out-Host

        # }

        # ([String]::Join('',(1..80 | % { "-" }))) | Write-Verbose -Verbose:$true

        $sb = New-Object System.Text.StringBuilder
        [void]$sb.Append("`$VerbosePreference = 'Continue'`n")
        [void]$sb.Append($ScriptBlock.ToString())

        '[{0}] ScritpBlock to execute: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $sb.ToString() | Write-Verbose

        Invoke-Command -ScriptBlock ([Scriptblock]::Create($sb.ToString())) -ErrorVariable CapturedError | Out-Null

        if ($null -ne $CaptureError)
        {

            $CapturedError | Out-Host

        }

        ([String]::Join('',(1..80 | ForEach-Object { "-" }))) | Write-Verbose -Verbose:$true

    }

    End
    {

        Stop-Transcript | Out-Null

        '[{0}] Stopped transcript logging.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        [System.IO.FileInfo]$_TranscriptFile

    }

}

Function Start-iseTranscript
{

    Param
    (

        [string]$logname = (Get-logNameFromDate -path "C:\fso" -postfix " $(hostname)" -Create)

    )

    $transcriptHeader = '**************************************
    Windows PowerShell ISE Transcript Start
    Start Time: {0}
    UserName: {1}
    UserDomain: {2}
    ComputerName: {3}
    Windows version: {4}
    **************************************
    Transcript started. Output file is {5}'
 -f [DateTime]::Now(), $env:username, $env:USERDNSDOMAIN, $env:COMPUTERNAME, (Get-CimObject win32_operatingsystem).version, $logname

    $transcriptHeader >> $logname

    $psISE.CurrentPowerShellTab.Output.Text >> $logname

    #Keep current Prompt
    if ($null -eq $__promptDef)
    {

        $__promptDef =  (gci Function:Prompt).Definition
        $promptDef = (gci Function:Prompt).Definition

    } 
    
    else
    {

        $promptDef = $__promptDef

    }

    $newPromptDef = '
    if ($global:_LastText -ne $psISE.CurrentPowerShellTab.Output.Text)
    {
 
        Compare-Object -ReferenceObject $global:_LastText.Split("`n") -DifferenceObject $psISE.CurrentPowerShellTab.Output.Text.Split("`n") | ? { $_.SideIndicator -eq "=>" } | % { $_.InputObject.TrimEnd() } | Out-File -FilePath ($Global:_DSTranscript) -Append
        $global:_LastText = $psISE.CurrentPowerShellTab.Output.Text
 
    }
    '
 + $promptDef

    New-Item -Path Function: -Name "Global:Prompt" -Value ([ScriptBlock]::Create($newPromptDef)) -Force | Out-Null
    
}

function Invoke-HPOVWebBrowser
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]

    Param 
    (
        
        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceStatus = New-Object System.Collections.ArrayList

    }

    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            start ("https://{0}/#/dashboard?s_sid={1}" -f $_appliance.Name, $_appliance.SessionID)

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Show-HPOVActiveUser
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]

    Param 
    (
        
        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose
            
            Try
            {

                $_ActiveUserSessions = Send-HPOVRequest -Uri $ActiveUserSessionsUri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            ForEach ($_usersession in $_ActiveUserSessions.members)
            {

                "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_usersession.username, $_ActiveUserSessions.count | Write-Verbose

                New-Object HPOneView.Appliance.ActiveUserSession ($_usersession.username, $_usersession.loginDomain, $_usersession.clientHost, $_usersession.timeCreated, [HPOneView.Library.ApplianceConnection]$_usersession.ApplianceConnection)

            }

        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

#######################################################
# Appliance Configuration:
#

function Get-HPOVApplianceCertificateStatus 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]

    Param 
    (
        
        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose
            
            Try
            {

                $_status = Send-HPOVRequest $applianceSslCert -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_status.PSObject.TypeNames.insert(0,'HPOneView.Appliance.ApplianceSslCertificateStatus')

            [void]$_ApplianceStatus.Add($_status)

        }

    }

    End 
    {

        Return $_ApplianceStatus    

    }

}

function New-HPOVApplianceSelfSignedCertificate 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default', SupportsShouldProcess, ConfirmImpact = 'High')]

    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ('C')]
        [ValidateNotNullOrEmpty()]
        [string]$Country,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ('ST','Province')]
        [ValidateNotNullOrEmpty()]    
        [string]$State,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('L','Locality')]    
        [ValidateNotNullOrEmpty()]
        [string]$City,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ('O')]
        [ValidateNotNullOrEmpty()]
        [string]$Organization,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ('CN')]
        [ValidateNotNullOrEmpty()]
        [string]$CommonName,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('OU')]    
        [ValidateNotNullOrEmpty()]
        [string]$OrganizationalUnit,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('SAN')]    
        [ValidateNotNullOrEmpty()]
        [string]$AlternativeName,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('Contact')]    
        [ValidateNotNullOrEmpty()]
        [string]$ContactName,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$Email,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('Sur')]    
        [ValidateNotNullOrEmpty()]
        [string]$Surname,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('Giv')]    
        [ValidateNotNullOrEmpty()]
        [string]$GivenName,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$Initials,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$DNQualifier,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_TaskStatus = New-Object System.Collections.ArrayList

        if ($Country.length -gt 2)
        {

            $TempCountry = $Country.Clone()

            $Country = GetTwoLetterCountry -Name $Country

            if (-not($Country))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException CountryNameNotFound ObjectNotFound 'Country' -Message ('{0} is not a valid Country Name, or unable to find mapping to RegionInfo ISO3166-2 compliant 2-Character name.' -f $Country )
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

    }

    Process 
    {    
            
        $_SelfSignedCertObject = NewObject -SelfSignedCert

        $_SelfSignedCertObject.country            =  $Country.ToUpper()
        $_SelfSignedCertObject.state              =  $State
        $_SelfSignedCertObject.locality           =  $City
        $_SelfSignedCertObject.organization       =  $Organization
        $_SelfSignedCertObject.commonName         =  $CommonName
        $_SelfSignedCertObject.organizationalUnit =  $OrganizationalUnit
        $_SelfSignedCertObject.alternativeName    =  $AlternativeName
        $_SelfSignedCertObject.contactPerson      =  $ContactName
        $_SelfSignedCertObject.email              =  $Email
        $_SelfSignedCertObject.surname            =  $Surname
        $_SelfSignedCertObject.givenName          =  $GivenName
        $_SelfSignedCertObject.initials           =  $Initials
        $_SelfSignedCertObject.dnQualifier        =  $DNQualifier

        Try
        {

            Write-Warning 'Updates to the certificate will require the appliance internal web server to be restarted. There will be a temporary service interruption estimated to last 30 seconds.'

            if ($PSCmdlet.ShouldProcess($ApplianceConnection.Name,"generate new self-signed certificate"))
            {    

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing: $($_SelfSignedCertObject | out-string)"

                $_resp = Send-HPOVRequest $applianceCsr POST $_SelfSignedCertObject -HostName $ApplianceConnection
        
            }

            else 
            {

                if ($PSBoundParameters['whatif'].ispresent) 
                { 

                    write-warning "-WhatIf was passed, would have proceeded 'New Self-Signed Certificate for Appliance $($ApplianceConnection.Name)'."

                    $_resp = $null

                }

                else 
                {

                    #If here, user chose "No", End Processing

                    $_resp = $Null

                }

            }

            [void]$_TaskStatus.Add($_resp)

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

    }

    End 
    {

        Return $_TaskStatus

    }

}

function New-HPOVApplianceCsr 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]

    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ('C')]
        [ValidateNotNullOrEmpty()]
        [string]$Country,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ('ST','Province')]
        [ValidateNotNullOrEmpty()]    
        [string]$State,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('L','Locality')]    
        [ValidateNotNullOrEmpty()]
        [string]$City,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ('O')]
        [ValidateNotNullOrEmpty()]
        [string]$Organization,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ('CN')]
        [ValidateNotNullOrEmpty()]
        [string]$CommonName,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('OU')]    
        [ValidateNotNullOrEmpty()]
        [string]$OrganizationalUnit,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('SAN')]    
        [ValidateNotNullOrEmpty()]
        [string]$AlternativeName,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('Contact')]    
        [ValidateNotNullOrEmpty()]
        [string]$ContactName,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$Email,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('Sur')]    
        [ValidateNotNullOrEmpty()]
        [string]$Surname,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('Giv')]    
        [ValidateNotNullOrEmpty()]
        [string]$GivenName,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$Initials,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$DNQualifier,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [string]$ChallengePassword,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('UN')]    
        [ValidateNotNullOrEmpty()]
        [string]$UnstructuredName,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_TaskStatus = New-Object System.Collections.ArrayList

        #Handle runtime, none-script use
        if ($PSBoundParameters['ChallengePassword'] -and $ChallengePassword -eq '*'  ) 
        {

            Do 
            {

                [SecureString]$ChallengePassword        = Read-Host "Challenge Password:" -AsSecureString

                [SecureString]$ChallengePasswordConfirm = Read-Host "Confirm Challenge Password:" -AsSecureString

                $pwd1_text = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($ChallengePassword))

                $pwd2_text = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($ChallengePasswordConfirm))

                if (-not($pwd1_text -ceq $pwd2_text)) 
                {

                    Write-Error "Passwords to not match. Please try again." -ea Continue

                    $PasswordsMatch = $False

                }

                else { $PasswordsMatch = $True }

            } Until ($PasswordsMatch)

        }

        if ($Country.length -gt 2)
        {

            $TempCountry = $Country.Clone()

            $Country = GetTwoLetterCountry -Name $Country

            if (-not($Country))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException CountryNameNotFound ObjectNotFound 'Country' -Message ('{0} is not a valid Country Name, or unable to find mapping to RegionInfo ISO3166-2 compliant 2-Character name.' -f $Country )
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

    }

    Process 
    {

        $_CsrObject = NewObject -ApplianceCSR

        $_CsrObject.country            =  $Country.ToUpper()
        $_CsrObject.state              =  $State
        $_CsrObject.locality           =  $City
        $_CsrObject.organization       =  $Organization
        $_CsrObject.commonName         =  $CommonName
        $_CsrObject.organizationalUnit =  $OrganizationalUnit
        $_CsrObject.alternativeName    =  $AlternativeName
        $_CsrObject.contactPerson      =  $ContactName
        $_CsrObject.email              =  $Email
        $_CsrObject.surname            =  $Surname
        $_CsrObject.givenName          =  $GivenName
        $_CsrObject.initials           =  $Initials
        $_CsrObject.dnQualifier        =  $DNQualifier
        $_CsrObject.unstructuredName   =  $UnstructuredName
        $_CsrObject.challengePassword  =  $ChallengePassword

        Try
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing: $($_CsrObject | out-string)"

            $_resp = Send-HPOVRequest $applianceCsr POST $_CsrObject -HostName $ApplianceConnection
                
            [void]$_TaskStatus.Add($_resp)

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }


    }

    End 
    {

        Return $_TaskStatus

    }

}

function GetTwoLetterCountry
{

    <#
        .DESCRIPTION
        Helper function to get ISO3166-2 Compliant Country Name
                     
        .Parameter Country
        Helper function to get ISO3166-2 Compliant Country Name
 
        .INPUTS
        None. You cannot pipe objects to this cmdlet.
                     
        .OUTPUTS
        System.String
        ISO3166-2 Compliant two character country name
         
        .EXAMPLE
        PS C:\> GetTwoLetterCountry 'United States'
        US
 
        Returns the ISO3166-2 Compliant 2-character Country name.
                 
    #>


    [CmdletBinding (DefaultParameterSetName = 'Default')]

    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Name

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

    }

    Process
    {

        Write-Verbose 'Building Country collection.'

        $CountriesCollection = New-Object Hashtable

        $Countries = [System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureTypes]'AllCultures')

        foreach ($ObjCultureInfo in [System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureTypes]'AllCultures'))
        {

            Try
            {

                [System.Globalization.RegionInfo]$_Country = $ObjCultureInfo.LCID

                if ($_Country.EnglishName -match ' AND ')
                {

                    $_CountriesSplit = $_Country.EnglishName.Split(' AND ')

                    ForEach ($_split in $_CountriesSplit)
                    {

                        if (-not($CountriesCollection.ContainsKey($_split)))
                        {
                
                            $CountriesCollection.Add($_split, $_Country.TwoLetterISORegionName.ToUpper());

                        }

                    }

                }

                else
                {

                    if (-not($CountriesCollection.ContainsKey($_Country.EnglishName)))
                    {


                        $CountriesCollection.Add($_Country.EnglishName, $_Country.TwoLetterISORegionName.ToUpper());

                    }

                }

            }

            Catch
            {

                Write-Verbose ("{0} Doesn't have RegionInfo" -f $ObjCultureInfo)

            }

        }

    }

    End
    {

        Write-Verbose 'Returning value'

        Write-verbose ('Country Collection: {0}' -f ($CountriesCollection | Out-String))

        Write-Verbose ('ISO3166-2 Country Name: {0}' -f $CountriesCollection[$Name])

        $_Return = $CountriesCollection[$Name]

        if (-not($_Return))
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException CountryNameNotFound ObjectNotFound 'Name' -Message ('{0} is not a valid Country Name, or unable to find mapping to RegionInfo ISO3166-2 compliant 2-Character name.' -f $Name )
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        Return $_Return

    }

}

function Install-HPOVApplianceCertificate 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]

    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default', ValueFromPipeline)]
        [Alias ('PrivateKey', 'Certificate')]
        [ValidateNotNullOrEmpty()]
        [Object]$Path,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_TaskStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        $_CertificateObject = NewObject -ApplianceSslCertificate

        'Path is valid: {0}' -f (Test-Path $Path) | Write-Verbose

        if ((Test-Path $Path) -or $Path -Is [System.IO.FileInfo])
        {

            "[{0}] Opening {1} file for reading.)" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Path | Write-Verbose

            Try
            {

                $_ReadFile = [System.IO.File]::OpenText($Path)
                $_Certificate = $_ReadFile.ReadToEnd()
                $_ReadFile.Close()
                $_CertificateObject.base64Data = ($_Certificate | Out-String) -join "`n"

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }            

        }

        elseif ($Path.Contains('-----BEGIN CERTIFICATE-----'))
        {

            "[{0}] Received certificate contents." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_CertificateObject.base64Data = ($Path | Out-String) -join "`n"
            
        }
        
        else 
        {

            $Exceptionmessage = 'The supplied Path value is not a valid X.509 certificate, System.IO.FileInfo object, or path to a valid X.509 certificate.'
            $ErrorRecord = New-ErrorRecord InvalidOperationException PathValueInvalid InvalidArgument 'Install-HPOVUpdate' -Message $Exceptionmessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        Try
        {

            "[{0}] Processing: $($_CertificateObject | out-string)" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_resp = Send-HPOVRequest -Uri $applianceCsr -Method PUT -BOdy $_CertificateObject -HostName $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($PSBoundParameters['Async'])
        {

            $_resp

        }

        else
        {

            $_resp | Wait-HPOVTaskComplete

        }

    }

    End 
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVPendingUpdate 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            #Check to see if ane existing update is present. Report to user if it is, and tell them to use -InstallNow
            Try
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Checking if Pending update exists"

                $_PendingUpdate = Send-HPOVRequest -Uri $ApplianceUpdatePendingUri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($_PendingUpdate)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Update found $($_PendingUpdate.fileName), $($_PendingUpdate.version)"

                $_PendingUpdate.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.Update.Pending')

            }

            $_PendingUpdate

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Finished"

    }

}

function Install-HPOVUpdate 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Update', SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Update')]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Stage')]
        [Alias ('f')]
        [ValidateScript({Test-Path $_})]
        [string]$File,
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Update')]
        [Parameter (Mandatory = $false, ParameterSetName = 'StageInstall')]
        [string]$Eula,

        [Parameter (Mandatory = $false, ParameterSetName = 'Update')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Stage')]
        [Parameter (Mandatory = $false, ParameterSetName = 'List')]
        [switch]$DisplayReleaseNotes,

        [Parameter (Mandatory, ParameterSetName = 'Stage')]
        [switch]$Stage,

        [Parameter (Mandatory, ParameterSetName = 'StageInstall')]
        [switch]$InstallNow,
        
        [Parameter (Mandatory, ParameterSetName = 'List')]
        [Alias ('list')]
        [switch]$ListPending,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Update")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Stage")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "List")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "StageInstall")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | Where-Object Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
        
        if (-not $File)
        {

            $Pipeline = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }                

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_StatusCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            # Check to see if ane existing update is present. Report to user if it is, and tell them to use -InstallNow
            Try
            {
                
                "[{0}] - Checking if Pending update exists" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_PendingUpdate = Send-HPOVRequest -Uri $ApplianceUpdatePendingUri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
            if ($_PendingUpdate)
            {

                "[{0}] - Update found '{1}', '{2}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_PendingUpdate.fileName, $_PendingUpdate.version | Write-Verbose

                $_PendingUpdate.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.Update.Pending')

            }

            Switch ($PSCmdlet.ParameterSetName) 
            {
                
                # List staged update
                "List" 
                {

                    # If the request is to install a staged update, we need to handle no response. If request is Update, then no Pending update will exist yet.
                    If (-not($_PendingUpdate)) 
                    {

                        "[{0}] - No Pending update found. Return is Null" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        $ErrorRecord = New-ErrorRecord InvalidOperationException PendingUpdateNotFound ObjectNotFound 'Install-HPOVUpdate' -Message "No Pending update found. Please first upload update and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    $_PendingUpdate
                    
                    If ($PSBoundParameters['DisplayReleaseNotes'])
                    {
                        
                        "[{0}] - Displaying Release Notes" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        # Display Release Notes
                        Try
                        {

                            $uri = "/rest/appliance/firmware/document-content/{0}/release" -f $Upload.fileName
                            Send-HPOVRequest -Uri $uri -Hostname $_appliance | ConvertFrom-HTML

                        }
                            
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        "[{0}] - Done. Displayed update release notes." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    }
                    
                    Return
                }

                # Stage Update
                "Stage" 
                {              

                    if (-not($_PendingUpdate)) 
                    {

                        "[{0}] - Stage Only" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                        "[{0}] - UPLOAD FILE: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $File | Write-Verbose

                        Try 
                        {
                    
                            # Upload update
                            $FileName = Get-Item $File

                            $_upload = Upload-File -Uri $ApplianceUpdateImageUri -File $File -ApplianceConnection $_appliance.Name
                    
                        }

                        Catch 
                        {
                        
                            $ErrorRecord = New-ErrorRecord InvalidOperationException StageUpdateFailed InvalidResult 'Install-HPOVUpdate' -Message $_.Exception.Message
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        If ($PSBoundParameters['DisplayReleaseNotes'])
                        {
                        
                            "[{0}] - Displaying Release Notes" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            # Display Release Notes
                            Try
                            {

                                $uri = "/rest/appliance/firmware/document-content/{0}/release" -f $Upload.fileName
                                Send-HPOVRequest -Uri $uri -Hostname $_appliance | ConvertFrom-HTML

                            }
                            
                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                            "[{0}] - Done. Displayed update release notes." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        }

                        Return $_upload

                    }

                    else 
                    {
                    
                        $ExceptionMessage = "An existing appliance update has been staged. Version: '{0}' Filename: '{1}' Please use the -InstallUpdate Parameter to proceed with the update, or use Remove-HPOVPendingUpdate cmdlet to remove the staged update." -f $PendingUpdate.version, $PendingUpdate.fileName
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.FirmwareUpdateException PendingUpdateConflict ResourceExists 'File' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                # Upload update then install update below.
                "Update" 
                {

                    if ($_PendingUpdate) 
                    {

                        $ExceptionMessage = "A Pending update was found. File name: '{0}'; Update Version: '{1}'. Please remove the update before continuing and try again." -f $PendingUpdate.version, $PendingUpdate.fileName
                        $ErrorRecord = New-ErrorRecord InvalidOperationException PendingUpdateFound ResourceExists 'File' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                    }
                                    
                    "[{0}] - UPLOAD FILE: '{1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $File | Write-Verbose

                    Try 
                    {
                    
                        # Upload update
                        $FileName = Get-Item $File

                        $PendingUpdate = Upload-File -Uri $ApplianceUpdateImageUri -File $File -ApplianceConnection $_appliance.Name

                        # Pause for 30 seconds? need to make sure appliance has finished Processing update file before invoking update
                        "[{0}] - Sleeping for 5 seconds." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        Start-Sleep -Seconds 5
                
                    }

                    Catch 
                    {

                        $ErrorRecord = New-ErrorRecord InvalidOperationException UploadUpdateFailed InvalidResult 'File' -Message $_.Exception.Message
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

            }

            # Process Pending update
            if (($PSCmdlet.ParameterSetName -eq "StageInstall") -or ($PSCmdlet.ParameterSetName -eq "Update" )) 
            {

                # If the request is to install a staged update, we need to handle no response. If request is Update, then no Pending update will exist yet.
                If ((-not($_PendingUpdate)) -and ($PSCmdlet.ParameterSetName -eq "StageInstall")) 
                {

                    "[{0}] - No Pending update found. Return is Null" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    
                    $ErrorRecord = New-ErrorRecord InvalidOperationException StorageSystemResourceNotFound ObjectNotFound 'Install-HPOVUpdate' -Message "No Pending update found. Please first upload update and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }


                "[{0}] - Install Now" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_PendingUpdate

                If ($Eula -ne "accept") 
                {

                    "[{0}] - EULA NOT Accepted" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    
                    $Uri = "https://{0}/ui-js/pages/upgrade/eula_content.html" -f $_appliance.Name

                    try
                    {

                        # Display eula of update
                        (New-Object System.Net.WebClient).DownloadString($Uri) | ConvertFrom-HTML -NoClobber

                    }

                    Catch [System.Net.WebException]
                    {

                        if ($_.Excpetion.Message -match '')
                        {

                            $_originalcertpolicy = [System.Net.ServicePointManager]::CertificatePolicy
                            [System.Net.ServicePointManager]::CertificatePolicy = new-object HPOneView.ITempPolicy 

                            Try
                            {

                                (New-Object System.Net.WebClient).DownloadString($Uri) | ConvertFrom-HTML -NoClobber

                            }
                            
                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    finally
                    {

                        [System.Net.ServicePointManager]::CertificatePolicy = $_originalcertpolicy

                    }

                    Do { $acceptEula = Read-Host "Accept EULA (Must type ACCEPT)" } Until ($acceptEula -eq "Accept")

                }
                    
                "[{0}] - EULA Accepted" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                "[{0}] - Beginning update $($_PendingUpdate.fileName)" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                "[{0}] - Estimated Upgrade Time $($_PendingUpdate.estimatedUpgradeTime) minutes" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_resp = $Null

                # Check to see if the update requires an appliance reboot.
                if ($_PendingUpdate.rebootRequired) 
                {

                    "[{0}] - Appliance reboot required $($_PendingUpdate.rebootRequired)" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    "[{0}] - Prompting for confirmation" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    "[{0}] - Is confirmation overridden $([bool]$confirm)" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    Write-Warning "Reboot required for the update."

                    # If it does require a reboot, then we need to prompt for confirmation. Overriden by -confirm:$false
                    if ($PSCmdlet.ShouldProcess($_appliance.Name,"upgrade appliance using $($_PendingUpdate.fileName)")) 
                    {

                        "[{0}] - Appliance reboot required and user selected YES or passed -Confirm:`$false, executing Invoke-Upgrade" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        Try
                        {

                            $_resp = Invoke-Upgrade $_PendingUpdate

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
                        
                    }

                    else 
                    {

                        if ($PSBoundParameters['whatif']) 
                        { 

                            write-warning "-WhatIf was passed, would have initiated appliance update."

                        }

                        else 
                        {

                            # If here, user chose "No", End Processing
                            "[{0}] - User selected NO." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose                        

                        }

                    }

                }

                else
                {
                     
                    "[{0}] - Appliance reboot NOT required, executing Invoke-Upgrade" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    
                    Try
                    {

                        $_resp = Invoke-Upgrade $_PendingUpdate

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                if ($null -ne $_resp)
                {

                    # Update PSLibraryVersion variable with new appliance version
                    Try
                    {

                        $applVersionInfo = Send-HPOVRequest -Uri $ApplianceVersionUri -Hostname $_appliance
                        $PSLibraryVersion."$($_appliance.Name)" = New-Object HPOneView.Appliance.NodeInfo ($applVersionInfo.softwareVersion, (Get-HPOVXApiVersion -ApplianceConnection $_appliance).currentVersion, $applVersionInfo.modelNumber)

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }                

                $_resp

            }

        }

    }

    End
    {

        "[{0}] - Finished" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Invoke-Upgrade  
{

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory)]
        [ValidateNotNullorEmpty()]
        [Object]$PendingUpdate

    )

    Begin 
    {
    
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        $_FinalStatus = $null

    }

    Process 
    {

        Try
        {

            $uri = "{0}?file={1}" -f $ApplianceUpdatePendingUri, $PendingUpdate.fileName
            $_updateTask = Send-HPOVRequest -Uri $uri -Method PUT -Hostname $PendingUpdate.ApplianceConnection

        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $sw = [System.Diagnostics.Stopwatch]::StartNew()

        $_PreviousTaskStep = $null

        # Loop to display progress-bar
        Do 
        {

            # Connect to update monitor web Process
            Try
            {

                $_MonitorUpdate = Send-HPOVRequest -Uri $ApplianceUpdateMonitorUri -Hostname $PendingUpdate.ApplianceConnection

                if ($_MonitorUpdate.taskStep)
                {

                    $_PreviousTaskStep = $_MonitorUpdate.taskStep.Replace(" ", $null)

                }

                else
                {

                    $_PreviousTaskStep = $_MonitorUpdate.status.Replace(" ", $null)

                }                

            }
        
            Catch
            {

                # Sleep 30 seconds to see make sure it wasn't a brief Apache issue
                "[{0}] Pausing 30 seconds after '{1}' exception was caught." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_.Exception.Message | Write-Verbose
                Start-Sleep -Seconds 30

                # Attempt a second connection, as appliance may have restarted Apache
                Try
                {

                    "[{0}] Trying 2nd time to get update monitor status." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $_MonitorUpdate = Send-HPOVRequest -Uri $ApplianceUpdateMonitorUri -Hostname $PendingUpdate.ApplianceConnection

                    if ($_MonitorUpdate.taskStep)
                    {

                        $_PreviousTaskStep = $_MonitorUpdate.taskStep.Replace(" ", $null)

                    }

                    else
                    {

                        $_PreviousTaskStep = $_MonitorUpdate.status.Replace(" ", $null)

                    }

                }
            
                Catch
                {
                    $PSCmdlet.ThrowTerminatingError($_)

                }                        

            }
                        
            # Remove % from value in order to get INT
            if ($_MonitorUpdate.percentageCompletion) 
            { 
                
                $PercentComplete = $_MonitorUpdate.percentageCompletion.Replace("%",$null).Replace(" ",$null)
            
            }
            
            else 
            { 
                
                $PercentComplete = 0 
            
            }
                        
            # Remove " State = " to get proper status
            if ($_MonitorUpdate.status) 
            { 
                
                $UpdateStatus = $_MonitorUpdate.status.Replace(" ", $null).Replace("State=", $null)

                if ($_MonitorUpdate.phase)
                {
                    
                    $UpdateStatus = '{0} - {1}' -f $UpdateStatus, $_MonitorUpdate.phase

                }
            
            }

            else 
            { 
                
                $UpdateStatus = "Starting" 
            
            }

            $Status = "{0} {1}% [{2}min {3}sec]" -f $UpdateStatus, $PercentComplete, $sw.elapsed.minutes, $sw.elapsed.seconds            
            
            # Handle the call from -Verbose so Write-Progress does not get borked on display.
            if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
            { 
                
                "[{0}] Skipping Write-Progress display." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                "[{0}] Update Status: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Status | Write-Verbose
            
            }
                          
            else 
            { 
                
                Write-Progress -id 1 -Activity ("Installing appliance update {0}" -f $PendingUpdate.fileName) -Status $Status -PercentComplete $PercentComplete 
            
            }

            if ($UpdateStatus -match "UpdateReboot") 
            {

                # Handle the call from -Verbose so Write-Progress does not get borked on display.
                if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                { 

                    "[{0}] pausing for 5 minutes while appliance reboots. Invoking Start-Sleep" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    
                    Start-Sleep -Seconds 300

                }

                else 
                { 
                    
                    $time = 300

                    foreach ($i in (1..$time)) 
                    {

                        $percentage = $i / $time
                        
                        Write-Progress -id 1 -activity ("Installing appliance update {0}" -f $PendingUpdate.fileName) -Status $Status -PercentComplete $PercentComplete

                        Write-Progress -id 2 -parent 1 -activity "Appliance Rebooting" -status "Pausing for 5 minutes" -percentComplete ($percentage * 100) -SecondsRemaining ($time - $i)

                        Start-Sleep 1

                    }
                        
                    Write-Progress -id 2 -parent 1 -activity "Appliance Rebooting" -status "Pausing for 5 minutes" -Completed            
                    
                }

            }

        } Until ([int]$percentComplete -eq 100 -or $_PreviousTaskStep -match 'FAILED')
                
        $sw.Stop()

        "[{0}] Upgrade operation took {1}min, {2}sec." -f $MyInvocation.InvocationName.ToString().ToUpper(), $sw.elapsed.minutes, $sw.elapsed.seconds | Write-Verbose

        # Retrieve final update status
        Try
        {

            $_FinalStatus = Send-HPOVRequest -Uri $ApplianceUpdateNotificationUri -Hostname $PendingUpdate.ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        Write-Progress -Activity ("Installing appliance update {0}" -f $PendingUpdate.fileName) -status $updateStatus -percentComplete $percentComplete

        Write-Progress -Activity ("Installing appliance update {0}" -f $PendingUpdate.fileName) -status $updateStatus -Completed

    }

    End 
    {

        Return $_FinalStatus

    }

}

function Remove-HPOVPendingUpdate 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default', SupportsShouldProcess,ConfirmImpact = 'High')]
    Param 
    (
    
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {
    
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ColStatus = New-Object System.Collections.ArrayList
    
    }

    Process 
    { 

        ForEach ($_appliance in $ApplianceConnection)
        {
            
            $_resp = $null

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            #Check to see if ane existing update is present. Report to user if it is, and tell them to use -InstallNow
            Try
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Checking if Pending update exists"

                $_PendingUpdate = Send-HPOVRequest -Uri $ApplianceUpdatePendingUri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
            if ($_PendingUpdate)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Update found $($_PendingUpdate.fileName), $($_PendingUpdate.version)"

                $_PendingUpdate.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.Update.Pending')

                $_PendingUpdate

                $RemoveMessage = "remove Pending update, {0}" -f $_PendingUpdate.fileName

                if ($PSCmdlet.ShouldProcess($_appliance.Name, $RemoveMessage)) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Pending update from applinace."

                    Try
                    {
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Checking if Pending update exists"

                        $_resp = Send-HPOVRequest -Uri $ApplianceUpdatePendingUri -Method DELETE -Hostname $_appliance

                        [void]$_ColStatus.Add($_resp)

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                else 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Pending update found"

                }

            }

        }

    }

    End 
    { 
    
        Return $_ColStatus

    }

}

function Get-HPOVVersion 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [switch]$ApplianceVer,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'CheckOnlineOnly')]
        [switch]$CheckOnline,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {    
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if  ($ApplianceConnection.Count -eq 0 -and (-not($PSBoundParameters['CheckOnline'])) -and $PSBoundParameters['ApplianceVer'])
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoAuthSessionFound InvalidArgument 'ApplianceConnection' -Message 'No ApplianceConnections were found. Please use Connect-HPOVMgmt to establish an appliance connection.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($PSBoundParameters['ApplianceVer'])
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }                    

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_ApplianceVersionCollection = New-Object System.Collections.ArrayList
    
    }
    
    Process 
    {

        if ($PSboundParameters['CheckOnline']) 
        {

            try 
            { 

                "[{0}] Testing for Proxy settings" -f  $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                [Uri]$_ProxyUri = $null

                $_Options = @{Uri = $Repository}

                $_Proxy = [System.Net.WebRequest]::GetSystemWebProxy()

                $_Proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
                $_ProxyUri = $_Proxy.GetProxy($_Options.Uri)

                if ($_ProxyUri.OriginalString -ne $_Options.Uri)
                {

                    $_Options.Add('Proxy',$_proxyUri)
                    $_Options.Add('ProxyUseDefaultCredentials', $true)
                    
                }

                $_OriginalProgressPreference = $ProgressPreference
                
                #Hide the display of Write-Progress Invoke-RestMethod displays
                $ProgressPreference = 'silentlyContinue'

                "[{0}] Invoke-RestMethod Options: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_Options | Out-String) | Write-Verbose
                
                $resp = Invoke-RestMethod @_Options

                $ProgressPreference = $_OriginalProgressPreference

                $versionMajorMinor = "{0}.{1}" -f $PSLibraryVersion.Major, $PSLibraryVersion.Minor

                #filter for versions that match Major and Minor release, and exclude the HP VCM to OneView Migration Tool
                $matchedVersions = $resp | ? { $_.tag_name -like "v$versionMajorMinor*" -and (-not($_.tag_name.startswith('HPVCtoOV'))) -and (-not($_.tag_name.startswith('HPSIMtoOV'))) } 

                "[{0}] Found versions online: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [System.String]::Join(' ,', $resp.tag_name) | Write-Verbose

                $newerVersion = $false

                #Compare the releases
                $matchedVersions | % { 
    
                    if ($newerVersion) 
                    { 
                        
                        write-verbose "Found previous version to compare: $newerVersion" 
                    
                    }

                    [version]$version = $_.tag_name -replace "v","" 

                    "[{0}] Comparing {1} to {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $version, $PSLibraryVersion.LibraryVersion | Write-Verbose
        
                    #Compare found version with library
                    if (-not($newerVersion) -and $version.build -gt $PSLibraryVersion.LibraryVersion.build) 
                    {
            
                        [version]$newerVersion = $version
                        $newerVersionObj = $_

                        "[{0}] Newer version found: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $newerVersion | Write-Verbose

                    }

                    elseif ($newerVersion.Build -lt $version.Build -and $version.build -gt $PSLibraryVersion.LibraryVersion.build) 
                    {

                        [version]$newerVersion = $version
                        $newerVersionObj = $_

                        "[{0}] Newer version found: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $newerVersion | Write-Verbose

                    }
    
                }

                if ($newerVersion) 
                { 

                    "[{0}] Found: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [string]$version | Write-Verbose

                    $PSLibraryVersion | Add-Member -NotePropertyName UpdateAvailable -NotePropertyValue $True

                    if ($ReleaseNotes) { $newerVersionObj.body -replace "## ","" -replace "\*"," ? " }

                    $caption = "Please Confirm";
                    $message = "You currently have v{0} installed. The HP OneView PowerShell Library v{1} was found that is newer. Do you want to download the current version of the HP OneView POSH Library (will open your web browser for you to download)?" -f $PSLibraryVersion.LibraryVersion, [string]$newerVersion
                    $yes     = new-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Open your browser to download latest HP OneView POSH Library version.";
                    $no      = new-Object System.Management.Automation.Host.ChoiceDescription "&No","No, you will do this later.";
                    $choices = [System.Management.Automation.Host.ChoiceDescription[]]($yes,$no);
                    $answer  = $host.ui.PromptForChoice($caption,$message,$choices,0) 

                    switch ($answer)
                    {

                        0 
                        {

                            "[{0}] Launching users browser to '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $newerVersionObj.html_url | Write-Verbose
                            
                            start "$($newerVersionObj.html_url)"
        
                        }

                    }     
    
                }

                else 
                { 
                
                    $PSLibraryVersion | Add-Member -NotePropertyName UpdateAvailable -NotePropertyValue $False

                    "[{0}] Library is already up-to-date." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    
                }

                $PSLibraryVersion

            }

            catch 
            {

                $errorMessage = "$($_[0].exception.message). $($_[0].exception.InnerException.message)"
                $ErrorRecord = New-ErrorRecord HPOneView.Library.UpdateConnectionError InvalidResult ConnectionError 'CheckOnline' -TargetType 'Switch' -Message "$($_[0].exception.message)." -InnerException $_.exception.InnerException
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else
        {

            $PSLibraryVersion

        }

    }

    end
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVHealthStatus 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    { 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_HealthStatusCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Try
            {

                $healthStatus = Send-HPOVRequest $applHealthStatus -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $healthStatus.members  | % { 
                
                $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.HealthStatus") 
            
                [void]$_HealthStatusCollection.Add($_)

            }

        }
    
    }

    End 
    {

        Return $_HealthStatusCollection | Sort-Object ApplianceConnection.Name,resourceType

    }

}

function Get-HPOVXApiVersion 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    { 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Cmdlet does not require authentication."

        #Check to see if a connection to the appliance exists
        #if ($ApplianceConnection -isnot [HPOneView.Appliance.Connection] -and $ApplianceConnection -isnot [System.Collections.IEnumerable] -and $ApplianceConnection -is [String])
        if ($ApplianceConnection -is [String])
        {

            if ((${Global:ConnectedSessions}.Name -notcontains $ApplianceConnection) -and (-not(${Global:ConnectedSessions} | ? Name -eq $ApplianceConnection).SessionID))
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Appliance Session not found. Running FTS sequence?"

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating temporary Session object"

                $_ApplianceName = $ApplianceConnection

                [HPOneView.Appliance.Connection]$ApplianceConnection = NewObject -TemporaryConnection

                $ApplianceConnection.Name = $_ApplianceName

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($ApplianceConnection | out-string)"
            
            }

            else
            {

                [HPOneView.Appliance.Connection]$ApplianceConnection = ${Global:ConnectedSessions} | ? Name -eq $ApplianceConnection

            }

        }

        $_XAPICollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Try
                {

                    $_XAPIVersion = Send-HPOVRequest $ApplianceXApiVersionUri -Hostname $_appliance

                }
            
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                finally
                {

                    #Remove Temporary appliance connection
                    if ((${Global:ConnectedSessions} | ? Name -eq $_appliance.Name).SessionID -eq 'TemporaryConnection')
                    {

                        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing temporary Session object"

                        [void]${Global:ConnectedSessions}.Remove($_appliance)

                    }

                }

                $_XAPIVersion | % { $_.PSObject.TypeNames.insert(0,'HPOneView.Appliance.XAPIVersion') }

                [void]$_XAPICollection.Add($_XAPIVersion)
        
            }

        }        

        else
        {

            Try
            {

                $_XAPIVersion = Send-HPOVRequest $ApplianceXApiVersionUri -Hostname $ApplianceConnection

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            finally
            {

                #Remove Temporary appliance connection
                if ((${Global:ConnectedSessions} | ? Name -eq $ApplianceConnection.Name).SessionID -eq 'TemporaryConnection')
                {

                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing temporary Session object"

                    [void]${Global:ConnectedSessions}.Remove($ApplianceConnection)

                }

            }

            $_XAPIVersion | % { $_.PSObject.TypeNames.insert(0,'HPOneView.Appliance.XAPIVersion') }

            [void]$_XAPICollection.Add($_XAPIVersion)
        
        }

    }

    End 
    { 
    
        Return $_XAPICollection
    
    }

}

function Get-HPOVEulaStatus 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [Object]$Appliance

    )

    Begin 
    { 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        # Need to create temporary Global:ConnectedSessions after validating it doesn't exist for appliance connection being created.
        # otherwise, cmdlet will fail when making call to REstClient and it performs the SSL validation and flag value in SSLChecked property
        # need to do the same with Set-HPOVEulaStatus
        #Check to see if a connection to the appliance exists

        if ($Appliance -is [String])
        {

            if (-not(${Global:ConnectedSessions}.Name -contains $Appliance) -and (-not(${Global:ConnectedSessions} | ? Name -eq $Appliance).SessionID))
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Appliance Session not found. Running FTS sequence?"

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating temporary Session object"

                $_ApplianceName = $Appliance

                [HPOneView.Appliance.Connection]$Appliance = NewObject -TemporaryConnection

                $Appliance.Name = $_ApplianceName

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($Appliance | fl * | out-string)"
            
            }

            else #if (${Global:ConnectedSessions}.Name -contains $Appliance)
            {

                "[{0}] Appliance is a string value, lookup connection in global tracker." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                [HPOneView.Appliance.Connection]$Appliance = ${Global:ConnectedSessions} | ? Name -eq $Appliance

                "[{0}] Found connection in global tracker: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Appliance | Out-String) | Write-Verbose

            }
            
        }

        elseif ($Appliance -is [HPOneView.Appliance.Connection])
        {

            "[{0}] Appliance is a Connection: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Appliance | Out-String) | Write-Verbose

        }
       
    }

    Process 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting EULA Status from '$($Appliance.Name)'."

        Try
        {

            $_ApplianceEulaStatus = Send-HPOVRequest $ApplianceEulaStatusUri -Hostname $Appliance.Name

            $_EulaStatus = New-Object HPOneView.Appliance.EulaStatus($Appliance.Name, !$_ApplianceEulaStatus)

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        finally
        {

            #Remove Temporary appliance connection
            if ((${Global:ConnectedSessions} | ? Name -eq $Appliance.Name).SessionID -eq 'TemporaryConnection')
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing temporary Session object"

                [void]${Global:ConnectedSessions}.Remove($Appliance)

            }

        }
        
    }

    End 
    { 

        Return $_EulaStatus
    
    }

}

function Set-HPOVEulaStatus 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [Object]$Appliance,

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [ValidateSet ('Yes', 'No')]
        [string]$SupportAccess

    )

    Begin 
    { 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #Check to see if a connection to the appliance exists
        if ($Appliance -is [String])
        {

            if (-not(${Global:ConnectedSessions}.Name -contains $Appliance) -and (-not(${Global:ConnectedSessions} | ? Name -eq $Appliance).SessionID))
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Appliance Session not found. Running FTS sequence?"

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating temporary Session object"

                $_ApplianceName = $Appliance

                [HPOneView.Appliance.Connection]$Appliance = NewObject -TemporaryConnection

                $Appliance.Name = $_ApplianceName

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($Appliance | fl * | out-string)"
            
            }

            else #if (${Global:ConnectedSessions}.Name -contains $Appliance)
            {

                "[{0}] Appliance is a string value, lookup connection in global tracker." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                [HPOneView.Appliance.Connection]$Appliance = ${Global:ConnectedSessions} | ? Name -eq $Appliance

                "[{0}] Found connection in global tracker: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Appliance | Out-String) | Write-Verbose

            }

        }        

        elseif ($Appliance -is [HPOneView.Appliance.Connection])
        {

            "[{0}] Appliance is a Connection: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Appliance | Out-String) | Write-Verbose

        }

        else
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException UnknownCondition InvalidOperation "Appliance" -Message "An unknown condition has ocurred."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }
    
    }

    Process 
    {

        $body = [PSCustomObject]@{
            
            supportAccess = $supportAccess
        
        }

        Try
        {

            $_eulastatus = Send-HPOVRequest $ApplianceEulaSaveUri POST $body -Hostname $Appliance

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        Finally
        {

            if ((${Global:ConnectedSessions} | ? Name -eq $Appliance.Name).SessionID -eq 'TemporaryConnection')
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing temporary Session object"

                [void]${Global:ConnectedSessions}.Remove($Appliance)

            }

        }
        
    }

    End 
    { 
    
        Return $_eulastatus
    
    }

}

function Get-HPOVApplianceNetworkConfig 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [Alias ("x", "export", 'exportFile')]
        [ValidateScript({Test-Path $_})]
        [String]$Location,
        
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceNetworkConfiguration = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {
        
            "[{0}] Processing Appliance Connection: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            Try
            {
            
                $_appliancenetconfig = Send-HPOVRequest -Uri $ApplianceNetworkConfigUri -Hostname $_appliance.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
        
        
            $_appliancenetconfig | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.ApplianceServerConfiguration") }
            $_appliancenetconfig.applianceNetworks | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.ApplianceServerConfiguration.ApplianceNetworks") }
        
            [void]$_ApplianceNetworkConfiguration.Add($_appliancenetconfig)

        }
    
    }

    End 
    {

        If ($PSBoundParameters['Location']) 
        {

            ForEach ($_ApplianceConfig in $_ApplianceNetworkConfiguration)
            {

                $_filename = "{0}_ApplianceNetConf.json" -f $_ApplianceConfig.ApplianceConnection.Name

                ForEach ($nic in $_ApplianceConfig.applianceNetworks) 
                {

                    if ($nic.IPv4Type -eq "DHCP") { $nic.app1IPv4Addr = $null }

                    if ($nic.IPv6Type -eq "DHCP") { $nic.app1IPv6Addr = $null }
                
                }

                $_ApplianceConfig = $_ApplianceConfig | Select * -ExcludeProperty ApplianceConnection

                $_ApplianceConfig | convertto-json -depth 99 > ($Location + '\' + $_filename)

                gci ($Location + '\' + $_filename)

            }
            
        }
        
        Else 
        {
        
            Return $_ApplianceNetworkConfiguration

        }

    }

}

function Get-HPOVApplianceDateTime
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding ()]
    Param 
    (
        
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceDateTimeCol = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance Connection $($_appliance.Name)"

            Try
            {
            
                $_appliancedatetime = Send-HPOVRequest $ApplianceDateTimeUri -Hostname $_appliance.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
        
            $_appliancedatetime | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.ApplianceServerDateTime") }
        
            [void]$_ApplianceDateTimeCol.Add($_appliancedatetime)

        }
    
    }

    End 
    {

        Return $_ApplianceDateTimeCol    

    }

}

function Set-HPOVApplianceDateTime
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = 'SyncHost')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'SyncHost')]
        [Switch]$SyncWithHost,

        [Parameter (Mandatory, ParameterSetName = 'NTPServers')]
        [Array]$NTPServers,

        [Parameter (Mandatory = $false, ParameterSetName = 'NTPServers')]
        [Int]$PollingInterval,

        [Parameter (Mandatory = $False, ParameterSetName = 'SyncHost')]
        [Parameter (Mandatory = $False, ParameterSetName = 'NTPServers')]
        [ValidateSet ('en_US','zh_CN','ja_JP')]
        [String]$Locale,

        [Parameter (Mandatory = $False, ParameterSetName = 'SyncHost')]
        [Parameter (Mandatory = $False, ParameterSetName = 'NTPServers')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceDateTimeCol = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance Connection $($_appliance.Name)"

            Try
            {

                $_CurrentConfig = Send-HPOVRequest $ApplianceDateTimeUri -Hostname $_appliance.Name

            }


            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_ApplianceTimeConfig = NewObject -ApplianceTimeLocale
            
            switch ($PSCmdlet.ParameterSetName)
            {

                'SyncWithHost'
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Seting ntpServers to 'null' for Sync with Host."
                    $_ApplianceTimeConfig.ntpServers = @()

                }

                'NTPServers'
                {

                    ForEach ($_ntpserver in $NTPServers)
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding $_ntpserver to collection."

                        [void]$_ApplianceTimeConfig.ntpServers.Add($_ntpserver)

                    }

                    if ($PSBoundParameters['PollingInterval'])
                    {

                        $_ApplianceTimeConfig.pollingInterval = $PollingInterval.ToString()

                    }

                }

            }

            if ($PSBoundParameters['TimeZone'])
            {

                $_ApplianceTimeConfig.timezone = $TimeZone

            }

            else
            {

                $_ApplianceTimeConfig.timezone = $_CurrentConfig.timezone

            }

            if ($PSBoundParameters['Locale'])
            {

                $_ApplianceTimeConfig.locale = $ApplianceLocaleSetEnum[$Locale]

            }

            else
            {

                $_ApplianceTimeConfig.locale = $_CurrentConfig.locale

            }

            Try
            {
            
                $_appliancedatetime = Send-HPOVRequest $ApplianceDateTimeUri POST $_ApplianceTimeConfig -Hostname $_appliance.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
        
            $_appliancedatetime | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.ApplianceServerDateTime") }
        
            [void]$_ApplianceDateTimeCol.Add($_appliancedatetime)

        }
    
    }

    End 
    {

        Return $_ApplianceDateTimeCol    

    }

}

function Set-HPOVApplianceNetworkConfig 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
       
    [CmdletBinding (DefaultParameterSetName = "VMA")]
    Param 
    (
       
        [Parameter (Mandatory, ParameterSetName = "VMA")]
        [Parameter (Mandatory, ParameterSetName = "Composer")]
        [ValidateNotNullorEmpty()]
        [string]$Hostname,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [ValidateSet ('DHCP','STATIC')]
        [string]$IPv4Type = 'STATIC',

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory, ParameterSetName = "Composer")]
        [ValidateScript({ [string]::IsNullOrEmpty($_) -or
            $_ -match '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' +
            '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' +
            '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' +
            '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' +
            '(/0*([1-9]|[12][0-9]|3[0-2]))?$' })]
        [Net.IPAddress]$IPv4Addr,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory, ParameterSetName = "Composer")]
        [ValidateScript({
        
            ($_ -ge 1 -and $_ -le 32) -or
            ($_ -match [Net.IPAddress]$_)            
        
        })]
        [String]$IPv4Subnet,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory, ParameterSetName = "Composer")]
        [ValidateScript({ [string]::IsNullOrEmpty($_) -or
            $_ -match [Net.IPAddress]$_})]
        [Net.IPAddress]$IPv4Gateway,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [ValidateSet ('DHCP','STATIC','UNCONFIGURE')]
        [string]$IPv6Type = 'UNCONFIGURE',

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [ValidateScript({ [string]::IsNullOrEmpty($_) -or
            $_ -match [Net.IPAddress]$_})]
        [Net.IPAddress]$IPv6Addr,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [ValidateNotNullorEmpty()]
        [string]$IPv6Subnet,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [ValidateScript({ [string]::IsNullOrEmpty($_) -or
            $_ -match [Net.IPAddress]$_})]
        [string]$IPv6Gateway,

        [Parameter (Mandatory, ParameterSetName = "Composer")]
        [ValidateScript({ [string]::IsNullOrEmpty($_) -or
            $_ -match [Net.IPAddress]$_})]
        [Net.IPAddress]$ServiceIPv4Node1,

        [Parameter (Mandatory, ParameterSetName = "Composer")]
        [ValidateScript({ [string]::IsNullOrEmpty($_) -or
            $_ -match [Net.IPAddress]$_})]
        [Net.IPAddress]$ServiceIPv4Node2,

        [Parameter (Mandatory= $false, ParameterSetName = "Composer")]
        [ValidateScript({ [string]::IsNullOrEmpty($_) -or
            $_ -match [Net.IPAddress]$_})]
        [Net.IPAddress]$ServiceIPv6Node1,
        
        [Parameter (Mandatory= $false, ParameterSetName = "Composer")]
        [ValidateScript({ [string]::IsNullOrEmpty($_) -or
            $_ -match [Net.IPAddress]$_})]
        [Net.IPAddress]$ServiceIPv6Node2,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [Alias ('overrideDhcpDns')]
        [switch]$OverrideIPv4DhcpDns,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [switch]$OverrideIPv6DhcpDns,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [ValidateNotNullorEmpty()]
        [string]$DomainName,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [ValidateNotNullorEmpty()]
        [Array]$SearchDomains,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [ValidateNotNullorEmpty()]
        [Alias ('nameServers')]
        [Array]$IPv4NameServers,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [ValidateNotNullorEmpty()]
        [Array]$IPv6NameServers,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Object]$NtpServers,

        [Parameter (Mandatory, ParameterSetName = "importFile")]
        [Alias ("i", "import")]
        [ValidateScript({Test-Path $_})]
        [Object]$importFile,

        [Parameter (Mandatory = $false, ParameterSetName = "VMA")]
        [Parameter (Mandatory = $false, ParameterSetName = "Composer")]
        [Parameter (Mandatory = $false, ParameterSetName = "importFile")]
        [ValidateNotNullOrEmpty()]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSBoundParameters['NtpServers'])
        {

            Write-Warning 'The -NtpServer Parameter has been deprecated, and is now controlled in the Set-HPOVApplianceDateTime Cmdlet. Please update your scripts accordingly.'

        }

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        if  ($ApplianceConnection.Count -gt 1)
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value. Please correct this and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $colStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        #Locate the Enclosure Group specified
        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Starting"

        if ($ApplianceConnection.ApplianceType -eq 'Composer' -and (-not($PSBoundParameters['ServiceIPv4Node1']) -or -not($PSBoundParameters['ServiceIPv4Node2'])))
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException MissingParameterValues InvalidOperation $ApplianceConnection.Name -Message 'The connected appliance type is a Synergy Composer, however the required -ServiceIPv4Node1 and/or -ServiceIPv4Node2 Parameter (s) was(were) not provided. Please correct the call and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Validate the appliance can Begin Network configuration of the appliance
        Try
        {

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Validating Network can be configured on the appliance."

            Try
            {

                $_resp = Send-HPOVRequest -Uri $ApplianceNetworkStatusUri -Hostname $ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if (-not($_resp.networkingAllowed))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException UnableToEditApplianceNetwork InvalidOperation $ApplianceConnection.Name -Message ($_resp.disabledReason -join " ")
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        # Get the current config (to get ETag & ensure we don't overwrite anything):
        Try
        {

            $_currentconfig = Send-HPOVRequest -Uri $ApplianceNetworkConfigUri -Hostname $ApplianceConnection.Name

        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        Switch ($PSCmdlet.ParameterSetName) 
        {
    
            {"VMA",'Composer' -contains $_}
            {

                 Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Looking for Primary interface configuration."
                
                [int]$i = 0
                
                $_deviceIndex = $null
                
                For ($i -eq 0; $i -le ($_currentconfig.applianceNetworks.Count - 1); $i++)
                {

                    if($_currentconfig.applianceNetworks[$i].interfaceName -eq "Appliance")
                    {
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found interface: $($_currentconfig.applianceNetworks[$i].interfaceName)"
                        
                        $_deviceIndex = $i

                        $_configured = $true
                        
                        #break out of for loop
                        break

                    }

                }

            }

            "importFile" 
            {

                try 
                {

                    $_importConfig = [string]::Join("", (gc $importfile -ErrorAction Stop))

                    $_importConfig = $_importConfig -replace "\s","" | convertfrom-json -ErrorAction Stop

                }

                catch [System.Management.Automation.ItemNotFoundException] 
                {
    
                    $ErrorRecord = New-ErrorRecord System.Management.Automation.ItemNotFoundException ImportFileNotFound ObjectNotFound 'Set-HPOVApplianceNetworkConfig' -Message "$importFile not found!"
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
    
                }
    
                catch [System.ArgumentException] 
                {
    
                    $ErrorRecord = New-ErrorRecord System.ArgumentException InvalidJSON ParseErrror 'Set-HPOVApplianceNetworkConfig' -Message "Input JSON format incorrect!"
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)    

                }

    
                [int]$i = 0

                For ($i -eq 0; $i -le ($_importConfig.applianceNetworks.Count - 1); $i++)
                {

                    if ($_importConfig.applianceNetworks[$i].IPv4Gateway -eq "127.0.0.1")
                    {

                        $_importConfig.applianceNetworks[$i].IPv4Gateway = $null

                    }

                    if ($_importConfig.applianceNetworks[$i].nameServers -is [String])
                    {

                        $_importConfig.applianceNetworks[$i].nameServers = New-Object.System.Collections.ArrayList

                    }

                    if ($_importConfig.applianceNetworks[$i].searchDomains -is [String])
                    {

                        $importConfig.applianceNetworks[$i].searchDomains = New-Object.System.Collections.ArrayList

                    }
                    
                    if (-not($_importConfig.applianceNetworks[$i].macAddress)) 
                    {

                        #$_macAddr = ($_importConfig.applianceNetworks | ? { $_.device -eq $_importConfig.applianceNetworks[$i].device }).macAddress

                        if (-not $_importConfig.applianceNetworks[$i].macAddress) 
                        {

                            $_macAddr = ($_currentconfig.applianceNetworks | ? { $_.device -eq $_importConfig.applianceNetworks[$i].device }).macAddress

                        }

                        if(-not $_macAddr)
                        {

                            $ErrorRecord = New-ErrorRecord InvalidOperationException ApplianceNICResourceNotFound ObjectNotFound 'Device' -Message ($_importConfig.applianceNetworks[$i].device + "does not exist on the appliance.")
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        $_importConfig.applianceNetworks[$i] | Add-Member -NotePropertyName macAddress -NotePropertyValue $_macAddr
    
                    }

                    if ($_importConfig.applianceNetworks[$i].interfaceName -eq 'Appliance' -and $_importConfig.applianceNetworks[$i].ipv4Type -eq 'STATIC')
                    {

                        #Clear non-virtIpv4Addr value for non-Composer appliances
                        if ($ApplianceConnection.ApplianceType -ne 'Composer')
                        {

                            $_importConfig.applianceNetworks[$i].virtIpv4Addr = $null
                            $_importConfig.applianceNetworks[$i].app2Ipv4Addr = $null

                        }

                        #This is needed for when we attempt to reconnect back to the appliance
                        [IPAddress]$IPv4Addr = $_importConfig.applianceNetworks[$i].app1Ipv4Addr

                    }

                }

                #zero the $currentConfig.applianceNetworks array so we can sEnd it all new values
                $_currentConfig.applianceNetworks = $_importConfig.applianceNetworks

            }

        }

        if ($_configured)
        {

            # Update any non-null values that were passed-in:
            
            if ($Hostname) 
            {

                if ($DomainName)
                {

                    $Hostname += '.{0}' -f $DomainName

                }

                $_currentconfig.applianceNetworks[$_deviceIndex].hostname = $Hostname 

            }

            if ($DomainName)    { $_currentconfig.applianceNetworks[$_deviceIndex].domainName    = $DomainName }
            if ($SearchDomains) { $_currentconfig.applianceNetworks[$_deviceIndex].searchDomains = $SearchDomains }

            $_currentconfig.applianceNetworks[$_deviceIndex].IPv4Type = $IPv4Type.ToUpper()
            $_currentconfig.applianceNetworks[$_deviceIndex].IPv6Type = $IPv6Type.ToUpper() 

            switch ($IPv4Type)
            {

                'DHCP'
                {

                    if ($ApplianceConnection.ApplianceType -eq 'Composer')
                    {

                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidIPv4AddressType InvalidOperation 'IPv4Type' -Message 'The connected appliance type is a Synergy Composer, only Static IPv4Address configurations are allowed.'
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    '[{0}] Configuring DHCP for NIC' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                    $_currentconfig.applianceNetworks[$_deviceIndex].app1IPv4Addr = $null

                    # If $overrideIPv4DhcpDns is true, set it, if not make sure it is fale
                    if ($PSBoundParameters['OverrideIPv4DhcpDns']) 
                    { 
                        
                        $_currentconfig.applianceNetworks[$_deviceIndex].overrideIPv4DhcpDnsServers = [bool]$OverrideIPv4DhcpDns 
                    
                    }

                    else 
                    { 
                        
                        $_currentconfig.applianceNetworks[$_deviceIndex].overrideIPv4DhcpDnsServers = $false 
                    
                    }

                }

                'STATIC'
                {

                    '[{0}] Configuring STATIC for NIC' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                    #Make sure override.. is false if STATIC ip addresses are in use.
                    $_currentconfig.applianceNetworks[$_deviceIndex].overrideIPv4DhcpDnsServers = $false 

                    if ((-not($PSBoundParameters['IPv4Subnet'])) -or ([Net.IPAddress]$IPv4Subnet -eq 0.0.0.0) -or $null -eq $IPv4Subnet)
                    {

                        $Message = 'A static IPv4 Address was provided, but not a valid IPv4Subnet Parameter value. Please correct this and try again.'
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.NetworkConfigurationException InvalidIPv4Subnet InvalidArgument 'IPv4Subnet' -Message $Message
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)   

                    }
                    
                    #Calculate the CIDR bit value to the SubnetMask Address
                    if ($PSBoundParameters['IPv4Subnet'].Length -le 2)
                    {

                        Try
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Converting Subnet CIDR Bit value to Subnet Mask Address."

                            [Int64]$_Int64Value = ([convert]::ToInt64(('1' * $IPv4Subnet + '0' * (32 - $IPv4Subnet)), 2))

                            $IPv4Subnet = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($_Int64Value / 16777216)).ToString(),
                                                               ([math]::Truncate(($_Int64Value % 16777216) / 65536)).ToString(),
                                                               ([math]::Truncate(($_Int64Value % 65536)/256)).ToString(),
                                                               ([math]::Truncate($_Int64Value % 256)).ToString()

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                    $_currentconfig.applianceNetworks[$_deviceIndex].IPv4Subnet  = $IPv4Subnet
                    $_currentconfig.applianceNetworks[$_deviceIndex].IPv4Gateway = $IPv4Gateway.IPAddressToString

                    if ($PSBoundParameters['IPv4NameServers']) { $_currentconfig.applianceNetworks[$_deviceIndex].IPv4NameServers = $IPv4NameServers }

                    if ($ApplianceConnection.ApplianceType -eq 'Composer')
                    {

                        '[{0}] Appliance is Composer, setting Service IP1 and Service IP2' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
                        $_currentconfig.applianceNetworks[$_deviceIndex].virtIPv4Addr = $IPv4Addr.IPAddressToString
                        $_currentconfig.applianceNetworks[$_deviceIndex].app1IPv4Addr = $ServiceIPv4Node1.IPAddressToString
                        $_currentconfig.applianceNetworks[$_deviceIndex].app2IPv4Addr = $ServiceIPv4Node2.IPAddressToString

                    }

                    else
                    {

                        $_currentconfig.applianceNetworks[$_deviceIndex].app1IPv4Addr = $IPv4Addr.IPAddressToString

                    }

                }

            }

            switch ($IPv6Type)    
            { 

                'STATIC'
                {

                    if ($ApplianceConnection.ApplianceType -eq 'Composer')
                    {

                        $_currentconfig.applianceNetworks[$_deviceIndex].virtIPv6Addr = $IPv6Addr.IPAddressToString

                        if ($ServiceIPv6Node1 -and $ServiceIPv6Node2)
                        {

                            '[{0}] Appliance is Composer, setting Service IPv6 1' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                            $_currentconfig.applianceNetworks[$_deviceIndex].app1IPv6Addr = $ServiceIPv6Node1.IPAddressToString

                            '[{0}] Appliance is Composer, setting Service IPv6 2' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                            $_currentconfig.applianceNetworks[$_deviceIndex].app2IPv6Addr = $ServiceIPv6Node2.IPAddressToString

                        }

                    }

                    else
                    {

                        $_currentconfig.applianceNetworks[$_deviceIndex].app1IPv6Addr = $IPv6Addr.IPAddressToString

                    }

                    $_currentconfig.applianceNetworks[$_deviceIndex].IPv6Subnet   = $IPv6Subnet 
                    $_currentconfig.applianceNetworks[$_deviceIndex].IPv6Gateway  = $IPv6Gateway.IPAddressToString                    

                    if ($PSBoundParameters['IPv6NameServers']) { $_currentconfig.applianceNetworks[$_deviceIndex].IPv6NameServers = $IPvV6NameServers }

                }

                'DHCP'
                {

                    # If setting DHCP, clear any existing IP address:
                    if ($IPv6Type -ieq "DHCP") { $_currentconfig.applianceNetworks[$_deviceIndex].app1IPv6Addr = $null }

                    if ($PSBoundParameters['OverrideIPv6DhcpDns']) 
                    { 
                        
                        $_currentconfig.applianceNetworks[$_deviceIndex].overrideIPv6DhcpDnsServers = [bool]$overrideIPv6DhcpDns 
                        $_currentconfig.applianceNetworks[$_deviceIndex].IPv6NameServers            = $IPv6NameServers
                    
                    }

                }
                
            }

            # Hard code the following settings, for now:
            $_currentconfig.applianceNetworks[$_deviceIndex].confOneNode = "true"  # Always "true", for now
            $_currentconfig.applianceNetworks[$_deviceIndex].activeNode = "1"      # Always "1", for now
        
        }

        "[{0}] Configuration to be applied: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_currentconfig | ConvertTo-Json -Depth 99 | out-string) | Write-Verbose

        #Remove MAC Address value or DHCP setting will break
        if ($_currentconfig.macAddress -and $ApplianceConnectionApplianceType -ne 'Composer')
        { 
            
            $_currentconfig.macAddress = $null 
        
        }

        # This is an asynch method, so get the returned Task object
        Try
        {

            $_task = Send-HPOVRequest -uri $ApplianceNetworkConfigUri -Method POST  -Body $_currentconfig -Hostname $ApplianceConnection | Wait-HPOVTaskStart

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        #validate status code 200, even though it should be HTTP/202
        if ($_task.category -eq "tasks" -and $_task.taskState -eq "Running") 
        {
        
            #Start a new stopwatch object
            $sw = [diagnostics.stopwatch]::StartNew()
                
            Do 
            {

                $_PercentComplete = [Math]::Round(((($sw.Elapsed.Minutes * 60) + $sw.Elapsed.Seconds) / 90) * 100,$MathMode)
                
                if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                { 
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Skipping Write-Progress display."
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Percent Complete: $_PercentComplete"
                    Start-Sleep -s 1

                }
                  
                else 
                {

                    #Display progress-bar
                    Write-Progress -activity "Update Appliance Network Configuration" -Status "Processing $_PercentComplete%" -percentComplete $_PercentComplete 

                }

            } until ($_PercentComplete -eq 100)

            #Stop the stopwatch
            $sw.stop()
            
            Write-Progress -activity "Update Appliance Network Configuration" -Completed
        
        }

        #task failed validation
        elseif ($_task.taskState -eq "Error") 
        {

            if ($_task.taskErrors -is [Array] -and $_task.taskErrors.count -gt 1 ) 
            {

                for ($e = 0; $e -gt $_task.taskErrors.count; $e++) 
                {

                    if ($e -ne $_task.taskErrors.length) 
                    {
                        
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.NetworkConfigurationException NoAuthSession AuthenticationError 'Set-HPOVApplianceNetworkConfig' -Message "No valid session ID found. Please use Connect-HPOVMgmt to connect and authenticate to an appliance."
                        $PSCmdlet.WriteError($ErrorRecord)    

                    }

                    else 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoAuthSession AuthenticationError 'Set-HPOVApplianceNetworkConfig' -Message "No valid session ID found. Please use Connect-HPOVMgmt to connect and authenticate to an appliance."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)    

                    }

                }

            }

        }

        if ($IPv4Type -eq "static") 
        {
            
            #Check to make sure we connect to a OneView appliance
            Try
            {
                
                #Temporarily disable SSL Cert verification to handle HTTP redirection to HTTPS
                #save the ServicePointManager configuration state to restore after our Invoke-WebRequest call
                $_originalcertpolicy = [System.Net.ServicePointManager]::CertificatePolicy
                [System.Net.ServicePointManager]::CertificatePolicy = new-object HPOneView.ITempPolicy 
                
                $_resp = Invoke-WebRequest -uri ("https://{0}" -f $IPv4Addr.IPAddressToString) -UseBasicParsing

            }

            Catch
            {

                #Return the ServicePointManager state back to original state
                [System.Net.ServicePointManager]::CertificatePolicy = $_originalcertpolicy

                #Try to connect to the appliance with the original address
                Try
                {

                    $_task = Send-HPOVRequest -uri $_task.uri -Hostname $ApplianceConnection

                    if ($_task.status -eq 'Error')
                    {

                        $_task.taskErrors | % { $Message += ('{0} {1} ({2}) {3}' -f $_.message, $_.details, $_.errorCode, ($_.recommEndedActions -Join ' ')) }
                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.NetworkConfigurationException InvalidApplianceNetworkConfigResult InvalidResult 'Set-HPOVApplianceNetworkConfig' -Message $Message
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    else
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                $PSCmdlet.ThrowTerminatingError($_)

            }

            finally
            {

                #Return the ServicePointManager state back to original state
                [System.Net.ServicePointManager]::CertificatePolicy = $_originalcertpolicy

            }
            

            #If successful, update current POSH session
            if ($_resp.Content -match "OneView") 
            { 

                "[{0}] Updating Global Connection Sessions appliance object with new appliance address: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $IPv4Addr.IPAddressToString | Write-Verbose
                
                ($Global:ConnectedSessions | ? name -eq $ApplianceConnection.Name).Name = $IPv4Addr.IPAddressToString

            }

            else 
            {

                #Unable to connect to new appliance address or connection failed. Need to generate error here.
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.NetworkConnectionException ApplianceUnreachable ConnectionError 'Set-HPOVApplianceNetworkConfig' -Message "Unable to reconnect to the appliance. Please check to make sure there are no IP Address conflicts or your set the IP Address and Subnet Mask correctly."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)    

            }

        }

        #Check to see if we can get the final status of the task resource
        Try
        {

            $Task = Send-HPOVRequest $_task.uri -Hostname $ApplianceConnection.Name | Wait-HPOVTaskComplete 

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        [void]$colStatus.Add($Task)

    }

    End
    {

        Return $colStatus

    }

}

function Get-HPOVSnmpReadCommunity 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding ()]
    Param 
    (
    
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceSnmpConfigCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {

                $_applSnmpReadCommunityStr = Send-HPOVRequest $applSnmpReadCommunity -Hostname $_appliance

                $_applSnmpReadCommunityStr.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.SnmpCommunity')

                [void]$_ApplianceSnmpConfigCollection.Add($_applSnmpReadCommunityStr)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            

        }
    
    }

    End
    {

        Return $_ApplianceSnmpConfigCollection

    }

}

function Set-HPOVSnmpReadCommunity 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory)]
        [string]$name,
            
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceSnmpConfigCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New SNMP Read Community Value: $($name)"
            
            $_NewApplSnmpReadCommunityStr = [PsCustomObject]@{ "communityString" = $name }

            Try
            {

                $_rspNewApplSnmpReadCommunity = Send-HPOVRequest $applSnmpReadCommunity PUT $_NewApplSnmpReadCommunityStr -Hostname $_appliance

                $_rspNewApplSnmpReadCommunity.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.SnmpCommunity')

                [void]$_ApplianceSnmpConfigCollection.Add($_rspNewApplSnmpReadCommunity)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
    
    }

    End
    {

        Return $_ApplianceSnmpConfigCollection

    }

}

function Get-HPOVApplianceGlobalSetting 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [string]$name,
            
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceGlobalSettingCol = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {

                $_settings = Send-HPOVRequest $ApplianceGlobalSettingsUri -Hostname $_appliance

                if ($Name)
                {

                    $_settings.members = $_settings.members | ? name -like $Name

                }

                $_settings.members | % {

                    $_.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.GlobalSetting')

                    [void]$_ApplianceGlobalSettingCol.Add($_)

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
        }

    }

    End
    {

        Return $_ApplianceGlobalSettingCol

    }

}

function Set-HPOVApplianceGlobalSetting 
{

   # .ExternalHelp HPOneView.310.psm1-help.xml
      
    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Pipeline')]
        [ValidateNotNullorEmpty()]
        [Object]$Object,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [string]$Name,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [string]$Value,

        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = 'Pipeline')]
        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSCmdlet.ParameterSetName -eq 'Pipeline')
        {

            $PipelineInput - $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_ApplianceGlobalSettingCol = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput)
        {

            #Error due to invalid object from pipeline
            if ($Object.category -ne 'global-settings')
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.GlobalSettingException InvalidGlobalSettingObject InvalidArgument 'Object' -TargetType 'PSObject' -Message "The '$(Object.name)' is an invalid Global Setting object. Please check the value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Error because Connection object doesn't exist
            if (-not($Object.category.ApplianceConnection.Name.Legth -gt 0))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.GlobalSettingException InvalidGlobalSettingObject InvalidArgument 'Object' -TargetType 'PSObject' -Message "The Global Setting '$(Object.name)' object is missing a required property, ApplianceConnection. Please validate the input object contains the 'ApplianceConnection' property and it contains a valid Appliance Connection Name."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing object: $($Object.Name)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing object: $($Object | FL * | Out-String)"

            Try
            {

                $Object.value = $Value

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updated Global Setting: $($Object | out-string)"

                $_results = Send-HPOVRequest $Object.uri PUT $Object -Hostname $Object.ApplianceConnection.Name

                [void]$_ApplianceGlobalSettingCol.Add($_results)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting current global setting value for $Name"

                Try
                {

                    $setting = Get-HPOVApplianceGlobalSetting($name)

                    $setting.value = $Value

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updated Global Setting: $($setting | out-string)"

                    $_results = Send-HPOVRequest $setting.uri PUT $setting -Hostname $_appliance

                    [void]$_ApplianceGlobalSettingCol.Add($_results)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                
            }

        }

    }

    End
    {

        Return $_ApplianceGlobalSettingCol

    }

}

function Set-HPOVApplianceProxy
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ParameterSetName = 'Authentication')]
        [ValidateNotNullorEmpty()]
        [String]$Hostname,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ParameterSetName = 'Authentication')]
        [ValidateNotNullorEmpty()]
        [int]$Port,

        [Parameter (Mandatory, ParameterSetName = 'Authentication')]
        [ValidateNotNullorEmpty()]
        [String]$Username,

        [Parameter (Mandatory, ParameterSetName = 'Authentication')]
        [ValidateNotNullorEmpty()]
        [SecureString]$Password,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Authentication')]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Authentication')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process
    {

        $_ApplianceProxyConfig = NewObject -ApplianceProxy
        $_ApplianceProxyConfig.server   = $Hostname
        $_ApplianceProxyConfig.port     = $Port
        
        if ($PSCmdlet.ParameterSetName -eq 'Authentication')
        {
            
            $_ApplianceProxyConfig.username = $Username
            $_ApplianceProxyConfig.password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))
        
        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            '[{0}] Processing "{1}" appliance connection.' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            Try
            {

                $_resp = Send-HPOVRequest -uri $ApplianceProxyConfigUri -Method POST -Body $_ApplianceProxyConfig -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)
                
            }

            if ($PSBoundParameters['Async'])
            {

                $_resp | Wait-HPOVTaskComplete

            }

            else
            {

                $_resp

            }            
                
        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVRemoteSupport
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceRemoteSupportCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            '[{0}] Processing "{1}" appliance connection.' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            #Get Appliance Remote Support configuration
            Try
            {
            
                $_resp = Send-HPOVRequest -Uri $RemoteSupportConfigUri -Hostname $_appliance.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            #Get Appliance Remote Support Insight Online portal configuration
            Try
            {
            
                $_InsightOnlineConfig = Send-HPOVRequest -Uri $InsightOnlinePortalRegistraionUri -Hostname $_appliance.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($_InsightOnlineConfig.userName)
            {

                $_resp | Add-Member -NotePropertyName InsightOnlineEnabled -NotePropertyValue $true

            }

            elseif (-not $_InsightOnlineConfig.userName)
            {

                $_resp | Add-Member -NotePropertyName InsightOnlineEnabled -NotePropertyValue $false

            }

            $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.RemoteSupportConfig')

            [void]$_ApplianceRemoteSupportCol.Add($_resp)

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        Return $_ApplianceRemoteSupportCol

    }

}

function Set-HPOVRemoteSupport
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ParameterSetName = 'InsightOnline')]
        [ValidateNotNullorEmpty()]
        [String]$CompanyName,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $False, ParameterSetName = 'InsightOnline')]
        [switch]$OptimizeOptIn,

        [Parameter (Mandatory, ParameterSetName = 'InsightOnline')]
        [ValidateNotNullorEmpty()]
        [String]$InsighOnlineUsername,

        [Parameter (Mandatory, ParameterSetName = 'InsightOnline')]
        [ValidateNotNullorEmpty()]
        [SecureString]$InsightOnlinePassword,

        [Parameter (Mandatory, ParameterSetName = 'Enable')]
        [Switch]$Enable,

        [Parameter (Mandatory, ParameterSetName = 'Disable')]
        [Switch]$Disable,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'InsightOnline')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Enable')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Disable')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceRemoteSupportCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            '[{0}] Processing "{1}" appliance connection.' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            Try
            {
            
                $_CurrentConfiguration = Send-HPOVRequest -Uri $RemoteSupportConfigUri -Hostname $_appliance.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['Disable'])
            {

                $_CurrentConfiguration.enableRemoteSupport = $false

            }

            elseif ($PSBoundParameters['Enable'])
            {

                $_CurrentConfiguration.enableRemoteSupport = $true

                #Check to make sure that 1 RS contact is default
                Try
                {

                    RemoteSupportDefaultContactExists $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                #Check to make sure that 1 RS contact is default
                Try
                {

                    RemoteSupportDefaultContactExists $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                switch ($PSBoundParameters.Keys)
                {

                    'CompanyName'
                    {

                        $_CurrentConfiguration.companyName = $CompanyName

                    }

                    'OptimizeOptIn'
                    {

                        $_CurrentConfiguration.marketingOptIn = $OptimizeOptIn

                    }

                }

                $_CurrentConfiguration.enableRemoteSupport = $true

            }
            
            Try
            {
            
                $_UpdatedConfiguration = Send-HPOVRequest -uri $RemoteSupportConfigUri -Method PUT -Body $_CurrentConfiguration -Hostname $_appliance.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSCmdlet.ParameterSetName -eq 'InsightOnline')
            {

                $_PortalRegsitrationObject = NewObject -InsightOnlineRegistration
                $_PortalRegsitrationObject.userName = $InsightOnlineUsername
                $_PortalRegsitrationObject.password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($InsightOnlinePassword))

                Try
                {
                
                    $_InsightOnlineConfig = Send-HPOVRequest -uri $InsightOnlinePortalRegistraionUri -Method POST -Body $_PortalRestrationObject -Hostname $_appliance.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                $_UpdatedConfiguration | Add-Member -NotePropertyName InsightOnlineEnabled -NotePropertyValue $true

            }

            else
            {

                $_UpdatedConfiguration | Add-Member -NotePropertyName InsightOnlineEnabled -NotePropertyValue $false

            }

            $_UpdatedConfiguration.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.RemoteSupportConfig')

            $_UpdatedConfiguration

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Enable-HPOVRemoteSupport
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default")]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Switch]$Async,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        
        if (-not $PSBoundParameters['InputObject'])
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -gt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList
        $_Collection     = New-OBject System.Collections.ArrayList
        
    }

    Process
    {

        $_PatchOperation       = NewObject -PatchOperation
        $_PatchOperation.op    = 'replace'
        $_PatchOperation.path  = '/supportEnabled'
        $_PatchOperation.value = $true

        switch ($InputObject.category)
        {

            'server-hardware'
            {

                $_uri = '{0}/{1}' -f $RemoteSupportComputeSettingsUri, $InputObject.uuid

            }

            'enclosures'
            {

                $_uri = '{0}/{1}' -f $RemoteSupportEnclosureSettingsUri, $InputObject.uuid

            }

            default
            {

                #Unsupported
                $ExceptionMessage = 'The {0} input object is an unsupported resource category type, "{1}". Only "server-hardware" or "enclosure" resources are supported.' -f $InputObject.category, $InputObject.name 
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.RemoteSupportResourceException InvalidResourceObject InvalidArgument "InputObject" -TargetType 'PSObject' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
            
        }

        try
        {

            $_Resp = Send-HPOVRequest -Uri $_uri -Method PATCH -Body $_PatchOperation -Hostname $ApplianceConnection

        }

        catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($PSBoundParameters['Async'])
        {

            $_Resp

        }

        else
        {

            Try
            {

                $_Resp | Wait-HPOVTaskComplete

            }

            Catch
            {

                $PSCmdlet.ThrowTerninatingError($_)

            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Disable-HPOVRemoteSupport
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default")]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Switch]$Async,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        
        if (-not $PSBoundParameters['InputObject'])
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -gt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList
        $_Collection     = New-OBject System.Collections.ArrayList
        
    }

    Process
    {

        $_PatchOperation       = NewObject -PatchOperation
        $_PatchOperation.op    = 'replace'
        $_PatchOperation.path  = '/supportEnabled'
        $_PatchOperation.value = $false

        switch ($InputObject.category)
        {

            'server-hardware'
            {

                $_uri = '{0}/{1}' -f $RemoteSupportComputeSettingsUri, $InputObject.uuid

            }

            'enclosures'
            {

                $_uri = '{0}/{1}' -f $RemoteSupportEnclosureSettingsUri,$InputObject.uuid

            }

            default
            {

                #Unsupported
                $ExceptionMessage = 'The {0} input object is an unsupported resource category type, "{1}". Only "server-hardware" or "enclosure" resources are supported.' -f $InputObject.category, $InputObject.name 
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.RemoteSupportResourceException InvalidResourceObject InvalidArgument "InputObject" -TargetType 'PSObject' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
            
        }

        try
        {

            $_Resp = Send-HPOVRequest -Uri $_uri -Method PATCH -Body $_PatchOperation -Hostname $ApplianceConnection

        }

        catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($PSBoundParameters['Async'])
        {

            $_Resp

        }

        else
        {

            Try
            {

                $_Resp | Wait-HPOVTaskComplete

            }

            Catch
            {

                $PSCmdlet.ThrowTerninatingError($_)

            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function RemoteSupportDefaultContactExists
{

    [CmdletBinding ()]
    Param 
    (

        [Object]$ApplianceConnection

    )

    Process
    {

        #Check to make sure that 1 RS contact is default
        Try
        {

            $_Contacts = Send-HPOVRequest -Uri $RemoteSupportContactsUri -Hostname $ApplianceConnection

            #No default contact exists, generate terminating error
            if (-not $_Contacts.members.default)
            {

                $ExceptionMessage = 'The appliance {0} does not have a configured default contact. One must exist before enabling Remote Support.' -f $ApplianceConnection
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.RemoteSupportException NoDefaultContact InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            }

            '[{0}] Default Contact: ' -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_Contacts.members | ? default).uri | Write-Verbose

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

    }    

}

function Get-HPOVRemoteSupportContact
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "Default" )]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_RemoteSupportContactsCol = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        ForEach($_appliance in $ApplianceConnection)
        {

            Try
            {

                $_RemoteSupportContacts = Send-HPOVRequest -Uri $RemoteSupportContactsUri -appliance $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['Name'])
            {

                [Array]$_RemoteSupportContacts.members = $_RemoteSupportContacts.members | ? { ('{0} {1}' -f $_.firstName, $_.lastName) -like $Name}

                if (-not $_RemoteSupportContacts.members)
                {

                    '[{0}] The "{1}" Remote Support Contact was not found on {2}. Please check the name and try again.' -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name, $_appliance.Name | Write-Verbose

                    $ExceptionMessage = 'The "{0}" Remote Support Contact was not found on {1}. Please check the name and try again.' -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException ObjectNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }

            }

            ForEach ($_Contact in $_RemoteSupportContacts.members) 
            {

                $_Contact.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.RemoteSupport.Contact')

                $_Contact

            }

        }

    }

    End 
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name, $_appliance.Name | Write-Verbose

    }
    
}

function New-HPOVRemoteSupportContact
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "Default" )]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('GivenName')]
        [String]$Firstname,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Surname')]
        [String]$Lastname,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$Email,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$PrimaryPhone,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$AlternatePhone,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$Language = 'en',

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$Notes,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [switch]$Default,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_RemoteSupportContactCol = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        $_c = 0

        ForEach($_Connection in $ApplianceConnection)
        {

            $_c++ 

            "[{0}] Processing {1} of {2} Appliance Connection(s)" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_c, ($ApplianceConnection | Measure-Object).Count | Write-Verbose

            $_RemoteSupportContact = NewObject -RemoteSupportContact

            $_RemoteSupportContact.default        = $PSBoundParameters['Default'].IsPresent
            $_RemoteSupportContact.alternatePhone = $AlternatePhone
            $_RemoteSupportContact.email          = $Email
            $_RemoteSupportContact.firstName      = $Firstname
            $_RemoteSupportContact.lastName       = $Lastname
            $_RemoteSupportContact.language       = $Language
            $_RemoteSupportContact.notes          = $Notes
            $_RemoteSupportContact.primaryPhone   = $PrimaryPhone

            $_PatchOp       = NewObject -PatchOperation
            $_PatchOP.op    = 'add'
            $_PatchOP.path  = '/contacts'
            $_PatchOP.value = $_RemoteSupportContact

            Try
            {

                $_Contacts = Send-HPOVRequest -Uri $RemoteSupportContactsUri -Hostname $_Connection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            #Check to see if there is a default contact, if so, add it as an array to the operation and set its default property to false
            if ($PSBoundParameters['Default'])
            {

                "[{0}] Checking for existing default contact" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                if ($_Contacts.members | ? default)
                {

                    "[{0}] Default contact found: {0} {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_Contacts.members | ? default).firstName, ($_Contacts.members | ? default).lastName | Write-Verbose
                    
                    $_DefaultContact = $_Contacts.members | ? default
                    $_DefaultContact.default = $false

                    $_UpdatePatchOp       = NewObject -PatchOperation
                    $_UpdatePatchOp.op    = 'replace'
                    $_UpdatePatchOp.path  = '/contacts/{0}' -f $_DefaultContact.contactKey
                    $_UpdatePatchOp.value = $_DefaultContact

                    $_NewContact = $_PatchOp.PSObject.Copy()

                    $_PatchOp = New-Object System.Collections.ArrayList
                    [void]$_PatchOp.Add($_NewContact)
                    [void]$_PatchOp.Add($_UpdatePatchOp)

                }

                else
                {

                    "[{0}] No default contact. Configured contacts: {0}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_Contacts.count | Write-Verbose

                }

            }

            elseif (-not ($_Contacts.members | ? default) -and -not $PSBoundParameters['Default'])
            {

                "[{0}] No default contacts were present, and new contact was not specified as default. Setting it as Default contact." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                $_PatchOP.value.default = $true

            }
            
            Try
            {

                #Task object is returned dur to PATCH operation
                $_resp = Send-HPOVRequest -Uri $RemoteSupportUri -Method PATCH -Body $_PatchOp -Hostname $_Connection | Wait-HPOVTaskComplete

                #If not successful, generate terminating error
                if ($_resp.taskState -ne 'Completed')
                {

                    $ExceptionMessage = [String]::Join(' ', $_resp.taskErrors.Message)
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidResult InvalidResult "Contact" -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            Try
            {

                #Get newly created contact
                $_Contacts = Send-HPOVRequest -Uri $RemoteSupportContactsUri -Hostname $_Connection

                $_NewContact = $_Contacts.members | ? { ('{0} {1}' -f $_.firstName, $_.lastName) -like ('{0} {1}' -f $Firstname, $Lastname) }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_NewContact.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.RemoteSupport.Contact')

            $_NewContact

        }

    }

    End
    {

        "Done." | Write-Verbose

    }

}

function Remove-HPOVRemoteSupportContact
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Contact')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {
    
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }        

        $_RemoteSupportContactsCol = New-Object System.Collections.ArrayList
        $_TaskCollection           = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        if ($InputObject -is [PSCustomObject]) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            "[{0}] Remote Support Contact Object provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | FL * | Out-String) | Write-Verbose

            If ($InputObject.type -eq 'Contact')
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The InputObject object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_RemoteSupportContactsCol.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidArgumentValue InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message "The InputObject object resource is not an expected type. The allowed resource category type is 'Contact'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_Connection.Name) (of $($ApplianceConnection.Count))"

                "[{0}] Processing Contact Name {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject | Write-Verbose

                Try
                {

                    $_Contact = Get-HPOVRemoteSupportContact -ApplianceConnection $_Connection | ? firstName -eq $InputObject

                    $_Contact | % {

                        [void]$_RemoteSupportContactsCol.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Begin resource removal Process."

        foreach ($_contact in $_RemoteSupportContactsCol) 
        {

            $Name          = "{0} {1}" -f $_contact.firstName, $_contact.lastName
            $RemoveMessage = "Remove Remote Support Contact '{0}'" -f $Name

            if ($_contact.default)
            {

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException UnableToRemoveDefaultContact InvalidOperation "Contact" -TargetType 'PSObject' -Message ("The Contact resource '{0}' is currently the default. The removal of the Default Contact is not supported. If you wish to remove this contact, please set another contact as the Default first." -f $Name)
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            else
            {

                if ($PSCmdlet.ShouldProcess($_contact.ApplianceConnection.Name,$RemoveMessage))
                {   
                             
                    Try
                    {
                    
                        $_task = Send-HPOVRequest -Uri $_contact.uri -Method DELETE -Hostname $_contact.ApplianceConnection.Name -AddHeader @{'If-Match' = $_contact.eTag}

                        [void]$_TaskCollection.Add($_task)

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                elseif ($PSBoundParameters['WhatIf'])
                {

                    "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                }

                else
                {

                    "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                }

            }
            
        }

        Return $_TaskCollection

    }

}

function Get-HPOVRemoteSupportPartner
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
        
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
        
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
    }

    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            $_uri = $RemoteSupportChannelPartnersUri

            Try
            {

                $_resp = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($Name)
            {

                [Array]$_resp.members = $_resp.members | ? name -match $Name

                if ($_resp.members.count -eq 0)
                {

                    $ExceptionMessage = "Unable to locate {0} on Appliance Connection {1}." -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException RemoteSupportContactNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                } 

            }
            
            $_resp.members | % {

                $_.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.RemoteSupport.Partner')

            }

            $_resp.members

        }        

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function New-HPOVRemoteSupportPartner
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateSet ('Support','Reseller')]
        [String]$Type,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [int]$PartnerId,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Switch]$Default,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
        
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
        
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
    }

    Process
    {

        $_RemoteSupportPartnerObject             = NewObject -RemoteSupportPartner
        $_RemoteSupportPartnerObject.id          = $PartnerId;
        $_RemoteSupportPartnerObject.default     = $Default.IsPresent;
        $_RemoteSupportPartnerObject.partnerType = $Type.ToUpper()

        "[{0}] Validating PartnerID: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PartnerId | Write-Verbose

        #Validate PartnerID
        Try
        {

            $_resp = Send-HPOVRequest -Uri $RemoteSupportChannelPartnersValidatorUri -Method POST -Body $PartnerId.ToString() -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        Try
        {

            $_resp = Send-HPOVRequest -Uri $RemoteSupportChannelPartnersUri -Method POST -Body $_RemoteSupportPartnerObject -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.RemoteSupport.Partner')
        $_resp

    }

    End
    {

        "Done." | Write-Verbose

    }

}

function Remove-HPOVRemoteSupportPartner
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Partner')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {
    
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }        

        $_RemoteSupportPartnerCol = New-Object System.Collections.ArrayList
        $_TaskCollection          = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        if ($PipelineInput -or $InputObject -is [PSCustomObject]) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Remote Support Contact Object provided: $($InputObject | FL * | Out-String)"

            If ($InputObject.type -eq 'ChannelPartner')
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The InputObject object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_RemoteSupportPartnerCol.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidArgumentValue InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message "The InputObject object resource is not an expected type. The allowed resource category type is 'ChannelPartner'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_Connection.Name) (of $($ApplianceConnection.Count))"

                "[{0}] Processing Contact Name {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Contact | Write-Verbose

                Try
                {

                    $_Partner = Get-HPOVRemoteSupportPartner -Name $InputObject -ApplianceConnection $ApplianceConnection[$c] -ErrorAction Stop

                    $_Partner | % {

                        [void]$_RemoteSupportPartnerCol.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Begin resource removal Process."

        foreach ($_partner in $_RemoteSupportPartnerCol) 
        {

            $RemoveMessage = "Remove Remote Support Channel Partner '{0}'" -f $_partner.Name

            if ($PSCmdlet.ShouldProcess($_partner.ApplianceConnection.Name,$RemoveMessage))
            {   
                            
                Try
                {
                
                    Send-HPOVRequest -Uri $_partner.uri -Method DELETE -Hostname $_partner.ApplianceConnection.Name -addHeader @{'If-Match' = $_partner.eTag}

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }
                        
        }

    }

}

function Get-HPOVRemoteSupportSetting
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "Default" )]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PipelineInput = $true

        }

        else
        {

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process 
    {

        switch ($InputObject.category)
        {

            'server-hardware'
            {

                $_uri = '{0}/{1}' -f $RemoteSupportComputeSettingsUri, $InputObject.uuid

            }

            'enclosures'
            {

                $_uri = '{0}/{1}' -f $RemoteSupportEnclosureSettingsUri,$InputObject.uuid

            }

            default
            {

                #Unsupported
                $ExceptionMessage = 'The {0} input object is an unsupported resource category type, "{1}". Only "server-hardware" or "enclosure" resources are supported.' -f $InputObject.category, $InputObject.name 
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.RemoteSupportResourceException InvalidResourceObject InvalidArgument "InputObject" -TargetType 'PSObject' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        Try
        {

            $_ResourceRemoteSupportSettings = Send-HPOVRequest -uri $_uri -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $_ResourceRemoteSupportSettings | Add-Member -NotePropertyName ResourceName -NotePropertyValue $InputObject.name
        $_ResourceRemoteSupportSettings | Add-Member -NotePropertyName ResourceType -NotePropertyValue $InputObject.category

        ForEach ($_EnumKey in $RemoteSupportResourceSettingEnum.GetEnumerator())
        {

            $_Setting    = $null
            $EnumKeyName = $_EnumKey.Name
            $Uri         = $_ResourceRemoteSupportSettings.$EnumKeyName

            if ($Uri)
            {

                'Processing: {0}' -f $Uri, $EnumKeyName | Write-Verbose

                Try
                {

                    $_Setting = Send-HPOVRequest -Uri $Uri -Hostname $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                '{0} contains a null value.' -f $EnumKeyName | Write-Verbose

            }        
            
            $_ResourceRemoteSupportSettings | Add-Member -NotePropertyName $_EnumKey.Value -NotePropertyValue $_Setting

        }

        $_ResourceRemoteSupportSettings.PSObject.TypeNames.Insert(0,'HPOneView.RemoteSupport.ResourceSetting')

        $_ResourceRemoteSupportSettings

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Set-HPOVRemoteSupportSetting
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]

    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Object]$PrimaryContact,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Object]$SecondaryContact,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Object]$ServicePartner,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Object]$Reseller,

        [Parameter (Mandatory = $false)]
        [ValidateSet ('PackagedSupport', 'SupportAgreement')]
        [String]$ContractType,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [String]$SupportID,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [String]$NewSerialNumber,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [String]$NewProductNumber,
        
        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {

        $_RemoteSupportSettingsToSet = New-Object System.Collections.ArrayList

        switch ($InputObject.category)
        {

            'server-hardware'
            {

                $_uri = '{0}/{1}' -f $RemoteSupportComputeSettingsUri, $InputObject.uuid

            }

            'enclosures'
            {

                $_uri = '{0}/{1}' -f $RemoteSupportEnclosureSettingsUri, $InputObject.uuid

            }

            default
            {

                #Unsupported
                $ExceptionMessage = 'The {0} input object is an unsupported resource category type, "{1}". Only "server-hardware" or "enclosure" resources are supported.' -f $InputObject.category, $InputObject.name 
                $ErrorRecord = New-ErrorRecord HPOneview.InputObjectResourceException InvalidResourceObject InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
            
        }

        Switch ($PSBoundParameters.Keys)
        {

            'PrimaryContact'
            {

                if ($PrimaryContact.Type -ne 'Contact')
                {

                    $ExceptionMessage = 'The PrimaryContact object is not a valid Remote Support Contact.'
                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.RemoteSupportContactException InvalidPrimaryContact InvalidArgument "InputObject" -TargetType $PrimaryContact.GetType().Name -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $_PrimaryContactOp = NewObject -PatchOperation
                $_PrimaryContactOp.op    = 'replace'
                $_PrimaryContactOp.path  = '/primaryContactUri'
                $_PrimaryContactOp.value = $PrimaryContact.uri

                [Void]$_RemoteSupportSettingsToSet.Add($_PrimaryContactOp)
                
            }

            'SecondaryContact'
            {

                if ($SecondaryContact.Type -ne 'Contact')
                {

                    $ExceptionMessage = 'The SecondaryContact object is not a valid Remote Support Contact.'
                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.RemoteSupportContactException InvalidSecondaryContact InvalidArgument "InputObject" -TargetType $SecondaryContact.GetType().Name -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $_SecondaryContactOp = NewObject -PatchOperation
                $_SecondaryContactOp.op    = 'replace'
                $_SecondaryContactOp.path  = '/secondaryContactUri'
                $_SecondaryContactOp.value = $SecondaryContact.uri

                [Void]$_RemoteSupportSettingsToSet.Add($_SecondaryContactOp)
                
            }

            'Reseller'
            {

                if ($Reseller.Type -ne 'ChannelPartner' -or $Reseller.partnerType -ne 'RESELLER')
                {

                    $ExceptionMessage = 'The Reseller object is not a valid Remote Support reseller partner.'
                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.RemoteSupportPartnerException InvalidReseller InvalidArgument "InputObject" -TargetType $Reseller.GetType().Name -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $_ResellerOp = NewObject -PatchOperation
                $_ResellerOp.op    = 'replace'
                $_ResellerOp.path  = '/salesChannelPartnerUri'
                $_ResellerOp.value = $Reseller.uri

                [Void]$_RemoteSupportSettingsToSet.Add($_ResellerOp)
                
            }

            'ServicePartner'
            {
                
                if ($ServicePartner.Type -ne 'ChannelPartner' -or $ServicePartner.partnerType -ne 'SUPPORT')
                {

                    $ExceptionMessage = 'The Reseller object is not a valid Remote Support suport partner.'
                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.RemoteSupportPartnerException InvalidServicePartner InvalidArgument "InputObject" -TargetType $ServicePartner.GetType().Name -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $_ServicePartnerOp = NewObject -PatchOperation
                $_ServicePartnerOp.op    = 'replace'
                $_ServicePartnerOp.path  = '/supportChannelPartnerUri'
                $_ServicePartnerOp.value = $ServicePartner.uri

                [Void]$_RemoteSupportSettingsToSet.Add($_ServicePartnerOp)
                
            }

            'SupportID'
            {

                $_SupportIDOp = NewObject -PatchOperation
                $_SupportIDOp.op    = 'replace'
                $_SupportIDOp.path  = '/entitlement'
                $_SupportIDOp.value = [PSCustomOBject]@{

                    obligationType = $ContractType;
                    obligationId   = $SupportID

                }

                [Void]$_RemoteSupportSettingsToSet.Add($_SupportIDOp)
                
            }

            'NewSerialNumber'
            {

                $_NewSerialNumberOp = NewObject -PatchOperation
                $_NewSerialNumberOp.op    = 'replace'
                $_NewSerialNumberOp.path  = '/enteredSerialNumber'
                $_NewSerialNumberOp.value = $NewSerialNumber

                [Void]$_RemoteSupportSettingsToSet.Add($_NewSerialNumberOp)
                
            }

            'NewProductNumber'
            {

                $_NewProductNumberOp = NewObject -PatchOperation
                $_NewProductNumberOp.op    = 'replace'
                $_NewProductNumberOp.path  = '/enteredProductNumber'
                $_NewProductNumberOp.value = $NewProductNumber

                [Void]$_RemoteSupportSettingsToSet.Add($_NewProductNumberOp)
                
            }
            
        }

        Try
        {

            $_resp = Send-HPOVRequest -Uri $_uri -Method PATCH -Body $_RemoteSupportSettingsToSet -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($PSBoundParameters['Async'])
        {

            $_resp

        }

        else
        {

            $_resp | Wait-HPOVTaskComplete

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Set-HPOVRemoteSupportDataCollectionSchedule
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateSet ('AHS','Basic')]
        [String]$Type,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [DateTime]$DateTime,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_SchedulesToUpdate = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach($_Appliance in $ApplianceConnection)
        {

            #Get the default schedules on the appliance
            Try
            {

                $_Schedules = Send-HPOVRequest -Uri $RemoteSupportDataCollectionScheduleUri -Hostname $_Appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if (-not $PSBoundParameters['Type'])
            {

                $_Type = 'AHS','Basic'

            }

            else
            {

                $_Type = $Type

            }

            Switch ($_Type)
            {

                'AHS'
                {

                    $_schedule = $_Schedules.members | ? serviceName -eq 'Active_Health_Service_Collection'

                    "[{0}] Processing schedule: {1}({2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_schedule.scheduleName, $_schedule.serviceName | Write-Verbose
                    $_schedule.hourOfDay = [int]$DateTime.Hour
                    $_schedule.minute    = $DateTime.Minute    
                    $_schedule.dayOfWeek = [int]$DateTime.DayOfWeek + 1 #Needs to be a value of 1 through 7. Windows defaults to 0 - 6.

                    $_PatchOperation = NewObject -PatchOperation

                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/schedules/{0}' -f $_schedule.taskKey
                    $_PatchOperation.value = $_schedule

                    [void]$_SchedulesToUpdate.Add($_PatchOperation)        
                    
                }

                'Basic'
                {

                    $_schedule = $_Schedules.members | ? serviceName -eq 'Server_Basic_Configuration_Collection'

                    "[{0}] Processing schedule: {1}({2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_schedule.scheduleName, $_schedule.serviceName | Write-Verbose
                    $_schedule.hourOfDay = [int]$DateTime.Hour
                    $_schedule.minute    = $DateTime.Minute    
                    $_schedule.dayOfMonth = [int]$DateTime.Day

                    $_PatchOperation = NewObject -PatchOperation

                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/schedules/{0}' -f $_schedule.taskKey
                    $_PatchOperation.value = $_schedule

                    [void]$_SchedulesToUpdate.Add($_PatchOperation)        

                }
                
            }

            Try
            {

                $_resp = Send-HPOVRequest -Uri $RemoteSupportUri -Method PATCH -Body $_SchedulesToUpdate -Hostname $_Appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['Async'])
            {

                $_resp

            }

            else
            {

                $_resp | Wait-HPOVTaskComplete

            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVRemoteSupportDataCollectionSchedule
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default")]
    Param 
    (
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateSet ('AHS','Basic')]
        [String]$Type,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {

        ForEach($_Appliance in $ApplianceConnection)
        {

            #Get the default schedules on the appliance
            Try
            {

                $_Schedules = Send-HPOVRequest -Uri $RemoteSupportDataCollectionScheduleUri -Hostname $_Appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if (-not $PSBoundParameters['Type'])
            {

                $_Type = 'AHS','Basic'

            }

            else
            {

                $_Type = $Type

            }

            Switch ($_Type)
            {

                'AHS'
                {

                    $_Schedules.members | ? serviceName -eq 'Active_Health_Service_Collection' | % {

                        New-Object HPOneView.Appliance.RemoteSupport.Schedule($_.scheduleName,
                                                                                $_.repeatOption,
                                                                                $_.hourOfDay,
                                                                                $_.minute,
                                                                                [DayOfWeek]$_.dayOfWeek,
                                                                                $_.ApplianceConnection)

                    }
                    
                }

                'Basic'
                {

                    $_Schedules.members | ? serviceName -eq 'Server_Basic_Configuration_Collection' | % {

                        New-Object HPOneView.Appliance.RemoteSupport.Schedule($_.scheduleName,
                                                                              $_.repeatOption,
                                                                              $_.hourOfDay,
                                                                              $_.minute,
                                                                              $_.dayOfMonth,
                                                                              $_.ApplianceConnection)

                    }

                }
                
            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Start-HPOVRemoteSupportCollection
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,
        
        [Parameter (Mandatory)]
        [ValidateSet ('AHS', 'Basic')]
        [String]$Type,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Switch]$Async,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_SchedulesToUpdate = New-Object System.Collections.ArrayList

    }

    Process 
    {

        $_DataCollection = [PSCustomObject]@{
            type           = "CollectionType";
            collectionType = "AHS"
        }

        switch ($InputObject.category)
        {

            'enclosures'
            {

                $_DataCollection.collectionType = 'Basic'
                $_Uri = '{0}?deviceID={1}&category=enclosures' -f $RemoteSupportDataCollectionsUri, $InputObject.uuid

            }

            'server-hardware'
            {

                $_DataCollection.collectionType = $RemoteSupportCollectionEnum[$Type]

                $_Uri = '{0}?deviceID={1}&category=server-hardware' -f $RemoteSupportDataCollectionsUri, $InputObject.uuid

            }

            'server-profiles'
            {

                if ($null -ne $InputObject.serverHardwareUri)
                {

                    $_DataCollection.collectionType = $RemoteSupportCollectionEnum[$Type]

                    $_Uri = '{0}?deviceID={1}&category=server-hardware' -f $RemoteSupportDataCollectionsUri, $InputObject.uuid

                }

                else
                {

                    $ExceptionMessage = 'The {0} Server Profile resource is not assigned to a compute resource.' -f $InputObject.category, $InputObject.name 
                    $ErrorRecord = New-ErrorRecord HPOneview.InputObjectResourceException InvalidResourceObject InvalidArgument "InputObject" -TargetType 'PSObject' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }                

            }

            default
            {

                #Unsupported
                $ExceptionMessage = 'The {0} input object is an unsupported resource category type, "{1}". Only "server-hardware", "server-profile" or "enclosure" resources are supported.' -f $InputObject.category, $InputObject.name 
                $ErrorRecord = New-ErrorRecord HPOneview.InputObjectResourceException InvalidResourceObject InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        if ($_Uri)
        {

            Try
            {
    
                $_resp = Send-HPOVRequest -Uri $_Uri -Method POST -Body $_DataCollection -Hostname $ApplianceConnection
    
            }
    
            Catch
            {
    
                $PSCmdlet.ThrowTerminatingError($_)
    
            }
    
            if ($PSBoundParameters['Async'])
            {
    
                $_resp
    
            }
    
            else
            {
    
                $_resp | Wait-HPOVTaskComplete
    
            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVRemoteSupportEntitlementStatus
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default")]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose
        
        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        
        if (-not $PSBoundParameters['InputObject'])
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -gt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process
    {

        $_ResourcesToProcess = New-Object System.Collections.ArrayList

        switch ($InputObject.category)
        {

            'enclosures'
            {

                "[{0}] Processing Enclosure: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose
                
                [void]$_ResourcesToProcess.Add($InputObject.PSObject.Copy())

            }

            'logical-enclosures'
            {

                "[{0}] Processing Logical Enclosure: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                ForEach ($_Uri in $InputObject.enclosureUris)
                {

                    Try
                    {
        
                        $_Resource = Send-HPOVRequest -Uri $_Uri -Hostname $ApplianceConnection                
        
                    }
        
                    Catch
                    {
        
                        $PSCmdlet.ThrowTerminatingError($_)
        
                    }

                    [void]$_ResourcesToProcess.Add($_Resource)

                }

            }

            'enclosure-groups'
            {

                "[{0}] Processing Enclosure Group, and getting associated Logical Enclosures: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose
                
                $_Uri = '{0}?parentUri={1}&name=ENCLOSURE_GROUP_TO_LOGICAL_ENCLOSURE' -f $AssociationsUri, $InputObject.uri
    
                Try
                {
    
                    [Array]$_AssoiatedLEs = (Send-HPOVRequest -Uri $_Uri -Hostname $ApplianceConnection).members  | % { Send-HPOVRequest $_.childUri -Hostname $_.ApplianceConnection.Name}

                    ForEach ($_Uri in $InputObject.enclosureUris)
                    {
    
                        Try
                        {
            
                            $_Resource = Send-HPOVRequest -Uri $_Uri -Hostname $ApplianceConnection                
            
                        }
            
                        Catch
                        {
            
                            $PSCmdlet.ThrowTerminatingError($_)
            
                        }
    
                        [void]$_ResourcesToProcess.Add($_Resource)
    
                    }
    
                }
    
                Catch
                {
    
                    $PSCmdlet.ThrowTerminatingError($_)
    
                }

            }

            'server-hardware'
            {

                "[{0}] Processing server hardware device: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                [void]$_ResourcesToProcess.Add($InputObject.PSObject.Copy())

            }

            'server-profiles'
            {

                "[{0}] Processing server profile: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                if ($Null -eq $InputObject.serverHardwareUri)
                {

                    "[{0}] Server Profile is currently unassigned." -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                }

                else
                {

                    Try
                    {
        
                        $_Resource = Send-HPOVRequest -Uri $InputObject.serverHardwareUri -Hostname $ApplianceConnection                
        
                    }
        
                    Catch
                    {
        
                        $PSCmdlet.ThrowTerminatingError($_)
        
                    }

                    [void]$_ResourcesToProcess.Add($_Resource)

                }                

            }

            default
            {

                #Generae error of unsupported resource
                $ExceptionMessage = 'The {0} input object is an unsupported resource category type, "{1}". Only "server-hardware"., "server-profile", "enclosure-group", "logical-enclosure" or "enclosure" resources are supported.' -f $InputObject.category, $InputObject.name 
                $ErrorRecord = New-ErrorRecord HPOneview.InputObjectResourceException InvalidInputObjectResource InvalidArgument "InputObject" -TargetType 'String' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        ForEach ($_Resource in $_ResourcesToProcess)
        {

            "[{0}] Getting Remote Support status for: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_Resource.name | Write-Verbose

            Try
            {

                $_RemoteSupportStatus = Send-HPOVRequest -Uri $_Resource.remoteSupportUri -Hostname $ApplianceConnection                

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($_RemoteSupportStatus.supportEnabled)
            {

                "[{0}] Resource has Remote Support enabled, getting entitlement information." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                Try
                {

                    $_ResourceEntitlementStatus = Send-HPOVRequest -Uri $_RemoteSupportStatus.entitlementUri -Hostname $ApplianceConnection

                }

                Catch
                {
    
                    $PSCmdlet.ThrowTerminatingError($_)
    
                }

                if ($null -eq $_ResourceEntitlementStatus.obligationStartDate)
                {

                    [DateTime]$_ResourceEntitlementStatus.obligationStartDate = '01/01/1970'
                    
                }

                if ($null -eq $_ResourceEntitlementStatus.obligationEndDate)
                {

                    [DateTime]$_ResourceEntitlementStatus.obligationEndDate = '01/01/1970'

                }

                if ($null -eq $_ResourceEntitlementStatus.offerStartDate)
                {

                    [DateTime]$_ResourceEntitlementStatus.offerStartDate = '01/01/1970'

                }

                if ($null -eq $_ResourceEntitlementStatus.offerEndDate)
                {

                    [DateTime]$_ResourceEntitlementStatus.offerEndDate = '01/01/1970'

                }

                # Get resource name
                switch ($_Resource.type)
                {

                    'server-hardware'
                    {

                        if ($null -ne $_Resource.serverName)
                        {

                            $_ResourceName = $_Resource.serverName

                        }

                        else
                        {

                            $_ResourceName = $_Resource.name

                        }

                    }

                    'enclosures'
                    {

                        $_ResourceName = $_Resource.name

                    }

                }

                $_EntitlementStatus = New-Object HPOneView.RemoteSupport.ContractAndWarrantyStatus ($_ResourceName,
                                                                                                    $_Uri,
                                                                                                    $_Resource.serialNumber,
                                                                                                    $_ResourceEntitlementStatus.entitlementPackage,
                                                                                                    $_ResourceEntitlementStatus.entitlementStatus,
                                                                                                    $_ResourceEntitlementStatus.offerStatus,
                                                                                                    $_ResourceEntitlementStatus.coverageDays,
                                                                                                    $_ResourceEntitlementStatus.coverageHoursDay1to5,
                                                                                                    $_ResourceEntitlementStatus.coverageHoursDay6,
                                                                                                    $_ResourceEntitlementStatus.coverageHoursDay7,
                                                                                                    $_ResourceEntitlementStatus.responseTimeDay1to5,
                                                                                                    $_ResourceEntitlementStatus.responseTimeDay6,
                                                                                                    $_ResourceEntitlementStatus.responseTimeDay7,
                                                                                                    [DateTime]$_ResourceEntitlementStatus.obligationStartDate,
                                                                                                    [DateTime]$_ResourceEntitlementStatus.obligationEndDate,
                                                                                                    [DateTime]$_ResourceEntitlementStatus.offerStartDate,
                                                                                                    [DateTime]$_ResourceEntitlementStatus.offerEndDate,
                                                                                                    $_ResourceEntitlementStatus.countryCode,
                                                                                                    $_ResourceEntitlementStatus.obligationType,
                                                                                                    $_ResourceEntitlementStatus.entitlementKey,
                                                                                                    $_ResourceEntitlementStatus.obligationId,
                                                                                                    $_ResourceEntitlementStatus.coversHolidays,
                                                                                                    $_ResourceEntitlementStatus.isEntitled,
                                                                                                    $_ResourceEntitlementStatus.responseTimeHolidays,
                                                                                                    $_ResourceEntitlementStatus.explanation,
                                                                                                    $_resourceEntitlementStatus.ApplianceConnection
                                                                                                )

            }

            else
            {

                "[{0}] Remote Support is disabled for the resource, returning ." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_EntitlementStatus = New-Object HPOneView.RemoteSupport.ContractAndWarrantyStatus ($_ResourceName,
                                                                                                    $_Uri,
                                                                                                    $_Resource.serialNumber,
                                                                                                    $false,
                                                                                                    'INVALID',
                                                                                                    $_Resource.ApplianceConnection
                                                                                                    )
                
            }

            $_EntitlementStatus

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }    

}

function Update-HPOVRemoteSupportEntitlement
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default")]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Switch]$Async,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin
    {

        Write-Warning "Not Implemented."

        Return $null

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose
        
        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        
        if (-not $PSBoundParameters['InputObject'])
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -gt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process
    {

        $_PatchOperation       = NewObject -PatchOperation
        $_PatchOperation.op    = 'replace'
        $_PatchOperation.path  = '/refreshState'
        $_PatchOperation.value = "RefreshPending"

        switch ($InputObject.category)
        {

            'server-hardware'
            {

                $_uri = '{0}/{1}' -f $RemoteSupportComputeSettingsUri, $InputObject.uuid

            }

            'enclosures'
            {

                $_uri = '{0}/{1}' -f $RemoteSupportEnclosureSettingsUri, $InputObject.uuid

            }

            default
            {

                #Unsupported
                $ExceptionMessage = 'The {0} input object is an unsupported resource category type, "{1}". Only "server-hardware" or "enclosure" resources are supported.' -f $InputObject.category, $InputObject.name 
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.RemoteSupportResourceException InvalidResourceObject InvalidArgument "InputObject" -TargetType 'PSObject' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
            
        }

        try
        {

            $_Resp = Send-HPOVRequest -Uri $uri -Method PATCH -Body $_PatchOperation -Hostname $ApplianceConnection

        }

        catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($PSBoundParameters['Async'])
        {

            $_Resp

        }

        else
        {

            Try
            {

                $_Resp | Wait-HPOVTaskComplete

            }

            Catch
            {

                $PSCmdlet.ThrowTerninatingError($_)

            }

        }

    }
    
    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVRemoteSupportDefaultSite
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (
        
        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $_connection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $_connection -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $defaultSiteCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        ForEach($_Connection in $ApplianceConnection)
        {

            Try
            {

                $_defaultSite = Send-HPOVRequest $RemoteSupportDefaultSitesUri -appliance $_Connection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_defaultSite.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.RemoteSupport.DefaultSite')

            [void]$defaultSiteCollection.Add($_defaultSite)

        }

    }

    End 
    {

        return $defaultSiteCollection

    }

}

function Set-HPOVRemoteSupportDefaultSite
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default" )]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('a1')]
        [String]$AddressLine1,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('a2')]
        [String]$AddressLine2,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$City,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Province')]
        [String]$State,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$PostalCode,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$Country,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$TimeZone,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $_connection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $_connection -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $defaultSiteCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach($_Connection in $ApplianceConnection)
        {

            Try
            {

                $_DefaultSite = Send-HPOVRequest -uri $RemoteSupportDefaultSitesUri -Hostname $_Connection
                $_method      = 'PUT'
                $_uri         = $_DefaultSite.uri
                
                
            }

            Catch 
            {

                if ($_.FullyQualifiedErrorId -match 'ResourceNotFound')
                {

                    $_method      = 'POST'
                    $_uri         = $RemoteSupportDefaultSitesUri
                    $_DefaultSite = NewObject -RemoteSupportSite

                }

                else
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }            

            }

            $_DefaultSite.streetAddress1 = $AddressLine1
            if ($PSBoundParameters['AddressLine2']) { $_DefaultSite.streetAddress2 = $AddressLine2 }
            $_DefaultSite.city           = $City 
            $_DefaultSite.provinceState  = $State
            $_DefaultSite.countryCode    = $Country
            if ($PSBoundParameters['PostalCode']) { $_DefaultSite.postalCode = $PostalCode }            
            $_DefaultSite.timeZone       = $TimeZone
         
            Try
            {

                $_resp = Send-HPOVRequest -method $_method -uri $_uri -body $_defaultSite -Hostname $_Connection

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.RemoteSupport.DefaultSite')

            $_resp

        }

    }

    End 
    {
        
        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVBaseline 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "ISOFileName" )]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "ISOFileName")]
        [ValidateNotNullOrEmpty()]
        [Alias ('isoFileName','FileName')]
        [Object]$File,

        [Parameter (Mandatory = $false, ParameterSetName = "BaselineName")]
        [Alias ('name')]
        [ValidateNotNullOrEmpty()]
        [string]$SppName,

        [Parameter (Mandatory = $false, ParameterSetName = "BaselineName")]
        [ValidateNotNullOrEmpty()]
        [string]$Version,

        [Parameter (Mandatory = $false, ParameterSetName = "HotFixesOnly")]
        [switch]$HotfixesOnly,

        [Parameter (Mandatory = $false, ParameterSetName = "ISOFileName")]
        [Parameter (Mandatory = $false, ParameterSetName = "BaselineName")]
        [Parameter (Mandatory = $false, ParameterSetName = "HotFixesOnly")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $BaselineCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        ForEach($_Connection in $ApplianceConnection)
        {

            Try
            {

                $_baselines = Send-HPOVRequest -Uri $fwDriversUri -appliance $_Connection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            switch ($PSCmdlet.ParameterSetName) 
            {
                
                "BaselineName" 
                {
                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SppName Parameter provided: $($SppName)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Version Parameter provided: $($version)"

                    if ($Version) 
                    {
                        
                        $_baselines.members = $_baselines.members | ? version -eq $version
                    
                    }

                    else 
                    {
                        
                        $_baselines.members = $_baselines.members | ? name -like $SppName 
                    
                    }

                    if ((-not $_baselines.members) -and $SppName) 
                    {

                        $ExceptionMessage = "The Baseline name '{0}' was not found on '{1}' appliance." -f $SppName, $_Connection.Name
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'SppName' -Message $ExceptionMessage
                        $PSCmdlet.WriteError($ErrorRecord)

                    }

                    elseif ((-not $_baselines.members) -and $version) 
                    {

                        $ExceptionMessage = "The Baseline name '{0}' version '{1}' was not found on '{2}' appliance." -f $SppName, $Version, $_Connection.Name
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'SppName' -Message $ExceptionMessage
                        $PSCmdlet.WriteError($ErrorRecord)

                    }
            
                }
            
                "ISOFileName" 
                {

                    if ($File) 
                    { 

                        if ($File.EndsWith('.exe') -or $File.EndsWith('.scexe') -or $File.EndsWith('.rpm'))
                        {

                            "[{0}] Looking for hotfix file" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            [Array]$_baselines.members = $_baselines.members | ? resourceId -like $File.Replace('.rpm',$null).Replace('.exe',$null).Replace('.scexe',$null).Replace('.','_')

                        }

                        else
                        {

                            "[{0}] Looking for Baseline ISO file" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            [Array]$_baselines.members = $_baselines.members | ? isoFileName -Match $File.Replace('.iso',$null).Replace('.','_')

                        }
                        
                        #$_baselines.members = $_baselines.members | ? isoFileName -like $File
                    
                    }

                    if ((-not $_baselines.members) -and $File) 
                    {

                        $ExceptionMessage = "The Baseline resource name '{0}' was not found on '{1}' appliance." -f $File, $_Connection.Name
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'File' -Message $ExceptionMessage
                        $PSCmdlet.WriteError($ErrorRecord)

                    }

                }

                'HotfixesOnly'
                {

                    [Array]$_baselines.members = $_baselines.members | ? bundleType -eq 'Hotfix'
                    $_baselines.count = $_baselines.members.Count

                }
            
                default 
                {
            
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Parameter provided. Looking for all SPP Baselines."

                }
            
            }

            foreach ($_baseline in $_baselines.members)
            {
            
                #return the full baseline object
                Try
                {

                    $_baseline = Send-HPOVRequest -Uri $_baseline.uri -Hostname $_baseline.ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                #Inject repository location as a property, should not cause issues with other API calls with the resource
                $_Locations = New-Object System.Collections.Arraylist

                ForEach ($_Location in ($_baseline.locations.PSObject.Members | ? { $_.MemberType -eq 'NoteProperty'}))
                {

                    [void]$_Locations.Add($_Location.Value)

                }

                $_baseline.locations = [String]::Join(', ', $_Locations.ToArray())

                $_baseline.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.Baseline')

                $_baseline

            }

        }

    }

    End 
    {
        
         "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Add-HPOVBaseline 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateScript({Test-Path $_})]
        [Alias ('sppFile')]
        [Object]$File,

        [Parameter (Mandatory = $false)]
        [switch]$Async,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['File']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        if (-not(Test-Path $File -PathType Leaf))
        {

            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineFileNotFound ObjectNotFound 'File' -Message ("The baseline file '{0}' was not found. Please check the path and filename." -f $File.Name)
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)                

        }

        if ($File -isnot [System.IO.FileInfo])
        { 
            
            $File = Get-ChildItem -Path $File
            
        }

        if ($File.Length -le 0)
        {
        
            $ExceptionMessage = ("The File resource '{0}' file size is 0." -f $File.Name)
            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException ResourceCannotBeZero InvalidArgument 'File' -TargetType 'System.IO.FileInfo' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        ForEach ($_Connection in $ApplianceConnection)
        {

            $_BaselineExists = $null

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_Connection.Name)"

            #Check if the Baseline exists already, instead of waiting for filetransfer to finish
            "[{0}] Checking if Baseline exists" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Try
            {

                $_BaselineExists = Get-HPOVBaseline -FileName ($File.BaseName.Replace('.','_') + $File.Extension) -ErrorAction SilentlyContinue

            }

            Catch
            {

              $PSCmdlet.ThrowTerminatingError($_)

            }

            if (-not $_BaselineExists)
            {

                #Start upload file
                Try
                {

                    $task = Upload-File $fwUploadUri $File.FullName $_Connection

                    if (-not($PSBoundParameters['Async']))
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response is a task resource, calling Wait-HPOVTaskComplete"

                        $task = $task | Wait-HPOVTaskComplete

                    }
                
                    $Task

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($_BaselineExists)
            {

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceAlreadyExists ResourceExists 'File' -Message ("The Baseline '{0}' is already present on the appliance. Please upload a different baseline." -f $File.Name)
                $PSCmdlet.WriteError($ErrorRecord)

            }

        }

    }
    
    End 
    {
    
        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
    
    }

}

function New-HPOVCustomBaseline
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullorEmpty()]
        [Object]$SourceBaseline,

        [Parameter (Mandatory)]
        [Array]$Hotfixes,

        [Parameter (Mandatory)]
        [String]$BaselineName,

        [Parameter (Mandatory = $false)]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['SourceBaseline']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        $_CustomBaseline = NewObject -CustomBaseline

        #Validate Source Baseline
        switch ($SourceBaseline.GetType().Name)
        {

            'PSCustomObject'
            {
                
                if ($SourceBaseline.category -ne 'firmware-drivers')
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException InvalidBaselineResource InvalidArgument 'SourceBaseline' -TargetType 'PSObject' -Message "The provided SourceBaseline object is not the required category, 'firmware-drivers'. Please correct the input Parameter."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline Object Provided"
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline Name: {0}" -f $SourceBaseline.shortName | Write-Verbose
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline URI: {0}" -f $SourceBaseline.uri | Write-Verbose

            }

            'String'
            {

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline Name Provided: {0}" -f $SourceBaseline | Write-Verbose

                #Get Source Baseline from Basline Name
                Try
                {

                    $BaselineParamName = $SourceBaseline.Clone()
                    $SourceBaseline = Get-HPOVBaseline -SppName $SourceBaseline -ApplianceConnection $ApplianceConnection -ErrorAction SilentlyContinue

                    If (-not $SourceBaseline)
                    {

                        $ExceptionMessage = "The provided SourceBaseline '{0}' was not found." -f $BaselineParamName
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'SourceBaseline' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
            }

        }
        
        #Loop through Hotfixes
        ForEach ($_HotFix in $Hotfixes)
        {

            switch ($_HotFix.GetType().Name)
            {

                'PSCustomObject'
                {
                    
                    if ($_HotFix.category -ne 'firmware-drivers' -and $_HotFix.bundleType -ne 'Hotfix')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException InvalidBaselineResource InvalidArgument 'Hotfixes' -TargetType 'PSObject' -Message "The provided Hotfix object is not the required category and type. Only 'firmware-drivers' category and 'Hotfix' type are allowed. Please correct the input Parameter."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Hotfix baseline object provided"
                    "[{0}] Hotfix baseline Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(),$_HotFix.shortName | Write-Verbose
                    "[{0}] Hotfix baseline URI: {1}" -f $MyInvocation.InvocationName.ToString(),$_HotFix.uri | Write-Verbose

                }

                'String'
                {

                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Hotfix Name Provided: {0}" -f $_HotFix | Write-Verbose

                    #Get Source Baseline from Basline Name
                    Try
                    {

                        $_HotFixName = $_HotFix.Clone()
                        $_HotFix = Get-HPOVBaseline  -File $_HotFix -ApplianceConnection $ApplianceConnection -ErrorAction SilentlyContinue

                        If (-not $_HotFix)
                        {

                            $ExceptionMessage = "The provided Hotfix '{0}' was not found." -f $_HotFixName
                            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Hotfixes' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                }

            }

            [void]$_CustomBaseline.hotfixUris.Add($_HotFix.uri)

        }

        $_CustomBaseline.baselineUri        = $SourceBaseline.uri
        $_CustomBaseline.customBaselineName = $BaselineName
        
        #Post the new object to the appliancenvocationName.ToString().ToUpper())] Processing Appliance $($_Connection.Name)"
        Try
        {

            $_Resp = Send-HPOVRequest $fwDriversUri POST $_CustomBaseline -Hostname $ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not($PSBoundParameters['Async']))
        {

            $_Resp | Wait-HPOVTaskComplete

        }

        else
        {

            $_Resp

        }

    }
    
    End 
    {
    
        "[{0}] Done." -f $MyInvocation.InvocationName.ToString() | Write-Verbose
    
    }

}

function Restore-HPOVCustomBaseline
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (
    
        [Parameter (Mandatory = $False)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_TaskCollection     = New-Object System.Collections.ArrayList
        $_BaselineCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count))"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting all baseline resources"

            Try
            {

                $_baselineresources = Send-HPOVRequest $fwUploadUri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
            foreach ($_baseline in ($_baselineresources.members | ? bundleType -eq 'Custom' -and state -eq 'Removed'))
            {

                $_CustomBaselineRestore = NewObject -CustomBaselineRestore

                $_CustomBaselineRestore.baselineUri        = $_baseline.uri    
                $_CustomBaselineRestore.customBaselineName = $_baseline.name

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper()) Looking up Associations for '$($_baseline.name) [$($_baseline.uuid)]' custom baseline."

                Try
                {

                    $_baselineassociations = Send-HPOVRequest "/rest/index/associations/?parentUri=$($_baseline.uri)" -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                foreach ($_association in $_baselineassociations.members)
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper()) Adding '$($_association.childUri)' to object collection."

                    [void]$_CustomBaselineRestore.hotfixUris.Add($_association.childUri)

                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper()) Sending request to recreate '$_CustomBaselineRestore.customBaselineName' custom baseline."

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper()) Custom Baseline object: $($_CustomBaselineRestore | FL * | Out-String)"

                Try
                {

                    $_resp = Send-HPOVRequest $fwUploadUri $_CustomBaselineRestore -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                [void]$_TaskCollection.Add($_resp)
                
            }                

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] done."

        Return $_TaskCollection

    }


}

function Remove-HPOVBaseline
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ("b",'Baseline')]
        [Object]$InputObject,
    
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection     = New-Object System.Collections.ArrayList
        $_BaselineCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomObject]) 
        { 

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Directory Object provided: $($InputObject | FL * | Out-String)"

            If ($InputObject.category -eq 'firmware-drivers')
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "Baseline:$($InputObject.Name)" -TargetType PSObject -Message "The Baseline resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_BaselineCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "Baseline:$($Baseline.Name)" -TargetType PSObject -Message "The Baseline resource is not an expected category type [$($Baseline.category)]. Allowed resource category type is 'firmware-drivers'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
        
        }

        else 
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_Connection.Name) (of $($ApplianceConnection.Count))"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Baseline Name $($InputObject)"

                if ($InputObject -is [String])
                {

                    Try
                    {

                        $BaselineName = $InputObject.Clone()
                        $InputObject = Get-HPOVBaseline  -File $_HotFix -ApplianceConnection $_Connection -ErrorAction SilentlyContinue

                        If (-not $_HotFix)
                        {

                            $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $BaselineName
                            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Baseline' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)                    

                    }

                }
                
                $InputObject | % {

                    [void]$_BaselineCollection.Add($_)

                }

            }

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_BaselineCollection.count) Baseline resources to remove."

        #Process Directory Resources
        ForEach ($_Baseline in $_BaselineCollection)
        {

            if ($PSCmdlet.ShouldProcess($_Baseline.ApplianceConnection.Name,"remove baseline '$($_Baseline.name)'")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Baseline '$($_Baseline.name)' from appliance '$($_Baseline.ApplianceConnection.Name)'."

                Try
                {
                    
                    $_resp = Send-HPOVRequest $_Baseline.Uri DELETE -Hostname $_Baseline.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Get-HPOVBaselineRepository
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $False)]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $False)]
        [ValidateSet ('Internal', 'External')]
        [String]$Type,
    
        [Parameter (Mandatory = $False)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing Appliance {1} (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose 

            "[{0}] Getting baseline repo information resources" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

            $_Uri = '{0}?sort=name:asc' -f $ApplianceRepositoriesUri

            if ($Name)
            {

                $_Uri += "&filter=name EQ '{0}'" -f $Name

            }

            if ($Type)
            {

                $_Uri += "&filter=repositoryType EQ '{0}'" -f $RepositoryType[$Type]

            }

            Try
            {

                $_BaselineRepos = Send-HPOVRequest -Uri $_Uri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($Name -and $_BaselineRepos.Count -eq 0)
            {

                $ExceptionMessage = "The specified '{0}' baseline repository resource was not found on '{1}' appliance connection. Please check the name and try again." -f $Name, $Connection.Name 
                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineRepositoryResourceException BaselineRepositoryResourceNotFound ObjectNotFound "Name" -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                ForEach ($_RepoEntry in $_BaselineRepos.members)
                {

                    $_RepoEntry.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.BaselineRepository')

                    $_RepoEntry

                }

            }

        }
        
    }

    End
    {

        "[{0}] done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function New-HPOVExternalRepository
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ParameterSetName = 'PSCredentials')]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ParameterSetName = 'PSCredentials')]
        [String]$Hostname,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ParameterSetName = 'PSCredentials')]
        [String]$Directory,

        [Parameter (Mandatory, ParameterSetName = 'PSCredentials')]
        [PSCredential]$Credential,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [String]$Username,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [SecureString]$Password,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'PSCredentials')]
        [switch]$Http,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'PSCredentials')]
        [String]$Certificate,

        [Parameter (Mandatory = $false,ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false,ParameterSetName = 'PSCredentials')]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'PSCredentials')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
        
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
        
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {

        if (-not $PSBoundParameters['Password'] -and $PSBoundParameters['Username'] -and $PSCmdlet.ParameterSetName -eq 'Default')
        {

            [SecureString]$Password = read-host -AsSecureString "Password"
            $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))
            
        }

        elseif ($Password -is [SecureString] -and $PSCmdlet.ParameterSetName -eq 'Default')
        {

            $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

        elseif ($PSCmdlet.ParameterSetName -eq 'Default')
        {

            $_DecryptPassword = "$Password"

        }

        elseif ($PSBoundParameters['Credential'])
        {

            $Username        = $Credential.UserName
            $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential.Password))

        }
        
        $_ExternalRepository = NewObject -ExternalRepository

        $_Protocol = 'https'

        if ($PSBoundParameters['Http'])
        {

            "[{0}] Setting protocol to HTTP." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_Protocol = 'http'

        }

        $_ExternalRepository.repositoryName = $Name
        $_ExternalRepository.userName       = $Username
        $_ExternalRepository.password       = $_DecryptPassword
        $_ExternalRepository.repositoryURI  = '{0}://{1}/{2}' -f $_Protocol, $Hostname, $Directory
        $_ExternalRepository.base64Data     = $Certificate
        
        #Post the new object to the appliancenvocationName.ToString().ToUpper())] Processing Appliance $($_Connection.Name)"
        Try
        {

            $_Resp = Send-HPOVRequest -Uri $ApplianceRepositoriesUri -Method POST $_ExternalRepository -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not($PSBoundParameters['Async']))
        {

            $_Resp | Wait-HPOVTaskComplete

        }

        else
        {

            $_Resp

        }

    }
    
    End 
    {
    
        "[{0}] Done." -f $MyInvocation.InvocationName.ToString() | Write-Verbose
    
    }

}

function Set-HPOVExternalRepository
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdLetBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "Default", ValueFromPipeline)]
        [Parameter (Mandatory, ParameterSetName = "PSCredentials", ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'PSCredentials')]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'PSCredentials')]
        [PSCredential]$Credential,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [String]$Username,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [SecureString]$Password,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'PSCredentials')]
        [String]$Certificate,

        [Parameter (Mandatory = $false,ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false,ParameterSetName = 'PSCredentials')]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "default", ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }
            
        }        

    }

    Process
    {

        if ($InputObject.category -ne 'repository-manager')
        {

            $ExceptionMessage = "The specified '{0}' InputObject parameter value is not supported." -f $InputObject.name
            $ErrorRecord = New-ErrorRecord HPOneView.InputObjectResourceException InvalidInputObjectResource InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($InputObject.repositoryType -eq 'FirmwareInternalRepo')
        {

            $ExceptionMessage = "The specified '{0}' InputObject parameter value is an Internal Basline Repository. Only External repositories can be removed." -f $InputObject.name
            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineRepositoryResourceException InvalidInputObjectResource InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_UpdatedInputObject = NewObject -ExternalRepository | Select * -ExcludeProperty repositoryType, repositoryURI
        $_UpdatedInputObject.repositoryName = $InputObject.name

        #Commented out until PATCH fully works
        #$_UpdatedInputObject = NewObject -PatchOperation
        #$_UpdatedInputObject.op = 'replace'
        #$_UpdatedInputObject.path = '/repository'

        #$_UpdatedValues = [PSCustomObject]@{}

        [Uri]$_RepositoryUrlObject       = $InputObject.repositoryUrl.Clone()
        [String]$_RespositoryUrlToUpdate = $InputObject.repositoryUrl.Clone()

        switch ($PSBoundParameters.Keys)
        {

            'Name'
            {

                "[{0}] Updating repository name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose
                #$_UpdatedValues | Add-Member -NotePropertyName respositoryName -NotePropertyValue $Name
                $_UpdatedInputObject.repositoryName = $Name

            }

            'Certificate'
            {

                "[{0}] Updating repository HTTPS certificate." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                #$_UpdatedValues | Add-Member -NotePropertyName base64Data -NotePropertyValue $Certificate
                $_UpdatedInputObject.base64Data = $Certificate

            }

            'Credential'
            {

                "[{0}] Updating repository credentials with PSCredential object." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $Username        = $Credential.UserName
                $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential.Password))

                #$_UpdatedValues | Add-Member -NotePropertyName userName -NotePropertyValue $Username
                #$_UpdatedValues | Add-Member -NotePropertyName password -NotePropertyValue $_DecryptPassword
                $_UpdatedInputObject.userName = $Username
                $_UpdatedInputObject.password = $_DecryptPassword

            }

            'Username'
            {

                "[{0}] Updating repository username." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                #$_UpdatedValues | Add-Member -NotePropertyName userName -NotePropertyValue $userName
                $_UpdatedInputObject.userName = $Username

            }

            'Password'
            {

                "[{0}] Updating repository password." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

                #$_UpdatedValues | Add-Member -NotePropertyName password -NotePropertyValue $_DecryptPassword

                $_UpdatedInputObject.password = $_DecryptPassword

            }

        }

        #$_UpdatedInputObject.value = $_UpdatedValues
    
        if ($PSCmdlet.ShouldProcess($InputObject.Name, ("Modify repository from appliance {0}" -f $InputObject.ApplianceConnection.Name)))
        {   
            
            Try
            {

                #$_Resp = Send-HPOVRequest -Uri $InputObject.uri -Method PATCH -Body $_UpdatedInputObject -AddHeader @{'If-Match' = $InputObject.eTag} -Hostname $InputObject.ApplianceConnection
                $_Resp = Send-HPOVRequest -Uri $InputObject.uri -Method PUT -Body $_UpdatedInputObject -AddHeader @{'If-Match' = $InputObject.eTag} -Hostname $InputObject.ApplianceConnection

                if (-not $PSBoundParameters['Async'])
                {

                     $_Resp | Wait-HPOVTaskComplete

                }

                else
                {

                    $_Resp

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        elseif ($PSBoundParameters['WhatIf'])
        {

            "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

        else
        {

            "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Update-HPOVExternalRepository
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdLetBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "Default", ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false,ParameterSetName = 'Default')]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "default", ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }
            
        }        

    }

    Process
    {

        if ($InputObject.category -ne 'repository-manager')
        {

            $ExceptionMessage = "The specified '{0}' InputObject parameter value is not supported." -f $InputObject.name
            $ErrorRecord = New-ErrorRecord HPOneView.InputObjectResourceException InvalidInputObjectResource InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($InputObject.repositoryType -eq 'FirmwareInternalRepo')
        {

            $ExceptionMessage = "The specified '{0}' InputObject parameter value is an Internal Basline Repository. Only External repositories can be removed." -f $InputObject.name
            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineRepositoryResourceException InvalidInputObjectResource InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_RefreshRepositoryOperation       = NewObject -PatchOperation
        $_RefreshRepositoryOperation.op    = 'replace'
        $_RefreshRepositoryOperation.path  = '/refreshState'
        $_RefreshRepositoryOperation.value = 'RefreshPending'

        if ($PSCmdlet.ShouldProcess($InputObject.Name, ("Refresh repository on appliance {0}" -f $InputObject.ApplianceConnection.Name)))
        {   
            
            Try
            {

                $_Resp = Send-HPOVRequest -Uri $InputObject.uri -Method PATCH -Body $_RefreshRepositoryOperation -Hostname $InputObject.ApplianceConnection

                if (-not $PSBoundParameters['Async'])
                {

                     $_Resp | Wait-HPOVTaskComplete

                }

                else
                {

                    $_Resp

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        elseif ($PSBoundParameters['WhatIf'])
        {

            "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

        else
        {

            "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVExternalRepository
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "Default", ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false,ParameterSetName = 'Default')]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "Default", ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }
            
        }        

    }

    Process
    {

        if ($InputObject.category -ne 'repository-manager')
        {

            $ExceptionMessage = "The specified '{0}' InputObject parameter value is not supported." -f $InputObject.name
            $ErrorRecord = New-ErrorRecord HPOneView.InputObjectResourceException InvalidInputObjectResource InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($InputObject.repositoryType -eq 'FirmwareInternalRepo')
        {

            $ExceptionMessage = "The specified '{0}' InputObject parameter value is an Internal Basline Repository. Only External repositories can be removed." -f $InputObject.name
            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineRepositoryResourceException InvalidInputObjectResource InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }
    
        if ($PSCmdlet.ShouldProcess($InputObject.Name, ("Remove repository from appliance {0}" -f $InputObject.ApplianceConnection.Name)))
        {   
            
            Try
            {

                $_resp = Send-HPOVRequest -Uri $InputObject.uri -Method DELETE -Hostname $InputObject.ApplianceConnection

                if (-not $PSBoundParameters['Async'])
                {

                    $_resp | Wait-HPOVTaskComplete

                }

                else
                {

                    $_resp

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        elseif ($PSBoundParameters['WhatIf'])
        {

            "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

        else
        {

            "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function New-HPOVSupportDump 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "values")]
    Param 
    (

        [Parameter (Mandatory = $false,ValueFromPipeline = $false, ParameterSetName = "values")]
        [Parameter (Mandatory = $false,ValueFromPipeline = $false, ParameterSetName = "Object")]
        [Alias ("save")]
        [string]$Location = (get-location).Path,

        [Parameter (Mandatory,ValueFromPipeline = $false, ParameterSetName = "values")]
        [ValidateSet ("Appliance","LI")]
        [string]$Type,

        [Parameter (Mandatory = $false,ValueFromPipeline = $false, ParameterSetName = "values")]
        [switch]$Encrypted,

        [Parameter (Mandatory,ValueFromPipeline, ParameterSetName = "Object")]
        [Alias ('liobject','li','name')]
        [object]$LogicalInterconnect,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "values")]
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "Object")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters["LogicalInterconnect"]) -and $PSCmdlet.ParameterSetName -eq "Object") 
        { 
            
            $PipelineInput = $true 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        #Validate the path exists. If not, create it.
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Validating $($Location) exists"

        if (-not(Test-Path $Location)) 
        { 
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($Location) Directory does not exist. Creating directory..."
            
            New-Item -ItemType directory -path $Location 
        
        }

    }

    Process
    {

        if ($PipelineInput -and $LogicalInterconnect)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Pipeline object: $($LogicalInterconnect.name)"

            #Validate input object is a Logical Interconnect resource
            if ($LogicalInterconnect.category -ne 'logical-interconnects')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectResourceException InvalidLogicalInterconnectResource InvalidArgument 'LogicalInterconnect' -TargetType $LogicalInterconnect.GetType().Name -Message "The LogicalInterconnect Parameter value is invalid. Resource category provided '$($LogicalInterconnect.category)', expected 'logical-interconnects'. Please check the value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
            
            $Request = [PSCustomObject]@{errorCode = $LogicalInterconnect.name}

            $targetURI = $LogicalInterconnect.uri + "/support-dumps"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Recieved information from pipeline"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Request : $($request | out-string) "

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] URI: $($targetURI)"

            #Send the request
            Write-Host "Please wait while the Support Dump is generated. This can take a few minutes..."

            Try
            {

                $resp = Send-HPOVRequest $targetUri POST $Request -Hostname $LogicalInterconnect.ApplianceConnection.Name

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            #Now that the Support Dump has been requested, download the file
            Try
            {

                Download-File $resp.uri $LogicalInterconnect.ApplianceConnection.Name $Location

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        else 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Support Dump Type: $($type)"

            switch ($Type)
            {
                        
                "appliance" 
                {

                    ForEach ($_appliance in $ApplianceConnection)
                    {

                        #Build the request and specify the target URI. Do not change errorCode value.
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Requesting Appliance Support Dump..."

                        $request = [PSCustomObject]@{
                                
                            errorCode = "CI";
                            encrypt   = [bool]$Encrypted.IsPresent
                            
                        }

                        $targetURI = $applSupportDump
                            
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Request : $($request | out-string) "

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] URI: $($targetURI)"

                        #Send the request
                        Write-Host "Please wait while the Support Dump is generated. This can take a few minutes..."

                        Try
                        {

                            $resp = Send-HPOVRequest $targetUri POST $Request -Hostname $_appliance

                        }
                            
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        #Now that the Support Dump has been requested, download the file
                        Try
                        {

                            Download-File $resp.uri $_appliance.Name $Location

                        }
                            
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }                    

                }
                            
                "li" 
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Requesting $LogicalInterconnect Support Dump..."
                            
                    if ($LogicalInterconnect -is [String]) 
                    {

                        Try
                        {

                            $resp = Get-HPOVLogicalInterconnect -InputObject $LogicalInterconnect -Hostname $ApplianceConnection

                        }
                            
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
                    
                        $request = @{errorCode = $resp.name.SubString(0,10)}
                        
                        $targetURI = $resp.uri + "/support-dumps"
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($resp.name) Logical Interconnect"


                    }

                    elseif ($LogicalInterconnect -is [PSCustomObject]) 
                    {
                            
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconnect Object provided."

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($LogicalInterconnect.name) Logical Interconnect"

                        $request = @{errorCode = $LogicalInterconnect.name.SubString(0,10)}

                        $targetUri = $LogicalInterconnect.uri

                    }

                    #Send the request
                    Write-Host "Please wait while the Support Dump is generated. This can take a few minutes..."

                    Try
                    {

                        $resp = Send-HPOVRequest $targetUri POST $Request -Hostname $ApplianceConnection

                    }
                            
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    #Now that the Support Dump has been requested, download the file
                    Try
                    {

                        Download-File $resp.uri $ApplianceConnection.Name $Location

                    }
                            
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            } 
                    
        }

    }

    End 
    {
        
        "Done." | Write-Verbose
            
    }

}

function Get-HPOVAutomaticBackupConfig
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_AutoBackupStatusCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {

                $_AutomaticBackup = Send-HPOVRequest $ApplianceAutoBackupConfUri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_AutomaticBackup.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.AutomaticBackupConfig')

            [void]$_AutoBackupStatusCollection.Add($_AutomaticBackup)


        }
        
    }

    End
    {

        Return $_AutoBackupStatusCollection

    }

}

function Set-HPOVAutomaticBackupConfig
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = 'Default', SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$Hostname,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$Directory,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$Username,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [SecureString]$Password,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$HostSSHKey,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateSet ('SCP','SFTP')]
        [String]$Protocol = 'SCP',

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateSet ('Daily','Weekly')]
        [String]$Interval,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Array]$Days,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateScript ({[RegEx]::IsMatch($_,"([01]?[0-9]|2[0-3]):[0-5][0-9]")})]
        [String]$Time,

        [Parameter (Mandatory, ParameterSetName = 'Disable')]
        [Switch]$Disabled,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Disable')]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Disable')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_AutoBackupStatusCollection = New-Object System.Collections.ArrayList

    }

    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            $_resp = $null

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {

                $_AutomaticBackupStatus = Send-HPOVRequest -Uri $ApplianceAutoBackupConfUri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_AutoBackupConfig = NewObject -AutoBackupConfig

            $_AutoBackupConfig.eTag = $_AutomaticBackupStatus.eTag

            if ($PSBoundParameters['Disabled'])
            {

                $_AutomaticBackupStatus.enabled = $false

            }

            else
            {

                if (-not $HostSSHKey.StartsWith('ssh-rsa'))
                {

                    $_ExceptionMessage = 'The provided HostSSHKey is not a valid OpenSSL RSA key.'
                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AutomatedBackupConfigException InvalidedHostSSHRsaKey InvalidArgument 'HostSSHKey' -Message $_ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $_AutoBackupConfig.remoteServerDir       = $Directory
                $_AutoBackupConfig.remoteServerName      = $Hostname
                $_AutoBackupConfig.remoteServerPublicKey = ($HostSSHKey | Out-String)
                $_AutoBackupConfig.userName              = $Username
                $_AutoBackupConfig.password              = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

                if ($PSBoundParameters['Protocol'])
                {

                    $_AutoBackupConfig.protocol = $Protocol

                }

                else
                {

                    $_AutoBackupConfig.protocol = $_AutomaticBackupStatus.Protocol

                }

                if ($PSBoundParameters['Interval'])
                {

                    $_AutoBackupConfig.scheduleInterval = $Interval.ToUpper()

                }

                else
                {
            
                    $_AutoBackupConfig.scheduleInterval = $_AutomaticBackupStatus.scheduleInterval
            
                }

                if ($PSBoundParameters['Days'] -and $PSBoundParameters['Interval'] -eq 'Weekly')
                {

                    ForEach ($_day in $Days)
                    {

                        [void]$_AutoBackupConfig.scheduleDays.Add($DayOfWeekEnum.$_day.ToUpper())

                    }

                }

                else
                {
            
                    $_AutoBackupConfig.scheduleDays = $_AutomaticBackupStatus.scheduleDays
            
                }

                if ($PSBoundParameters['Time'])
                {

                    $_AutoBackupConfig.scheduleTime = $Time

                }

                else
                {
            
                    $_AutoBackupConfig.scheduleTime = $_AutomaticBackupStatus.scheduleTime
            
                }

            }

            #Prompt the user if they really want to disable Automatic Backups
            if ($PSBoundParameters['Disabled'])
            {

                if ($PSCmdlet.ShouldProcess($_appliance.Name,'disable automatic backup schedule on appliance')) 
                {

                    Try
                    {

                        $_resp = Send-HPOVRequest $ApplianceAutoBackupConfUri PUT $_AutomaticBackupStatus -Hostname $_appliance

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                elseif ($PSBoundParameters['WhatIf'])
                {

                    "[{0}] User provided -WhatIf switch." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                }

                else
                {
                
                    "[{0}] User cancelled or stated 'No'." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    Return

                }

            }

            else
            {

                "[{0}] Sending request" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                Try
                {

                    $_resp = Send-HPOVRequest $ApplianceAutoBackupConfUri PUT $_AutoBackupConfig -Hostname $_appliance

                }
                    
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            if ($PSBoundParameters['Async'])
            {

                $_resp

            }

            else
            {
                
                $_resp | Wait-HPOVTaskComplete

            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVBackup
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [DateTime]$Before,
            
        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [DateTime]$After,
        
        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Validate the path exists. If not, create it.
        if ($PSBoundParameters['Location'] -and -not(Test-Path $Location))
        {
             
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Directory does not exist. Creating directory..."
            
            New-Item $Location -itemtype directory

        }

        $_BackupFileStatusCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {
                
                $_Backups = Send-HPOVRequest -Uri $ApplianceBackupUri -Hostname $_appliance

            }   

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['Before'])
            {

                $_Backups.members | ? { [DateTime]$_.created -le $Before.ToUniversalTime() }

            }

            elseif ($PSBoundParameters['After'])
            {

                $_Backups.members | ? { [DateTime]$_.created -ge $After.ToUniversalTime() }

            }

            else
            {

                $_Backups.members

            }            

        }
        
    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

# // TODO: DEVELOP DOCUMENT TEST
function Save-HPOVBackup
{

    Throw "Not implemented."

}

function New-HPOVBackup 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("save")]
        [string]$Location = (get-location).Path,
        
        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$Force,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$Async,
            
        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Validate the path exists. If not, create it.
        if ($PSBoundParameters['Location'] -and -not(Test-Path $Location))
        {
             
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Directory does not exist. Creating directory..."
            
            New-Item $Location -itemtype directory

        }

        $_BackupFileStatusCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            #Check to see if Automatic Backup is set on the appliance.
            Try
            {

                $_AutomaticBackup = Send-HPOVRequest -Uri $ApplianceAutoBackupConfUri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Please wait while the appliance backup is generated. This can take a few minutes..."

            Try
            {
                
                $_taskStatus = Send-HPOVRequest -Uri $ApplianceBackupUri -Method POST -Hostname $_appliance | Wait-HPOVTaskComplete -timeout (New-Timespan -minutes 45)

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response: $($_taskStatus | out-string)"

                $_backupObject = Send-HPOVRequest -Uri $_taskStatus.associatedResource.resourceUri -Hostname $_appliance
                
            }   

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            #If no automatic backup is configured, then download
            if (-not($_AutomaticBackup.enabled) -or $PSBoundParameters['Force'])
            {

                "[{0}] Backup File URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_backupObject.downloadUri | Write-Verbose

                "[{0}] Downloading to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Location | Write-Verbose

                Try
                {

                    $_resp = Download-File $_backupObject.downloadUri $_appliance $Location

                    [void]$_BackupFileStatusCollection.Add($_resp)

                }
            
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                "[{0}] Created backup will be saved to remote location: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_AutomaticBackup.remoteServerName | Write-Verbose

                Try
                {

                    $_resp = Send-HPOVRequest $_backupObject.saveUri PUT -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if (-not($PSboundParameters['Async']))
                {

                    "[{0}] Monitoring remote save operation." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    Try
                    {

                        $_resp = Wait-HPOVTaskComplete $_resp

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                [void]$_BackupFileStatusCollection.Add($_resp)

            }

        }
        
    }

    End
    {

        Return $_BackupFileStatusCollection

    }

}

function New-HPOVRestore 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("File")]
        [string]$FileName,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose
            
            #Validate the path exists. If not, create it.
            if (-not(Test-Path $FileName))
            {
                 
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Backup file specified does not exist."
                
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.RestoreException BackupFileNotFound ObjectNotFound 'FileName' -Message "'$FileName' was not found. Please check the directory and/or name and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if ($PSCmdlet.ShouldProcess($_appliance.Name,'restore backup to appliance')) 
            {    
            
                #Send the request
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Please wait while the appliance backup is uploaded. This can take a few minutes..."

                Try
                {

                    $resp = Upload-File $ApplianceRestoreRepoUri $FileName -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
                if ($resp.id)
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to restore appliance"

                    $_restoreObject = [PSCustomObject]@{

                        type                 = "RESTORE"
                        uriOfBackupToRestore = $resp.uri

                    }

                    Try
                    {
                    
                        $_restoreStatus = Send-HPOVRequest $ApplianceRestoreUri POST $_restoreObject -Hostname $_appliance
                    
                        Write-warning "Appliance restore in progress. All users are now logged off."
                    
                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    $sw = [System.Diagnostics.Stopwatch]::StartNew()

                    While ($_restoreStatus.status -eq "IN_PROGRESS") 
                    {

                        $_statusMessage = "{0} {1}% [{2}min {3}sec]" -f $script:progressStepEnum[$_restoreStatus.progressStep],$_restoreStatus.percentComplete, $sw.Elapsed.Minutes, $sw.Elapsed.Seconds

                        #Handle the call from -Verbose so Write-Progress does not get borked on display.
                        if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                        { 

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - $_statusMessage"

                        }

                        else 
                        { 

                            Write-Progress -id 1 -activity "Restoring Appliance Backup $($_restoreStatus.id)" -status $_statusMessage -percentComplete $_restoreStatus.percentComplete
                        
                        }


                        Try
                        {
                    
                            $_restoreStatus = Send-HPOVRequest $_restoreStatus.uri -Hostname $_appliance
                                    
                        }
                    
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    } #Until ($restoreStatus.percentComplete -eq 100 -or $restoreStatus -ne "IN_PROGRESS")

                    $sw.Stop()

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Operation took $($sw.elapsed.minutes)min $($sw.elapsed.seconds)sec"

                    Write-Progress -id 1 -activity "Restoring Appliance Backup $($_restoreStatus.id)" -status $_statusMessage -Completed

                    Write-warning "Appliance restore in has completed for $($_appliance.Name). Address Pool ranges will need to be re-enabled, and verify the managed or monitored resources do not need a refresh."

                }

                [void]$_ApplianceStatus.Add($_restoreStatus)

            }

        }
    
    }

    End 
    {

        Return $_ApplianceStatus
    
    }

}

function Download-File 
{

    <#
        .DESCRIPTION
        Helper function to download files from appliance.
                     
        .Parameter uri
        The location where the Support Dump or backup will be downloaded from
             
        .Parameter SaveLocation
        The full path to where the Support Dump or backup will be saved to. This path will not be validated in this helper function
 
        .Parameter ApplianceConnection
        The Appliance Connection Object, Name or ConnectionID
 
        .INPUTS
        None. You cannot pipe objects to this cmdlet.
                     
        .OUTPUTS
        Downloads the requested file using net.WebRequest
 
        .EXAMPLE
        PS C:\> Download-File /rest/appliance/support-dumps/ci5401AB76-CI-2013_09_04-04_52_00.014786.sdmp -ApplianceConnection MyAppliance.domain.com c:\temp
             
    #>


    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$uri,
        
        [Parameter (Mandatory)]
        [ValidateNotNullorEmpty()]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory)]
        [Alias ("save")]
        [ValidateNotNullOrEmpty()]
        [string]$SaveLocation

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection -is [HPOneView.Appliance.Connection]) -and (-not($ApplianceConnection -is [System.String])))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException InvalidApplianceConnectionDataType InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter is not type [HPOneView.Appliance.Connection] or [System.String]. Please correct this value and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif  ($ApplianceConnection.Count -gt 1)
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value. Please correct this and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        else
        {

            Try 
            {
    
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -TargetType $ApplianceConnection.GetType().Name -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {

        $_downloadfilestatus = NewObject -DownloadFileStatus
    
        $fsCreate = [System.IO.FileAccess]::Create
        $fsWrite = [System.IO.FileAccess]::Write

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Download URI: $uri"
        [System.Net.ServicePointManager]::UseNagleAlgorithm = $false
        [System.Net.httpWebRequest]$_fileDownload           = RestClient GET $uri $ApplianceConnection.Name
        $_fileDownload.Headers.Item('Accept-Encoding')      = 'gzip, deflate'
        $_fileDownload.accept                               = "application/zip,application/octet-stream,*/*"
        $_fileDownload.Headers.Item("auth")                 = $ApplianceConnection.SessionID

        $i = 0

        ForEach ($_h in $_fileDownload.Headers) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Request Header $($i): $($_h) = $($_fileDownload.Headers[$i])"
            
            $i++
        
        }
            
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Request: GET $($_fileDownload | out-string)"
        
        Try
        {

            #Get response
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting response"
            [Net.httpWebResponse]$_rs = $_fileDownload.GetResponse()

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        Finally
        {

            if ($rs)
            {

                $_rs.Close()

            }

        }        

        #Display the response status if verbose output is requested
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response Status: $([int]$_rs.StatusCode) $($_rs.StatusDescription)"

        $i = 0

        ForEach ($_h in $_rs.Headers) 
        { 
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response Header $($i): $($_h) = $($_rs.Headers[$i])"
            
            $i++ 
        
        }

        #Request is a redirect to download file contained in the response headers
        if (($_rs.headers["Content-Disposition"]) -and ($_rs.headers["Content-Disposition"].StartsWith("attachment; filename="))) 
        {
        
            $_fileName = ($_rs.headers["Content-Disposition"].SubString(21)) -replace "`"",""
        
        }
                        
        #Detect if the download is a Support Dump or Appliance Backup
        elseif ($uri.Contains("/rest/backups/archive"))
        {

            #Need to get the Appliance file name
            $_fileName = $uri.split("/")
            
            $_fileName = $_fileName[-1] + ".bkp"
        
        }

        else 
        {
            #Need to get the Support Dump file name
            $_fileName = $uri.split("/")

            $_fileName = $ApplianceConnection.Name + "_" + $_fileName[-1]

        }

        if ($_rs.headers['Content-Length']) 
        { 
            
            [int64]$_fileSize = $_rs.headers['Content-Length'] 
            write-Verbose ('*****Filesize from Header: {0}' -f $_fileSize)
        
        }

        elseif ($_rs.ContentLength) 
        { 
            
            [int64]$_fileSize = $_rs.ContentLength 
            write-Verbose ('*****Filesize from ContentLength: {0}' -f $_fileSize)
        
        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filename: $($_fileName)"
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filesize: $($_fileSize)"
        
        if($_rs.StatusCode -eq 200) 
        {

            Try
            {

                #Read from response and write to file
                $_stream = $_rs.GetResponseStream() 
                
                #Define buffer and buffer size
                write-Verbose ('Creating Buffer of size: {0}MB' -f ((1024 * 8192) / 1MB))
                [byte[]]$_buffer   = New-Object byte[] (1024 * 8192)
                [int] $_bytesRead  = 0

                write-Verbose ('Buffer size: {0}' -f $_buffer.length)

                #This is used to keep track of the file upload progress.
                $_numBytesRead     = 0
                $_numBytesWrote    = 0
     
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Saving to $($saveLocation)\$($_fileName)"

                $_fs = New-Object IO.FileStream ($saveLocation + "\" + $_fileName),'Create' #,'Write','Read'

                #Throughput Stopwatch
                $_sw = New-Object System.Diagnostics.StopWatch
                $_progresssw = New-Object System.Diagnostics.StopWatch
                $_sw.Start()
                $_progresssw.Start()

                while (($_bytesRead = $_stream.Read($_buffer, 0, $_buffer.Length)) -gt 0)
                {

                    #Write from buffer to file
                    $_fs.Write($_buffer, 0, $_bytesRead)
                
                    #Keep track of bytes written for progress meter
                    $_total += $_bytesRead

                    #Elapsed time to calculate throughput
                    $_transferrate = ($_total / $_sw.Elapsed.TotalSeconds) / 1MB

                    #Use the Write-Progress cmd-let to show the progress of uploading the file.
                    [int]$_percent = (($_total / $_fileSize)  * 100)

                    $_status = '{0:0}MB of {1:0}MB @ {2:N2}MB/s' -f ($_total / 1MB), ($_fileSize / 1MB), $_transferrate

                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    { 
                
                        if ($_progresssw.Elapsed.TotalMilliseconds -ge 500)
                        {
                            
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Skipping Write-Progress display."
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Downloading file: $_fileName, status: $_status, Percent: $_percent"

                            $_progresssw.Restart()

                        }
                    
                    }
                  
                    else 
                    { 
                    
                        if ($_progresssw.Elapsed.TotalMilliseconds -ge 500)
                        {

                            Write-Progress -id 0 -Activity "Downloading file $_fileName" -Status $_status -percentComplete $_percent 

                            $_progresssw.Restart()

                        }                        
                
                    }

                } #while ($_bytesRead -gt 0)

                Write-Progress -id 0 -Activity "Downloading file $_fileName" -Completed

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] File saved to $($saveLocation)"

                $_downloadfilestatus.status              = 'Completed'
                $_downloadfilestatus.file                = "$saveLocation\$_fileName"
                $_downloadfilestatus.ApplianceConnection = $ApplianceConnection.Name

                Return $_downloadfilestatus

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            finally
            {

                #Clean up our work
                if ($_stream) { $_stream.Close() }
                if ($_rs) { $_rs.Close() }
                if ($_fs) { $_fs.Close() }

            }

        }

        else
        {

            #Clean up
            if ($_rs) { $_rs.Close() }
            if ($_fs) { $_fs.Close() }

            Throw 'Unhandled download exception'

        }    
        
    }

}

function Upload-File 
{

    <#
 
        .SYNOPSIS
        Upload a file to the appliance.
 
        .DESCRIPTION
        This cmdlet will upload a file to the appliance that can accepts file uploads (SPP firmware bundle, Appliance Restore, and Appliance Updates.)
 
        .Parameter URI
        Location where to upload file to.
 
        .Parameter File
        Full path to the file to be uploaded.
         
        .Parameter ApplianceConnection
        Appliance Connection
 
        .INPUTS
        None. You cannot pipe objects to this cmdlet.
 
        .OUTPUTS
        Write-Progress
        The progress of uploading the file to the appliance.
 
        .LINK
        Add-HPOVBaseline
 
        .LINK
        New-HPOVRestore
 
        .EXAMPLE
        PS C:\> Upload-File "/rest/firmware-bundles" "C:\Users\me\Documents\SPP2012060B.2012_0525.1.iso"
 
        Upload a new SPP into the appliance.
 
        .EXAMPLE
        PS C:\> Upload-File "/rest/restores" "C:\Users\me\Documents\appliance.bak"
 
        Upload a backup file to restore in the appliance.
 
    #>


    [CmdletBinding ()]

    Param 
    (

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [Alias ('u')]
        [string]$uri,

        [Parameter (Mandatory)]
        [Alias ('f')]
        [ValidateScript({Test-Path $_})]
        [string]$File,
        
        [Parameter (Mandatory = $false)]
        [Alias ('Hostname')]
        [ValidateNotNullorEmpty()]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection -is [HPOneView.Appliance.Connection]) -and (-not($ApplianceConnection -is [System.String])))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException InvalidApplianceConnectionDataType InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter is not type [HPOneView.Appliance.Connection] or [System.String]. Please correct this value and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif  ($ApplianceConnection.Count -gt 1)
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value. Please correct this and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        else
        {

            Try 
            {
    
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -TargetType $ApplianceConnection.GetType().Name -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
    }
    
    Process 
    {

        $_fileObj = Get-Item -path $File
        
        $fs = New-Object IO.FileStream ($File, $FSOpenMode, $FSRead)

        [string]$filename = $_fileObj.name

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Uploading $($filename) file to appliance, this may take a few minutes..."

        try 
        {

            $uri = "{0}?uploadfilename={1}" -f $uri, $filename

            [System.Net.httpWebRequest]$uploadRequest = RestClient POST $uri -Appliance $ApplianceConnection.Name

            $boundary                                     = "---------------------------" + [DateTime]::Now.Ticks.ToString("x")
            [byte[]]$BoundaryBytes                        = [System.Text.Encoding]::UTF8.GetBytes("`r`n--" + $boundary + "`r`n");
            $disposition                                  = "Content-Disposition: form-data; name=`"file`"; filename=`"{0}`";`r`nContent-Type: application/octet-stream`r`n`r`n" -f $_fileObj.Name
            [byte[]]$ContentDispBytes                     = [System.Text.Encoding]::UTF8.GetBytes($disposition);
            [byte[]]$EndBoundaryBytes                     = [System.Text.Encoding]::UTF8.GetBytes("`r`n--" + $boundary + "--`r`n")

            $uploadRequest.Timeout                        = 1200000
            $uploadRequest.ContentType                    = "multipart/form-data; boundary={0}" -f $boundary
            $uploadRequest.Headers.Item("auth")           = $ApplianceConnection.SessionID
            $uploadRequest.Headers.Item("uploadfilename") = $filename
            $uploadRequest.AllowWriteStreamBuffering      = $false
            $uploadRequest.SendChunked                    = $false
            $uploadRequest.ContentLength                  = $BoundaryBytes.length + $ContentDispBytes.length + $_fileObj.Length + $EndBoundaryBytes.Length
            $uploadRequest.Headers.Item("ContentLength")  = $BoundaryBytes.length + $ContentDispBytes.length + $_fileObj.Length + $EndBoundaryBytes.Length

            "[{0}] Request: POST {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $uri | Write-Verbose

            $i = 0

            foreach ($h in $uploadRequest.Headers) 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Request Header {$i} $($h) : $($uploadRequest.Headers[$i])"
                
                $i++
            
            }

            $rs = $uploadRequest.GetRequestStream()

            [byte[]]$readbuffer = New-Object byte[] (4096*1024)        
            $rs.write($BoundaryBytes,0,$BoundaryBytes.Length);
            $rs.write($ContentDispBytes,0,$ContentDispBytes.Length);

            #This is used to keep track of the file upload progress.
            $numBytesToRead = $fs.Length    
            [int64]$numBytesRead = 0

            if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
            { 
            
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Skipping Write-Progress display." 
            
            }

            $_sw = [System.Diagnostics.Stopwatch]::StartNew()
            $_progresssw = [System.Diagnostics.Stopwatch]::StartNew()

            while ($byteCount = $fs.Read($readbuffer,0,$readbuffer.length))
            {                

                $rs.write($readbuffer,0,$byteCount)
                $rs.flush()
            
                #Keep track of where we are at clearduring the read operation
                $_numBytesRead += $bytecount

                #Use the Write-Progress cmd-let to show the progress of uploading the file.
                [int]$_percent = [math]::floor(($_numBytesRead / $fs.Length) * 100)

                #Elapsed time to calculat throughput
                [int]$_elapsed = $_sw.ElapsedMilliseconds / 1000
                
                if ($_elapsed -ne 0 ) 
                {

                    [single]$_transferrate = [Math]::Round(($_numBytesRead/$_elapsed) / 1mb)
                
                } 
                
                else 
                {

                    [single]$_transferrate = 0.0
                
                }

                $status = "({0:0}MB of {1:0}MB transferred @ {2}MB/s) Completed {3}%" -f ($_numBytesRead / 1MB), ($numBytesToRead / 1MB), $_transferrate, $_percent

                #Handle the call from -Verbose so Write-Progress does not get borked on display.
                if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Uploading file $fileName, status: $status"
                    
                }
                  
                else 
                { 

                    if ($_progresssw.Elapsed.TotalMilliseconds -ge 500)
                    {

                        if ($_numBytesRead % 1mb -eq 0) { Write-Progress -activity "Upload File" -status "Uploading $Filename" -CurrentOperation $status -PercentComplete $_percent }

                    }

                }

            } #while ($bytecount -gt 0)

            "[{0}] Finalizing upload." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $fs.close()

            $rs.write($EndBoundaryBytes,0,$EndBoundaryBytes.Length)

            $rs.close()

            $_sw.stop()
            $_sw.Reset()

            Write-Progress -activity "Upload File" -status "Uploading $Filename" -Complete

        }

        catch [System.Exception] 
        {

            #dispose if still exist
            if ($rs) { $rs.close() }
            if ($fs) { $fs.close() }

            if ($_sw.IsRunning) 
            { 
                
                $_sw.Stop() 
                $_sw.Reset()
            
            }

            $PSCmdlet.ThrowTerminatingError($_)

        }

        try 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Upload Request completed."
        
            if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
            {

                 Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Waiting for completion response from appliance."

            }

            else 
            { 

                Write-Progress -activity "Upload File" -status "Uploading $Filename" -CurrentOperation "Waiting for completion response from appliance." -percentComplete $_percent 
            
            }

            [Net.httpWebResponse]$WebResponse = $uploadRequest.getResponse()
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response Status: ($([int]$WebResponse.StatusCode)) $($WebResponse.StatusDescription)"
            
            $uploadResponseStream = $WebResponse.GetResponseStream()

            #Read the response & convert to JSON
            $reader       = New-Object System.IO.StreamReader($uploadResponseStream)
            $responseJson = $reader.ReadToEnd()

            $uploadResponse = ConvertFrom-Json $responseJson

            $uploadResponseStream.Close()

            #need to parse the output to know when the upload is truly complete
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response: $($uploadResponse | out-string)"

            $uploadRequest = $Null
            
            #dispose if still exist
            if ($rs) { $rs.close() }
            if ($fs) { $fs.close() }
            Write-Progress -activity "Upload File" -CurrentOperation "Uploading $Filename " -Completed

        }

        catch [Net.WebException] 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] WebException caught. Getting exception response from API."
 
            Try
            {

                $sr = New-Object IO.StreamReader ($_.Exception.Response.GetResponseStream())

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
            $errorObject = $sr.readtoEnd() | ConvertFrom-Json
            
            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Error Response from API: {0}" -f ($errorObject | Out-String) | Write-Verbose

            #dispose if still exist
            if ($rs) { $rs.close() }
            if ($fs) { $fs.close() }

            #$errorResponse.close()
            $sr.close()

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.UploadFileException $errorObject.ErrorCode InvalidResult 'Upload-File' -Message $errorObject.Message -InnerException $_.Exception

            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            #Write-Error "$([int]$errorObject.ErrorCode)) $($errorObject.message)" -ErrorAction Stop
            
        }

    }

    End 
    {

        #Handle file uploads that generate task resource (i.e. Upload SPP Baseline)
        if ($uploadResponse.category -eq "tasks") 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response is a task resource"            

            $uploadResponse | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.TaskResource") }

        }

        Add-Member -InputObject $uploadResponse -NotePropertyName ApplianceConnection -NotePropertyValue (New-Object HPOneView.Library.ApplianceConnection($ApplianceConnection.Name, $ApplianceConnection.ConnectionId)) -Force 

        Return $uploadResponse

    }

}

function Get-HPOVScmbCertificates 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'default')]
    Param
    (

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "convert")]
        [ValidateNotNullOrEmpty()]
        [Alias ("save")]
        [string]$Location = ($pwd).path,

        [Parameter (Mandatory = $false, ParameterSetName = "convert")]
        [ValidateNotNullOrEmpty()]
        [Alias ("pfx")]
        [switch]$ConvertToPFx,
        
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "convert")]
        [ValidateNotNullOrEmpty()]
        [SecureString]$Password,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "convert")]
        [switch]$InstallApplianceRootCA,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "convert")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
        $TaskCollection = New-Object System.Collections.ArrayList
        
        #Validate the path exists. If not, create it.
        if (-not(Test-Path $Location))
        { 

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Directory does not exist. Creating directory..."

            New-Item -path $Location -ItemType Directory

        }

    }

    Process
    {
        
        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($_appliance.Name)' appliance connection (of $($ApplianceConnection.count))"

            #Appliance CA
            $caFile = '{0}\{1}_ca.cer' -f $Location, $_appliance.Name
        
            #Appliance Public Key
            $publicKeyFile = '{0}\{1}_cert.cer' -f $Location, $_appliance.Name
        
            #Rabbit Client Private Key
            $privateKeyFile = '{0}\{1}_privateKey.key' -f $Location, $_appliance.Name #$Location + "\" + "$($_appliance.Name)_privateKey.key"

            #Check to see if the Rabbit client cert was already created
            Try
            {

                $_keys = Send-HPOVRequest -Uri $RabbitMQKeyPairUri -Hostname $_appliance.Name

            }

            Catch [HPOneView.ResourceNotFoundException]
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] RabbitMQ SSL cert key pair does not exist."

                Try
                {

                    $_rabbitbody = NewObject -RabbitmqCertReq

                    #Generate the client private key request
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Body: $($_rabbitbody | out-string)"

                    Send-HPOVRequest -Uri $applRabbitmqUri -Method POST -Body $_rabbitbody -Hostname $_appliance.Name | Wait-HPOVTaskComplete | Out-Null

                    #Retrieve generated keys
                    $_keys = Send-HPOVRequest -Uri $RabbitMQKeyPairUri -Hostname $_appliance.Name

                }

                Catch
                {
            
                    $PSCmdlet.ThrowTerminatingError($_)
            
                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
        
            try 
            {

                New-Item $PrivateKeyFile -type file -force -value $_keys.base64SSLKeyData | write-verbose

                $PrivateKeyFile = [System.IO.FileInfo]$PrivateKeyFile

                "[{0}] Created rabbitmq_readonly user Private Key: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PrivateKeyFile.Name | Write-Verbose 

            }

            catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)
        
            }

            try 
            {

                New-Item $PublicKeyFile -type file -force -value $_keys.base64SSLCertData | Write-Verbose

                $PublicKeyFile = [System.IO.FileInfo]$PublicKeyFile

                "[{0}] Created rabbitmq_readonly user Public Key: {0}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PublicKeyFile.FullName | Write-Verbose 

            }

            catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            If ($PSBoundParameters['ConvertToPFx'])
            {
            
                Try
                {

                    ConvertTo-Pfx -PrivateKeyFile $PrivateKeyFile -PublicKeyFile $PublicKeyFile -Password $Password

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                
            
            }

            try 
            {

                $_ca = Send-HPOVRequest $applCaURI -Hostname $_appliance.Name

                New-Item $caFile -type file -force -value $_ca | Write-Verbose

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Created $($caFile)"
        
            }

            catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['InstallApplianceRootCA'])
            {

                #Get certificate
                [Security.Cryptography.X509Certificates.X509Certificate2]$Cert = [System.Convert]::FromBase64String($_ca.Replace('-----BEGIN CERTIFICATE-----',$null).Replace('-----End CERTIFICATE-----',$null)) 

                $StoreScope = "CurrentUser"
                $StoreName  = "Root" 

                #Save to users Trusted Root Authentication Hosts store
                $store = New-Object System.Security.Cryptography.X509Certificates.X509Store $StoreName, $StoreScope

                $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)

                try 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Attempting to add cert to store"

                    $store.Add($cert)
                    $store.Close()

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Cert added successfully"

                }

                catch 
                {

                    $store.Close()

                    $PSCmdlet.ThrowTerminatingError($_.Exception)

                }

            }

        }

    }

}

function ConvertTo-Pfx
{

    # Modified from Script provided by Vadims Padans (https://www.sysadmins.lv/blog-en/how-to-convert-pem-to-x509certificate2-in-powershell-revisited.aspx)

    [CmdletBinding ()]
    Param
    ( 

        [Parameter (Mandatory)]
        [System.IO.FileSystemInfo]$PrivateKeyFile,

        [Parameter (Mandatory)]
        [System.IO.FileSystemInfo]$PublicKeyFile,
    
        [Parameter (Mandatory)]
        [SecureString]$Password
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

    }

    Process
    {

        function __normalizeAsnInteger ($array) 
        {

            $padding = $array.Length % 8

            if ($padding) 
            {

                $array = $array[$padding..($array.Length - 1)]
                
            }

            [array]::Reverse($array)

            [Byte[]]$array

        }

        function __extractCert([string]$Text) 
        {

            $keyFlags = [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable

            $Text -match "(?msx).*-{5}BEGIN\sCERTIFICATE-{5}(.+)-{5}End\sCERTIFICATE-{5}" | Out-Null

            $RawData = [Convert]::FromBase64String($matches[1])

            try 
            {

                New-Object Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $RawData, "", $keyFlags

            }
            
            catch 
            {
                
                throw "The data is not valid security certificate."
            
            }

            Write-Debug "X.509 certificate is correct."

        }

        # returns [byte[]]
        function __composePRIVATEKEYBLOB($modulus, $PublicExponent, $PrivateExponent, $Prime1, $Prime2, $Exponent1, $Exponent2, $Coefficient) {

            Write-Debug "Calculating key length."

            $bitLen = "{0:X4}" -f $($modulus.Length * 8)

            Write-Debug "Key length is $($modulus.Length * 8) bits."

            [byte[]]$bitLen1 = Invoke-Expression 0x$([int]$bitLen.Substring(0,2))
            [byte[]]$bitLen2 = Invoke-Expression 0x$([int]$bitLen.Substring(2,2))
            [Byte[]]$PrivateKey = 0x07,0x02,0x00,0x00,0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x32,0x00
            [Byte[]]$PrivateKey = $PrivateKey + $bitLen1 + $bitLen2 + $PublicExponent + ,0x00 + $modulus + $Prime1 + $Prime2 + $Exponent1 + $Exponent2 + $Coefficient + $PrivateExponent

            Return $PrivateKey

        }

        # returns RSACryptoServiceProvider for dispose purposes
        function __attachPrivateKey($Cert, [Byte[]]$PrivateKey) {

            $cspParams = New-Object Security.Cryptography.CspParameters -Property @{
                ProviderName = $ProviderName
                KeyContainerName = "pspki-" + [Guid]::NewGuid().ToString()
                KeyNumber = 1 #AT_KEYEXCHANGE
            }

            $rsa = New-Object Security.Cryptography.RSACryptoServiceProvider $cspParams
            $rsa.ImportCspBlob($PrivateKey)
            $Cert.PrivateKey = $rsa
            Return $rsa

        }

        # returns Asn1Reader
        function __decodePkcs1($base64) 
        {

            Write-Debug "Processing PKCS#1 RSA KEY module."

            $asn = New-Object SysadminsLV.Asn1Parser.Asn1Reader @(,[Convert]::FromBase64String($base64))

            if ($asn.Tag -ne 48) {throw "The data is invalid."}

            Return $asn

        }

        # returns Asn1Reader
        function __decodePkcs8($base64) 
        {

            Write-Debug "Processing PKCS#8 Private Key module."

            $asn = New-Object SysadminsLV.Asn1Parser.Asn1Reader @(,[Convert]::FromBase64String($base64))

            if ($asn.Tag -ne 48) {throw "The data is invalid."}

            # version
            if (!$asn.MoveNext()) {throw "The data is invalid."}

            # algorithm identifier
            if (!$asn.MoveNext()) {throw "The data is invalid."}

            # octet string
            if (!$asn.MoveNextCurrentLevel()) {throw "The data is invalid."}
            if ($asn.Tag -ne 4) {throw "The data is invalid."}
            if (!$asn.MoveNext()) {throw "The data is invalid."}

            Return $asn

        }

        $PfxFileName = $PrivateKeyFile.FullName.Replace(".key",".pfx")

        #Merge Public and Private Key file contents together
        [String]$PrivateKeyFileContents = [System.IO.File]::ReadAllLines($PrivateKeyFile.FullName)
        [String]$CertFileContents       = [System.IO.File]::ReadAllLines($PublicKeyFile.FullName)

        Write-Debug "Extracting certificate information..."

        $Cert = __extractCert $CertFileContents #Validate PEM certificate

        $PrivateKeyFileContents -match "(?msx).*-{5}BEGIN\sRSA\sPRIVATE\sKEY-{5}(.+)-{5}End\sRSA\sPRIVATE\sKEY-{5}" | Out-Null
        $asn = __decodePkcs1 $matches[1]

        # private key version
        if (!$asn.MoveNext()) {throw "The data is invalid."}

        # modulus n
        if (!$asn.MoveNext()) {throw "The data is invalid."}

        $modulus = __normalizeAsnInteger $asn.GetPayload()
        Write-Debug "Modulus length: $($modulus.Length)"

        # public exponent e
        if (!$asn.MoveNext()) {throw "The data is invalid."}

        # public exponent must be 4 bytes exactly.
        $PublicExponent = if ($asn.GetPayload().Length -eq 3) 
        {
            ,0 + $asn.GetPayload()

        } 
        
        else 
        {

            $asn.GetPayload()

        }

        Write-Debug "PublicExponent length: $($PublicExponent.Length)"

        # private exponent d
        if (!$asn.MoveNext()) {throw "The data is invalid."}
        $PrivateExponent = __normalizeAsnInteger $asn.GetPayload()
        Write-Debug "PrivateExponent length: $($PrivateExponent.Length)"

        # prime1 p
        if (!$asn.MoveNext()) {throw "The data is invalid."}
        $Prime1 = __normalizeAsnInteger $asn.GetPayload()
        Write-Debug "Prime1 length: $($Prime1.Length)"

        # prime2 q
        if (!$asn.MoveNext()) {throw "The data is invalid."}
        $Prime2 = __normalizeAsnInteger $asn.GetPayload()
        Write-Debug "Prime2 length: $($Prime2.Length)"

        # exponent1 d mod (p-1)
        if (!$asn.MoveNext()) {throw "The data is invalid."}
        $Exponent1 = __normalizeAsnInteger $asn.GetPayload()
        Write-Debug "Exponent1 length: $($Exponent1.Length)"

        # exponent2 d mod (q-1)
        if (!$asn.MoveNext()) {throw "The data is invalid."}
        $Exponent2 = __normalizeAsnInteger $asn.GetPayload()
        Write-Debug "Exponent2 length: $($Exponent2.Length)"

        # coefficient (inverse of q) mod p
        if (!$asn.MoveNext()) {throw "The data is invalid."}
        $Coefficient = __normalizeAsnInteger $asn.GetPayload()
        Write-Debug "Coefficient length: $($Coefficient.Length)"

        # creating Private Key BLOB structure
        $PrivateKey = __composePRIVATEKEYBLOB $modulus $PublicExponent $PrivateExponent $Prime1 $Prime2 $Exponent1 $Exponent2 $Coefficient

        #region key attach and export routine
        $rsaKey = __attachPrivateKey $Cert $PrivateKey

        $pfxBytes = $Cert.Export("pfx", $Password)

        [System.IO.File]::WriteAllBytes($PfxFileName, $pfxBytes)

        $rsaKey.Dispose()
        [System.IO.FileInfo]$PfxFileName

        "[{0}] Created PFX certificate: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PfxFileName | Write-Verbose

    }

    End
    {


    }

}

function Remove-HPOVScmbCertificate
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process
    {
        
        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($_appliance.Name)' appliance connection (of $($ApplianceConnection.count))"

            Try
            {

                $_keys = Send-HPOVRequest $RabbitMQKeyPairUri -Hostname $_appliance

            }

            Catch [HPOneview.ResourceNotFoundException]
            {

                $ExceptionMessage = 'The SCMB certificate key pair has not bee generated on the appliance "{0}". Please use Get-HPOVScmbCertificates to generate a new certificate key pair.' -f $_appliance.Name
                $ErrorRecord = New-ErrorRecord HPOneview.ResourceNotFoundException ResourceNotFound ObjectNotFound "ScmbCertifcateKeyPait" -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSCmdlet.ShouldProcess($_appliance.Name, "Remove SCMB (RabbitMQ) rabbit_readonly user certificates"))
            {   
             
                Try
                {

                    Send-HPOVRequest $RabbitMQKeyPairCertUri DELETE -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Import-HPOVSslCertificate 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]

    Param 
    (
    
        [Parameter (ValueFromPipeline, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['ApplianceConnection'])) 
        { 
            
            $PipelineInput = $True 
        
        }

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($_appliance -is [HPOneView.Appliance.Connection])
            {

                $_appliance = $_appliance.Name

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance '$($_appliance)' (of $($ApplianceConnection.Count))"

            try 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting response"

                [System.Net.HttpWebRequest]$WebRequest = [System.Net.HttpWebRequest]::Create("https://$_appliance")

                $WebRequest.ServerCertificateValidationCallback = { $True }
                
                $Response = $WebRequest.GetResponse()
            
            }
            
            catch [Net.WebException] 
            { 

                if (-not($WebRequest.Connection) -and ([int]$Response.StatusCode -eq 0)) 
                {

                    Write-Error $_.Exception.Message -Category ObjectNotFound -ErrorAction Stop

                } 

            }

            #Close the response connection, as it is no longer needed, and will cause problems if left open.
            if ($response) 
            {
                
                write-verbose "Closing response connection"
                
                $Response.Close() 
            
            }

            if ($null -ne $WebRequest.ServicePoint.Certificate) 
            {

                #Get certificate
                $Cert = [Security.Cryptography.X509Certificates.X509Certificate2]$WebRequest.ServicePoint.Certificate

                $StoreScope = "CurrentUser"
                $StoreName  = "Root" 

                #Save to users Trusted Root Authentication Hosts store
                $store = New-Object System.Security.Cryptography.X509Certificates.X509Store $StoreName, $StoreScope

                $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)

                try 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Attempting to add cert to store"

                    $store.Add($cert)
                    $store.Close()

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Cert added successfully"

                }

                catch 
                {

                    $store.Close()
                    #Write-Error $_.Exception.Message -Category InvalidResult -ErrorAction Stop
                    $PSCmdlet.ThrowTerminatingError($_.Exception)

                }

            }

        }

    }
    
    End    
    { 
        
        Write-Warning "Please note that the Subject Alternate Name (SAN) must match that of the Appliance hostname you use to connect to your appliance. If it does not, an SSL connection failure will occur. When creating a CSR on the appliance, make sure to include the additional FQDN and IP address(es) in the Alternative Name field." 
    
    }

}

function Restart-HPOVAppliance 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (
    
        [Parameter (ValueFromPipeline, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['ApplianceConnection'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if (-not($ApplianceConnection))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance '$($_appliance.Name)' (of $($ApplianceConnection.Count))"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Appliance Restart being request."

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Presenting confirmation prompt."

            if ($PSCmdlet.ShouldProcess(("Restart appliance {0}" -f $_appliance.Name),"WARNING: Restarting the appliance will cause all users to be disconnected and all ongoing tasks to be interrupted.",('Perform operation "Restart appliance" on target "{0}"?' -f $_appliance.Name)))
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User confirmed appliance shutdown."    
                
                Try
                {

            
                    $_resp = Send-HPOVRequest -uri $script:applianceRebootUri -method POST -Hostname $_appliance

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }
            
            elseif ($PSBoundParameters['Whatif'])
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User passed -WhatIf."

            }

            else
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User cancelled shutdown request."

            }
        
        }
        
    }

    End
    {

        Return $TaskCollection

    }

}

function Stop-HPOVAppliance 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (
    
        [Parameter (ValueFromPipeline, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['ApplianceConnection']) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
                
        $TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance '$($_appliance.Name)' (of $($ApplianceConnection.Count))"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Appliance SHUTDOWN being requested..."

            write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Presenting confirmation prompt."

            if ($PSCmdlet.ShouldProcess(("Shutdown appliance {0}" -f $_appliance.Name),"WARNING: Shutdown of the appliance will cause all users to be disconnected and all ongoing tasks to be interrupted.",('Perform operation "Shutdown appliance" on target "{0}"?' -f $_appliance.Name)))
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User confirmed appliance shutdown."    
                
                Try
                {

                    $_resp = Send-HPOVRequest -uri $applianceShutDownUri POST -Hostname $_appliance

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                [void]$TaskCollection.Add($_resp)

            }

            elseif ($PSBoundParameters['Whatif'])
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User passed -WhatIf."

            }

            else
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User cancelled shutdown request."

            }
        
        }
        
    }

    End
    {

        Return $TaskCollection

    }

}

#######################################################
# Facilities:
#

function Get-HPOVRack
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_RackCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        $uri = $DataCenterRacksUri.Clone()

        if ($Name)
        {

            $method = 'EQ'

            if ($Name.Contains('*'))
            {

                $method = 'matches'

            }

            $uri = "{0}?filter=name {1} '{2}'" -f $uri, $method, $Name.Replace('*','%25').Replace('?','%26')

        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            '[{0}] Processing "{1}" appliance connection.' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            try
            {

                $Resp = Send-HPOVRequest -Uri $uri -Hostname $_appliance

            }

            catch
            {
            
                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($Resp.count -eq 0 -and $Name)
            {

                $ExceptionMessage = 'The "{0}" rack was not found on {1}. Please check the name and try again.' -f $Name, $_appliance.Name
                $ErrorRecord = New-ErrorRecord HPOneView.ResourceNotFoundException ObjectNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

             $resp.members | % {

                 $_.PSObject.TypeNames.Insert(0,'HPOneView.Facilities.Rack')

                [void]$_RackCol.Add($_)

            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        Return $_RackCol

    }

}

function New-HPOVRack
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Int]$ThermalLimit,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$SerialNumber,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$PartNumber,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Int]$Depth = 1000,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Int]$Height = 2004,
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Int]$UHeight = 40,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Int]$Width = 600,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_RackCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        $_Rack = NewObject -Rack
        $_Rack.name          = $Name
        $_Rack.thermalLimit  = $ThermalLimit
        $_Rack.serialNumber  = $SerialNumber
        $_Rack.partNumber    = $PartNumber
        $_Rack.depth         = $Depth
        $_Rack.height        = $Height
        $_Rack.uHeight       = $UHeight
        $_Rack.width         = $Width

        Try
        {

            Send-HPOVRequest -Uri $DataCenterRacksUri -Method POST -Body $_Rack -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }


    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

Function Add-HPOVResourceToRack
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
      
    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Object]$Rack,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Int]$ULocation,

        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $InputObject)
        {

            $PipelineInput - $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_Collection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($Rack.category -ne 'racks')
        {

            $ExceptionMessage = 'The Rack is not a valid Rack object.'
            $ErrorRecord = New-ErrorRecord HPOneview.RackResourceException InvalidParameter InvalidArgument 'Rack' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Get the most current version of the object
        Try
        {

            $Rack = Send-HPOVRequest -Uri $Rack.uri -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        switch ($InputObject.category)
        {

            'server-hardware'
            {

                $_RelativeOrder = 0
                [int]$_UHeight = $InputObject.formFactor.Replace('U',$null)

            }

            'unmanaged-devices'
            {

                $_RelativeOrder = 0
                [int]$_UHeight = $InputObject.height

            }

            'enclosures'
            {

                $_RelativeOrder = -1
                [int]$_UHeight = 10

            }

            #Unsupported type
            default
            {

                $ExceptionMessage = 'The resource {0} you are attempting to associate with the Rack {1} is not a supported object.' -f $InputObject.name, $Rack.name
                $ErrorRecord = New-ErrorRecord HPOneView.RackResourceException InvalidParameter InvalidArgument 'InputObject' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        if (($ULocation + $_UHeight - 1) -le 0)
        {

            $ExceptionMessage = 'The resource {0} you are attempting to associate with the Rack {1} at {2} U location is not valid. The device is {3} Rack Units in size and cannot fit at {2} U rack position.' -f $InputObject.name, $Rack.name, $_UHeight, $ULocation
            $ErrorRecord = New-ErrorRecord HPOneView.RackResourceException InvalidParameter InvalidArgument 'Rack' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_RackItem = NewObject -RackItem
        $_RackItem.mountUri      = $InputObject.uri
        $_RackItem.relativeOrder = $_RelativeOrder
        $_RackItem.topUSlot      = $ULocation + $_UHeight - 1
        $_RackItem.uHeight       = $_UHeight

        $_OriginalRackContents = [Array]$Rack.rackMounts.Clone()
        $Rack.rackMounts = New-Object System.Collections.ArrayList

        $_OriginalRackContents | % { [void]$Rack.rackMounts.Add($_) }
        [void]$Rack.rackMounts.Add($_RackItem)

        Try
        {

            Send-HPOVRequest -Uri $Rack.uri -Method PUT -Body $Rack -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVRackMember
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {
    
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }        

        $_RackCol        = New-Object System.Collections.ArrayList
        $_TaskCollection = New-Object System.Collections.ArrayList

    }

    Process
    {

        if ($InputObject -is [PSCustomObject]) 
        {

            "[{0}] Rack Object provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | FL * | Out-String) | Write-Verbose

            If ('racks' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.RackResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The InputObject object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.RackResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message "The InputObject object resource is not an expected type. The allowed resource category type is 'racks'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            "[{0}] Get most current Rack object version" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject | Write-Verbose

            Try
            {

                $InputObject = Send-HPOVRequest -Uri $InputObject.uri -Hostname $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        else 
        {

            "[{0}] Processing Rack Name {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject | Write-Verbose

            Try
            {

                $InputObject = Get-HPOVRack -Name $InputObject -ApplianceConnection $ApplianceConnection -ErrorAction Stop

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Get list of rack mounted objects to then either return to the caller or search for specific resource name
        ForEach ($_RackItem in $InputObject.rackMounts)
        {

            Try
            {

                $_RackItemObject = Send-HPOVRequest -Uri $_RackItem.mountUri -Hostname $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            switch ($_RackItemObject.category)
            {

                'server-hardware'
                {

                    $_Model = $_RackItemObject.model
                    [int]$_UHeight = $_RackItemObject.formFactor.Replace('U',$null)

                }

                'unmanaged-devices'
                {

                    $_Model = $_RackItemObject.model
                    [int]$_UHeight = $_RackItemObject.height

                }

                'enclosures'
                {

                    $_Model = $_RackItemObject.enclosureModel
                    [int]$_UHeight = 10

                }

            }

            $_RackULocation = $_RackItem.topUSlot - $_UHeight + 1

            Try
            {

                $_RackMember = New-Object HPOneView.Facilities.RackMember($_RackItemObject.name, $_Model, $_UHeight, $_RackULocation, $_RackItemObject.uri, $InputObject.name, $InputObject.uri, $_RackItemObject.ApplianceConnection)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            [void]$_RackCol.Add($_RackMember)

        }

        if ($Name)
        {

            $_RackCol = $_RackCol | ? { $_.Name -match $Name }

            if (-not $_RackCol)
            {

                $ExceptionMessage = 'The "{0}" rack member was not found in {1}. Please check the name and try again.' -f $Name, $InputObject.name
                $ErrorRecord = New-ErrorRecord HPOneView.ResourceNotFoundException ObjectNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

        }

        $_RackCol

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Set-HPOVRackMemberLocation
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Facilities.RackMember]$InputObject,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Int]$ULocation,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {
    
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }        

        $_RackCol        = New-Object System.Collections.ArrayList
        $_TaskCollection = New-Object System.Collections.ArrayList

    }

    Process
    {

        "[{0}] RackMember Object provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | FL * | Out-String) | Write-Verbose

        If (-not($InputObject.ApplianceConnection))
        {

            $ErrorRecord = New-ErrorRecord HPOneView.RackResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The InputObject object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Get Rack from member
        Try
        {

            $Rack = Send-HPOVRequest -Uri $InputObject.RackUri -Hostname $InputObject.ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        ($Rack.rackMounts | ? mountUri -eq $InputObject.Uri).topUSlot = ($ULocation + $InputObject.UHeight - 1)

        Try
        {

            Send-HPOVRequest -Uri $Rack.uri -Method PUT -Body $Rack -Hostname $Rack.ApplianceConnection | Out-Null

            Get-HPOVRackMember -InputObject $Rack -Name $InputObject.Name -ErrorAction Stop

        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVRackMember
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [HPOneView.Facilities.RackMember]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {
    
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }        

        $_RackCol        = New-Object System.Collections.ArrayList
        $_TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Begin resource removal Process."

        $RemoveMessage = "Remove Rack member '{0}'" -f $InputObject.Name

        if ($PSCmdlet.ShouldProcess($InputObject.RackName, $RemoveMessage))
        {   
                        
            Try
            {
                
                #Get Rack resource object, which is what needs to be modified.
                $Rack = Send-HPOVRequest -Uri $InputObject.RackUri -Hostname $InputObject.ApplianceConnection

                [Array]$Rack.rackMounts = $Rack.rackMounts | ? mountUri -ne $InputObject.Uri
                
                Send-HPOVRequest -Uri $Rack.uri -Method PUT -Body $Rack -Hostname $Rack.ApplianceConnection -addHeader @{'If-Match' = $Rack.eTag}

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        elseif ($PSBoundParameters['WhatIf'])
        {

            "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

        else
        {

            "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVRack
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {
    
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }        

        $_RackCol        = New-Object System.Collections.ArrayList
        $_TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        if ($InputObject -is [PSCustomObject]) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Remote Support Contact Object provided: $($InputObject | FL * | Out-String)"

            If ('racks' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.RackResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The InputObject object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_RackCol.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.RackResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message "The InputObject object resource is not an expected type. The allowed resource category type is 'racks'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            For ($c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($ApplianceConnection[$c].Name) (of $($ApplianceConnection.Count))"

                "[{0}] Processing DataCenter Name {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject | Write-Verbose

                Try
                {

                    $_Racks = Get-HPOVRack -Name $InputObject -ApplianceConnection $ApplianceConnection[$c]

                    $_Racks | % {

                        [void]$_RackCol.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Begin resource removal Process."

        foreach ($_rack in $_RackCol) 
        {

            $RemoveMessage = "Remove Rack '{0}'" -f $_rack.Name

            if ($PSCmdlet.ShouldProcess($_rack.ApplianceConnection.Name,$RemoveMessage))
            {   
                            
                Try
                {
                
                    Send-HPOVRequest -Uri $_rack.uri -Method DELETE -Hostname $_rack.ApplianceConnection.Name -addHeader @{'If-Match' = $_rack.eTag}

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }
                        
        }

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVDataCenter
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        $Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_DCCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        $uri = $DataCentersUri.Clone()

        if ($Name)
        {

            $method = 'EQ'

            if ($Name.Contains('*'))
            {

                $method = 'matches'

            }

            $uri = "{0}?filter=name {1} '{2}'" -f $uri, $method, $Name.Replace('*','%25').Replace('?','%26')

        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            '[{0}] Processing "{1}" appliance connection.' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            try
            {

                $Resp = Send-HPOVRequest -Uri $uri -Hostname $_appliance

            }

            catch
            {
            
                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($Resp.count -eq 0 -and $Name)
            {

                $ExceptionMessage = 'The "{0}" datacenter was not found on {1}. Please check the name and try again.' -f $Name, $_appliance.Name
                $ErrorRecord = New-ErrorRecord HPOneView.ResourceNotFoundException ObjectNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                Try
                {

                    $RemoteSupportConfigured = Send-HPOVRequest -Uri $RemoteSupportConfigUri -Hostname $_appliance.Name

                }

                catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($RemoteSupportConfigured.enableRemoteSupport)
                {

                    '[{0}] Appliance has Remote Support enabled. Collecting DataCenter location and contact information.' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

                    ForEach ($member in $resp.members)
                    {

                        Try
                        {

                            $_DCRemoteSupportLocation = Send-HPOVRequest -uri $member.remoteSupportUri -Hostname $_appliance.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        $member | Add-Member -NotePropertyName RemoteSupportLocation -NotePropertyValue ([HPOneView.Facilities.RemoteSupportLocation]$_DCRemoteSupportLocation)

                        $member.PSObject.TypeNames.Insert(0,'HPOneView.Facilities.DataCenter')

                        [void]$_DCCol.Add($member)

                    }

                }

                else
                {

                    $resp.members | % {

                        $_.PSObject.TypeNames.Insert(0,'HPOneView.DataCenter')

                        [void]$_DCCol.Add($_)

                    }

                }

            }

        }

    }

    End
    {

        Return $_DCCol

    }

}

function New-HPOVDataCenter
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [Float]$Width,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [Float]$Depth,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [Switch]$Millimeters,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [Int]$ElectricalDerating = 20,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateSet ('NaJp', 'Custom', 'None')]
        [String]$ElectricalDeratingType = 'NaJp',

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [Int]$DefaultVoltage = 220,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [String]$Currency = 'USD',

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [Float]$PowerCosts,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [Int]$CoolingCapacity,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [Float]$CoolingMultiplier = 1.5,

        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [Object]$PrimaryContact,

        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [Object]$SecondaryContact,

        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [String]$Address1,

        [Parameter (Mandatory = $False, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [String]$Address2,

        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [String]$City,

        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [String]$State,

        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [String]$PostCode,

        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [String]$Country,

        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullOrEmpty()]
        [String]$TimeZone,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'RemoteSupport')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ApplianceRemoteSupportCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        $RemoteSupportStatus = $null

        if ($PSCmdlet.ParameterSetName -eq 'RemoteSupport')
        {

            "[{0}] Validate Remote Support is configured on the appliance." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Try
            {

                $RemoteSupportStatus = Send-HPOVRequest -Uri $RemoteSupportConfigUri -Hostname $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if (-not $RemoteSupportStatus.enableRemoteSupport)
            {

                "[{0}] Remote Support is not enabled and configured on the appliance. Generate non-terminating error." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $ExceptionMessage = 'Remote Support is not configured on the appliance, {0}. In order to set the Remote Support location for the DataCenter, Remote SUpport must be enabledon the appliance. Either enable Remote Support or do not attempt to set the Data Center location until Remote Support has been anabled on the appliance.' -f $ApplianceConnection.Name
                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportException RemoteSupportNotEnabled InvalidOperation 'ApplianceConnect' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                "[{0}] Remote Support is enabled and configured on the appliance. Will set Data Center RS location." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_DataCenterAddressPatchOp = New-Object System.Collections.ArrayList

                switch ($PSBoundParameters.Keys)
                {

                    'Address1'
                    {

                        $_PatchOperation = NewObject -PatchOperation
                        $_PatchOperation.op    = 'replace'
                        $_PatchOperation.path  = '/streetAddress1'
                        $_PatchOperation.value = $Address1

                        [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                    }

                    'Address2'
                    {

                        $_PatchOperation = NewObject -PatchOperation
                        $_PatchOperation.op    = 'replace'
                        $_PatchOperation.path  = '/streetAddress2'
                        $_PatchOperation.value = $Address2

                        [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                    }

                    'City'
                    {

                        $_PatchOperation = NewObject -PatchOperation
                        $_PatchOperation.op    = 'replace'
                        $_PatchOperation.path  = '/city'
                        $_PatchOperation.value = $City

                        [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                    }

                    'State'
                    {

                        $_PatchOperation = NewObject -PatchOperation
                        $_PatchOperation.op    = 'replace'
                        $_PatchOperation.path  = '/provinceState'
                        $_PatchOperation.value = $State

                        [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                    }

                    'PostCode'
                    {

                        $_PatchOperation = NewObject -PatchOperation
                        $_PatchOperation.op    = 'replace'
                        $_PatchOperation.path  = '/postalCode'
                        $_PatchOperation.value = $PostCode

                        [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                    }

                    'Country'
                    {

                        $_PatchOperation = NewObject -PatchOperation
                        $_PatchOperation.op    = 'replace'
                        $_PatchOperation.path  = '/countryCode'
                        $_PatchOperation.value = $Country

                        [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                    }

                    'TimeZone'
                    {

                        $_PatchOperation = NewObject -PatchOperation
                        $_PatchOperation.op    = 'replace'
                        $_PatchOperation.path  = '/timeZone'
                        $_PatchOperation.value = $TimeZone

                        [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                    }

                    'PrimaryContact'
                    {

                        if ($PrimaryContact.Type -ne 'Contact')
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidArgumentValue InvalidArgument "PrimaryContact" -TargetType PSObject -Message "The PrimaryContact object resource provided is not a Remote Support Contact. Please use the Get-HPOVRemoteSupportContact Cmdlet to get a valid contact object."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        $_PatchOperation = NewObject -PatchOperation
                        $_PatchOperation.op    = 'replace'
                        $_PatchOperation.path  = '/primaryContactUri'
                        $_PatchOperation.value = $PrimaryContact.uri

                        [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                    }

                    'SecondaryContact'
                    {

                        if ($SecondaryContact.Type -ne 'Contact')
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidArgumentValue InvalidArgument "SecondaryContact" -TargetType PSObject -Message "The SecondaryContact object resource provided is not a Remote Support Contact. Please use the Get-HPOVRemoteSupportContact Cmdlet to get a valid contact object."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        $_PatchOperation = NewObject -PatchOperation
                        $_PatchOperation.op    = 'replace'
                        $_PatchOperation.path  = '/secondaryContactUri'
                        $_PatchOperation.value = $SecondaryContact.uri

                        [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                    }

                }

                if ($PrimaryContact.uri -eq $SecondaryContact.uri)
                {

                    "[{0}] Primary and Secondary Contact are the same. Must be uniquel; generating terminating error." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $ExceptionMessage =  "Both the PrimaryContact and SecondaryContact objects are the same. Please specify unique Primary and Secondary contacts." 
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidArgumentValue InvalidArgument "PrimaryContact" -TargetType PSObject -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

        }

        if (-not $Millimeters.IsPresent)
        {

            #Convert from Feet to Millimeters
            $Width = [Math]::Round($Width * .3048 * 1000, 2)
            $Depth = [Math]::Round($Depth * .3048 * 1000, 2)

        }    

        $NewDataCenter = NewObject -DataCenter
        $NewDataCenter.name                    = $Name
        $NewDataCenter.coolingCapacity         = $CoolingCapacity
        $NewDataCenter.costPerKilowattHour     = $PowerCosts
        $NewDataCenter.currency                = $Currency
        $NewDataCenter.deratingType            = $ElectricalDeratingType
        $NewDataCenter.deratingPercentage      = $ElectricalDerating
        $NewDataCenter.defaultPowerLineVoltage = $DefaultVoltage
        $NewDataCenter.coolingMultiplier       = $CoolingMultiplier
        $NewDataCenter.width                   = $Width
        $NewDataCenter.depth                   = $Depth

        #Create DC
        Try
        {

            $Resp = Send-HPOVRequest -Uri $DataCentersUri -Method POST -Body $NewDataCenter -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        #Update Remote Support DC if needed
        if ($_DataCenterAddressPatchOp.Count -gt 0)
        {

            "[{0}] Modifying datacenter Remote Support location to the specified value." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Try
            {

                $_UpdateDCLocationResults = Send-HPOVRequest -Uri $Resp.remoteSupportUri -Method PATCH -Body $_DataCenterAddressPatchOp -Hostname $ApplianceConnection | Wait-HPOVTaskComplete

                if ($_UpdateDCLocationResults.taskState -ne 'Completed')
                {

                    $ExceptionMessage = 'Updating the datacenter with the specified location did not complete successfully with: {0}' -f [String]::Join(' ', $_UpdateDCLocationResults.taskErrors)
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportException InvalidOperation InvalidOperation 'ApplianceConnect' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Send-HPOVRequest -Uri $Resp.uri -Hostname $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        else
        {

            $Resp

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Add-HPOVRackToDataCenter
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
      
    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Object]$DataCenter,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Int]$X,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Int]$Y,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Switch]$Millimeters,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateRange(0,360)]
        [Int]$Rotate = 0,

        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $InputObject)
        {

            $PipelineInput - $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_Collection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($InputObject.category -ne 'racks')
        {

            $ExceptionMessage = 'The InputObject is not a valid Rack object.'
            $ErrorRecord = New-ErrorRecord HPOneview.RackResourceException InvalidParameter InvalidArgument 'InputObject' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($DataCenter.category -ne 'datacenters')
        {

            $ExceptionMessage = 'The DataCenter is not a valid data center object.'
            $ErrorRecord = New-ErrorRecord HPOneview.DatacenterResourceException InvalidParameter InvalidArgument 'DataCenter' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Get the most current version of the object
        Try
        {

            $DataCenter = Send-HPOVRequest -Uri $DataCenter.uri -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $_DataCenterToUpdate = $DataCenter.PSObject.Copy()

        $_UpdatedAssociations = $_DataCenterToUpdate.contents
        
        $_DataCenterToUpdate.contents = New-Object System.Collections.ArrayList
        $_UpdatedAssociations | % { [void]$_DataCenterToUpdate.contents.Add($_) }

        if (-not $Millimeters.IsPresent)
        {

            #Convert from Feet to Millimeters
            $X = [Math]::Round([int]$X * .3048 * 1000, 2)
            $Y = [Math]::Round([int]$Y * .3048 * 1000, 2)

        }        

        $_NewDCItem = NewObject -DataCenterItem
        $_NewDCItem.resourceUri = $InputObject.uri
        $_NewDCItem.rotation    = $Rotate
        $_NewDCItem.x           = $X
        $_NewDCItem.y           = $y

        [void]$_DataCenterToUpdate.contents.Add($_NewDCItem)

        Try
        {

            Send-HPOVRequest -Uri $DataCenter.uri -Method PUT -Body ($_DataCenterToUpdate | Select * -Exclude RemoteSupportLocation) -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Set-HPOVDataCenterRemoteSupport
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$PrimaryContact,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$SecondaryContact,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Address1,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Address2,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$City,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$State,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$PostCode,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Country,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$TimeZone,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {
    
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }    

        $_ApplianceRemoteSupportCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        if ($InputObject -is [PSCustomObject]) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Remote Support Contact Object provided: $($InputObject | FL * | Out-String)"

            If ('datacenters' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.DataCenterResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The InputObject object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.DataCenterResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message "The InputObject object resource is not an expected type. The allowed resource category type is 'DataCenters'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else
        {

            Try
            {

                $InputObject = Get-HPOVDataCenter -Name $InputObject -ApplianceConnection $ApplianceConnection -ErrorAction Stop

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $RemoteSupportStatus = $null

        "[{0}] Validate Remote Support is configured on the appliance." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        Try
        {

            $RemoteSupportStatus = Send-HPOVRequest -Uri $RemoteSupportConfigUri -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not $RemoteSupportStatus.enableRemoteSupport)
        {

            "[{0}] Remote Support is not enabled and configured on the appliance. Generate non-terminating error." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $ExceptionMessage = 'Remote Support is not configured on the appliance, {0}. In order to set the Remote Support location for the DataCenter, Remote SUpport must be enabledon the appliance. Either enable Remote Support or do not attempt to set the Data Center location until Remote Support has been anabled on the appliance.' -f $ApplianceConnection.Name
            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportException RemoteSupportNotEnabled InvalidOperation 'ApplianceConnect' -Message $ExceptionMessage
            $PSCmdlet.WriteError($ErrorRecord)

        }

        else
        {

            "[{0}] Remote Support is enabled and configured on the appliance. Will set Data Center RS location." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_DataCenterAddressPatchOp = New-Object System.Collections.ArrayList

            switch ($PSBoundParameters.Keys)
            {

                'Address1'
                {

                    $_PatchOperation = NewObject -PatchOperation
                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/streetAddress1'
                    $_PatchOperation.value = $Address1

                    [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                }

                'Address2'
                {

                    $_PatchOperation = NewObject -PatchOperation
                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/streetAddress2'
                    $_PatchOperation.value = $Address2

                    [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                }

                'City'
                {

                    $_PatchOperation = NewObject -PatchOperation
                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/city'
                    $_PatchOperation.value = $City

                    [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                }

                'State'
                {

                    $_PatchOperation = NewObject -PatchOperation
                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/provinceState'
                    $_PatchOperation.value = $State

                    [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                }

                'PostCode'
                {

                    $_PatchOperation = NewObject -PatchOperation
                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/postalCode'
                    $_PatchOperation.value = $PostCode

                    [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                }

                'Country'
                {

                    $_PatchOperation = NewObject -PatchOperation
                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/countryCode'
                    $_PatchOperation.value = $Country

                    [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                }

                'TimeZone'
                {

                    $_PatchOperation = NewObject -PatchOperation
                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/timeZone'
                    $_PatchOperation.value = $TimeZone

                    [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                }

                'PrimaryContact'
                {

                    if ($PrimaryContact.Type -ne 'Contact')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidArgumentValue InvalidArgument "PrimaryContact" -TargetType PSObject -Message "The PrimaryContact object resource provided is not a Remote Support Contact. Please use the Get-HPOVRemoteSupportContact Cmdlet to get a valid contact object."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    $_PatchOperation = NewObject -PatchOperation
                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/primaryContactUri'
                    $_PatchOperation.value = $PrimaryContact.uri

                    [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                }

                'SecondaryContact'
                {

                    if ($SecondaryContact.Type -ne 'Contact')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidArgumentValue InvalidArgument "SecondaryContact" -TargetType PSObject -Message "The SecondaryContact object resource provided is not a Remote Support Contact. Please use the Get-HPOVRemoteSupportContact Cmdlet to get a valid contact object."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    $_PatchOperation = NewObject -PatchOperation
                    $_PatchOperation.op    = 'replace'
                    $_PatchOperation.path  = '/secondaryContactUri'
                    $_PatchOperation.value = $SecondaryContact.uri

                    [void]$_DataCenterAddressPatchOp.Add($_PatchOperation)

                }

            }

            if (($PSBoundParameters['PrimaryContact'] -or $PSBoundParameters['SecondaryContact']) -and $PrimaryContact.uri -eq $SecondaryContact.uri)
            {

                "[{0}] Primary and Secondary Contact are the same. Must be unique; generating terminating error." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $ExceptionMessage =  "Both the PrimaryContact and SecondaryContact objects are the same. Please specify unique Primary and Secondary contacts." 
                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportContactException InvalidArgumentValue InvalidArgument "PrimaryContact" -TargetType PSObject -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }









        }

        #Update Remote Support DC if needed
        if ($_DataCenterAddressPatchOp.Count -gt 0)
        {

            "[{0}] Modifying datacenter Remote Support location to the specified value." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Try
            {

                $_UpdateDCLocationResults = Send-HPOVRequest -Uri $InputObject.remoteSupportUri -Method PATCH -Body $_DataCenterAddressPatchOp -Hostname $ApplianceConnection

                if (-not $Async.IsPresent)
                {

                    $_UpdateDCLocationResults | Wait-HPOVTaskComplete

                    if ($_UpdateDCLocationResults.taskState -ne 'Completed')
                    {

                        $ExceptionMessage = 'Updating the datacenter with the specified location did not complete successfully with: {0}' -f [String]::Join(' ', $_UpdateDCLocationResults.taskErrors)
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.RemoteSupportException InvalidOperation InvalidOperation 'ApplianceConnect' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                else
                {

                    $_UpdateDCLocationResults
                    
                }                

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        else
        {

            "[{0}] Nothing to do." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Set-HPOVDataCenter
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Float]$Width,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Float]$Depth,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Switch]$Millimeters,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Int]$ElectricalDerating,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateSet ('NaJp', 'Custom', 'None')]
        [String]$ElectricalDeratingType,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Int]$DefaultVoltage,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Currency,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Float]$PowerCosts,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Int]$CoolingCapacity,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Float]$CoolingMultiplier,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {
    
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }    

        $_ApplianceRemoteSupportCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        if ($InputObject -is [PSCustomObject]) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Remote Support Contact Object provided: $($InputObject | FL * | Out-String)"

            If ('datacenters' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.DataCenterResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The InputObject object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.DataCenterResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message "The InputObject object resource is not an expected type. The allowed resource category type is 'DataCenters'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else
        {

            Try
            {

                $InputObject = Get-HPOVDataCenter -Name $InputObject -ApplianceConnection $ApplianceConnection -ErrorAction Stop

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_DataCenterObject = $InputObject.PSObject.Copy()

        switch ($PSBoundParameters.Keys)
        {

            'Name'
            {

                $_DataCenterObject.name = $Name

            }

            'Width'
            {

                if (-not $Millimeters.IsPresent)
                {

                    #Convert from Feet to Millimeters
                    $Width = [Math]::Round($Width * .3048 * 1000, 2)

                }    

                $_DataCenterObject.width = $Width

            }

            'Depth'
            {

                if (-not $Millimeters.IsPresent)
                {

                    #Convert from Feet to Millimeters
                    $Depth = [Math]::Round($Depth * .3048 * 1000, 2)

                }

                $_DataCenterObject.depth = $Depth

            }

            'ElectricalDerating'
            {

                if ($PSBoundParameters['ElectricalDeratingType'] -ne 'Custom')
                {

                    $ExceptionMessage = 'The ElectricalDerating paraemter was used with a custom value, without providing the ElectricalDeratingType parameter. ElectricalDerating will not be set to the value.'
                    $ErrorRecord = New-ErrorRecord HPOneview.DataCenterResourceException InvalidParameter InvalidArgument 'ElectricalDerating' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                else
                {

                    $_DataCenterObject.deratingPercentage = $ElectricalDerating

                }

            }

            'ElectricalDeratingType'
            {

                if ($PSBoundParameters['ElectricalDerating'] -eq 'Custom' -and (-not $PSBoundParameters['ElectricalDerating']))
                {

                    $ExceptionMessage = 'The ElectricalDeratingType paraemter is set to "Custom" without providing the ElectricalDerating parameter. ElectricalDeratingType will not be set to the value.'
                    $ErrorRecord = New-ErrorRecord HPOneview.DataCenterResourceException InvalidParameter InvalidArgument 'ElectricalDeratingType' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                else
                {

                    $_DataCenterObject.deratingType = $ElectricalDeratingType

                    $NeedToUpdateTwice = $false

                    if ($ElectricalDeratingType -eq 'Custom')
                    {

                        $NeedToUpdateTwice = $true

                    }

                }

            }

            'DefaultVoltage'
            {

                $_DataCenterObject.defaultPowerLineVoltage = $DefaultVoltage

            }

            'Currency'
            {

                $_DataCenterObject.currency = $Currency

            }

            'PowerCosts'
            {

                $_DataCenterObject.costPerKilowattHour = $PowerCosts

            }

            'CoolingCapacity'
            {

                $_DataCenterObject.coolingCapacity = $CoolingCapacity

            }

            'CoolingMultiplier'
            {

                $_DataCenterObject.coolingMultiplier = $CoolingMultiplier

            }
            
        }

        Try
        {

            $Resp = Send-HPOVRequest -Uri $_DataCenterObject.uri -Method PUT -Body ($_DataCenterObject | Select * -Exclude RemoteSupportLocation) -Hostname $_DataCenterObject.ApplianceConnection

            if ($NeedToUpdateTwice)
            {

                "[{0}] Need to update the DC object again in order to set deratingPercentage custom value" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $resp.deratingPercentage = $ElectricalDerating

                $Resp = Send-HPOVRequest -Uri $Resp.uri -Method PUT -Body ($Resp | Select * -Exclude RemoteSupportLocation) -Hostname $Resp.ApplianceConnection

            }

            $Resp

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVDataCenter
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

       [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {
    
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }        

        $_DataCenterCol  = New-Object System.Collections.ArrayList
        $_TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        if ($InputObject -is [PSCustomObject]) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Remote Support Contact Object provided: $($InputObject | FL * | Out-String)"

            If ('datacenters' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.DataCenterResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The InputObject object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_DataCenterCol.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.DataCenterResourceException InvalidArgumentValue InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message "The InputObject object resource is not an expected type. The allowed resource category type is 'DataCenters'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            For ($c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($ApplianceConnection[$c].Name) (of $($ApplianceConnection.Count))"

                "[{0}] Processing DataCenter Name {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject | Write-Verbose

                Try
                {

                    $_DataCenter = Get-HPOVDataCenter -Name $InputObject -ApplianceConnection $ApplianceConnection[$c]

                    $_DataCenter | % {

                        [void]$_DataCenterCol.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Begin resource removal Process."

        foreach ($_dc in $_DataCenterCol) 
        {

            $RemoveMessage = "Remove DataCenter '{0}'" -f $_dc.Name

            if ($PSCmdlet.ShouldProcess($_dc.ApplianceConnection.Name,$RemoveMessage))
            {   
                            
                Try
                {
                
                    $resp = Send-HPOVRequest $_dc.uri DELETE -Hostname $_dc.ApplianceConnection.Name -addHeader @{'If-Match' = $_dc.eTag}
                    $resp | Add-Member -NotePropertyName ResourceName -NotePropertyValue $_dc.Name
                    $resp

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }
                        
        }

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

#######################################################
# Server Hardware and Enclosures:
#

function Get-HPOVServer 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [string]$ServerName,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [switch]$NoProfile,

        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = "Default")]
        [Alias ('ServerHardwareType','ServerProfileTemplate')]
        [object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($PSBoundParameters['Label'])
            {

                $_uri = '{0}?category:storage-hardare&query=labels:{1}' -f $IndexUri, $Label

                Try
                {

                    $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                    #Loop through all found members and get full object
                    ForEach ($_memeber in $_IndexMembers.members)
                    {

                        Try
                        {

                            $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                        

                        $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.ServerHardare')

                        $_memeber

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                $uri = $ServerHardwareUri + "?sort=name:asc"

                if ($PSBoundParameters['Scope'])
                {

                    "[{0}] Setting Scope to: {1} ({2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Scope, $Scope.Uri | Write-Verbose 

                    $uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri

                }

                if ($InputObject)
                {

                    switch ($InputObject.category)
                    {

                        'server-profile-templates'
                        {

                            $uri += "&filter=serverHardwareTypeUri EQ '{0}'" -f $InputObject.serverHardwareTypeUri

                        }

                        'server-hardware-types'
                        {

                            $uri += "&filter=serverHardwareTypeUri EQ '{0}'" -f $InputObject.uri

                        }

                        default
                        {

                            if ($InputObject.PSObject.properties -match 'category')
                            {

                                $InputObjectName = $InputObject.name.Clone()

                            }

                            else
                            {

                                $InputObjectName = $InputObject.Clone()

                            }

                            $ExceptionMessage = "The provided InputObject parameter value, '{0}', is not a supported resource type. Only server profile template or server hardware type resources are supported. Please check the value, and try again." -f $InputObjectName
                            $ErrorRecord = New-ErrorRecord HPOneView.InputObjectResourceException InvalidInputObject InvalidArgument 'InputObject' -TargetType 'PSObject' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                }            

                if ($PSBoundParameters['Name'])
                {

                    if ($Name.Contains('*'))
                    {

                        $Name = $Name.Replace('*','%25')

                    }

                    $uri += "&filter=name matches '{0}'" -f $Name

                }

                if ($PSBoundParameters['ServerName'])
                {

                    if ($ServerName.Contains('*'))
                    {

                        $ServerName = $ServerName.Replace('*','%25')

                    }

                    $uri += "&filter=serverName matches '{0}'" -f $ServerName

                }

                if ($PSBoundParameters['NoProfile']) 
                { 
                    
                    "[{0}] Filtering for server hardware with no assigned profiles." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                    $uri += "&filter=serverProfileUri=null"
                
                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

                Try
                {

                    $svrs = Send-HPOVRequest -Uri $uri -appliance $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($svrs.members.count -eq 0 -and $Name) 
                {
                        
                    $ExceptionMessage = "Server Hardware '{0}' not found on '{1}' appliance connection. Please check the name again, and try again." -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerHardwareResourceException ServerHardwareResourceNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                else
                {

                    ForEach ($s in ($svrs.members | Sort-Object name)) 
                    {

                        $s.PSObject.TypeNames.Insert(0,'HPOneView.ServerHardare')

                        $s

                    }

                }    

            }
            
        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | write-verbose

    }

}

function Get-HPOVIloSso
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (ValueFromPipeline, Mandatory, ParameterSetName = 'Default')]
        [Parameter (ValueFromPipeline, Mandatory, ParameterSetName = 'IloRestSession')]
        [ValidateNotNullOrEmpty()]
        [Alias('Server')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Switch]$RemoteConsoleOnly,        

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'IloRestSession')]
        [Switch]$IloRestSession,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "IloRestSession")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if (-not($InputObject -is [PSCustomObject]) -or (-not($InputObject.ApplianceConnection)))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException InvalidApplianceConnectionDataType InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The specified 'InputObject' is not an object or is missing the 'ApplianceConnection' property. Please correct this value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            else
            {

                Try 
                {
    
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -TargetType $InputObject.ApplianceConnection.GetType().Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if (-not($PipelineInput) -and (-not($InputObject -is [PSCustomObject])))
        {

            $ExceptionMessage = "The specified 'InputObject' is not an object. Please correct this value and try again."
            $ErrorRecord = New-ErrorRecord HPOneview.ServerResourceException InvalidServerObject InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ('server-hardware','server-profiles' -notcontains $InputObject.category)
        {
            
            $ExceptionMessage = "The specified 'InputObject' is not a Server or Server Profile object. Please correct this value and try again."
            $ErrorRecord = New-ErrorRecord HPOneview.ServerResourceException InvalidObject InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($InputObject.category -eq 'server-profiles')
        {

            "[{0}] Server Profile was provided." -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose
            $_uri = $InputObject.serverHardwareUri

        }

        else
        {

            "[{0}] Server Hardware was provided." -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose
            $_uri = $InputObject.uri

        }

        if ($PSBoundParameters['RemoteConsoleOnly'])
        {

            $_uri = $_uri + '/remoteConsoleUrl'

        }

        else
        {

            $_uri = $_uri + '/iloSsoUrl'

        }
        

        "[{0}] Processing {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

        Try
        {
        
            $_ssoresp = Send-HPOVRequest -URI $_uri -Hostname $InputObject.ApplianceConnection.Name
        
        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not $PSBoundParameters['IloRestSession'])
        {

            "[{0}] Returning iLO SSO Session" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_ssoresp

        }

        else
        {

            #Get-HPOVServer | Select -First 1 | Get-HPOVIloSso -IloRestSession -OutVariable IloUrl

            "[{0}] Generating and returning iLO REST/RedFish SSO Session object" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Try
            {

                $CookieContainer = New-Object System.Net.CookieContainer
                
                [System.Net.HttpWebRequest]$WebRequest          = [System.Net.HttpWebRequest]::Create($_ssoresp.iloSsoUrl)
                $WebRequest.CookieContainer                     = $CookieContainer
                $WebRequest.Accept                              = 'application/json, *.*'
                $WebRequest.ServerCertificateValidationCallback = { $True }
                
                "[{0}] Getting Redfish SessionID token from iLO, {1}." -f $MyInvocation.InvocationName.ToString().ToUpper(), ([URI]$_ssoresp.iloSsoUrl).Host | Write-Verbose

                $Response = $WebRequest.GetResponse()
                $Response.Close()
                $Response.Dispose()

                "[{0}] Getting Redfish SessionID token from cookies." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                $SessionID = $CookieContainer.GetCookieHeader($_ssoresp.iloSsoUrl)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            "[{0}] Building iLO Session Object." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
            $IloSession                = NewObject -IloRestSession
            $IloSession.RootUri        = "https://{0}/rest/v1" -f ([URI]$_ssoresp.iloSsoUrl).Host
            $IloSession.'X-Auth-Token' = $SessionID.Replace('sessionKey=',$null)

            $IloSession

        }
       
    }

    End 
    {
        
        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Add-HPOVServer 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Managed", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (ValueFromPipeline, Mandatory, ParameterSetName = "Monitored")]
        [Parameter (ValueFromPipeline, Mandatory, ParameterSetName = "Managed")]
        [ValidateNotNullOrEmpty()]
        [string]$Hostname,
         
        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [ValidateNotNullOrEmpty()]
        [string]$Username,

        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [ValidateNotNullOrEmpty()]
        [Object]$Password,

        [Parameter (Mandatory = $false, ParameterSetName = "Managed")]
        [ValidateSet ("OneView", "OneViewNoiLO")]
        [string]$LicensingIntent = 'OneView',

        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [switch]$Monitored,

        [Parameter (Mandatory = $False, ParameterSetName = "Monitored")]
        [Parameter (Mandatory = $False, ParameterSetName = "Managed")]
        [switch]$Async,

        [Parameter (Mandatory = $False, ParameterSetName = "Monitored")]
        [Parameter (Mandatory = $False, ParameterSetName = "Managed")]
        [ValidateNotNullorEmpty()]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        if ($Password -is [SecureString])
        {

            $Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

    }

    Process 
    {

        #New Server Resource Object
        $_server = NewObject -ServerImport
        $_server.hostname        = $Hostname;
        $_server.username        = $Username;
        $_server.password        = $Password;
        $_server.licensingIntent = $LicensingIntent;        

        if ([bool]$Monitored) 
        { 
        
            $_server.licensingIntent    = "OneViewStandard"
            $_server.configurationState = "Monitored"

        }

        else 
        { 
            
            $_server.configurationState = "Managed" 
        
        }

        "[{0}] Sending request to add server resource {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Hostname | Write-Verbose

        Try
        {
        
            $task = Send-HPOVRequest -Uri $ServerHardwareUri -Method POST -Body $_server -Hostname $ApplianceConnection.Name
        
        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        "[{0}] Initial task response: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($resp | out-string) | Write-Verbose

        Try
        {
            
            $resp = Wait-HPOVTaskStart $task

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        "[{0}] Second task response: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($resp | out-string) | Write-Verbose

        #Check to see if the task errored, which should be in the Task Validation stage
        if ($resp.taskState -ne "Running") 
        {

            if (($resp.taskState -eq "Error") -and ($resp.stateReason -eq "ValidationError")) 
            {

                "[{0}] Task error found: {1}, {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $resp.taskState, $resp.stateReason | Write-Verbose
                
                #taskErrors should contain only a single value, so we will force pick the first one.
                $errorMessage = $resp.taskerrors[0]
                
                switch ($errorMessage.errorCode) 
                {

                    "SERVER_ALREADY_MANAGED"
                    { 
                    
                        $externalManagerType = $errorMessage.data.managementProduct
                        $externalManagerIP   = $errorMessage.data.managementUrl.Replace("https://","")

                        Try
                        {
                        
                            $externalManagerFQDN = [System.Net.DNS]::GetHostByAddress($externalManagerIP)
                        
                        }

                        Catch
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Unable to resolve IP Address to DNS A Record."
                            $externalManagerFQDN = [PSCustomObject]@{HostName = 'UnknownFqdn'; Aliases = @(); AddressList = @($externalManagerIP.Clone())}

                        }
                        
                        "[{0}] Found server '{1}' is already being managed by {2} at {3}." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Hostname, $externalManagerType, $externalManagerIP | Write-Verbose
                        "[{0}] {1} resolves to {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $externalManagerIP,  $($externalManagerFQDN | out-string) | Write-Verbose

                        write-warning ("Server '{0}' is already being managed by {1} at {2} ({3})." -f $hostname, $externalManagerType, $externalManagerIP,  $($externalManagerFQDN | out-string))

                        $_ShouldProcessMessage = "force add server that is already managed/monitored by {0} at {1} ({2})" -f $externalManagerType, $externalManagerIP, $externalManagerFQDN.HostName

                        if ($PSCmdlet.ShouldProcess($hostname, $_ShouldProcessMessage)) 
                        {
                    
                            "[{0}] Server was claimed and user chose YES to force add." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            $_server | Add-Member -NotePropertyName force -NotePropertyValue $true -force | out-null
                            
                            Try
                            {

                                $resp = Send-HPOVRequest -Uri $ServerHardwareUri -Method POST -BOdy $_server -Hostname $ApplianceConnection.Name

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }                            

                        }

                        else 
                        {

                            if ($PSBoundParameters['whatif'].ispresent) 
                            { 
                    
                                write-warning "-WhatIf was passed, would have force added '$hostname' server to appliance."
                                
                                $resp = $null
                    
                            }

                            else 
                            {

                                #If here, user chose "No", End Processing
                                write-warning "Not importing server, $hostname."
                                
                                $resp = $Null

                            }

                        }
                    
                    }

                    'SERVER_ALREADY_ADDED'
                    {

                        $_EmbeddedJson = ([Regex]::Match($errorMessage.message, "\{.*\}")).value | ConvertFrom-Json

                        # Throw exception that resource is already managed by the appliance as $Server.name
                        "[{0}] Generating error: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($errorMessage.message) | Write-Verbose

                        $ExceptionMessage = 'The server hardware has already been added as "{0}". {1} If the server is orphaned, use Remove-HPOVServer -Force Cmdlet, and then try your add again.' -f $_EmbeddedJson.name, [String]::Join(" ", $errorMessage.recommendedActions)
                        $ErrorRecord = New-ErrorRecord HPOneView.ServerHardwareResourceException ServerResourceExists ResourceExists 'Hostname' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    "INVALID_ADDR" 
                    { 
                    
                        "[{0}] Generating error: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($errorMessage.message) | Write-Verbose
                        $ExceptionMessage = '{0} {1}' -f $errorMessage.message, [String]::Join(" ", $errorMessage.recommendedActions)
                        $ErrorRecord = New-ErrorRecord HPOneView.ServerHardwareResourceException ServerResourceNotFound ObjectNotFound 'Hostname' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                    }

                }
                    
            }

        }

        if (-not($PSBoundParameters['Async']))
        {

            $resp | Wait-HPOVTaskComplete

        }

        else
        {

            $resp

        }        
       
    }

    End 
    {
        
        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVServer 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (
    
        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri","name","Server")]
        [object]$InputObject,

        [Parameter (Mandatory = $false)] 
        [switch]$Force,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose
        
        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_ServersToRemoveCol = New-Object System.Collections.ArrayList
        $_TaskCollection     = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomObject])
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing pipeline input objects."

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received object: $($InputObject | fl * | Out-String)"

            if ($InputObject.category -ne 'server-hardware')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.ServerHardwareResourceException UnsupportedResourceCategory InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided Server object {$($InputObject.name)} is an unsupported object category, '$($InputObject.category)'. Only 'server-hardware' category objects are supported. please check the Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Throw error that you cannot remove a BL server
            if ($null -ne $InputObject.locationUri -and [RegEx]::Match($InputObject.model,'BL|WS|SY').Success)
            {

                $ErrorRecord = New-ErrorRecord HPOneView.ServerHardwareResourceException CannotRemoveBLServerTypes InvalidOperation 'InputObject' -TargetType 'PSObject' -Message "The provided Server object {$($InputObject.name)} cannot be removed from the appliance, as it is a WS/BL server class. If you wish to remove a WS/BL server from the appliance, you either physically remove the server from the enclosure or remove the enclosure from the appliance. Please check the Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            [void]$_ServersToRemoveCol.Add($InputObject)

        }

        Else
        {

            ForEach ($_connection in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_connection.Name) appliance connection (of $($ApplianceConnection.Count))."

                Try
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Network Set object from Get-HPOVNetworkSet."

                    $InputObject = Get-HPOVServer $InputObject -ApplianceConnection $_connection

                    [void]$_ServersToRemoveCol.Add($InputObject)

                }

                Catch
                {


                    $PSCmdlet.ThrowTerminatingError($_)
                }

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_ServersToRemoveCol.count) Server object resources to remove."

        #Process Storage Resources
        ForEach ($_server in $_ServersToRemoveCol)
        {

            if ($PSCmdlet.ShouldProcess($_server.ApplianceConnection.Name,"Remove Server resource '$($_server.name)' from appliance")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Server resource '$($_server.name)' from appliance '$($_storagesystem.ApplianceConnection.Name)'."

                if ($PSboundParameters['force'])
                {

                    $_server.uri += "?force=true"

                }

                Try
                {

                    $_resp = Send-HPOVRequest $_server.Uri DELETE -Hostname $_server.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Start-HPOVServer
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (
    
        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias('Server')]
        [object]$InputObject,

        [Parameter (Mandatory = $false)]
        [switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_PowerControl = 'MomentaryPress'
        $_PowerState   = 'On'

        $_ServerPowerControlCol = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        #Checking if the input is PSCustomObject, and the category type is server-profiles, which could be passed via pipeline input
        if (($InputObject -is [System.Management.Automation.PSCustomObject]) -and $InputObject.category -ieq "server-hardware") 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a Server Device object: $($InputObject.name)"

            $_uri = $InputObject.uri
        
        }

        #Checking if the input is PSCustomObject, and the category type is server-hardware, which would be passed via pipeline input
        elseif (($InputObject -is [System.Management.Automation.PSCustomObject]) -and ($InputObject.category -ieq "server-profiles") -and ($InputObject.serverHardwareUri)) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a Server Profile object: $($InputObject.name)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting server hardware device assigned to Server Profile."

            $_uri = $InputObject.serverHardwareUri
        
        }

        else 
        {

            if (-not($InputObject.serverHardwareUri))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException ServerProfileUnassigned InvalidArgument 'InputObject' -TargetType $InputObjectServer.GetType().Name -Message "The Server Profile '$($InputObject.name)' is unassigned. This cmdlet only supports Server Profiles that are assigned to Server Hardware resources. Please check the input object and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message "The Parameter 'InputObject' value is invalid. Please validate the 'Server' Parameter value you passed and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }            

        }

        #Validate the server power state and lock
        Try
        {

            $_serverObj = Send-HPOVRequest $_uri -appliance $ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        #Need to add confirm prompt here.
        if (($_serverObj.powerState -ine $_PowerState -and (-not($_serverObj.powerLock)))) 
        {
        
            "[{0}] Set Server '{1}' to desired Power State '{2}'." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_serverObj.name, $_PowerState | Write-Verbose
       
            $_uri = $_serverObj.uri + "/powerState"
                
            $body = [pscustomobject]@{
            
                powerState   = $_PowerState;
                powerControl = $_PowerControl
            
            }
        
            Try
            {

                $_resp = Send-HPOVRequest $_uri PUT $body -Hostname $_serverObj.ApplianceConnection.Name
                
                if (-not($PSBoundParameters['Async']))
                {

                    $_resp = Wait-HPOVTaskComplete $_resp

                }

            }
        
            Catch
            {
        
                $PSCmdlet.ThrowTerminatingError($_)
        
            }

            [void]$_ServerPowerControlCol.Add($_resp)
                        
        }
    
        else 
        { 
        
            $_Message = $null

            if ($serverPowerState.powerState -ieq $_PowerState) 
            {
                
                 $_Message = "Requested Power State '{0}' is the same value as the current Server Power State '{0}'. "  -f $_PowerState
            
            }

            if ($serverPowerState.powerLock) 
            { 
                
                $_Message += "Server is currently under Power Lock."  
            
            }

            if ($errorMessage) 
            { 
            
                $_ErrorRecord = New-ErrorRecord HPOneView.InvalidServerPowerControlException InvalidServerPowerControlOpertion InvalidOperation 'Server' -TargetType 'PSObject' $_Message
                $PSCmdlet.WriteError($_ErrorRecord)
            
            }
        
        }
    
    }

    End
    {

        Return $_ServerPowerControlCol

    }

}

function Stop-HPOVServer
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High', DefaultParameterSetName = 'Default')]
    Param 
    (
    
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Force')]
        [ValidateNotNullOrEmpty()]
        [Alias('Server')]
        [object]$InputObject,
        
        [Parameter (Mandatory, ParameterSetName = 'Force')]
        [switch]$Force,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Force')]
        [switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Force')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_PowerControl = if ($PSBoundParameters['Force'])
        {

             'PressAndHold'

        }

        else
        {

            'MomentaryPress'

        }
        
        $_PowerState   = 'Off'

        $_ServerPowerControlCol = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        #Checking if the input is PSCustomObject, and the category type is server-profiles, which could be passed via pipeline input
        if (($InputObject -is [System.Management.Automation.PSCustomObject]) -and ($InputObject.category -ieq "server-hardware")) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a Server Device object: $($InputObject.name)"

            $_uri = $InputObject.uri
        
        }

        #Checking if the input is PSCustomObject, and the category type is server-hardware, which would be passed via pipeline input
        elseif (($InputObject -is [System.Management.Automation.PSCustomObject]) -and ($InputObject.category -ieq "server-profiles") -and ($InputObject.serverHardwareUri)) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a Server Profile object: $($InputObject.name)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting server hardware device assigned to Server Profile."

            $_uri = $InputObject.serverHardwareUri
        
        }

        else 
        {

            if (-not($InputObject.serverHardwareUri))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException ServerProfileUnassigned InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message "The Server Profile '$($InputObject.name)' is unassigned. This cmdlet only supports Server Profiles that are assigned to Server Hardware resources. Please check the input object and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message "The Parameter 'InputObject' value is invalid. Please validate the 'Server' Parameter value you passed and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }            

        }

        #Validate the server power state and lock
        Try
        {

            $_serverObj = Send-HPOVRequest $_uri -appliance $ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        #Need to add confirm prompt here.
        if (($_serverObj.powerState -ine $_PowerState -and (-not($_serverObj.powerLock)))) 
        {
        
            if ($PSCmdlet.ShouldProcess($_serverObj.name,'Poweroff server resource'))
            {

                "[{0}] Set Server '{1}' to desired Power State '{2}'." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_serverObj.name, $_PowerState | Write-Verbose
       
                $_uri = $_serverObj.uri + "/powerState"
                
                $body = [pscustomobject]@{
            
                    powerState   = $_PowerState;
                    powerControl = $_PowerControl
            
                }
        
                Try
                {

                    $_resp = Send-HPOVRequest -uri $_uri -method PUT -body $body -Hostname $_serverObj.ApplianceConnection.Name

                    if (-not($PSBoundParameters['Async']))
                    {

                        $_resp = Wait-HPOVTaskComplete -InputObject $_resp

                    }
        
                }
        
                Catch
                {
        
                    $PSCmdlet.ThrowTerminatingError($_)
        
                }

                $_resp

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] -WhatIf scenario." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] User cancelled oepration by choosing No." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }
                        
        }
    
        else 
        { 
        
            $_Message = $null

            if ($serverPowerState.powerState -ieq $_PowerState) 
            {
                
                 $_Message = "Requested Power State '{0}' is the same value as the current Server Power State '{0}'. "  -f $_PowerState
            
            }

            if ($serverPowerState.powerLock) 
            { 
                
                $_Message += "Server is currently under Power Lock."  
            
            }

            if ($errorMessage) 
            { 
            
                $_ErrorRecord = New-ErrorRecord HPOneView.InvalidServerPowerControlException InvalidServerPowerControlOpertion InvalidOperation 'Server' -TargetType 'PSObject' $_Message
                $PSCmdlet.WriteError($_ErrorRecord)
            
            }
        
        }
    
    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Restart-HPOVServer
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High', DefaultParameterSetName = 'Default')]
    Param 
    (
    
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'ColdBoot')]
        [ValidateNotNullOrEmpty()]
        [object]$Server,
        
        [Parameter (Mandatory, ParameterSetName = 'ColdBoot')]
        [switch]$ColdBoot,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'ColdBoot')]
        [switch]$Async,
        
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'ColdBoot')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Server']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_PowerControl = if ($PSBoundParameters['ColdBoot'])
        {

             'ColdBoot'

        }

        else
        {

            'Reset'

        }
        
        $_PowerState   = 'On'

        $_ServerPowerControlCol = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        #Checking if the input is PSCustomObject, and the category type is server-profiles, which could be passed via pipeline input
        if (($server -is [System.Management.Automation.PSCustomObject]) -and ($server.category -ieq "server-hardware")) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a Server Device object: $($server.name)"

            $_uri = $server.uri
        
        }

        #Checking if the input is PSCustomObject, and the category type is server-hardware, which would be passed via pipeline input
        elseif (($server -is [System.Management.Automation.PSCustomObject]) -and ($server.category -ieq "server-profiles") -and ($server.serverHardwareUri)) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a Server Profile object: $($server.name)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting server hardware device assigned to Server Profile."

            $_uri = $server.serverHardwareUri
        
        }

        else 
        {

            if (-not($server.serverHardwareUri))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException ServerProfileUnassigned InvalidArgument 'Server' -TargetType $Server.GetType().Name -Message "The Server Profile '$($Server.name)' is unassigned. This cmdlet only supports Server Profiles that are assigned to Server Hardware resources. Please check the input object and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Server' -TargetType $Server.GetType().Name -Message "The Parameter 'Server' value is invalid. Please validate the 'Server' Parameter value you passed and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }            

        }

        #Validate the server power state and lock
        Try
        {

            $_serverObj = Send-HPOVRequest $_uri -appliance $ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        #Need to add confirm prompt here.
        if (($_serverObj.powerState -ine 'Off' -and (-not($_serverObj.powerLock)))) 
        {
        
            if ($PSCmdlet.ShouldProcess($_serverObj.name,'Restart server resource'))
            {

                "[{0}] Set Server '{1}' to desired Power State '{2}'." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_serverObj.name, $_PowerState | Write-Verbose
       
                $_uri = $_serverObj.uri + "/powerState"
                
                $body = [pscustomobject]@{
            
                    powerState   = $_PowerState;
                    powerControl = $_PowerControl
            
                }
        
                Try
                {

                    $_resp = Send-HPOVRequest $_uri PUT $body -Hostname $_serverObj.ApplianceConnection.Name
                    
                    if (-not($PSBoundParameters['Async']))
                    {

                        $_resp = Wait-HPOVTaskComplete $_resp

                    }

                }
        
                Catch
                {
        
                    $PSCmdlet.ThrowTerminatingError($_)
        
                }

                [void]$_ServerPowerControlCol.Add($_resp)

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] -WhatIf scenario." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] User cancelled oepration by choosing No." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }
                        
        }
    
        else 
        { 
        
            $_Message = $null

            if ($serverPowerState.powerState -ieq $_PowerState) 
            {
                
                 $_Message = "Requested Power State '{0}' is the same value as the current Server Power State '{0}'. "  -f $_PowerState
            
            }

            if ($serverPowerState.powerLock) 
            { 
                
                $_Message += "Server is currently under Power Lock."  
            
            }

            if ($errorMessage) 
            { 
            
                $_ErrorRecord = New-ErrorRecord HPOneView.InvalidServerPowerControlException InvalidServerPowerControlOpertion InvalidOperation 'Server' -TargetType 'PSObject' $_Message
                $PSCmdlet.WriteError($_ErrorRecord)
            
            }
        
        }
    
    }

    End
    {

        Return $_ServerPowerControlCol

    }

}

function Set-HPOVServerPower 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (
    
        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ("name","uri","serverUri")]
        [object]$Server,

        [Parameter (Mandatory = $false)]
        [Alias ('PowerState')]
        [ValidateSet ("On", "Off")]
        [string]$State = "On",

        [Parameter (Mandatory = $false)]
        [ValidateSet ("PressAndHold", "MomentaryPress", "ColdBoot", "Reset")]
        [string]$powerControl = "MomentaryPress",

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        Write-Warning "This Cmdlet has been deprecated. Please use either Start-HPOVServer, Stop-HPOVServer or Restart-HPOVServer."

    }

}

function Update-HPOVServer
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (
    
        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ("name",'Server')]
        [object]$InputObject,

        [Parameter (Mandatory = $false)]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server object provided by pipeline."

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }                    

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_ServerRefreshCol = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        #Validate input object type
        #Checking if the input is System.String and is NOT a URI
        if (($InputObject -is [string]) -and (-not($InputObject.StartsWith($ServerHardwareUri)))) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a Server Name: $($InputObject)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Server from Name"

            Try
            {

                $InputObject = Get-HPOVServer -Name $InputObject -ApplianceConnection $ApplianceConnection

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Checking if the input is System.String and IS a URI
        elseif (($InputObject -is [string]) -and ($InputObject.StartsWith($ServerHardwareUri))) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a Server device URI: $($InputObject)"

            Try
            {

                $InputObject = Send-HPOVRequest -Uri $InputObject -Hostname $ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
        
        }

        #Checking if the input is PSCustomObject, and the category type is server-profiles, which could be passed via pipeline input
        elseif (($InputObject -is [System.Management.Automation.PSCustomObject]) -and ($InputObject.category -ieq "server-hardware")) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a Server Device object: $($InputObject.name)"
        
        }

        #Checking if the input is PSCustomObject, and the category type is server-hardware, which would be passed via pipeline input
        elseif (($InputObject -is [System.Management.Automation.PSCustomObject]) -and ($InputObject.category -ieq "server-profiles")) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a Server Profile object: $($InputObject.name)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting server hardware device assigned to Server Profile."

            if (-not($InputObject.serverHardwareUri))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException ServerProfileUnassigned InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message "The Server Profile '$($InputObject.name)' is unassigned. This cmdlet only supports Server Profiles that are assigned to Server Hardware resources. Please check the input object and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Try
            {

                $InputObject = Send-HPOVRequest -Uri $InputObject.serverHardwareUri -Hostname $ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
        
        }

        else 
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message "The Parameter 'Server' value is invalid. Please validate the 'Server' Parameter value you passed and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Refreshing Server Hardware device: {0}" -f $InputObject.name | Write-Verbose 
        
        $uri = $InputObject.uri + "/refreshState"

        $body = [pscustomobject]@{
            
            refreshState   = 'RefreshPending'
            
        }
        
        Try
        {

            $_resp = Send-HPOVRequest -Uri $uri -Method PUT -Body $body -Hostname $InputObject.ApplianceConnection.Name
        
        }
        
        Catch
        {
        
            $PSCmdlet.ThrowTerminatingError($_)
        
        }

        if ($PSBoundParameters['Async'])
        {

            $_resp

        }

        else
        {

            $_resp | Wait-HPOVTaskComplete

        }
    
    }

    End
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVEnclosureGroup 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]    
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false)]
        [Alias ("x", "export")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$exportFile

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $EGCollection = New-Object System.Collections.ArrayList
        
    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            if ($PSboundParameters['name']) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group name provided: '$name'"
    
                $name = $name -replace ("[*]","%25") -replace ("[&]","%26")
    
                #$uri = $enclosureGroupsUri + "?filter=name='$name'"
                $uri = $enclosureGroupsUri + "?filter=name matches '$name'"
    
            }
    
            else 
            {
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Enclosure Group name provided. Looking for all Enclosure Group resources."
    
                $uri = $enclosureGroupsUri
    
            }
    
            Try
            {
    
                $enclGrps = Send-HPOVRequest $uri -Hostname $_appliance
    
            }
            
            Catch
            {
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] API Error Caught: $($_.Exception.Message)"
    
                $PSCmdlet.ThrowTerminatingError($_)
    
            }
    
            if ($enclGrps.count -eq 0 -and $name) 
            { 
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group '$name' resource not found. Generating error"

                $ExceptionMessage = "The specified Enclosure Group '{0}' was not found on '{1}'. Please check the name and try again." -f $Name, $_appliance.Name
                $ErrorRecord = New-ErrorRecord InvalidOperationException EnclosureGroupNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)  
                
            }
    
            elseif ($enclGrps.count -eq 0) 
            { 
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Enclosure Group resources found."
    
            }
    
            else 
            {
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($enclGrps.count) Enclosure Group resources."
    
                $enclGrps.members | % { 
                    
                    $_.PSObject.TypeNames.Insert(0,'HPOneView.EnclosureGroup')    
    
                    [void]$EGCollection.Add($_) 
                    
                }
     
            }

        }

   
    }

    End 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. $($enclGrps.count) enclosure group(s) found."     

        if ($exportFile)
        { 
            
            $enclGrps.members | convertto-json -Depth 99 | Set-Content -Path $exportFile -force -encoding UTF8 
        
        }
                
        else 
        {
            
            Return $EGCollection
        
        }  

    }

}

function New-HPOVEnclosureGroup 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'C7000')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'C7000')]
        [Parameter (Mandatory, ParameterSetName = 'Synergy')]
        [Parameter (Mandatory, ParameterSetName = 'DiscoverFromEnclosure')]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Synergy')]
        [ValidateRange(1,5)]
        [int]$EnclosureCount = 1,
         
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'C7000')]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Synergy')]
        [ValidateNotNullOrEmpty()]
        [Alias ('logicalInterconnectGroupUri','logicalInterconnectGroup')]
        [object]$LogicalInterconnectGroupMapping,

        [Parameter (Mandatory = $false, ParameterSetName = 'C7000')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Synergy')]
        [Parameter (Mandatory = $false, ParameterSetName = 'DiscoverFromEnclosure')]
        [ValidateSet ('RedundantPowerFeed','RedundantPowerSupply', IgnoreCase = $false)]
        [string]$PowerRedundantMode = "RedundantPowerFeed",

        [Parameter (Mandatory = $false, ParameterSetName = 'C7000')]
        [Parameter (Mandatory = $false, ParameterSetName = 'DiscoverFromEnclosure')]
        [ValidateNotNullOrEmpty()]
        [string]$ConfigurationScript,      
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Synergy')]
        [ValidateSet ('AddressPool', 'DHCP', 'External')]
        [String]$IPv4AddressType = 'DHCP',
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Synergy')]
        [ValidateNotNullOrEmpty()]
        [object]$AddressPool,
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Synergy')]
        [ValidateSet ('None', 'Internal', 'External')]
        [String]$DeploymentNetworkType = 'None',
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Synergy')]
        [ValidateNotNullOrEmpty()]
        [object]$DeploymentNetwork,

        [Parameter (Mandatory, ParameterSetName = 'DiscoverFromEnclosure')]
        [switch]$DiscoverFromEnclosure,

        [Parameter (Mandatory, ParameterSetName = 'DiscoverFromEnclosure')]
        [ValidateNotNullorEmpty()]
        [String]$OAAddress,

        [Parameter (Mandatory, ParameterSetName = 'DiscoverFromEnclosure')]
        [ValidateNotNullorEmpty()]
        [String]$Username,

        [Parameter (Mandatory, ParameterSetName = 'DiscoverFromEnclosure')]
        [ValidateNotNullorEmpty()]
        [String]$Password,

        [Parameter (Mandatory = $false, ParameterSetName = 'DiscoverFromEnclosure')]
        [ValidateNotNullorEmpty()]
        [String]$LigPrefix,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'C7000')]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'ImportFile')]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Synergy')]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'DiscoverFromEnclosure')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory, ParameterSetName = "ImportFile")]
        [ValidateNotNullOrEmpty()]
        [Alias ("i", "import")]
        [string]$ImportFile

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Resolved Parameter Set Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PSCmdlet.ParameterSetName | Write-Verbose

        if (-not($PSBoundParameters['LogicalInterconnectGroupMapping']))
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_EnclosureGroupCreateResults = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PSCmdlet.ParameterSetName -eq 'DiscoverFromEnclosure')
        {

            if ($ApplianceConnection.ApplianceType -eq 'Composer')
            {
                
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is a Synergy Composer, which does not support Enclosure Discovery to create an Enclosure Group.' -f $ApplianceConnection.Name)
                $PSCmdlet.WriteError($ErrorRecord)
                
            }

            else
            {

                $_EnclosureGroupPreview = NewObject -EnclosureGroupPreview

                $_EnclosureGroupPreview.username  = $Username
                $_EnclosureGroupPreview.password  = $Password
                $_EnclosureGroupPreview.hostname  = $OAAddress
                $_EnclosureGroupPreview.ligPrefix = $LigPrefix

                Try
                {

                    $_EnclosurePreview = Send-HPOVRequest $EnclosurePreviewUri POST $_EnclosureGroupPreview -Hostname $ApplianceConnection

                    if (-not($PSBoundParameters['LigPrefix']))
                    {

                        $_EnclosurePreview.logicalInterconnectGroup.name = $_EnclosurePreview.logicalInterconnectGroup.name.Replace('null',$Name)

                    }

                    $LigTaskResp = Send-HPOVRequest $LogicalInterconnectGroupsUri POST $_EnclosurePreview.logicalInterconnectGroup -Hostname $ApplianceConnection | Wait-HPOVTaskComplete

                    $LogicalInterconnectGroupMapping = Send-HPOVRequest $LigTaskResp.associatedResource.resourceUri -Hostname $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }    

            }                    

        }

        if ($PSCmdlet.ParameterSetName -eq 'importFile')
        {

            $_EnclosureGroup = (GC $ImportFile).ToString()

            "[{0}] Enclosure Group object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_EnclosureGroup | Write-Verbose

            Try
            {

                $resp = Send-HPOVRequest $enclosureGroupsUri POST $_EnclosureGroup -Hostname $ApplianceConnection.Name

                $resp.PSObject.TypeNames.Insert(0,'HPOneView.EnclosureGroup')

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        else
        {
            
            $_EnclosureGroup           = NewObject -EnclosureGroup
            $_EnclosureGroup.name      = $Name
            $_EnclosureGroup.powerMode = $PowerRedundantMode

            switch ($PSCmdlet.ParameterSetName)
            {

                'Synergy'
                {

                    if ($ApplianceConnection.ApplianceType -ne 'Composer')
                    {
                
                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. Creating an Enclosure Group with OSDeployment Settings is only supported with Synergy Composers and the HPE Synergy Image Streamer.' -f $ApplianceConnection.Name)
                        $PSCmdlet.WriteError($ErrorRecord)
                
                    }

                    else
                    {

                        $_EnclosureGroup.enclosureTypeUri = $SyngergyEnclosureTypeUri

                        "[$($MyInvocation.InvocationName.ToString().ToUpper())] LIG: {0}" -f ($LogicalInterconnectGroupMapping | fl * | out-string) | Write-Verbose

                        $_c = 0

                        #Explicit Mapping with Hashtable
                        if ($LogicalInterconnectGroupMapping -is [System.Collections.IEnumerable] -and $LogicalInterconnectGroupMapping -isnot [String])
                        {
                    
                            #Loop through LIGs to build EG Interconnect Bay Mapping
                            # -LogicalInterConnectGroupMapping $MyMultiFrameVCEthLig,$MyVCFCLig
                            # -LogicalInterConnectGroupMapping @{Frame1=$MyMultiFrameVCEthLig,$MyVCFCLig;Frame2=$MyMultiFrameVCEthLig,$MyVCFCLig;Frame3=$MyMultiFrameVCEthLig}
                            foreach ($_FrameLig in $LogicalInterconnectGroupMapping.GetEnumerator())
                            {

                                if (($_FrameLig -is [System.Collections.IEnumerable] -and $_FrameLig -isnot [String] -and $_FrameLig -isnot [Array]) -or ($_FrameLig -is [System.Collections.DictionaryEntry]))
                                {

                                    $_FrameLigIndex = $_FrameLig.Key.ToLower().TrimStart('frameenclosure')

                                    $_FrameLig = $_FrameLig.Value

                                    '[{0}] Frame LIG Index ID: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_FrameLigIndex | Write-Verbose

                                }    

                                ForEach ($_LigEntry in $_FrameLig)
                                {

                                    '[{0}] Processing LIG: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_LigEntry.name | Write-Verbose

                                    if (('sas-logical-interconnect-groups' -eq $_LigEntry.category) -or ('-1' -contains $_LigEntry.enclosureIndexes))
                                    {

                                        '[{0}] Frame LIG is either Natasha or Carbon, storing EnclosrueIndexID from FrameLigIndex: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_FrameLigIndex | Write-Verbose

                                        $_EnclosureIndexID = $_FrameLigIndex

                                    }

                                    else
                                    {

                                        $_EnclosureIndexID = $null

                                    }

                                    if ('logical-interconnect-groups','sas-logical-interconnect-groups' -notcontains $_LigEntry.category)
                                    {

                                        $Message     = "The provided Logical Interconnect Group value for Bay {0} is not a valid Logical Interconnect Group Object {1}." -f $_LigEntry.Name, $_LigEntry.Value.category
                                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidLogicalInterconnectGroupCategory InvalidType 'LogicalInterconnectGroupMapping' -TargetType 'PSObject' -Message $Message
                                    
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }                    

                                    if ($_LigEntry.enclosureType -NotMatch 'SY')
                                    {

                                        $Message     = "The provided Logical Interconnect Group {0} is modeled for the HPE BladeSystem C7000 enclosure type. Please provide a Synergy Logical Interconnect Grou presource, and try again." -f $_LigEntry.name
                                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidLogicalInterconnectGroupCategory InvalidType 'LogicalInterconnectGroupMapping' -TargetType 'PSObject' -Message $Message
                                    
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }
                                    
                                    #Loop through InterconnectMapTemplate Entries
                                    ForEach ($_InterconnectMapTemplate in $_LigEntry.interconnectMapTemplate.interconnectMapEntryTemplates)
                                    {

                                        #Detect I3S setting in the Uplink Sets of the LIG
                                        if (-not $_I3SSettingsFound)
                                        {
                                            
                                            $_I3SSettingsFound = $_LigEntry.uplinkSets | ? ethernetNetworkType -eq 'ImageStreamer'
                                        
                                        }

                                        $_InterconnectBayMapping = NewObject -InterconnectBayMapping

                                        $_InterconnectBayMapping.enclosureIndex              = if (-not $_EnclosureIndexID) { $_InterconnectMapTemplate.enclosureIndex } else { $_EnclosureIndexID }
                                        $_InterconnectBayMapping.interconnectBay             = ($_InterconnectMapTemplate.logicalLocation.locationEntries | ? type -eq 'Bay').relativeValue
                                        $_InterconnectBayMapping.logicalInterconnectGroupUri = $_LigEntry.uri 

                                        #If LIG is not present in the EG interconnectBayMapping
                                        if ((Compare-Object $_EnclosureGroup.interconnectBayMappings -DifferenceObject $_InterconnectBayMapping -Property enclosureIndex,interconnectBay,logicalInterconnectGroupUri -IncludeEqual).SideIndicator -notcontains '==') 
                                        {

                                            '[{0}] Mapping Frame {1} Bay {2} -> {3} ({4})' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_InterconnectBayMapping.enclosureIndex, $_InterconnectBayMapping.interconnectBay, $_LigEntry.Name, $_LigEntry.uri | Write-Verbose

                                            [void]$_EnclosureGroup.interconnectBayMappings.Add($_InterconnectBayMapping)

                                            $_c++

                                        }
                                        
                                    }

                                }    

                            }

                        }

                        ElseIf ($LogicalInterconnectGroupMapping -is [PSCustomObject] -and ('logical-interconnect-groups','sas-logical-interconnect-groups' -contains $LogicalInterconnectGroupMapping.category))
                        {

                            if ($LogicalInterconnectGroupMapping.enclosureType -NotMatch 'SY')
                            {

                                $Message     = "The provided Logical Interconnect Group {0} is modeled for the HPE BladeSystem C7000 enclosure type. Please provide a Synergy Logical Interconnect Group resource, and try again." -f $LogicalInterconnectGroupMapping.name
                                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidLogicalInterconnectGroupCategory InvalidType 'LogicalInterconnectGroupMapping' -TargetType 'PSObject' -Message $Message
                                
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                            #Detect I3S setting in the Uplink Sets of the LIG
                            $_I3SSettingsFound = $LogicalInterconnectGroupMapping.uplinkSets | ? ethernetNetworkType -eq 'ImageStreamer'

                            ForEach ($_InterconnectMapEntry in $LogicalInterconnectGroupMapping.interconnectMapTemplate.interconnectMapEntryTemplates)
                            {

                                ForEach ($_LocationEntry in ($_InterconnectMapEntry.logicalLocation.locationEntries | ? type -eq 'Bay'))
                                {

                                    if (-not($_EnclosureGroup.interconnectBayMappings | ? interconnectBay -eq $_LocationEntry.relativeValue))
                                    {

                                        $_InterconnectBayMapping = NewOBject -InterconnectBayMapping

                                        $_InterconnectBayMapping.interconnectBay             = ($_LocationEntry | ? type -eq 'bay').relativeValue
                                        $_InterconnectBayMapping.logicalInterconnectGroupUri = $LogicalInterconnectGroupMapping.uri

                                        $_InterconnectBayMapping = $_InterconnectBayMapping | Select * -ExcludeProperty enclosureIndex

                                        '[{0}] Mapping Interconnect Bay to LIG URI {1} --> {2}' -f $MyInvocation.InvocationName.ToString().ToUpper(),($_LocationEntry | ? type -eq 'bay').relativeValue, $LogicalInterconnectGroupMapping.uri | Write-Verbose 

                                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Interconnect Bay Mapping Entry found in LIG resource: $($_LocationEntry)" 

                                        [void]$_EnclosureGroup.interconnectBayMappings.Add($_InterconnectBayMapping)

                                    } 

                                    $_c++

                                }

                            }

                        }

                        else
                        {

                            '[{0}] Invalid LIG Category value provided: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), ($LogicalInterconnectGroupMapping | Out-String) | Write-Verbose

                            $Message     = "Invalid LogicalInterconnectGroupMapping value provided '{0}'. Please check the value and try again." -f ($LogicalInterconnectGroupMapping )
                            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidLogicalInterconnectGroupCategory InvalidType 'LogicalInterconnectGroupMapping' -TargetType $LogicalInterconnectGroupMapping.GetType().Fullname -Message $Message
                                
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        $_EnclosureGroup.interconnectBayMappingCount = $_c

                        if (-not($PSBoundParameters['EnclosureCount']))
                        {

                            if ($LogicalInterconnectGroupMapping -is [System.Collections.IEnumerable])
                            {

                                $_EnclosureGroup.enclosureCount = $LogicalInterconnectGroupMapping.Count

                            }

                            else
                            {

                                $_EnclosureGroup.enclosureCount = $LogicalInterconnectGroupMapping.enclosureIndexes.Count

                            }

                        }

                        else
                        {

                            $_EnclosureGroup.enclosureCount = $EnclosureCount

                        }

                        $_DeploymentSettings                = NewObject -EnclosureGroupI3SDeploymentSettings
                        $_DeploymentSettings.deploymentMode = $DeploymentNetworkType

                        $_EnclosureGroup.osDeploymentSettings = NewObject -DeploymentModeSettings

                        # // Need to update error message that I3S Setting was detected in LIG but no DeploymentSetting defined in EG params.
                        if ($DeploymentNetworkType -eq 'None' -and $_I3SSettingsFound)
                        {

                            $Message     = "The provided LogicalInterconnectGroupMapping Parameter contains 1 or more LIGs with an ImageStreamer Uplink Set configured, but no DeploymentNetwork or DeploymentNetworkType Parameter were provided. You must specify a DeploymentNetwork and DeploymentNetworkType cannot be 'none'."
                            $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidDeploymentNetworkSettings InvalidArgument 'DeploymentNetworkType' -TargetType 'PSObject' -Message $message
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)   

                        }

                        elseif ($DeploymentNetworkType -ne 'None')
                        {
                            
                            $_EnclosureGroup.osDeploymentSettings.manageOSDeployment = $true    

                            if ($DeploymentNetworkType -eq 'External')
                            {

                                if (-not $DeploymentNetwork)
                                {

                                    '[{0}] DeploymentNetworkType is set to "External", but no DeploymentNetwork value.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                    $Message     = "The DeploymentNetworkType was set to 'External', which requires the DeploymentNetwork parameter."
                                    $ErrorRecord = New-ErrorRecord InvalidOperationException NullDeploymentNetwork InvalidArgument 'DeploymentNetworkType' -TargetType 'SwitchParameter' -Message $Message

                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                switch ($DeploymentNetwork.GetType())
                                {

                                    'PSCustomObject'
                                    {

                                        if ($DeploymentNetworkType.category -ne 'ethernet-networks')
                                        {

                                            $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidEthernetNetworkResource InvalidArgument 'DeploymentNetworkType' -TargetType 'PSObject' -Message "The provided Deployment Network resource object is not an Ethernet Network. Please validate the Parameter value and try again."
                                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)   

                                        }

                                        if ($DeploymentNetworkType.ethernetNetworkType -ne 'Tagged')
                                        {

                                            $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidEthernetNetworkResource InvalidArgument 'DeploymentNetworkType' -TargetType 'PSObject' -Message "The provided Deployment Network resource object is not a 'Tagged' Ethernet Network. Please validate the Parameter value and try again."
                                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)   

                                        }

                                    }

                                    'String'
                                    {

                                        Try
                                        {

                                            $DeploymentNetwork = Get-HPOVNetwork -Name $DeploymentNetwork -ApplianceConnection $ApplianceConnection -ErrorAction Stop

                                        }

                                        Catch
                                        {

                                            $PSCmdlet.ThrowTerminatingError($_)

                                        }

                                        if ($DeploymentNetwork.ethernetNetworkType -ne 'Tagged')
                                        {


                                            $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidEthernetNetworkResource InvalidArgument 'DeploymentNetwork' -Message "The provided Deployment Network resource object is not a 'Tagged' Ethernet Network. Please validate the Parameter value and try again."
                                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)   

                                        }

                                    }

                                }
        
                                $_DeploymentSettings.deploymentNetworkUri = $DeploymentNetwork.uri            

                            }

                        }

                        $_EnclosureGroup.osDeploymentSettings.deploymentModeSettings = $_DeploymentSettings    

                        $_EnclosureGroup.ipAddressingMode = $EnclosureGroupIpAddressModeEnum[$IPv4AddressType]

                        foreach ($_Pool in $AddressPool)
                        {

                            "[$($MyInvocation.InvocationName.ToString().ToUpper())] IPv4 Pool Object: {0}" -f ($_Pool | fl * | out-string) | Write-Verbose

                            if ($_Pool.category -ne 'id-range-IPv4')
                            {
                        
                                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolResourceException InvalidAddressPoolResource InvalidArgument 'AddressPool' -TargetType 'PSObject' -Message "An invalid Address Pool object was provided. Please check the value and try again."
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                        
                            }

                            [void]$_EnclosureGroup.ipRangeUris.Add($_Pool.uri)

                        }
                    

                    }

                }

                {'C7000','DiscoverFromEnclosure' -contains $_}
                {

                    $_EnclosureGroup.interconnectBayMappingCount = 8

                    #Process LIG Object here, and will be on a single Appliance Connection
                    if ($LogicalInterconnectGroupMapping -is [PSCustomObject]) 
                    { 
            
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Single LIG Object: $($LogicalInterconnectGroupMapping | fl * | out-string)" 

                        #Check to make sure the object is a LIG, generate error if not
                        if ($LogicalInterconnectGroupMapping.category -ne 'logical-interconnect-groups')
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid LIG Category value provided '$($LogicalInterconnectGroupMapping.category)'"

                            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidLogicalInterconnectGroupCategory InvalidType 'LogicalInterconnectGroupMapping' -TargetType 'PSObject' -Message "Invalid [PSObject] value provided '$LogicalInterconnectGroupMapping'. Logical Interconnect Group category must Begin with 'logical-interconnect-groups'. Please check the value and try again."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Will Process {0} Interconnect Bay Logical Location Entries in LIG Object." -f ($LogicalInterconnectGroupMapping.interconnectMapTemplate.interconnectMapEntryTemplates.logicalLocation | Measure-Object).Count | Write-Verbose

                        $_c = 1

                        #Process Interconnect Bay Mapping, which is 1 LIG
                        ForEach ($_LigBayMapping in $LogicalInterconnectGroupMapping.interconnectMapTemplate.interconnectMapEntryTemplates)
                        {

                            "Processing {0} of {1} Bay Mappings" -f $_c,($LogicalInterconnectGroupMapping.interconnectMapTemplate.interconnectMapEntryTemplates.logicalLocation | Measure-Object).Count | Write-Verbose

                            $_InterconnectBayMapping = NewOBject -InterconnectBayMapping

                            $_InterconnectBayMapping.interconnectBay             = ($_LigBayMapping.logicalLocation.locationEntries | ? type -EQ 'bay').relativeValue
                            $_InterconnectBayMapping.logicalInterconnectGroupUri = $LogicalInterconnectGroupMapping.uri

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Interconnect Bay Mapping Entry found in LIG resource: $($_LigBayMapping)" 

                            [void]$_EnclosureGroup.interconnectBayMappings.Add($_InterconnectBayMapping)

                            $_c++

                        }

                    }

                    elseif ($LogicalInterconnectGroupMapping -is [System.Collections.IEnumerable] -and $LogicalInterconnectGroupMapping -isnot [String])
                    {

                        ForEach ($_key in $LogicalInterconnectGroupMapping.Keys)
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Hashtable key '$_key'"

                            $_InterconnectBayMapping = NewOBject -InterconnectBayMapping

                            switch (($LogicalInterconnectGroupMapping.$_key).GetType().Name)
                            {

                                'PSCustomObject'
                                {

                                    #Validate object is a LIG
                                    if (-not(($LogicalInterconnectGroupMapping.$_key).category -eq 'logical-interconnect-groups'))
                                    {

                                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid [PSCustomObject] value provided '$(($LogicalInterconnectGroupMapping.$_key).category)' for '$_key' Hashtable entry."
                                    
                                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidLogicalInterconnectGroupMappingObject InvalidArgument 'LogicalInterconnectGroupMapping' -TargetType 'PSObject' -Message "Invalid [PSCustomObject] value provided '$(($LogicalInterconnectGroupMapping.$_key).category)' for '$_key' Hashtable entry. Logical Interconnect Group object category must be 'logical-interconnect-groups'. Please check the value and try again."
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }

                                    $_InterconnectBayMapping.interconnectBay             = ((($LogicalInterconnectGroupMapping.$_key).interconnectMapTemplate.interconnectMapEntryTemplates.LogicalLocation.locationEntries) | ? { $_.type -EQ 'bay' -and $_.relativeValue -EQ $_key}).relativeValue
                                    $_InterconnectBayMapping.logicalInterconnectGroupUri = ($LogicalInterconnectGroupMapping.$_key).uri

                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Interconnect Bay Mapping Entry: $($_InterconnectBayMapping)" 

                                }

                                'String'
                                {

                                    #Value is an Objects URI
                                    if (($LogicalInterconnectGroupMapping.$_key).StartsWith($logicalInterconnectGroupUri))
                                    {

                                        $_InterconnectBayMapping.interconnectBay             = $_key
                                        $_InterconnectBayMapping.logicalInterconnectGroupUri = $LogicalInterconnectGroupMapping.$_key

                                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Interconnect Bay Mapping Entry: $($_InterconnectBayMapping)" 

                                    }

                                    #Object Name value
                                    else
                                    {

                                        Try
                                        {
                                    
                                            $_LogicalInterconnectGroupObject = Get-HPOVLogicalInterconnectGroup $LogicalInterconnectGroupMapping.$_key -ApplianceConnection $ApplianceConnection.Name

                                            $_InterconnectBayMapping.interconnectBay             = $_key
                                            $_InterconnectBayMapping.logicalInterconnectGroupUri = $_LogicalInterconnectGroupObject.uri
                                    
                                        }
                                    
                                        Catch
                                        {

                                            $PSCmdlet.ThrowTerminatingError($_)

                                        }

                                    }

                                }

                            }

                            [void]$_EnclosureGroup.interconnectBayMappings.Add($_InterconnectBayMapping)

                        }

                    }

                    else
                    {

                        '[{0}] Invalid LIG Category value provided: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), ($LogicalInterconnectGroupMapping | Out-String) | Write-Verbose

                        $Message     = "Invalid LogicalInterconnectGroupMapping value provided '{0}'. Please check the value and try again." -f ($LogicalInterconnectGroupMapping.ToString())
                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidLogicalInterconnectGroupCategory InvalidType 'LogicalInterconnectGroupMapping' -TargetType $LogicalInterconnectGroupMapping.GetType().Fullname -Message $Message
                            
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if (($_EnclosureGroup.interconnectBayMappings | Measure-Object).count -lt 8)
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding null interconnectBayMapping entries." 

                        for ($b = $_EnclosureGroup.interconnectBayMappingCount - $_EnclosureGroup.interconnectBayMappings.count; $b -ne 0; $b--)
                        {

                            $_InterconnectBayMapping = NewObject -InterconnectBayMapping

                            $n = 1

                            do
                            {

                                $_bayId = $null

                                if (-not($_EnclosureGroup.interconnectBayMappings | ? interconnectBay -eq $n))
                                {

                                    $_bayId = $n

                                }

                                #ERROR, we should never get more than the number of $_EnclosureGroup.interconnectBayMappingCount
                                if ($n -gt $_EnclosureGroup.interconnectBayMappingCount)
                                {

                                    $ErrorRecord = New-ErrorRecord System.InvalidOperationException InvalidOperation InvalidOperation 'InterconnectBayMappingCount' -TargetType 'Int' -Message "Could not determine Enclosure Group interconnectBay ID (`$_bayId). (`$n = $n)"

                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                $n++

                            }
                            until ($_bayId)

                            $_InterconnectBayMapping.interconnectBay = $_bayId

                            [void]$_EnclosureGroup.interconnectBayMappings.Add($_InterconnectBayMapping)

                        }
            
                    }

                    $_EnclosureGroup.configurationScript = $ConfigurationScript

                }

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group object: $($_EnclosureGroup | out-string)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating $($_EnclosureGroup.name) Enclosure Group"

            Try
            {

                $resp = Send-HPOVRequest $EnclosureGroupsUri POST $_EnclosureGroup -Hostname $ApplianceConnection.Name

                $resp.PSObject.TypeNames.Insert(0,'HPOneView.EnclosureGroup')

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        [void]$_EnclosureGroupCreateResults.Add($resp)

    }

    End 
    {

        return $_EnclosureGroupCreateResults

    }

}

function Remove-HPOVEnclosureGroup 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default",SupportsShouldProcess,ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri", "name", "EnclosureGroup",'Resource')]
        [object]$InputObject,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$Force

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Enclosure'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection           = New-Object System.Collections.ArrayList
        $_EnclosureGroupCollection = New-OBject System.Collections.ArrayList
        
    }

    Process 
    {

        if  ($ApplianceConnection.Count -eq 0)
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoAuthSessionFound InvalidArgument 'ApplianceConnection' -Message 'No ApplianceConnections were found. Please use Connect-HPOVMgmt to establish an appliance connection.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Object provided: $($InputObject | FL * | Out-String)"

            If ($InputObject.category -eq 'enclosure-groups')
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType PSObject -Message "The Enclosure Group resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_EnclosureGroupCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType PSObject -Message "The Enclosure Group resource is not an expected category type [$($InputObject.category)]. Allowed resource category type is 'enclosure-groups'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            foreach ($enclosuregroup in $InputObject) 
            {

                #Enclosure passed is a URI
                if (($enclosuregroup -is [String]) -and [System.Uri]::IsWellFormedUriString($enclosure,'Relative')) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received URI: $($enclosuregroup)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Enclosure Group Object"

                    # // NEED APPLIANCE NAME HERE with If Condition
                    Try
                    {
                        
                        $enclosuregroup = Send-HPOVRequest $enclosuregroup -ApplianceConnection $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                #Enclosure passed is the Name
                elseif (($enclosuregroup -is [string]) -and (-not($enclosuregroup.startsWith("/rest")))) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received Enclosure Group Name $($enclosuregroup)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Enclosure Group object from Get-HPOVEnclosureGroup"
                    
                    # // NEED APPLIANCE NAME HERE with If Condition
                    Try
                    {

                        $enclosuregroup = Get-HPOVEnclosureGroup -Name $enclosuregroup -ErrorAction Stop -ApplianceConnection $ApplianceConnection

                    }
                    

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                #Enclosure passed is an object
                elseif ($enclosuregroup -is [PSCustomObject] -and ($enclosuregroup.category -ieq 'enclosure-groups')) 
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Object provided: $($enclosuregroup | FL * | out-string)"
                
                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Resource' -TargetType 'PSObject' -Message "Invalid Resource Parameter: $($enclosuregroup | FL * | Out-String)"
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                [void]$_EnclosureGroupCollection.Add($enclosuregroup)

            }

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_EnclosureGroupCollection.count) Enclosure Group resources to remove."

        #Process Enclosure Resources
        ForEach ($_enclosuregroup in $_EnclosureGroupCollection)
        {

            if ($PSCmdlet.ShouldProcess($_enclosuregroup.name,"Remove Enclosure Group from appliance '$($_enclosuregroup.ApplianceConnection.Name)'?")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Enclosure Group '$($_enclosuregroup.name)' from appliance '$($_enclosuregroup.ApplianceConnection.Name)'."

                Try
                {
                    
                    if ($PSBoundParameters['Force'])
                    {

                        $_enclosuregroup.uri += "?force=true"

                    }

                    $_resp = Send-HPOVRequest $_enclosuregroup.Uri DELETE -Hostname $_enclosuregroup.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Add-HPOVEnclosure 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Managed", SupportsShouldProcess, ConfirmImpact = "High")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [ValidateNotNullOrEmpty()]
        [Alias ("oa")]
        [string]$Hostname,
         
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Managed")]
        [ValidateNotNullOrEmpty()]
        [Alias ("eg",'EnclGroupName')]
        [object]$EnclosureGroup,

        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [ValidateNotNullOrEmpty()]
        [Alias ("u", "user")]
        [string]$Username,

        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [ValidateNotNullOrEmpty()]
        [Alias ("p", "pw")]
        [Object]$Password,

        [Parameter (Mandatory = $false, ParameterSetName = "Managed")]
        [ValidateSet ('OneView', 'OneViewNoiLO', IgnoreCase = $False)]
        [Alias ("license", "l")]
        [string]$LicensingIntent = 'OneView',

        [Parameter (Mandatory = $false, ParameterSetName = "Managed")]
        [Alias ("fwIso","fwBaselineIsoFilename")]
        [object]$Baseline,

        [Parameter (Mandatory = $false, ParameterSetName = "Managed")]
        [Alias ('forceFw','forceInstall')]
        [switch]$ForceInstallFirmware,

        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [switch]$Monitored,

        [Parameter (Mandatory = $False, ParameterSetName = "Monitored")]
        [Parameter (Mandatory = $False, ParameterSetName = "Managed")]
        [switch]$Async,

        [Parameter (Mandatory = $False, ParameterSetName = "Monitored")]
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "Managed")]
        [ValidateNotNullorEmpty()]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['EnclosureGroup']) -and ($PSCmdlet.ParameterSetName -ne 'Monitored'))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection -is [HPOneView.Appliance.Connection]) -and (-not($ApplianceConnection -is [System.String])))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException InvalidApplianceConnectionDataType InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter is not type [HPOneView.Appliance.Connection] or [System.String]. Please correct this value and try again.'
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif  ($ApplianceConnection.Count -gt 1)
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value. Please correct this and try again.'
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            else
            {

                Try 
                {
    
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -TargetType $ApplianceConnection.GetType().Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

        if ($Password -is [SecureString])
        {

            $Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

    }

    Process 
    {

        #Locate the Enclosure Group specified
        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Starting"

        $_import          = NewObject -EnclosureImport
        $_import.hostname = $hostname
        $_import.username = $username
        $_import.password = $password

        If ($PSCmdlet.ParameterSetName -eq 'Monitored')
        {

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Building Monitored Enclosure request"

            $_import.licensingIntent = "OneViewStandard"
            $_import.state           = "Monitored"

        }

        else
        {

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Building Managed Enclosure request"

            switch ($EnclosureGroup.GetType().Name)
            {

                'PSCustomObject'
                {

                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - EnclosureGroup Parameter is 'PSCustomObject'"

                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - EnclosureGroup object category: '$($EnclosureGroup.category)'"

                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - EnclosureGroup object name: '$($EnclosureGroup.name)'"

                    if ($EnclosureGroup.category -ne 'enclosure-groups')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.EnclosureGroupResourceException InvalidEnclosureGroupObject InvalidArgument 'EnclosureGroup' -TargetType 'PSObject' -Message "The EnclosureGroup Parameter value contains an invalid or unsupported resource category, '$($EnclosureGroup.category)'. The object category must be 'enclosure-groups'. Please correct the value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    else
                    {

                        $_enclosuregroup = $EnclosureGroup.PSObject.Copy()

                    }

                }

                'String'
                {

                    if ($EnclosureGroup.StartsWith($enclosureGroupsUri))
                    {

                        Try
                        {

                            $_enclosuregroup = Get-HPOVEnclosureGroup -Name $EnclosureGroup -ErrorAction Stop -ApplianceConnection $ApplianceConnection

                        }

                        catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                    else
                    {

                        Try
                        {

                            $_enclosuregroup = Get-HPOVEnclosureGroup -Name $EnclosureGroup -ErrorAction Stop -ApplianceConnection $ApplianceConnection

                        }
                            
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }
                        
                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Found Enclosure Group $($_enclosuregroup | out-String)"

                }

            }

            $_import.licensingIntent      = $licensingIntent
            $_import.enclosureGroupUri    = $_enclosuregroup.uri
            $_import.forceInstallFirmware = [bool]$forceInstallFirmware
            $_import.updateFirmwareOn     = "EnclosureOnly" 
            
            if ($PSBoundParameters['Baseline']) 
            {
                    
                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Firmware Baseline is to be configured"
                    
                switch ($baseline.Gettype().Name) 
                {

                    "String" 
                    {
                            
                        if ($baseline.StartsWith($script:fwDriversUri)) 
                        {
                                
                            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Firmware Baseline URI Provided '$Basline'"
                                
                            Try
                            {

                                $fwBaseLine = Send-HPOVRequest $baseline -Hostname $ApplianceConnection.Name

                            }
                                
                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }
                        
                            
                        }
                            
                        elseif ((-not ($baseline.StartsWith($script:fwDriversUri)) -and ($baseline.StartsWith('/rest/')))) 
                        {

                            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Invalid Firmware Baseline URI Provided '$Basline'"
                                
                            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException InavlideBaselineUri InvalidArgument 'Baseline' -Message "The Basline URI '$baseline' provided does not Begin with '$script:fwDriversUri'. Please correct the value and try again."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                        }

                        else 
                        {

                            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Firmware Baseline Name Provided '$Basline'"
                                
                            if ($Baseline -match ".iso") 
                            {

                                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Getting Baseline based on isoFileName."

                                Try
                                {

                                    $FirmwareBaslineName = $Baseline.Clone()

                                    $fwBaseLine = Get-HPOVBaseline -isoFileName $Baseline -ApplianceConnection $ApplianceConnection -ErrorAction SilentlyContinue

                                    If (-not $fwBaseLine)
                                    {

                                        $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $FirmwareBaslineName
                                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Baseline' -Message $ExceptionMessage
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }

                                }

                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }
                                                                
                            }

                            else 
                            {

                                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Getting Baseline based on Baseline Name."

                                Try
                                {

                                    $FirmwareBaslineName = $Baseline.Clone()

                                    $fwBaseLine = Get-HPOVBaseline -SppName $Baseline -ApplianceConnection $ApplianceConnection -ErrorAction SilentlyContinue

                                    If (-not $fwBaseLine)
                                    {

                                        $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $FirmwareBaslineName
                                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Baseline' -Message $ExceptionMessage
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }

                                }

                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }
                                
                            }

                        }

                        $_import.firmwareBaselineUri = $fwBaseLine.uri
                        
                    }

                    "PSCustomObject" 
                    {

                        if ($baseline.category -eq "firmware-drivers" -and $baseline.ApplianceConnection.Name -eq $ApplianceConnection.Name) 
                        {

                            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Firmware Baseline Object Provided: $($Basline | Out-String)"
                                
                            $_import.firmwareBaselineUri = $Basline.uri    

                        }

                        else 
                        {

                            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Invalid Firmware Baseline Object Provided: $($Basline | Out-String)"

                            if ($baseline.category -ne "firmware-drivers" -and $baseline.ApplianceConnection.Name -eq $ApplianceConnection.Name) 
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException InvalideBaselineObject InvalidArgument 'Baseline' -TargetType 'PSObject' -Message "The Basline Category '$($baseline.category)' provided does not match the required value 'firmware-drivers'. Please correct the value and try again."

                            }
                                
                            elseif ($baseline.category -eq "firmware-drivers" -and $baseline.ApplianceConnection.Name -ne $ApplianceConnection.Name) 
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException InvalidBaselineOrigin InvalidArgument 'Baseline' -TargetType 'PSObject' -Message "The Basline '$($baseline.name)' provided does not originate from the same ApplianceConnection you have specified. Please correct the value and try again."

                            }
                                
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                }

            }       

        }

        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Sending request to claim enclosure"

        Try
        {

            $resp = Send-HPOVRequest -uri $EnclosuresUri -Method POST -Body $_import -Hostname $ApplianceConnection.Name | Wait-HPOVTaskStart

        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - task response: $($resp | out-string)"

        #Check to see if the task errored, which should be in the Task Validation stage
        if ($resp.taskState -ne "Running") 
        {

            if ($resp.taskState -eq "Error")
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Task error found $($resp.taskState) $($resp.stateReason) "

                if ($resp.taskerrors | Where-Object { ($_.errorCode -eq "ENCLOSURE_ALREADY_MANAGED") -or ($_.errorCode -eq "ENCLOSURE_MANAGED_BY_VCM") }) 
                {
                
                    $errorMessage = $resp.taskerrors | Where-Object { ($_.errorCode -eq "ENCLOSURE_ALREADY_MANAGED") -or ($_.errorCode -eq "ENCLOSURE_MANAGED_BY_VCM") }

                    $externalManagerType = $errorMessage.data.managementProduct
                    $externalManagerIP   = $errorMessage.data.managementUrl.Replace("https://","")
                    
                    Try
                    {

                         $externalManagerFQDN = [System.Net.DNS]::GetHostByAddress($externalManagerIP)

                    }

                    Catch
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Unable to resolve IP Address to DNS A Record."
                        $externalManagerFQDN = [PSCustomObject]@{HostName = 'UnknownFqdn'; Aliases = @(); AddressList = @($externalManagerIP.Clone())}

                    }

                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Found enclosure '$hostname' is already being managed by $externalManagerType at $externalManagerIP."
                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - $externalManagerIP resolves to $($externalManagerFQDN | out-string)"
                    
                    write-warning "Enclosure '$hostname' is already being managed by $externalManagerType at $externalManagerIP ($($externalManagerFQDN.HostName))."

                    if ($PSCmdlet.ShouldProcess($hostname,"Enclosure '$hostname' is already being managed by $externalManagerType at $externalManagerIP ($($externalManagerFQDN.HostName)). Force add?")) 
                    {
                    
                        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Server was claimed and user chose YES to force add."

                        $_import.force = $true
                        
                        Try
                        {
                        
                            $resp = Send-HPOVRequest $EnclosuresUri POST $_import -Hostname $ApplianceConnection.Name
                        
                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
                        

                    }

                    else 
                    {

                        if ($PSBoundParameters['whatif'].ispresent) 
                        {     
                    
                            write-warning "-WhatIf was passed, would have force added '$hostname' enclosure to appliance."

                            $resp = $null
                    
                        }

                        else 
                        {

                            #If here, user chose "No", End Processing
                            write-warning "Not importing enclosure, $hostname."

                            $resp = $Null

                        }

                    }

                }

                else 
                {

                    $errorMessage = $resp.taskerrors

                    if ($errorMessage -is [Array]) 
                    { 
                
                        #Loop to find a Message value that is not blank.
                        $displayMessage = $errorMessage | ? { $_.message }

                        $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException $displayMessage.errorCode InvalidResult 'New-HPOVEnclosure' -Message $displayMessage.message 
                    
                    }
                
                    else 
                    { 
                        
                        $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException $errorMessage.errorCode InvalidResult 'New-HPOVEnclosure' -Message ($errorMessage.details + " " + $errorMessage.message) 
                    
                    }

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

        }

        if (-not($PSBoundParameters['Async']))
        {

            Try
            {

                $resp = Wait-HPOVTaskComplete -InputObject $resp

            }

            catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }        

        [void]$colStatus.Add($resp)

    }

    End 
    {
        
        Return $colStatus

    }

}

function Add-HPOVRemoteFrame
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [string]$Hostname,
        
        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [switch]$Async,
        
        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose
        
        $Caller = (Get-PSCallStack)[1].Command
        
        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
        
        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
        
        if (-not($ApplianceConnection -is [HPOneView.Appliance.Connection]) -and (-not($ApplianceConnection -is [System.String])))
        {
            
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException InvalidApplianceConnectionDataType InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter is not type [HPOneView.Appliance.Connection] or [System.String]. Please correct this value and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
        
        }

        elseif  ($ApplianceConnection.Count -gt 1)
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value. Please correct this and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
        
        }

        else
        {

            Try 
            {

                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -TargetType $ApplianceConnection.GetType().Name -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {
        
        #Locate the Enclosure Group specified
        "[{0}] - Starting" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
        
        if (-not $Hostname.StartsWith('fe80:'))
        {

            $ExceptionMessage = 'The value provided for Hostname, {0}, is not a valid IPv6 Link Local Address.' -f $Hostname
            $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException InvalidIPv6LinkLocalAddress InvalidArgument 'Hostname' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_RemoteFrameAdd = @{hostname = $Hostname}

        "[{0}] - Sending request to claim remote frame: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Hostname | Write-Verbose
        
        Try
        {

            $resp = Send-HPOVRequest -uri $EnclosuresUri -Method POST -Body $_RemoteFrameAdd -Hostname $ApplianceConnection | Wait-HPOVTaskStart

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not $PSBoundParameters['Async'])
        {
            
            Try
            {

                $resp | Wait-HPOVTaskComplete

            }

            catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        else
        {

            $resp

        }    

    }

    End 
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Update-HPOVEnclosure 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Refresh", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (
        
        [Parameter (ValueFromPipeline, Mandatory = $false, ParameterSetName = "Reapply")]
        [Parameter (ValueFromPipeline, Mandatory = $false, ParameterSetName = "Refresh")]
        [ValidateNotNullOrEmpty()]
        [Alias('Enclosure')]
        [object]$InputObject,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "Reapply")]
        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "Refresh")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory, ParameterSetName = "Refresh")]
        [Switch]$Refresh,

        [Parameter (Mandatory = $false, ParameterSetName = "Refresh")]
        [String]$Hostname,

        [Parameter (Mandatory = $false, ParameterSetName = "Refresh")]
        [string]$Username,

        [Parameter (Mandatory = $false, ParameterSetName = "Refresh")]
        [Object]$Password,

        [Parameter (Mandatory, ParameterSetName = "Reapply")]
        [Switch]$Reapply,

        [Parameter (Mandatory = $false, ParameterSetName = "Reapply")]
        [Parameter (Mandatory = $false, ParameterSetName = "Refresh")]
        [switch]$Async

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection           = New-Object System.Collections.ArrayList
        $_EnclosureCollection      = New-OBject System.Collections.ArrayList
        $_RefreshOptionsCollection = New-OBject System.Collections.ArrayList
        
    }

    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomobject]) 
        {
        
            "[{0}] Processing Pipeline input." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            #error if the input value is not a PSObject
            if (-not $InputObject -is [PSCustomObject])
            {

                $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException InvalidEnclosureObjectType InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided InputObject value is not a valid PSObject ($($InputObject.GetType().Name)). Please correct your input value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure PSObject: $($InputObject | FL * | out-string)."

            #Validate the Input object is the allowed category
            if ($InputObject.category -ne 'enclosures')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException InvalidEnclosureCategory InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided InputObject object ($($InputObject.name)) category '$($InputObject.category)' is not an allowed value. Expected category value is 'enclosures'. Please correct your input value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if(-not $InputObject.ApplianceConnection)
            {

                $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException InvalidEnclosureObject InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided InputObject object ($($InputObject.name)) does not contain the required 'ApplianceConnection' object property. Please correct your input value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            [void]$_EnclosureCollection.Add($InputObject)
        
        }

        #Not Pipeline input, and support Array of Enclosure Name or PSObject
        else
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Enclosure Parameter."

            ForEach ($_encl in $InputObject)
            {
                    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure value: $($_encl)."

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Looking for Enclosure Name on connected sessions provided"

                #Loop through all Appliance Connections
                ForEach ($_appliance in $ApplianceConnection)
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($_appliance.Name)' Session."

                    Try
                    {

                        $_resp = Get-HPOVLogicalEnclosure $_encl -ApplianceConnection $_appliance.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    [void]$_EnclosureCollection.Add($_resp)

                }
                    
            }

        }

    }

    End
    {
        #Perform the work
        ForEach ($_enclosure in $_EnclosureCollection) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Enclosure: '$($_enclosure.name) [$($_enclosure.uri)]'"

            switch ($PSCmdlet.ParameterSetName) 
            {

                "Reapply" 
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Reapply Enclosure configuration."

                    $_Params = @{ uri = $_enclosure.uri + "/configuration"; method = 'PUT' }
                        
                }
                        
                "Refresh"
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Refreshing Enclosure data."

                    $_RefreshOptions = NewObject -EnclosureRefresh

                    $_uri = $_enclosure.uri + "/refreshState"

                    if ($_enclosure.state -ieq 'unmanaged' -and $_enclosure.stateReason -ieq 'unowned')
                    {

                        $_RefreshOptions.refreshForceOptions = NewObject -EnclosureRefreshForceOptions

                        if (-not $PSBoundParameters['Username'])
                        {

                            $ExceptionMessage = "The appliance can no longer communicate with {0} Enclosure, and requires a valid Username, Password and Hostname/IPAddress. Please provide the correct parameters." -f $_enclosure.name
                            $ErrorRecord = New-ErrorRecord HPOneView.UnsupportedArgumentException MissingRequiredUsernameParameter InvalidOperation 'Enclosure' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        if (-not $PSBoundParameters['Password'])
                        {

                            $ExceptionMessage = "The appliance can no longer communicate with {0} Enclosure, and requires a valid Username, Password and Hostname/IPAddress. Please provide the correct parameters." -f $_enclosure.name
                            $ErrorRecord = New-ErrorRecord HPOneView.UnsupportedArgumentException MissingRequiredPasswordParameter InvalidOperation 'Password' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        if (-not $PSBoundParameters['Hostname'])
                        {

                            $ExceptionMessage = "The appliance can no longer communicate with {0} Enclosure, and requires a valid Username, Password and Hostname/IPAddress. Please provide the correct parameters." -f $_enclosure.name
                            $ErrorRecord = New-ErrorRecord HPOneView.UnsupportedArgumentException MissingRequiredHostnameParameter InvalidOperation 'Hostname' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        if ($Password -is [SecureString])
                        {

                            $Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

                        }

                        $_RefreshOptions.refreshForceOptions.address  = $Hostname
                        $_RefreshOptions.refreshForceOptions.username = $Username
                        $_RefreshOptions.refreshForceOptions.password = $Password

                    }

                    $_Params = @{ uri = $_uri; method = 'PUT'; body = $_RefreshOptions }
                        
                }
                
            }
            
            if ($PSCmdlet.ShouldProcess($_enclosure.name,"$($PSCmdlet.ParameterSetName) Enclosure configuration. WARNING: Depending on this action, there might be a brief outage."))
            { 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to $($PSCmdlet.ParameterSetName) Enclosure configuration"

                Try
                {
                    
                    $_task = Send-HPOVRequest @_Params -Hostname $_enclosure.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if (-not $PSBoundParameters['Async'])
                {
                    
                     $_task | Wait-HPOVTaskComplete
                
                }

                else
                {

                    $_task

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {
                
                "[{0}] User included -WhatIf." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
            
            }

            else
            {

                "[{0}] User cancelled." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }           

        }

    }

}

function Get-HPOVLogicalEnclosure 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
  
    [CmdletBinding (DefaultParameterSetName = "default")]    
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [validateNotNullorEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_LogicalEnclosureCollection = New-Object System.Collections.ArrayList
        
    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($_appliance.Name)' Appliance (of $($Appliance.Count))"

            if ($PSboundParameters['Name']) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Enclosure name provided: '$Name'"
    
                $Name = $Name -replace ("[*]","%25") -replace ("[&]","%26")
    
                $uri = $logicalEnclosuresUri + "?filter=name matches '$Name'&sort=name:asc"
    
            }
    
            else 
            {
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Logical Enclosure name provided. Looking for all resources."
    
                $uri = $logicalEnclosuresUri + "?sort=name:asc"
    
            }

            Try
            {
    
                $_LogicalEnclosures = Send-HPOVRequest $uri -Hostname $_appliance
    
            }
            
            Catch
            {
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] API Error Caught: $($_.Exception.Message)"
    
                $PSCmdlet.ThrowTerminatingError($_)
    
            }
    
            if ($_LogicalEnclosures.count -eq 0 -and $Name) 
            { 
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Enclosure '$Name' resource not found. Generating error"

                $ExceptionMessage = "The specified Logical Enclosure '{0}' was not found on '{1}' appliance. Please check the name and try again." -f $Name, $_appliance.Name
                $ErrorRecord = New-ErrorRecord HPOneView.LogicalEnclosureResourceException LogicalEnclosureNotFound ObjectNotFound 'Name' -Message $ExceptionMessage  
                $PSCmdlet.WriteError($ErrorRecord)  
                
            }
    
            elseif ($_LogicalEnclosures.count -eq 0) 
            { 
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Logical Enclosure resources found on $($_appliance.name)."
    
            }
    
            else 
            {
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($_LogicalEnclosures.count) Enclosure Group resources."
    
                $_LogicalEnclosures.members | % { 
                    
                    $_.PSObject.TypeNames.Insert(0,'HPOneView.LogicalEnclosure')    
    
                    [void]$_LogicalEnclosureCollection.Add($_) 
                    
                }
     
            }

        }

    }

    End 
    {
                
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. $($_LogicalEnclosureCollection.count) enclosure(s) found."
                
        #Export results to exportfile
        if ($exportFile) 
        { 
            
            $_LogicalEnclosureCollection | convertto-json -depth 99 > $exportFile 
        
        }
        
        # else Return Logical Enclosure object(s)
        else 
        { 

            Return $_LogicalEnclosureCollection
        
        }

    }

}

function New-HPOVLogicalEnclosure
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
         
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [object]$Enclosure,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('eg')]
        [object]$EnclosureGroup,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$FirmwareBaseline,
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [bool]$ForceFirmwareBaseline,
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Enclosure']))
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Try 
            {
    
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_TaskResourceCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput) 
        {
                
            "[{0}] Synergy Frame object was passed via pipeline." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

        #Error when target appliance is not a Synergy Composer or the Enclosure object is not a Synergy Frame
        if ((${Global:ConnectedSessions} | ? Name -EQ $ApplianceConnection.Name).ApplianceType -ne 'Composer')
        {

            $Message = 'The Appliance {0} is not a Synergy Composer, and this operation is not supported. Only Synergy managed resources are supported with this Cmdlet.' -f $ApplianceConnection.Name

            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.ComposerNodeException UnsupportedMethod InvalidOperation 'ApplianceConnection' -TargetType 'HPOneView.Appliance.Connection' -Message $Message

            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_LogicalEnclosure      = NewObject -LogicalEnclosure
        $_LogicalEnclosure.name = $Name

        #Get Frame object type
        switch ($Enclosure.GetType().Name)
        {

            'PSCustomObject'
            {

                "[{0}] Synergy Frame object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Enclosure | Out-String) | Write-Verbose 

                if ($Enclosure.category -ne 'enclosures')
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException InvalidResourceObject InvalidArgument 'Enclosure' -TargetType 'PSObject' -Message "The provided -Enclosure resource object is not an Enclosure or Synergy Frame. Please correct the input object and try again."

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }

                #Validate Frame resource object
                if ($Enclosure.enclosureType -ne 'SY12000')
                {

                    #Throw error, wrong resource
                    $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException UnsupportedEnclosureType InvalidArgument 'Enclosure' -TargetType 'PSObject' -Message "The provided input object is not a Synergy Frame resource object. Only Synergy Frames are supported with this Cmdlet."

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                if ($Enclosure.state -ne 'Monitored')
                {

                    $ExceptionMessage = "The provided Synergy Frame resource '{0}' is already managed. Please select another Synergy Frame resource object." -f $Enclosure.name
                    $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException InvalidConfigurationState InvalidArgument -TargetType 'PSObject' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            'String'
            {

                "[{0}] Synergy Frame Name provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Enclosure | Write-Verbose 

                Try
                {

                    $Enclosure = Get-HPOVEnclosure -Name $Enclosure -ApplianceConnection $ApplianceConnection

                    #Validate Frame resource object
                    if ($Enclosure.enclosureType -ne 'SY12000')
                    {

                        #Throw error, wrong resource
                        $ExceptionMessage = "The provided input object is not a Synergy Frame resource object. Only Synergy Frames are supported with this Cmdlet."
                        $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException UnsupportedEnclosureType InvalidArgument -TargetType 'PSObject' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if ($Enclosure.state -ne 'Monitored')
                    {

                        $ExceptionMessage = "The provided Synergy Frame resource '{0}' is already managed. Please select another Synergy Frame resource object." -f $Enclosure.name
                        $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException InvalidConfigurationState InvalidArgument -TargetType 'PSObject' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        #Get list of logical Frame members fro ILT
        Try
        {

            $_LinkedSynergyFrames = Send-HPOVRequest -Uri $InterconnectLinkTopologies -Hostname $ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $_IltGroup = $_LinkedSynergyFrames.members | ? { $_.enclosureMembers.enclosureUri -contains $Enclosure.uri }
        
        foreach ($_member in $_IltGroup.enclosureMembers)
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Enclosure URI: {0}" -f $_member.enclosureUri | Write-Verbose

            if ($_member.errorFlag)
            {

                Try
                {

                    $_EnclosureObject = Send-HPOVRequest $_member.enclosureUri -Hostname $ApplianceConnection.Name

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Synergy Frame is in an Error State: {0} ({1})" -f $_EnclosureObject.state, $_EnclosureObject.stateReason | Write-Verbose 

                $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException InvalidConfigurationState InvalidArgument -TargetType 'PSObject' -Message ("The provided or linked Synergy Frame resource '{0}' is in an Error State: {1} ({2}) Please select another Synergy Frame resource object." -f $_EnclosureObject.name, $_EnclosureObject.state, $_EnclosureObject.stateReason)

                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            [void]$_LogicalEnclosure.enclosureUris.Add($_member.enclosureUri)

        }

        #Validate EG
        switch ($EnclosureGroup.GetType().Name)
        {

            'PSCustomObject'
            {

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group object: {0}" -f ($EnclosureGroup | ConvertTo-Json -Depth 99 | Out-String) | Write-Verbose 

                if ($EnclosureGroup.category -ne 'enclosure-groups')
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneView.EnclosureGroupResourceException InvalidResourceObject InvalidArgument -TargetType 'PSObject' -Message "The provided -EnclosureGroup resource object is not an Enclosure Group. Please correct the input object and try again."

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }

            }

            'String'
            {

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Name provided: {0}" -f $EnclosureGroup | Write-Verbose 

                Try
                {

                    $EnclosureGroup = Get-HPOVEnclosureGroup -Name $EnclosureGroup -ErrorAction Stop -ApplianceConnection $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_LogicalEnclosure.enclosureGroupUri = $EnclosureGroup.uri
        
        if ($PSBoundParameters['FirmwareBasline'])
        {

            #Validate Firmware Baseline
            switch ($FirmwareBasline.GetType().Name)
            {
                
                'PSCustomObject'
                {

                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] FirmwareBasline object: {0}" -f ($FirmwareBasline | Out-String) | Write-Verbose 

                    if ($FirmwareBasline.category -ne 'firmware-drivers')
                    {
                    
                        $ErrorRecord = New-ErrorRecord HPOneView.FirmwareBaselineResourceException InvalidResourceObject InvalidArgument -TargetType 'PSObject' -Message "The provided -FirmwareBasline resource object is not a Firmwaer Baseline. Please correct the input object and try again."

                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                    }

                }

                'String'
                {

                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Firmware Basline Name provided: {0}" -f $FirmwareBasline | Write-Verbose 

                    Try
                    {

                        $FirmwareBaslineName = $FirmwareBasline.Clone()
                        $FirmwareBasline = Get-HPOVBaseline  -File $FirmwareBasline -ApplianceConnection $ApplianceConnection -ErrorAction SilentlyContinue

                        If (-not $FirmwareBasline)
                        {

                            $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $FirmwareBaslineName
                            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'FirmwareBasline' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            $_LogicalEnclosure.firmwareBaselineUri  = $FirmwareBaseline.uri
            $_LogicalEnclosure.forceInstallFirmware = $ForceFirmwareBaseline

        }

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Enclosure object: {0}" -f ($_LogicalEnclosure | out-string) | Write-Verbose 

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating {0} Logical Enclosure" -f $_LogicalEnclosure.name | Write-Verbose

        Try
        {

            $resp = Send-HPOVRequest $LogicalEnclosuresUri POST $_LogicalEnclosure -Hostname $ApplianceConnection.Name
            
            if (-not($PSBoundParameters['Async']))
            {
                
                $resp = $resp | Wait-HPOVTaskComplete 
                
            }

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        

        [void]$_TaskResourceCollection.Add($resp)

    }

    End 
    {

        return $_TaskResourceCollection

    }

}

# // TODO: TEST DOCUMENTATION
function Set-HPOVLogicalEnclosure
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('eg')]
        [object]$EnclosureGroup,

        # RedundantPowerFeed There are at least twice as many power supplies as are necessary (n + n).
        # RedundantPowerSupply There is at least 1 more power supply than is necessary (n + 1).

        [Parameter (Mandatory = $false)]
        [ValidateSet ('RedundantPowerFeed', 'RedundantPowerSupply')]
        [String]$PowerMode,

        # ASHRAE_A3 Extended ambient temperatures up to 40C/104F degrees.
        # ASHRAE_A4 Extended ambient temperatures up to 45C/113F degrees.
        # Standard Expected ambient temperatures up to 35C/95F degrees.
        # Telco Extended ambient temperatures up to 40C/104F degrees and operation extremes up to 55C/131F degrees.

        [Parameter (Mandatory = $false)]
        [ValidateSet ('ASHRAE_A3', 'ASHRAE_A4', 'Standard', 'Telco')]
        [String]$AmbientTemperatureSetting,
        
        [Parameter (Mandatory = $false)]
        [switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Try 
            {
    
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process 
    {

        if ((${Global:ConnectedSessions} | ? Name -EQ $ApplianceConnection.Name).ApplianceType -ne 'Composer')
        {

            $Message = 'The Appliance {0} is not a Synergy Composer, and this operation is not supported. Only Synergy managed resources are supported with this Cmdlet.' -f $ApplianceConnection.Name
            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.ComposerNodeException UnsupportedMethod InvalidOperation 'ApplianceConnection' -TargetType 'HPOneView.Appliance.Connection' -Message $Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }    

        if ($PipelineInput) 
        {
                
            "[{0}] Synergy Frame object was passed via pipeline."  -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }        

        #Get type
        switch ($InputObject.GetType().Name)
        {

            'PSCustomObject'
            {

                "[{0}] Synergy Frame object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | Out-String) | Write-Verbose 

                if ($InputObject.category -ne 'logical-enclosures')
                {
                
                    $ExceptionMessage = "The provided -Enclosure resource object is not an Enclosure or Synergy Frame. Please correct the input object and try again."
                    $ErrorRecord = New-ErrorRecord HPOneView.InputObjectResourceException InvalidResourceObject InvalidArgument 'InputObject' -TargetType 'PSObject' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }

                Try
                {

                    "[{0}] Getting associated Enclosure Group to identify enclosure type." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
                    
                    $_EnclosureGroup = Send-HPOVRequest -Uri $InputObject.enclosureGroupUri -Hostname $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
                if ($_EnclosureGroup.enclosureTypeUri -NotMatch 'SY12000')
                {

                    #Throw error, wrong resource
                    $ExceptionMessage = "The provided input object is not a Synergy Frame resource object. Only Synergy Frames and associated Logical Enclousres are supported with this Cmdlet."
                    $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException UnsupportedEnclosureType InvalidArgument -TargetType 'PSObject' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $_UpdatedLogicalEnclosure = $InputObject.PSObject.Copy()

            }

            'String'
            {

                "[{0}] Synergy Frame name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject | Write-Verbose 

                Try
                {

                    $_UpdatedLogicalEnclosure = Get-HPOVLogicalEnclosure -Name $InputObject -ErrorAction Stop -ApplianceConnection $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                Try
                {

                    "[{0}] Getting associated Enclosure Group to identify enclosure type." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
                    
                    $_EnclosureGroup = Send-HPOVRequest -Uri $InputObject.enclosureGroupUri -Hostname $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
                if ($_EnclosureGroup.enclosureTypeUri -NotMatch 'SY12000')
                {

                    #Throw error, wrong resource
                    $ExceptionMessage = "The provided input object is not a Synergy Frame resource object. Only Synergy Frames and associated Logical Enclousres are supported with this Cmdlet."
                    $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException UnsupportedEnclosureType InvalidArgument -TargetType 'PSObject' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

        }

        switch ($PSBoundParameters.Keys)
        {

            'Name'
            {

                $_UpdatedLogicalEnclosure.name = $Name

            }

            'EnclosureGroup'
            {

                #Validate EG
                switch ($EnclosureGroup.GetType().Name)
                {

                    'PSCustomObject'
                    {

                        "[{0}] Enclosure Group object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($EnclosureGroup | ConvertTo-Json -Depth 99 | Out-String) | Write-Verbose 

                        if ($EnclosureGroup.category -ne 'enclosure-groups')
                        {
                        
                            $ExceptionMessage = "The provided -EnclosureGroup resource object is not an Enclosure Group. Please correct the input object and try again."
                            $ErrorRecord = New-ErrorRecord HPOneView.EnclosureGroupResourceException InvalidResourceObject InvalidArgument -TargetType 'PSObject' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                        
                        }

                    }

                    'String'
                    {

                        "[{0}] Enclosure Group Name provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $EnclosureGroup | Write-Verbose 

                        Try
                        {

                            $EnclosureGroup = Get-HPOVEnclosureGroup -Name $EnclosureGroup -ErrorAction Stop -ApplianceConnection $ApplianceConnection

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                }

                $_UpdatedLogicalEnclosure.enclosureGroupUri = $EnclosureGroup.uri

            }

            'PowerMode'
            {

                $_UpdatedLogicalEnclosure.powerMode = $FramePowerModeEnum[$PowerMode]

            }

            'AmbientTemperatureSetting'
            {

                $_UpdatedLogicalEnclosure.ambientTemperatureMode = $FrameAmbientTemperatureEnum[$AmbientTemperatureSetting]

            }

        }

        Try
        {

            $resp = Send-HPOVRequest -Uri $InputObject.uri -Method PUT $_UpdatedLogicalEnclosure -Hostname $ApplianceConnection.Name
            
            if (-not($PSBoundParameters['Async']))
            {
                
                $resp = $resp | Wait-HPOVTaskComplete -TimeOut (New-TimeSpan -Minutes 45)
                
            }

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        $resp

    }

    End 
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Update-HPOVLogicalEnclosure 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Reapply", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (
        
        [Parameter (ValueFromPipeline, Mandatory = $false, ParameterSetName = "Update")]
        [Parameter (ValueFromPipeline, Mandatory = $false, ParameterSetName = "Reapply")]
        [ValidateNotNullOrEmpty()]
        [Alias ('le','LogicalEnclosure')]
        [object]$InputObject,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "Update")]
        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "Reapply")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory, ParameterSetName = "Update")]
        [Alias ('UpdateFromGroup')]
        [Switch]$Update,

        [Parameter (Mandatory, ParameterSetName = "Reapply")]
        [Switch]$Reapply,

        [Parameter (Mandatory = $false, ParameterSetName = "Update")]
        [Parameter (Mandatory = $false, ParameterSetName = "Reapply")]
        [Switch]$Async

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection             = New-Object System.Collections.ArrayList
        $_LogicalEnclosureCollection = New-OBject System.Collections.ArrayList
        
    }

    Process 
    {

        if ($PipelineInput -or $InputObject) 
        {
        
            "[{0}] Processing Pipeline input." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            #error if the input value is not a PSObject
            if (-not $InputObject -is [PSCustomObject])
            {

                $ErrorRecord = New-ErrorRecord HPOneView.LogicalEnclosureResourceException InvalidLogicalEnclosureObjectType InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided LogicalEnclosure value is not a valid PSObject ($($LogicalEnclosure.GetType().Name)). Please correct your input value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] LogicalEnclosure PSObject: $($InputObject | FL * | out-string)."

            #Validate the Input object is the allowed category
            if ($InputObject.category -ne 'logical-enclosures')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.LogicalEnclosureResourceException InvalidLogicalEnclosureCategory InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided LogicalEnclosure object ($($LogicalEnclosure.name)) category '$($LogicalEnclosure.category)' is not an allowed value. Expected category value is 'logical-enclosures'. Please correct your input value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if(-not $InputObject.ApplianceConnection)
            {

                $ErrorRecord = New-ErrorRecord HPOneView.LogicalEnclosureResourceException InvalidLogicalEnclosureObject InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided LogicalEnclosure object ($($LogicalEnclosure.name)) does not contain the required 'ApplianceConnection' object property. Please correct your input value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            [void]$_LogicalEnclosureCollection.Add($InputObject)
        
        }

        #Not Pipeline input, and support Array of Logical Enclosure Name or PSObject
        else
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing InputObject Parameter."

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] InputObject is [$($InputObject.GetType().Name)]."

            ForEach ($_le in $InputObject)
            {
                    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] InputObject value: $($_le)."

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Looking for Logical Enclosure Name on connected sessions provided"

                #Loop through all Appliance Connections
                ForEach ($_appliance in $ApplianceConnection)
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($_appliance.Name)' Session."

                    Try
                    {

                        $_resp = Get-HPOVLogicalEnclosure $_le -ApplianceConnection $_appliance.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    [void]$_LogicalEnclosureCollection.Add($_resp)

                }

            }

        }

    }

    End
    {
        #Perform the work
        ForEach ($_leObject in $_LogicalEnclosureCollection) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Logical Enclosure: '$($_leObject.name) [$($_leObject.uri)]'"

            $NothingToDo = $false
            
            switch ($PSCmdlet.ParameterSetName) 
            {

                "Reapply" 
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Reapply configuration."
                    
                    $uri = $_leObject.uri + "/configuration" 
                
                }
                
                "Update"
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Update from Group."
                    
                    $uri = $_leObject.uri + "/updateFromGroup" 

                    if ($_leObject.state -eq 'Consistent')
                    {

                        $NothingToDo = $true

                    }
                
                }
                
            }

            if ((-not $NothingToDo) -and $PSCmdlet.ShouldProcess($_leObject.name,"$($PSCmdlet.ParameterSetName) Logical Enclosure configuration. WARNING: Depending on this action, there might be a brief outage."))
            { 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to $($PSCmdlet.ParameterSetName) configuration"

                Try
                {

                    $_task = Send-HPOVRequest $uri PUT -Hostname $_leObject.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if (-not($PSBoundParameters['Async']))
                {
                    
                    $_task | Wait-HPOVTaskComplete
                
                }

                else
                {

                    $_task

                }

            }

            elseif ($NothingToDo)
            {

                Write-Warning ("The {0} Logical Enclosure is already consistent. There is nothing to do." -f $_leObject.Name)

            }

            elseif ($PSBoundParameters['WhatIf'])
            {
                
                "[{0}] User included -WhatIf." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                if ($PSCmdlet.ParameterSetName -eq 'Update')
                {

                    Try
                    {

                        Compare-LogicalInterconnect -InputObject $_leObject

                    } 

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }
            
            }

            else
            {

                "[{0}] User cancelled." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }           

        }

    }

}

function Remove-HPOVLogicalEnclosure 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default",SupportsShouldProcess,ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri", "name", "le",'Resource')]
        [object]$InputObject,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$Force

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Resource'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList
        $_LECollection   = New-OBject System.Collections.ArrayList
        
    }

    Process 
    {

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Enclosure Object provided: $($InputObject | FL * | Out-String)"

            If ($InputObject.category -eq 'logical-enclosures')
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType PSObject -Message "The Network resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_LECollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType PSObject -Message "The Enclosure resource is not an expected category type [$($InputObject.category)]. Allowed resource category type is 'enclosures'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            foreach ($enclosure in $InputObject) 
            {

                #Enclosure passed is a URI
                if (($enclosure -is [String]) -and [System.Uri]::IsWellFormedUriString($enclosure,'Relative')) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received URI: $($enclosures)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Enclosure Object"

                    # // NEED APPLIANCE NAME HERE with If Condition
                    Try
                    {

                        $enclosure = Send-HPOVRequest $enclosure -ApplianceConnection $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                
                }

                #Enclosure passed is the Name
                elseif (($enclosure -is [string]) -and (-not($enclosure.startsWith("/rest")))) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received Enclosure Name $($enclosure)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Enclosure object from Get-HPOVEnclosure"
                    
                    # // NEED APPLIANCE NAME HERE with If Condition
                    Try
                    {

                        $enclosure = Get-HPOVEnclosure $enclosure -ApplianceConnection $ApplianceConnection

                    }
                    

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                #Enclosure passed is an object
                elseif ($enclosure -is [PSCustomObject] -and ($enclosure.category -ieq 'enclosures')) 
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Object provided: $($enclosure | FL * | out-string)"
                
                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Resource' -TargetType 'PSObject' -Message "Invalid Resource Parameter: $($enclosure | FL * | Out-String)"
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                [void]$_LECollection.Add($enclosure)

            }

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_LECollection.count) Logical Enclosure resources to remove."

        #Process Enclosure Resources
        ForEach ($_enclosure in $_LECollection)
        {

            if ($PSCmdlet.ShouldProcess($_enclosure.name,"Remove Logical Enclosure from appliance '$($_enclosure.ApplianceConnection.Name)'")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Logical Enclosure '$($_enclosure.name)' from appliance '$($_enclosure.ApplianceConnection.Name)'."

                Try
                {
                    
                    if ($PSBoundParameters['Force'])
                    {

                        $_enclosure.uri += "?force=true"

                    }

                    $_resp = Send-HPOVRequest $_enclosure.Uri DELETE -Hostname $_enclosure.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Invoke-HPOVVcmMigration 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = "High")]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "Report")]    
        [Parameter (Mandatory, ParameterSetName = "VCEMMigration")]
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Alias ('oip')]
        [ValidateNotNullOrEmpty()]
        [System.String]$OAIPAddress,

        [Parameter (Mandatory, ParameterSetName = "Report")]
        [Parameter (Mandatory, ParameterSetName = "VCEMMigration")]
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Alias ('ou')]
        [ValidateNotNullOrEmpty()]
        [System.String]$OAUserName,

        [Parameter (Mandatory, ParameterSetName = "Report")]
        [Parameter (Mandatory, ParameterSetName = "VCEMMigration")]
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Alias ('op')]
        [ValidateNotNullOrEmpty()]
        [System.Object]$OAPassword,

        [Parameter (Mandatory, ParameterSetName = "Report")]
        [Parameter (Mandatory, ParameterSetName = "VCEMMigration")]
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Alias ('vu')]
        [ValidateNotNullOrEmpty()]
        [System.String]$VCMUserName,

        [Parameter (Mandatory, ParameterSetName = "Report")]
        [Parameter (Mandatory, ParameterSetName = "VCEMMigration")]
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Alias ('vp')]
        [ValidateNotNullOrEmpty()]
        [System.Object]$VCMPassword,

        [Parameter (Mandatory = $false, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "Report")]
        [Parameter (Mandatory = $false, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "VCEMMigration")]
        [Parameter (Mandatory = $false, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [Alias ('eg')]
        [ValidateScript({
            if (($_ -is [String]) -and ($_.StartsWith('/rest/')) -and (-not ($_.StartsWith('/rest/enclosure-groups')))) { Throw "'$_' is not an allowed resource URI. Enclosure Group Resource URI must start with '/rest/enclosure-groups'. Please check the value and try again." } 
            elseif ($_ -is [String] -and ($_.StartsWith('/rest/'))) { $True }
            elseif ($_ -is [String]) { $True }
            
            elseif (($_ -is [PSCustomObject]) -and (-not ($_.category -eq "enclosure-groups"))) { 
            
                if ($_.category) { Throw "'$_.category' is not an allowed resource category. The resource object category must be 'enclosure-groups'. Please check the value and try again." }
                else { Throw "The object provided does not contain an the allowed resource category 'enclosure-groups'. Please check the value and try again." }
            }
            else { $True } })]
        [Object]$EnclosureGroup,

        [Parameter (Mandatory = $false, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "Report")]
        [Parameter (Mandatory = $false, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "VCEMMigration")]
        [Parameter (Mandatory = $false, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [Alias ('lig')]
        [ValidateScript({
            if (($_ -is [String]) -and ($_.StartsWith('/rest/')) -and (-not ($_.StartsWith('/rest/logical-interconnect-groups')))) { Throw "'$_' is not an allowed resource URI. Logical Interconnect Group Resource URI must start with '/rest/logical-interconnect-groups'. Please check the value and try again." } 
            elseif ($_ -is [String] -and ($_.StartsWith('/rest/'))) { $True }
            elseif ($_ -is [String]) { $True }
            
            elseif (($_ -is [PSCustomObject]) -and (-not ($_.category -eq "logical-interconnect-groups"))) { 
            
                if ($_.category) { Throw "'$_.category' is not an allowed resource category. The resource object category must be 'logical-interconnect-groups'. Please check the value and try again." }
                else { Throw "The object provided does not contain an the allowed resource category 'logical-interconnect-groups'. Please check the value and try again." }
            }
            else { $True } })]
        [Object]$LogicalInterconnectGroup,

        [Parameter (Mandatory, ParameterSetName = "Report")]
        [Parameter (Mandatory, ParameterSetName = "VCEMMigration")]
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateSet ("OneView", "OneViewNoiLO", IgnoreCase = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ("license", "l")]
        [System.String]$LicensingIntent,

        #[Parameter (Mandatory, ParameterSetName = "Report")]
        [Parameter (Mandatory, ParameterSetName = "VCEMMigration")]
        [String]$VCEMCMS,

        #[Parameter (Mandatory, ParameterSetName = "Report")]
        [Parameter (Mandatory, ParameterSetName = "VCEMMigration")]
        [String]$VCEMUser,

        #[Parameter (Mandatory, ParameterSetName = "Report")]
        [Parameter (Mandatory, ParameterSetName = "VCEMMigration")]
        [System.Object]$VCEMPassword,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Alias ('NoWait')]
        [Switch]$Async,

        [Parameter (Mandatory, ParameterSetName = "Report")]
        [Switch]$Report,

        [Parameter (Mandatory = $false, ParameterSetName = "Report")]
        [ValidateScript({
            if ({split-path $_ | Test-Path}) { $True } 
            else { Throw "'$(Split-Path $_)' is not a valid directory. Please verify $(Split-Path $_) exists and try again." } 
            })]
        [System.String]$Export,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "VCEMMigration")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Report")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
        
    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        if ($OAPassword -is [SecureString])
        {

            $OAPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($OAPassword))
            
        }

        if ($VCMPassword -is [SecureString])
        {

            $VCMPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($OAPassword))

        }

        if ($VCEMPassword -is [SecureString])
        {

            $VCEMPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($OAPassword))

        }

    }
    
    Process 
    {

        $VcMigrationObject = NewObject -vcMigration
        
        $VcMigrationObject.iloLicenseType          = $LicensingIntent
        $VcMigrationObject.credentials.oaIpAddress = $OAIPAddress
        $VcMigrationObject.credentials.oaUsername  = $OAUserName
        $VcMigrationObject.credentials.oaPassword  = $OAPassword
        $VcMigrationObject.credentials.vcmUsername = $VCMUserName
        $VcMigrationObject.credentials.vcmPassword = $VCMPassword

        #Check to see if EnclosureGroup was provided
        if ($PSBoundParameters['EnclosureGroup']) 
        {
        
            switch ($EnclosureGroup.Gettype().Name) 
            {

                #Validate the String value
                "String" 
                { 
                
                    #The value is an Enclosure Group URI
                    if ($EnclosureGroup.startswith('/rest/enclosure-groups')) 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Enclosure Group URI provided: $EnclosureGroup"
                       
                        $VcMigrationObject.enclosureGroupUri = $EnclosureGroup

                    }

                    #The value is an enclosure group name
                    else 
                    {
                        
                        #Enclosure group name provided. Check if this is for a custom EG and LIG (LIG name also provided), or existing EG
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Enclosure Group Name provided: $EnclosureGroup"

                        try 
                        { 
                            
                            $eg = (Get-HPOVEnclosureGroup -Name $EnclosureGroup -ErrorAction Stop -appliance $ApplianceConnection).uri 
                                
                            #Add the URI property to the migration object
                            $VcMigrationObject.enclosureGroupUri = $eg
                                
                        }

                        catch 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Enclosure Group '$EnclosureGroup' not found. Specifying custom Enclosure Group Name."
                            $VcMigrationObject | Add-Member -NotePropertyName "enclosureGroupName" -NotePropertyValue $EnclosureGroup -force

                        }

                    }
                    
                }
                "PSCustomObject" 
                {
            
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Enclosure Group resource object provided: $($EnclosureGroup | fl | out-string)"
                    $VcMigrationObject.enclosureGroupUri = $EnclosureGroup.uri
            
                }

            }#SWITCH

        }#If EG provided

        #Check to see if LogicalInterconnectGroup was provided
        if ($PSBoundParameters['LogicalInterconnectGroup']) 
        {
        
            switch ($LogicalInterconnectGroup.Gettype().Name) 
            {

                #Validate the String value
                "String" 
                { 
                
                    #The value is an Enclosure Group URI
                    if ($LogicalInterconnectGroup.startswith('/rest/logical-interconnect-groups')) 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Logical Interconnect Group URI provided: $LogicalInterconnectGroup"
                        $VcMigrationObject.logicalInterconnectGroupUri = $LogicalInterconnectGroup

                    }

                    #The value is an Logical Interconnect group name
                    else 
                    {
                        
                        #Enclosure group name provided. Check if this is for a custom EG and LIG (LIG name also provided), or existing EG
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Logical Interconnect Group Name provided: $LogicalInterconnectGroup"

                        try 
                        { 
                            
                            $lig = (Get-HPOVLogicalInterconnectGroup -Name $LogicalInterconnectGroup -ErrorAction Stop -appliance $ApplianceConnection).uri 
                                
                            #Add the URI property to the migration object
                            $VcMigrationObject.logicalInterconnectGroupUri = $lig
                                
                        }

                        catch 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Logical Interconnect Group '$LogicalInterconnectGroup' not found. Specifying custom Logical Interconnect Group Name."
                            $VcMigrationObject | Add-Member -NotePropertyName logicalInterconnectGroupName -NotePropertyValue $LogicalInterconnectGroup -force

                        }

                    }
                    
                }

                "PSCustomObject" 
                {
            
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Logical Interconnect Group resource object provided: $($LogicalInterconnectGroup | fl | out-string)"
                    $VcMigrationObject.logicalInterconnectGroupUri  = $LogicalInterconnectGroup.uri
            
                }

            }#SWITCH

        }#If EG provided

        #Send the POST and retrieve the Uri for the MigratableVcDomain resource

        Try
        {

            $thisTask = Send-HPOVRequest -method POST -uri $VCMigratorUri -body $VcMigrationObject -appliance $ApplianceConnection | Wait-HPOVTaskComplete

        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        if ($thisTask.taskState -ieq "Error") 
        {

            $ErrorRecord = New-ErrorRecord HPOneView.EnclosureResourceException $thisTask.taskErrors.errorCode InvalidArgument 'Invoke-HPOVVcMigration' -Message "$($thisTask.taskErrors.message)"
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #If we get here, task was successful. Get the migration resource
        $vcMigrationReport = MigrationReport $thisTask

        $EnclosureName = $vcMigrationReport.apiVcMigrationReport.enclosureName

        if ($Export) 
        {

            [Array]$Output = @()

            $Output += $vcMigrationReport.apiVcMigrationReport | ft $a -AutoSize -wrap
            $Output += $vcMigrationReport.apiVcMigrationReport| ft $b -AutoSize -wrap
            $Output += $vcMigrationReport.outReport | sort severity | fl $i

            $outFile = "$export\$($vcMigrationReport.apiVcMigrationReport.enclosureName)_$(get-date -uformat %Y%m%d).report"

            $vcMigrationReport.outReport += "Generated on $(get-date -uformat %c)"

            Out-File -InputObject  $Output -FilePath $outFile -Encoding utf8 -force -confirm:$false

            write-host "Report saved to: " -nonewline -ForegroundColor Green
            write-host "$outFile" -ForegroundColor Yellow

        }

        else 
        {

            #Generate and return the report
            ""
            "Migration Compatibility Report"
            "------------------------------"
            ""
            $vcMigrationReport.apiVcMigrationReport | ft $a -AutoSize -wrap
            $vcMigrationReport.apiVcMigrationReport| ft $b -AutoSize -wrap
            $vcMigrationReport.outReport | sort severity | fl $i

        }

        #Generate terminating error if caller didn't include VCEMCMS Parameter and $vcMigrationReport.VcemManaged is True
        if (-not ($PSBoundParameters["vcemcms"]) -and $vcMigrationReport.VcemManaged) 
        {

            $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException VCEMCMSParameterMissing InvalidArgument 'VCEMCMS' -Message "The Enclosure is currently managed by a Virtual Connect Enterprise Manager (VCEM) CMS, and the -VCEMCMS Parameter was not provided. Please provide the required Parameter and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
        }
        
        $_ServicePointManagerOriginalState = [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} #Workaround self-signed certificates on OA and VCEM CMS

        if ($VCEMCMS -and $vcMigrationReport.VcemManaged -and ($vcMigrationReport.apiVcMigrationReport.criticalCount -le 1) -and (-not ($Report.IsPresent))) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Entering Eject VCM from VCEM DG Process"
       
            $oaUrl = "https://{0}/xmldata?item=all" -f $OAIPAddress

            '[{0}] {1} - Building SOAP Request to OA: {2}' -f $MyInvocation.InvocationName.ToString().ToUpper(), (get-date -UFormat `"%Y-%m-%d %T`"), $oaUrl

            try 
            {

                $soapWebRequest        = [System.Net.WebRequest]::Create($oaUrl) 
                $soapWebRequest.Accept = "text/xml" 
                $soapWebRequest.Method = "GET" 
                $resp                  = $soapWebRequest.GetResponse() 
                $responseStream        = $resp.GetResponseStream() 
                $soapReader            = [System.IO.StreamReader]($responseStream) 
                $ReturnXml             = [Xml] $soapReader.ReadToEnd() 

                $responseStream.Close() 
                $resp.Close()

                $soapWebRequest = $Null
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Response received: $($returnXML.OuterXml | Out-String)"
    
            }

            catch [Net.WebException]
            {

                if ($_.exception.InnerException -match "The remote name could not be resolved") 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException OnboardAdministratorUnavailable ResourceUnavailable 'OAIP' -Message "$($_.exception.InnerException)"
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException $_.FullyQualifiedErrorId ResourceUnavailable 'OAIP' -Message "$($_.exception.message)"
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                }

            }

            catch 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException $_.FullyQualifiedErrorId ResourceUnavailable 'OAIP' -Message "$($_.exception.message)"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Recieved valid OA XML reply
            if ($ReturnXml.RIMP.INFRA2) 
            { 
    
                if ($ReturnXml.RIMP.INFRA2.VCM.vcmMode -eq "true") 
                {
            
                    $vcDomainName = $ReturnXml.RIMP.INFRA2.VCM.vcmDomainName
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Found VC Domain from OA: '$vcDomainName'"
                            
                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException NoVCDomainFound ResourceUnavailable 'OAIP' -Message "Enclosure is not managed by VCM or no valid VC Domain Found."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }
    
            }
    
            #Reply will not have any returned data beyond the RIMP XML node, so generate error
            else 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException NoVCDomainFound ResourceUnavailable 'OAIP' -Message "No data provided from XML Interface. Is it disabled?"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #VCEM CodeBlock
            #Use the mvcd7_3 API Endpoint
            $XmlAuth = @"
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v7="http://v7_3.api.mvcd.hp.com">
           <soapenv:Header/>
           <soapenv:Body>
              <v7:login>
                 <String_1>$VCEMUser</String_1>
                 <String_2>$VCEMPassword</String_2>
              </v7:login>
           </soapenv:Body>
        </soapenv:Envelope>
"@

            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") $(get-date -UFormat `"%Y-%m-%d %T`") Authenticating to VCEM CMS host: $VCEMCMS."
            
            try 
            {

                $Uri = "https://$($VCEMCMS):50000/mvcd7_3/SoapApi"
                $reply = Invoke-WebRequest -uri $Uri -Method POST -ContentType "text/xml" -Body $XmlAuth

            }

            catch [System.Net.WebException] 
            {

                if ($_.exception -match "The remote name could not be resolved") 
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException VcemHostUnavailable ResourceUnavailable 'VCEMCMS' -Message "The VCEM host '$VCEMCMS' remote name could not be resolved. Please check the name and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)    

                }
                
                else 
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") [System.Net.WebException] Error Caught: $($_.Exception.Response | out-string)"

                    $ResponseCode = [int]$_.Exception.response.statuscode
                    $ResponseMessage = $_.Exception.Message

                    #Get exception response from Web Service API.
                    if ($_.Exception.InnerException) { $HttpWebResponse = $_.Exception.InnerException.Response }
                    else { $HttpWebResponse = $_.Exception.Response }

                    $rs = $HttpWebResponse.GetResponseStream()
                    $reader = New-Object System.IO.StreamReader($rs)
                    
                    if ($HttpWebResponse.ContentType.Contains("text/xml")) { [XML]$ErrorBodyResponse = $reader.ReadToEnd() }
                    else { $ErrorBodyResponse = $reader.ReadToEnd() }

                    switch ([int]$ResponseCode) 
                    {
                    
                        404 
                        {  

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") [System.Net.WebException] SOAP API Endpoint not found"
                    
                            $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException VCEMSoapAPIEndPointNotFound ResourceUnavailable 'VCEMCMS' -Message "The provided VCEM CMS host '$VCEMCMS' does not have the VCEM role of HP Insight Software installed. Please verify the VCEMCMS Parameter value and try again."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                        }

                        default 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") [System.Net.WebException] Internal Server Error or auth exception"
                            
                            if ($ErrorBodyResponse -is [XML]) 
                            {

                                $ResponseMessage = $ErrorBodyResponse.Envelope.body.Fault.faultstring

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Received XML Response FaultString: $ResponseMessage"
                            
                            }              
                            
                            $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException VCEMSoapApiInternalError InvalidResult 'VCEMCMS' -Message "HTTP '$ResponseCode' Error. $ResponseMessage"
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                }

            }

            [XML]$ContentResponse = $reply.content
            $AuthToken = $ContentResponse.Envelope.Body.loginResponse.result

            #Check for new VCEM API Endpoint
            $getVcemApiVersion = @"
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v7="http://v7_3.api.mvcd.hp.com">
               <soapenv:Header/>
               <soapenv:Body>
                  <v7:getProductVersion>
                     <String_1>$AuthToken</String_1>
                  </v7:getProductVersion>
               </soapenv:Body>
            </soapenv:Envelope>
"@


            $Uri = "https://$($VCEMCMS):50000/mvcd7_3/SoapApi"

            Try
            {

                $reply = Invoke-WebRequest -uri $Uri -Method POST -ContentType "text/xml" -Body $getVcemApiVersion

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
            [XML]$ContentResponse = $reply.content
            
            [version]$apiVersion = ($ContentResponse.Envelope.Body.getProductVersionResponse.result) -replace ("Virtual Connect Enterprise Manager v","")
            $apiVersionString = ($ContentResponse.Envelope.Body.getProductVersionResponse.result) -replace ("Virtual Connect Enterprise Manager v","") -replace ("\.","_")

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") VCEM API Version found: $apiVersion"


            if ($apiVersion -lt 7.3) 
            {

                #Generate error that VCEM version is too old to support patch and instruct caller to upgrade to either 7.3+Patch or 7.4.1
                $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException VcemVersionTooOld ResourceUnavailable 'VCEMCMS' -Message "The VCEM host '$VCEMCMS' version '$($apiVersion.ToString())' is not supported. Please upgrade your VCEM CMS to at least 7.3 and obtain the VCEM 7.3/7.4 Patch (ftp://ftp.hp.com/pub/softlib2/software1/pubsw-generic/p270829882/v106568) and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Locate VCM Domain within VCEM
            $FindVCDomainByNameRequest = @"
        <s11:Envelope xmlns:s11='http://schemas.xmlsoap.org/soap/envelope/'>
          <s11:Body>
            <ns1:findVCDomainByName xmlns:ns1='http://v7_3.api.mvcd.hp.com'>
              <String_1>$AuthToken</String_1>
              <String_2>$vcDomainName</String_2>
            </ns1:findVCDomainByName>
          </s11:Body>
        </s11:Envelope>
"@


            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Looking for '$vcDomainName' VC Domain on VCEM host."

            Try
            {

                $reply = Invoke-WebRequest -uri $Uri -Method POST -ContentType "text/xml" -Body $FindVCDomainByNameRequest

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            [xml]$findVCDomainByNameResponse = $reply.content

            if ($findVCDomainByNameResponse.Envelope.body.findVCDomainByNameResponse.result.nil) 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException NoVCDomainFound ResourceUnavailable 'OAIP' -Message "No data provided from XML Interface. Is it disabled?"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Found VC Domain: $($findVCDomainByNameResponse.Envelope.body.findVCDomainByNameResponse.result | out-string)"

            if ($findVCDomainByNameResponse.Envelope.body.findVCDomainByNameResponse.result.status -eq "LICENSED_UNMANAGED") 
            {

                Write-Warning "'$vcDomainName' is not currently managed by the VCEM CMS host."
                Return

            }

            $vcemDomainId = $findVCDomainByNameResponse.Envelope.body.findVCDomainByNameResponse.result.vcDomainId

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Attempting to remove VC Domain from VCEM Domain Group"

            if ($PSCmdlet.ShouldProcess($vcDomainName,"Remove VC Domain From VC Domain Group")) 
            {

                if ($apiVersion -ge "7.4.1") 
                { 
                
                    $uri = "https://$($VCEMCMS):50000/mvcd$($apiVersionString)/SoapApi" 
                    $nameSpaceVer = "v$($apiVersionString)"
                }

                else 
                { 
                
                    $uri = "https://$($VCEMCMS):50000/mvcdExtra/SoapApi" 
                    $nameSpaceVer = "vExtra"
                        
                }

                $removeVcDomainRequest = @"
<s11:Envelope xmlns:s11='http://schemas.xmlsoap.org/soap/envelope/'>
    <s11:Body>
    <ns1:removeVcDomainFromGroup xmlns:ns1='http://$nameSpaceVer.api.mvcd.hp.com'>
        <String_1>$AuthToken</String_1>
        <Long_2>$vcemDomainId</Long_2>
    </ns1:removeVcDomainFromGroup>
    </s11:Body>
</s11:Envelope>
"@


                #Attempt removeVcDomainFromGroup request to API
                try 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Attempting SOAP Call to '$uri'"

                    $soapWebRequest               = [System.Net.HttpWebRequest]::Create($uri) 
                    $soapWebRequest.Accept        = "text/xml" 
                    $soapWebRequest.ContentType   = "text/xml"
                    $soapWebRequest.Method        = "POST" 
                    $bytes                        = [System.Text.Encoding]::UTF8.GetBytes($removeVcDomainRequest) 
                    $soapWebRequest.ContentLength = $bytes.Length

                    [System.IO.Stream] $outputStream = [System.IO.Stream]$soapWebRequest.GetRequestStream()
                    $outputStream.Write($bytes,0,$bytes.Length)  
                    $outputStream.Close()

                    $resp           = $soapWebRequest.GetResponse() 
                    $responseStream = $resp.GetResponseStream() 
                    $soapReader     = [System.IO.StreamReader]($responseStream) 
                    $reply          = [Xml]$soapReader.ReadToEnd() 
                    $responseStream.Close() 
                    $resp.Close()
                    $soapWebRequest = $Null
                    
                    "[{0}] {1} Response received: {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), (get-date -UFormat "%Y-%m-%d %T"), $reply.OuterXml | Write-Verbose 
    
                }

                Catch [System.Net.WebException] 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") [System.Net.WebException] exception caught: $($_.Exception.Response | out-string)"

                    $HttpWebResponse = $_.Exception.Response
                    $ResponseCode = [int]$_.Exception.response.statuscode
                    $ResponseMessage = $_.Exception.Message

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Getting error response stream."
                    
                    $rs = $HttpWebResponse.GetResponseStream()
                    $reader = New-Object System.IO.StreamReader($rs)

                    if ($HttpWebResponse.ContentType.Contains("text/xml")) { [XML]$ErrorBodyResponse = $reader.ReadToEnd() }

                    else { [String]$ErrorBodyResponse = $reader.ReadToEnd() }

                    if ($ErrorBodyResponse -is [String] -and $ErrorBodyResponse.StartsWith("<script>") -and [int]$ResponseCode -eq 404) 
                    { 
                    
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") [System.Net.WebException] SOAP API Endpoint not found. Generating terminating error."
                
                        $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException VCEMSoapAPIEndPointNotFound ResourceUnavailable 'VCEMCMS' -Message "The provided VCEM CMS host '$VCEMCMS' does not have the required VCEM patch installed. Please download the patch from (ftp://ftp.hp.com/pub/softlib2/software1/pubsw-generic/p270829882/v106568) and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    elseif ($ErrorBodyResponse -is [XML] -and [int]$HttpWebResponse.StatusCode -eq 500 -and $ErrorBodyResponse.Envelope.Body.Fault.faultstring -match "Failed to parse source: For input string: `"$vcemDomainId`"") 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") '$vcDomainName' was not found on the VCEM host '$VCEMCMS'. Generating terminating error."

                        $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException VcDomainNotFound ResourceUnavailable 'VCEMCMS' -Message "The Virtual Connect Domain '$vcDomainName' not found on VCEM host '$VCEMCMS'. Please verify the Virtual Connect Domain is managed by the provided VCEM CMS host and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    elseif ($ErrorBodyResponse -is [XML]) 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException $ErrorBodyResponse.Envelope.Body.Fault.faultcode InvalidResult 'VCEMCMS' -Message "$($ErrorBodyResponse.Envelope.Body.Fault.faultstring)"
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                    }
                    else 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException VCEMApiCallGenericError InvalidResult 'VCEMCMS' -Message "HTTP '$ResponseCode ' Error. Message: $ResponseMessage"
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                    }

                }

                $jobId = $reply.Envelope.body.removeVcDomainFromGroupResponse.result

                if (-not ($jobId))
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.VCMigratorException InvalidJobIdResult InvalidResult 'VCEMCMS' -Message "A valid VCEM Job ID was not provided."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Monitoring VCEM Job ID '$jobId'"

                $Uri = "https://$($VCEMCMS):50000/mvcd7_3/SoapApi"

                $jobMonitorRequest = @"
        <s11:Envelope xmlns:s11='http://schemas.xmlsoap.org/soap/envelope/'>
          <s11:Body>
            <ns1:listStatusForMvcdJob xmlns:ns1='http://v7_3.api.mvcd.hp.com'>
              <String_1>$AuthToken</String_1>
              <Long_2>$jobId</Long_2>
            </ns1:listStatusForMvcdJob>
          </s11:Body>
        </s11:Envelope>
"@


                do 
                {

                    #Hide the progress display of Invoke-WebRequest, which adds unecessary tet to the Write-Progress output
                    $progressPreference = 'silentlyContinue' 
                    $reply = Invoke-WebRequest -uri $Uri -Method POST -ContentType "text/xml" -Body $jobMonitorRequest

                    #Reset hidding progress display prior to executing Write-Progress
                    $progressPreference = 'Continue'  

                    [xml]$jobStatus = $reply.Content

                    Write-Verbose $($jobStatus.Envelope.body.listStatusForMvcdJobResponse.result | out-string)
                    Write-Verbose $($jobStatus.Envelope.body.listStatusForMvcdJobResponse.result.jobProgress[-1] | out-string)

                    if ($jobStatus.Envelope.body.listStatusForMvcdJobResponse.result.jobProgress[-1].progressDescription) { $status = $jobStatus.Envelope.body.listStatusForMvcdJobResponse.result.jobProgress[-1].progressDescription}
                    else { $status = "Waiting" }

                    if ($jobStatus.Envelope.body.listStatusForMvcdJobResponse.result.jobProgress[-1].percentComplete) { $PrecentComplete = $jobStatus.Envelope.body.listStatusForMvcdJobResponse.result.jobProgress[-1].percentComplete}
                    else { $PrecentComplete = 0 }

                    Write-Progress -id 2 -Activity $jobStatus.Envelope.body.listStatusForMvcdJobResponse.result.jobName -Status $status -PercentComplete $PrecentComplete

                } Until ($jobStatus.Envelope.body.listStatusForMvcdJobResponse.result.state -eq "COMPLETED" -or $jobStatus.Envelope.body.listStatusForMvcdJobResponse.result -eq "FAILED")
    
                
                [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $_ServicePointManagerOriginalState #restore certificate validation

                #Job Failed, terminate
                if ($jobStatus.Envelope.body.listStatusForMvcdJobResponse.result -eq "FAILED") 
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneView.VCMigratorException $thisTask.taskErrors.errorCode InvalidArgument 'Invoke-HPOVVcMigration' -Message "$($thisTask.taskErrors.message)"
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }           
                
                Write-Progress -id 2 -Activity $jobStatus.Envelope.body.listStatusForMvcdJobResponse.result.jobName -Completed

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(get-date -UFormat `"%Y-%m-%d %T`") Checking Compatibility again."

                #Check for report status now
                Try
                {

                    $thisTask = Send-HPOVRequest -method POST -uri $VCMigratorUri -body $VcMigrationObject -appliance $ApplianceConnection | Wait-HPOVTaskComplete

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

                if ($thisTask.taskState -ieq "Error") 
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.VCMigratorException $thisTask.taskErrors.errorCode InvalidResult 'Invoke-HPOVVcMigration' -Message "$($thisTask.taskErrors.message)"
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                #If we get here, task was successful. Generate new VCMMigrator report
                $vcMigrationReport = MigrationReport $thisTask

                if ($vcMigrationReport.apiVcMigrationReport.migrationState -eq "UnableToMigrate") 
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.VCMigratorException UnableToMigrateVCDomain InvalidResult 'Invoke-HPOVVcMigration' -Message "The VC Domain in unable to be migrated due to $($vcMigrationReport.apiVcMigrationReport.highCount) Critical Issues. Please examine the VC Migration Report to identify what needs to be resolved before migration can continue."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                #Generate and return the report
                ""
                "Migration Compatibility Report"
                "------------------------------"
                ""
                $vcMigrationReport.apiVcMigrationReport | ft $a -AutoSize -wrap
                $vcMigrationReport.apiVcMigrationReport| ft $b -AutoSize -wrap
                $vcMigrationReport.outReport | sort severity | fl $i

            }

            Else 
            {

                if ($PSBoundParameters['whatif'].ispresent) 
                { 
                            
                    write-warning "-WhatIf was passed, would have proceeded with removing '$vcDomainName' from VCEM Domain Group."
                    $resp = $null
            
                }
                else 
                {

                    #If here, user chose "No", End Processing
                    write-host ""
                    write-warning "Not removing '$vcDomainName'from VCEM Domain Group and unable to proceed without removing the VC Domain from the VCEM Domain Group."
                    write-host ""
                    
                    $resp = $Null

                }

            }

        }

        #We are ready to migrate
        if ($vcMigrationReport.migrationState -eq "ReadyToMigrate" -and -not ($report.IsPresent)) 
        {
            
            if ($PSCmdlet.ShouldProcess("enclosure $EnclosureName at $($vcMigrationReport.apiVcMigrationReport.enclosureIp)","Process migration")) 
            {
                
                Try
                {

                    #Make the PUT call to migrate
                    $migrateTask = Send-HPOVRequest -method PUT -uri $vcMigrationReport.apiVcMigrationReport.uri -body @{acknowledgements = $vcMigrationReport.apiVcMigrationReport.acknowledgements; migrationState = "Migrated"; type = "MigratableVcDomainV300"}  -appliance $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                

                if (-Not($PSBoundParameters['Async']))
                {

                    $migrateTask = $migrateTask | Wait-HPOVTaskComplete -timeout (New-TimeSpan -Minutes 60)

                }

            }

            else 
            {

                if ($PSBoundParameters['whatif'].ispresent) 
                { 
                            
                    write-warning "-WhatIf was passed, would have proceeded with migration of $($vcMigrationReport.apiVcMigrationReport.enclosureName)."
                    $migrateTask = $null
            
                }

                else 
                {

                    #If here, user chose "No", End Processing
                    write-host ""
                    write-warning "Not migrating enclosure, $($vcMigrationReport.apiVcMigrationReport.enclosureName)."
                    write-host ""
                    
                    $migrateTask = $Null

                }

            }

        }#End if ReadyToMigrate

        #Handle error conditions that need to be resolved by the caller before migration can be performed.
        elseif ($vcMigrationReport.migrationState -eq "UnableToMigrate" -and $vcMigrationReport.apiVcMigrationReport.criticalCount -ge 1) 
        {
        
            $ErrorRecord = New-ErrorRecord HPOneView.VCMigratorException UnableToMigrateEnclosure InvalidResult 'Invoke-HPOVVcMigration' -Message "There are 1 or more critical issues preventing the enclosure from being eligible to migrate. Please run a compatibility report using the -report switch, then review and resolve the reported issues before continuing."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($vcMigrationReport.migrationState -eq "Migrated") 
        {
        
            $ErrorRecord = New-ErrorRecord HPOneView.VCMigratorException EnclosureMigrated OperationStopped 'OAIP' -Message "The enclosure '$EnclosureName' was already migrated. Not performing action again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($vcMigrationReport.migrationState -eq "Migrating") 
        {
        
            $ErrorRecord = New-ErrorRecord HPOneView.VCMigratorException MigratingEnclosure InvalidOperation 'OAIP' -Message "An asynchronOut task migrating enclosure '$EnclosureName' exists and is currently still running."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }
           
    }#End Process
    
    End 
    {
         
        Return $migrateTask

    }

}

function MigrationReport
{

    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory)]
        [Object]$task

    )

    Process
    {

        $vcMigrationReport = NewObject -VCMigratorReport

        Try
        {

            $vcMigrationReport.apiVcMigrationReport = Send-HPOVRequest $task.associatedResource.resourceUri

        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $vcMigrationReport.migrationState = $vcMigrationReport.apiVcMigrationReport.migrationState

        $vcMigrationReport.issueCount = $vcMigrationReport.apiVcMigrationReport.highCount + $vcMigrationReport.apiVcMigrationReport.mediumCount + $vcMigrationReport.apiVcMigrationReport.lowCount
        
        if ($vcMigrationReport.migrationState -eq "UnableToMigrate" -or $vcMigrationReport.issueCount -gt 0) 
        {
            
            foreach ($itemCategory in $vcMigrationReport.apiVcMigrationReport.items) 
            {
            
                foreach ($issue in $itemCategory.issues) 
                {
            
                    $issue | % { 

                        if ($_.description -match "The specified enclosure is managed by Virtual Connect Enterprise Manager") 
                        {

                            Write-Warning "Enclosure is currently managed by Virtual Connect Enterprise Manager."
                                
                            $vcMigrationReport.VcemManaged = $True
                        
                        }

                        $_ | add-member -NotePropertyName name -NotePropertyValue $itemCategory.name -force 
                        $_ | add-member -NotePropertyName resourceName -NotePropertyValue $_.name -force 
                        
                        [void]$vcMigrationReport.outReport.Add($_)
                        
                    }
            
                }
            
                foreach ($item in $itemCategory.items) 
                { 
            
                    $items = $item | ? severity -notmatch "OK"

                    $items | % { 
            
                        $_.issues | add-member -NotePropertyName name -NotePropertyValue $itemCategory.name -force 
                        $_.issues | add-member -NotePropertyName resourceName -NotePropertyValue $_.name -force 

                        [void]$vcMigrationReport.outReport.Add($_.issues)
            
                    }
                
                }
            
            }

        }

    }

    End
    {

        Return $vcMigrationReport

    }

}

function Get-HPOVEnclosure 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
  
    [CmdletBinding (DefaultParameterSetName = "default")]    
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "export")]
        [Parameter (Mandatory = $false, ParameterSetName = "report")]
        [validateNotNullorEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "export")]
        [Parameter (Mandatory = $false, ParameterSetName = "report")]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "export")]
        [Parameter (Mandatory = $false, ParameterSetName = "report")]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "export" )]
        [Parameter (Mandatory = $false, ParameterSetName = "report")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "export")]
        [Alias ("x", "export")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$exportFile,
            
        [Parameter (Mandatory = $false, ParameterSetName = "report")]
        [switch]$Report

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $EnclosureCollection = New-Object System.Collections.ArrayList
        
    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            if ($PSBoundParameters['Label'])
            {

                $_uri = '{0}?category:storage-volume-templates&query=labels:{1}' -f $IndexUri, $Label

                Try
                {

                    $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                    #Loop through all found members and get full SVT object
                    ForEach ($_memeber in $_IndexMembers.members)
                    {

                        Try
                        {

                            $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                        

                        $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.Enclosure')    
    
                        [void]$EnclosureCollection.Add($_) 

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                $Uri = $EnclosuresUri + '?sort=name:asc'

                if ($PSboundParameters['Name']) 
                {

                    "[{0}] Enclosure Group name provided: '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose
        
                    $Uri += "&filter=name matches '{0}'" -f $Name.Replace("*","%25").Replace("&","%26")
        
                }

                # Uncomment when defect for EM is fixed.
                # if ($PSBoundParameters['Scope'])
                # {

                # "[{0}] Filtering Enclosure Group on Scope: {1} ({2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Scope.Name, $Scope.Uri | Write-Verbose

                # $Uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri
                
                # }

                Try
                {
        
                    $_enclosures = Send-HPOVRequest -Uri $uri -Hostname $_appliance
        
                }
                
                Catch
                {
        
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] API Error Caught: $($_.Exception.Message)"
        
                    $PSCmdlet.ThrowTerminatingError($_)
        
                }
        
                if ($_enclosures.count -eq 0 -and $Name) 
                { 
        
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure '$Name' resource not found. Generating error"

                    $ExceptionMessage = "The specified Enclosure '{0}' was not found on '{1}' appliance. Please check the name and try again." -f $Name, $_appliance.Name 
                    $ErrorRecord = New-ErrorRecord InvalidOperationException EnclosureGroupNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)  
                    
                }
        
                elseif ($_enclosures.count -eq 0) 
                { 
        
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Enclosure resources found on $($_appliance.name)."
        
                }
        
                else 
                {

                    if ($PSBoundParameters['Scope'])
                    {

                        $_enclosures.members = $_enclosures.members | ? scopeUris -contains $Scope.Uri

                    }
        
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($_enclosures.count) Enclosure Group resources."
        
                    ForEach ($_Enclosure in $_enclosures.members)
                    { 
                        
                        $_Enclosure.PSObject.TypeNames.Insert(0,'HPOneView.Enclosure')

                        [void]$EnclosureCollection.Add($_Enclosure)
                        
                    }
        
                }

            }

        }

    }

    End 
    {
                
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. $($EnclosureCollection.count) enclosure(s) found."
                
        #Display a report of an enclsosure
        if ($Report) 
        { 
            
            $EnclosureCollection | % { Enclosure-Report $_ } 
        
        }
        
        #display the JSON body of the enclosure
        elseif ($exportFile) 
        { 
            
            $EnclosureCollection | convertto-json -depth 99 > $exportFile 
        
        }
        
        # else Return enclosure object
        else 
        { 

            Return $EnclosureCollection
        
        }

    }

}

function Reset-HPOVEnclosureDevice
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "ManagerOrDeviceBay")]
        [ValidateNotNullOrEmpty()]
        [Object]$Enclosure,

        [Parameter (ParameterSetName = "default", Mandatory)]
        [Parameter (ParameterSetName = "ManagerOrDeviceBay", Mandatory)]
        [ValidateNotNullorEmpty()]
        [ValidateSet ('FLM','Appliance','ICM','Device')]
        [String]$Component,

        [Parameter (ParameterSetName = "default", Mandatory)]
        [Parameter (ParameterSetName = "ManagerOrDeviceBay", Mandatory)]
        [ValidateNotNullorEmpty()]
        [Int]$DeviceID,

        [Parameter (ParameterSetName = 'ManagerOrDeviceBay', Mandatory)]
        [Switch]$Reset,

        [Parameter (ParameterSetName = 'default', Mandatory = $False)]
        [Switch]$Efuse,

        [Parameter (ParameterSetName = 'default', Mandatory = $False)]
        [Parameter (ParameterSetName = 'ManagerOrDeviceBay', Mandatory = $False)]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "ManagerOrDeviceBay")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
        
        if (-not($PSBoundParameters['Enclosure'])) 
        { 
        
            $PipelineInput = $True 
            
        }

        else
        {

            if ($Enclosure -isnot [PSCustomObject])
            {

                $_Message = 'An invalid Enclosure object type was provided, {0}. This Cmdlet only support PSObject types from Get-HPOVEnclosure. Please check the value and try agin.'
                $ErrorRecord = New-ErrorRecord HPOneview.EnclosureResourceException InvalidObjectType InvalidArgument 'Enclosure' -TargetType $Enclousre.Gettype().Name -Message $_Message
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection      = New-Object System.Collections.ArrayList
        $_EnclosureCollection = New-OBject System.Collections.ArrayList
        
    }

    Process
    {

        if ($Enclosure -isnot [PSCustomObject] -and $Enclosure.category -ne 'enclosures')
        {

            $_Message = 'An invalid Enclosure object type was provided, {0}. This Cmdlet only support PSObject types from Get-HPOVEnclosure. Please check the value and try agin.' -f $Enclousre.Gettype().Name
            $ErrorRecord = New-ErrorRecord HPOneview.EnclosureResourceException InvalidObjectType InvalidArgument 'Enclosure' -TargetType $Enclousre.Gettype().Name -Message $_Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if (-not($Enclosure.ApplianceConnection))
        {

            $_Message = 'The provided Enclosure resource object is missing the ApplianceConnection property. This Cmdlet only support PSObject types from Get-HPOVEnclosure. Please check the value and try agin.'
            $ErrorRecord = New-ErrorRecord HPOneview.EnclosureResourceException InvalidObjectType InvalidArgument 'Enclosure' -TargetType $Enclousre.Gettype().Name -Message $_Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_Operation       = NewObject -PatchOperation
        $_Operation.op    = 'replace'
        $_Operation.value = 'E-Fuse'

        switch ($Component)
        {

            'FLM'
            {

                $_Operation.path = '/managerBays/{0}/bayPowerState' -f $DeviceID

                if ($PSBoundParameters['Reset'])
                {

                    $_Operation.value = 'Reset'

                }

            }

            'Device'
            {
                
                $_Operation.path = '/deviceBays/{0}/bayPowerState' -f $DeviceID

                if ($PSBoundParameters['Reset'])
                {

                    $_Operation.value = 'Reset'

                }

            }

            'ICM'
            {

                $_Operation.path = '/interconnectBays/{0}/bayPowerState' -f $DeviceID

            }

            'Appliance'
            {

                $_Operation.path = '/applianceBays/{0}/bayPowerState' -f $DeviceID

            }
        
        }

        "[{0}] Power Operation: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_Operation | Out-String) | Write-Verbose

        if ($PSCmdlet.ShouldProcess(('{0} {1} within {2}' -f $Component, $DeviceID, $Enclosure.name),'Reset power for device'))
        {

            Try
            {

                $_resp = Send-HPOVRequest -Uri $Enclosure.Uri -Method PATCH -Body $_Operation -AddHeader @{'If-Match' = $Enclosure.eTag} -Hostname $Enclosure.ApplianceConnection.Name | Wait-HPOVTaskStart

                if (-not($PSBoundParameters['Async']))
                {

                    $_resp = Wait-HPOVTaskComplete $_resp

                }

                [Void]$_TaskCollection.Add($_resp)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
        elseif ($PSCmdlet.PSBoun['WhatIf'])
        {

            "[{0}] WhatIf operation." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

        else
        {

            "[{0}] User cancelled operation." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

    }

    End
    {

        Return $_TaskCollection

    }

}

function Set-HPOVEnclosureActiveFLM
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default", SupportsShouldProcess,ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [object]$Enclosure,

        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Int]$BayID,

        [Parameter (Mandatory = $false)]
        [switch]$Force

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
        
        if (-not($PSBoundParameters['Enclosure'])) 
        { 
        
            $PipelineInput = $True 
            
        }

        else
        {

            if ($Enclosure -isnot [PSCustomObject])
            {

                $_Message = 'An invalid Enclosure object type was provided, {0}. This Cmdlet only support PSObject types from Get-HPOVEnclosure. Please check the value and try agin.'
                $ErrorRecord = New-ErrorRecord HPOneview.EnclosureResourceException InvalidObjectType InvalidArgument 'Enclosure' -TargetType $Enclousre.Gettype().Name -Message $_Message
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }


        $_TaskCollection      = New-Object System.Collections.ArrayList
        
    }

    Process
    {

        if ($Enclosure -isnot [PSCustomObject] -and $Enclosure.category -ne 'enclosures')
        {

            $_Message = 'An invalid Enclosure object type was provided, {0}. This Cmdlet only support PSObject types from Get-HPOVEnclosure. Please check the value and try agin.' -f $Enclousre.Gettype().Name
            $ErrorRecord = New-ErrorRecord HPOneview.EnclosureResourceException InvalidObjectType InvalidArgument 'Enclosure' -TargetType $Enclousre.Gettype().Name -Message $_Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if (-not($Enclosure.ApplianceConnection))
        {

            $_Message = 'The provided Enclosure resource object is missing the ApplianceConnection property. This Cmdlet only support PSObject types from Get-HPOVEnclosure. Please check the value and try agin.'
            $ErrorRecord = New-ErrorRecord HPOneview.EnclosureResourceException InvalidObjectType InvalidArgument 'Enclosure' -TargetType $Enclousre.Gettype().Name -Message $_Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_Operation = NewObject -PatchOperation
        $_Operation.op    = 'replace'
        $_Operation.path  = '/managerBays/{0}/role' -f $BayID
        $_Operation.value = 'Active'
                
        "[{0}] Requesting to Activate FLM in Bay {1} within {2} Enclosure" -f $MyInvocation.InvocationName.ToString().ToUpper(), $BayID, $Enclosure.name | Write-Verbose
        
        if ($PSCmdlet.ShouldProcess(('FLM Bay {0} within {1} Enclosure' -f $BayID, $Enclosure.name),'Change FLM State to Active'))
        {

            Try
            {

                $_resp = Send-HPOVRequest $Enclosure.Uri PATCH $_Operation -Hostname $Enclosure.ApplianceConnection.Name | Wait-HPOVTaskStart

                if (-not($PSBoundParameters['Async']))
                {

                    $_resp = Wait-HPOVTaskComplete $_resp

                }

                [Void]$_TaskCollection.Add($_resp)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
        elseif ($PSCmdlet.PSBoun['WhatIf'])
        {

            "[{0}] WhatIf operation." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

        else
        {

            "[{0}] User cancelled operation." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

    }

    End
    {

        Return $_TaskCollection

    }

}

function Set-HPOVEnclosure
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param
    (

        [Parameter (ValueFromPipeline, Mandatory, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias('Enclosure', 'Encl')]
        [object]$InputObject,

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [String]$RackName,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        #Support ApplianceConnection property value via pipeline from Enclosure Object
        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_RequestCollection = New-Object System.Collections.ArrayList
        $_TaskCollection    = New-Object System.Collections.ArrayList
        
    }

    Process 
    {

        "[{0}] Processing Enclosure: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

        if ($InputObject.enclosureModel -notmatch 'Synergy' -and ($PSBoundParameters['Name'] -or $PSBoundParameters['RackName']))
        {

            $ExceptionMessage = 'The InputObject {0} is not a supported resource to set the Enclosure Name. For C-Class, you must update the Enclosure or Rack Name within the Onboard Admoinistrator.' -f $InputObject.name
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType 'PSObject' -Message $ExceptionMessage
            $PSCmdlet.WriteError($ErrorRecord)

        }

        elseif ($PSBoundParameters['Name'])
        {

            "[{0}] Setting Enclosure Name to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose

            $_PatchRequest = NewObject -PatchOperation

            $_PatchRequest.op = 'replace'
            $_PatchRequest.path  = '/name'
            $_PatchRequest.value = $Name

            [void]$_RequestCollection.Add($_PatchRequest)

            Try
            {

                $_resp = Send-HPOVRequest $InputObject.uri PATCH $_RequestCollection -AddHeader @{'If-Match' = $InputObject.eTag} -Hostname $InputObject.ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }    
                
        if ($PSBoundParameters['RackName'])
        {

            "[{0}] Setting Enclosure RackName to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $RackName | Write-Verbose

            if ($PSBoundParameters['Name'])
            {

                Try
                {

                    $_resp = Wait-HPOVTaskComplete -InputObject $_resp

                    [void]$_TaskCollection.Add($_resp)

                    "[{0}] Getting updated object" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $InputObject = Send-HPOVRequest -Uri $InputObject.uri -Hostname $InputObject.ApplianceConnection.Name

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
            
            }

            $_RequestCollection = New-Object System.Collections.ArrayList

            $_PatchRequest = NewObject -PatchOperation

            $_PatchRequest.op = 'replace'
            $_PatchRequest.path  = '/rackName'
            $_PatchRequest.value = $RackName

            [void]$_RequestCollection.Add($_PatchRequest)

            Try
            {

                $_resp = Send-HPOVRequest $InputObject.uri PATCH $_RequestCollection -AddHeader @{'If-Match' = $InputObject.eTag} -Hostname $InputObject.ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        [void]$_TaskCollection.Add($_resp)

    }

    End
    {

        Return $_TaskCollection

    }

}

function Start-HPOVEnclosureAppliance
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("Encl")]
        [Object]$Enclosure,

        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateRange(1,2)]
        [int]$BayID,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
        
        if (-not($PSBoundParameters['Enclosure'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            if ($Enclosure -isnot [PSCustomObject] -or ($Enclosure -is [PSCustomObject] -and $Enclosure.category -ne 'enclosures') -or ($Enclosure.model -notmatch 'Synergy'))
            {

                $Message = '{0} is an unsupported resource object ({1}). This Cmdlet only supports Synergy Frame resource objects.' -f $Enclosure.name, $Enclosure.category
                $ErrorRecord = New-ErrorRecord HPOneview.EnclosureResourceException InvalidResoureObject InvalidArgument 'Enclosure' -Message $Message
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_TaskCollection  = New-Object System.Collections.ArrayList
        
    }

    Process 
    {

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Enclosure: {0}" -f $Enclosure.name | Write-Verbose

        if ($PipelineInput)
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $Enclosure.ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        Try
        {

            #Validate to make sure the Appliance bay is not already powered on.
            $Enclosure = Send-HPOVRequest $Enclosure.uri -ApplianceConnection $ApplianceConnection

            if (($Enclosure.applianceBays | ? bayNumber -eq $BayID).poweredOn)
            {
            
                'Appliance Bay {0} in {1} Enclosure is already powered on. Not Processing.' -f $BayID, $Enclosure.name | Write-Warning 
            
            }

            else
            {

                'Appliance Bay {0} in {1} Enclosure is already powered off. Processing.' -f $BayID, $Enclosure.name | Write-Verbose

                $_PatchRequest = NewObject -PatchOperation

                $_PatchRequest.path  = '/applianceBays/{0}/power' -f $BayID
                $_PatchRequest.value = 'on'

                $_resp = Send-HPOVRequest $Enclosure.uri PATCH $_PatchRequest -ApplianceConnection $ApplianceConnection

            }

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
                
        [void]$_TaskCollection.Add($_resp)

    }

    End
    {

        Return $_TaskCollection

    }

}

function Get-HPOVComposerNode
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory = $False)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
        
        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ComposerNodeCollection = New-OBject System.Collections.ArrayList
        
    }

    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($_appliance.ApplianceType -ne 'Composer')
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. This Cmdlet is only supported with Synergy Composers.' -f $_appliance.Name)
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                "[{0}] Processing Appliance Connection {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

                Try
                {

                    $_ComposerNodes = Send-HPOVRequest $ApplianceHANodesUri -Hostname $_appliance

                    $_ComposerNodes.members | % {

                        $_.PSObject.TypeNames.Insert(0,'HPOneView.ComposerNode')

                        [void]$_ComposerNodeCollection.Add($_)

                    }
                
                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }        

        }
        
    }

    End
    {

        Return $_ComposerNodeCollection

    }

}

function Enable-HPOVComposerHANode
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory = $False)]
        [switch]$Async,

        [Parameter (Mandatory = $False)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
        
        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ComposerNodeTaskCollection = New-Object System.Collections.ArrayList
        
    }

    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing Appliance Connection {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            if ($_appliance.ApplianceType -ne 'Composer')
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. This Cmdlet is only supported with Synergy Composers.' -f $_appliance.Name)
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                Try
                {

                    $_ComposerNodes = Send-HPOVRequest $ApplianceHANodesUri -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                $_StandbyComposer = $_ComposerNodes.members | ? role -eq 'Standby'

                if ($_StandbyComposer)
                {

                    if ($PSCmdlet.ShouldProcess($_StandbyComposer.name,"transition from Standby to Active"))
                    {

                        $_operation       = NewObject -PatchOperation
                        $_operation.op    = 'replace'
                        $_operation.path  = '/role'
                        $_operation.value = 'Standby'

                        Try
                        {

                            $_resp = Send-HPOVRequest $_StandbyComposer.uri PATCH $_operation -Hostname $_appliance -AddHeader @{'If-Match' = $_StandbyComposer.eTag}

                        }
                        
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        if (-not($PSBoundParameters['Async']))
                        {

                            Try
                            {

                                $_resp = Wait-HPOVTaskComplete $_resp

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }                            

                        }

                        [void]$_ComposerNodeTaskCollection.Add($_resp)

                    }

                    elseif ($PSBoundParameters['Whatif'])
                    {

                        "[{0}] -Whatif scenario." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    }

                    else
                    {

                        "[{0}] User cancelled operation." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    }

                }

                else
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException NoStandbyComposerFound ObjectNotFound 'Composer' -Message ('No standby Composers were found in {0} ApplianceConnection.' -f $_connection.Name)
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }                

            }

        }
        
    }

    End
    {

        Return $_ComposerNodeTaskCollection

    }

}

function Remove-HPOVStandbyComposerNode
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory = $False)]
        [switch]$Async,

        [Parameter (Mandatory = $False)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
        
        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ComposerNodeTaskCollection = New-OBject System.Collections.ArrayList
        
    }

    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing Appliance Connection {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            if ($_appliance.ApplianceType -ne 'Composer')
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. This Cmdlet is only supported with Synergy Composers.' -f $_appliance.Name)
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                Try
                {

                    $_ComposerNodes = Send-HPOVRequest $ApplianceHANodesUri -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                $_StandbyComposer = $_ComposerNodes.members | ? role -eq 'Standby'

                if ($_StandbyComposer)
                {

                    if ($PSCmdlet.ShouldProcess($_StandbyComposer.name,"Remove Standby from Cluster, factory reset and power off"))
                    {

                        $_operation       = NewObject -PatchOperation
                        $_operation.op    = 'replace'
                        $_operation.path  = '/role'
                        $_operation.value = 'Unused'

                        Try
                        {

                            $_resp = Send-HPOVRequest $_StandbyComposer.uri PATCH $_operation -Hostname $_appliance -AddHeader @{'If-Match' = $_StandbyComposer.eTag}

                        }
                        
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        if (-not($PSBoundParameters['Async']))
                        {

                            Try
                            {

                                $_resp = Wait-HPOVTaskComplete $_resp

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }                            

                        }

                        [void]$_ComposerNodeTaskCollection.Add($_resp)

                    }

                    elseif ($PSBoundParameters['Whatif'])
                    {

                        "[{0}] -Whatif scenario." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    }

                    else
                    {

                        "[{0}] User cancelled operation." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    }

                }

                else
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException NoStandbyComposerFound ObjectNotFound 'Composer' -Message ('No standby Composers were found in {0} ApplianceConnection.' -f $_connection.Name)
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }                

            }

        }
        
    }

    End
    {

        Return $_ComposerNodeTaskCollection

    }

}

function Enclosure-Report 
{

    <#
        .DESCRIPTION
        Internal helper function to display the report of an enclosure
 
        .Parameter Enclosure
        The enclosure object.
     
        .Parameter file
        File to save the report to.
     
        .INPUTS
        Enclosure object.
 
        .OUTPUTS
        Enclosure report.
 
        .LINK
        Get-HPOVEnclosure
 
        .LINK
        Send-HPOVRequest
 
        .EXAMPLE
        PS C:\> $enclosures = Get-HPOVEnclosure
        Return all the enclosure hardware managed by this appliance.
 
    #>

    
    [CmdletBinding ()]    
    Param 
    (

        [Parameter (Mandatory,ValueFromPipeline)]
        [object]$Enclosure,
    
        [Parameter (Mandatory = $false,ValueFromPipeline = $false)]
        [object]$file,
    
        [Parameter (Mandatory = $false)]
        [switch]$fwreport
    )

    Process 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose
        
        write-verbose "ENCLOSURE OBJECT: $($enclosure)"
        write-verbose "ENCLOSURE UUID: $($Enclosure.uuid)"
    
    #ENCLOSURE REPORT DATA
        $a = @{Expression={$_.name};Label="Enclosure Name";width=15},
             @{Expression={$_.serialNumber};Label="Serial Number";width=15},
             @{Expression={$_.enclosureType};Label="Enclosure Model";width=30},
             @{Expression={$_.rackName};Label="Rack Name";width=12},
             @{Expression={$_.isFwManaged};Label="FW Managed";width=10},
             @{Expression={$_.fwBaseLineName};Label="Baseline Name";width=30}

        #Generate Report
        $Enclosure | format-table $a -AutoSize
        
        #License Intent Report
        $a = @{Expression={$_.licensingIntent};Label="Licensing";width=15}

        $Enclosure | format-table $a -AutoSize
        
    #ONBOARD ADMINISTRATOR REPORT DATA
        $a = @{Expression={$_.bayNumber};Label="OA Bay";width=10},
             @{Expression={$_.role};Label="Role";width=15},
             @{Expression={$_.ipAddress};Label="IP Address";width=15},
             @{Expression={($_.fwVersion + " " + $_.fwBuildDate)};Label="Firmware Version";width=20}
        
        $Enclosure.oa | Format-Table $a -AutoSize
        
    #DEVICE BAY REPORT DATA
        #Looking for servers related to the requested enclosure
        $serversCol = New-Object System.Collections.ArrayList
        
        #Loop through populated device bays
        ForEach ($_DeviceBay in ($Enclosure.deviceBays | ? { $_.devicePresence -eq 'Present' -and $_.deviceUri } ))
        {
            
            #Loop through index association results
            Try
            {
                
                $_server = Send-HPOVRequest $_DeviceBay.deviceUri -Hostname $Enclosure.ApplianceConnection.Name

                [void]$serversCol.Add($_server)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
    
        }
        
        $serversCol | out-string | write-verbose
        
        $a = @{Expression={$_.name};Label="Server Name";width=20},
             @{Expression={$_.serialNumber};Label="Serial Number";width=15},
             @{Expression={$_.shortModel};Label="Model";width=12},
             @{Expression={$_.romVersion};Label="System ROM";width=15},
             @{Expression={($_.mpModel + " " + $_.mpFirmwareVersion)};Label="iLO Firmware Version";width=22},
             @{Expression={

                 if (-not($_.serverProfileUri))
                { 
                    
                    'No Profile' 
                
                }

                 else 
                { 
                 
                    Try
                    {

                        (Send-HPOVRequest $_.serverProfileUri -Hostname $Enclosure.ApplianceConnection.Name).name 

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                
                }

             };Label="Server Profile";width=30},
             @{Expression={$_.licensingIntent};Label="Licensing";width=15}
        
        $serversCol | Sort-Object name | format-table $a -AutoSize
        
    #INTERCONNECT BAY REPORT DATA
        #Loop through interconnect bays
        $interconnectsCol = New-Object System.Collections.ArrayList

        foreach ($interconnect in $enclosure.interconnectBays)
        {

            Write-Verbose "INTERCONNECT: $($interconnect)"

            if ($interconnect.interconnectUri)
            {

                Try
                {

                    #Get the Interconnect object to read properties
                    $tempInterconnect = Send-HPOVRequest $interconnect.interconnectUri -Hostname $Enclosure.ApplianceConnection.Name

                    #Get Logical Interconnect associated with the Interconnect to report its Name
                    $li = Send-HPOVRequest $interconnect.logicalInterconnectUri -Hostname $Enclosure.ApplianceConnection.Name

                    $tempInterconnect | Add-Member -type NoteProperty -name liName -value $li.name
                    $tempInterconnect | out-string | Write-Verbose
                
                    [void]$interconnectsCol.Add($tempInterconnect)

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        #Display Interconnect information (Name, Model, Serial Number, FW Ver)
        $a = @{Expression={$_.name};Label="Interconnect Name";width=22},
             @{Expression={$_.model};Label="Module";width=38},
             @{Expression={$_.serialNumber};Label="Serial Number";width=20},
             @{Expression={$_.firmwareVersion};Label="Firmware Version";width=20}

        $interconnectsCol | format-Table $a -AutoSize

        #Display Interconnect information (PAD, Name, Logical Interconnect Name, State, Status)
        $b = @{Expression={' '};Label=" ";width=5},
             @{Expression={$_.name};Label="Interconnect Name";width=22},
             @{Expression={$_.liName};Label="Logical Interconnect";width=30},
             @{Expression={$_.state};Label="State";width=14},
             @{Expression={$_.status};Label="Status";width=20},
             @{Expression={ 
                 
                 Try
                 {

                     $tempLI = Send-HPOVRequest $_.logicalInterconnectUri -Hostname $Enclosure.ApplianceConnection.Name

                 }

                 Catch
                 {

                     $PSCmdlet.ThrowTerminatingError($_)

                 }
                 
                 switch ($tempLI.consistencyStatus) 
                 {
 
                    'CONSISTENT'     { "Consistent" }
                    'NOT_CONSISTENT' { "Inconsistent with group" }
                    default          { $tempLI.consistencyStatus }
                 
                 }
             
             };Label="Consistency state";width=26}

        $interconnectsCol | format-Table $b -AutoSize

        #Write-Host "=================================================================================================================="

    }

}

function Remove-HPOVEnclosure 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default",SupportsShouldProcess,ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri", "name", "Enclosure",'Resource')]
        [object]$InputObject,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$Force

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        
        if (-not($PSBoundParameters['Enclosure'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection      = New-Object System.Collections.ArrayList
        $_EnclosureCollection = New-OBject System.Collections.ArrayList
        
    }

    Process 
    {

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Object provided: $($InputObject | FL * | Out-String)"

            If ($InputObject.category -eq 'enclosures')
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType PSObject -Message "The Network resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_EnclosureCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType PSObject -Message "The Enclosure resource is not an expected category type [$($InputObject.category)]. Allowed resource category type is 'enclosures'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            foreach ($enclosure in $InputObject) 
            {

                #Enclosure passed is a URI
                if (($enclosure -is [String]) -and [System.Uri]::IsWellFormedUriString($enclosure,'Relative')) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received URI: $($enclosures)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Enclosure Object"

                    # // NEED APPLIANCE NAME HERE with If Condition
                    Try
                    {

                        $enclosure = Send-HPOVRequest $enclosure -ApplianceConnection $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                
                }

                #Enclosure passed is the Name
                elseif (($enclosure -is [string]) -and (-not($enclosure.startsWith("/rest")))) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received Enclosure Name $($enclosure)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Enclosure object from Get-HPOVEnclosure"
                    
                    # // NEED APPLIANCE NAME HERE with If Condition
                    Try
                    {

                        $enclosure = Get-HPOVEnclosure $enclosure -ApplianceConnection $ApplianceConnection

                    }
                    

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                #Enclosure passed is an object
                elseif ($enclosure -is [PSCustomObject] -and ($enclosure.category -ieq 'enclosures')) 
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Object provided: $($enclosure | FL * | out-string)"
                
                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Resource' -TargetType 'PSObject' -Message "Invalid Resource Parameter: $($enclosure | FL * | Out-String)"
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                [void]$_EnclosureCollection.Add($enclosure)

            }

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_EnclosureCollection.count) Enclosure resources to remove."

        #Process Enclosure Resources
        ForEach ($_enclosure in $_EnclosureCollection)
        {

            if ($PSCmdlet.ShouldProcess($_enclosure.name,"Remove Enclosure from appliance '$($_enclosure.ApplianceConnection.Name)'")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Enclosure '$($_enclosure.name)' from appliance '$($_enclosure.ApplianceConnection.Name)'."

                Try
                {
                    
                    if ($PSBoundParameters['Force'])
                    {

                        $_enclosure.uri += "?force=true"

                    }

                    $_resp = Send-HPOVRequest $_enclosure.Uri DELETE -Hostname $_enclosure.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Get-HPOVServerHardwareType 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [string]$Model,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ("x", "export")]
        [ValidateScript ({split-path $_ | Test-Path})]
        [String]$exportFile

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_SHTCollection = New-OBject System.Collections.ArrayList
        
    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing Appliance Connection {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            $uri = '{0}?sort=name:asc' -f $ServerHardwareTypesUri

            if ($PSBoundParameters['Name'])
            {

                "[{0}] Server Hardware Type name provided: '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose

                $uri = "{0}&filter=name matches '{1}'" -f $uri, $Name.Replace('*','%25')

            }

            if ($PSBoundParameters['Model'])
            {

                "[{0}] Server Hardware Type model provided: '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Model | Write-Verbose

                $uri = "{0}&filter=model matches '{1}'" -f $uri, $model.Replace('*','%25')

            }

            Try
            {

                $_resp = Send-HPOVRequest $uri -hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['Name'] -and $_resp.count -eq 0)
            {

                $ExceptionMessage = "'{0}' Server Hardware Type not found on '{1}' appliance connection. Please check the name and try again." -f $Name, $_appliance.Name
                $ErrorRecord = New-ErrorRecord InvalidOperationException ServerHardwareTypeNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

            elseif ($PSBoundParameters['Model'] -and $_resp.count -eq 0)
            {

                $ExceptionMessage = "'{0}' Server Hardware Type model not found on '{1}' appliance connection. Please check the name and try again." -f $Model, $_appliance.Name
                $ErrorRecord = New-ErrorRecord InvalidOperationException ServerHardwareTypeNotFound ObjectNotFound 'Model' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                $_resp.members | % { 
                    
                    $_.PSObject.TypeNames.Insert(0,'HPOneView.ServerHardwareType')

                    [void]$_SHTCollection.Add($_)
                
                }

            }

        }

    }

    End 
    {

        if ($PSboundParameters['ExportFile']) 
        {

            $_SHTCollection | ConvertTo-JSON -Depth 99 > $ExportFile

        }

        else
        {

            Return $_SHTCollection

        }

    }

}

function Show-HPOVFirmwareReport 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [Alias('Resource')]
        [validateNotNullorEmpty()]
        [Object]$InputObject,
    
        [Parameter (Mandatory = $false)]
        [validateNotNullorEmpty()]
        [Object]$Baseline,
            
        [Parameter (Mandatory = $false)]
        [Switch]$Export,
            
        [Parameter (Mandatory = $false)]
        [validateNotNullorEmpty()]
        [String]$Location = (get-location).Path,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        #Support ApplianceConnection property value via pipeline from Enclosure Object
        if(-not($PSboundParameters['Resource']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_ResourceCollection       = New-OBject System.Collections.ArrayList
        $_FirmwareReportCollection = New-OBject System.Collections.ArrayList

        #Test for location
        if ($Export) 
        {
        
            if ( -not (Test-Path $Location)) 
            {  

                $ErrorRecord = New-ErrorRecord InvalidOperationException LocationPathNotFound ObjectNotFound 'Location' -Message "The specified path $Location does not exist. Please verify it and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

        }
    
    }

    Process 
    {    

        $_r = 1

        #Add Resource to Collection, which can be accepted via the pipeline
        ForEach ($_resource in $InputObject)
        {

            if ($_resource -is [String])
            {

                #Error that the Resource isn't an object
                $ExcpetionMessage = 'The Inputobject {0} is not a supported resource type, PSObject.' -f $_resource
                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidBaselineResouce InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding '{0}' object to collection ({1}/{2})." -f $_resource.name, $_r, ($InputObject | Measure-Object).Count | Write-Verbose 

            [void]$_ResourceCollection.Add($_resource)

            $_r++

        }

    }

    End 
    {

        $_P = 0

        #Process the report generation here
        ForEach ($_resource in $_ResourceCollection)
        {

            if (-not($PSBoundParameters['Verbose']) -or -not($VerbosePreference -eq 'Continue'))
            {
                
                Write-Progress -id 1 -activity "Generate Firmware Report" -percentComplete (($_P / $_ResourceCollection.count) * 100)

            }

            switch ($_resource.category) 
            {

                "enclosure-groups"
                {

                    $_P++

                    $_ProgressParams = @{

                        ID = 1;
                        Activity = "Generate Firmware Report";
                        CurrentOperation = ("Processing '{0}' Enclosure Group" -f $_resource.name);
                        PercentComplete = (($_P / $_ResourceCollection.count) * 100)

                    }

                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    {
                        
                          "[$($MyInvocation.InvocationName.ToString().ToUpper())] Collecting Enclosure Firmware Information - {0}" -f ($_ProgressParams | Out-String) | Write-Verbose
                    }
                    
                    else 
                    { 

                        Write-Progress @_ProgressParams
                    
                    }

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Enclosure Group to Enclosure associations, then getting found Enclosure Resources."

                    Try
                    {

                        [Array]$_LogicalEnclosures = (Send-HPOVRequest "/rest/index/associations?parentUri=$($_resource.uri)&name=ENCLOSURE_GROUP_TO_LOGICAL_ENCLOSURE" -Hostname $_resource.ApplianceConnection.Name).members  | % { Send-HPOVRequest $_.childUri -Hostname $_.ApplianceConnection.Name}

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                        
                    #Make sure the EG has associated Enclosures/LogicalEnclosures.
                    if ($_LogicalEnclosures) 
                    {

                        $_e = 0

                        $_TotalEnclosures = ($_LogicalEnclosures.enclosureUris | Measure-Object).Count

                        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Total number of Enclosures to Process: {0}" -f $_TotalEnclosures | Write-Verbose 

                        foreach ($_le in $_LogicalEnclosures) 
                        { 

                            #Loop through LE EnclosureUris
                            foreach ($_enclosure in $_le.enclosureUris)
                            {

                                #Get Enclosure Resource Object
                                Try
                                {

                                    $_enclosure = Send-HPOVRequest $_enclosure -Hostname $_resource.ApplianceConnection.Name

                                }
                            
                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }

                                $_e++

                                $_EnclParams = @{

                                    ID               = 10;
                                    ParentID         = 1;
                                    Activity         = "Create Enclosure Firmware Report";
                                    CurrentOperation = ("[{0}\{1}] Processing '{2}' Enclosure" -f $_e, $_TotalEnclosures, $_enclosure.name);
                                    PercentComplete  = (($_e / $_TotalEnclosures) * 100)

                                }

                                #Handle the call from -Verbose so Write-Progress does not get borked on display.
                                if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                                { 

                                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Collecting Enclosure Firmware Information: {0}" -f ($_EnclParams | Out-String) | Write-Verbose
                            
                                }
                    
                                else 
                                { 
                                
                                    Write-Progress @_EnclParams
                            
                                }

                                Try
                                {

                                    $_EnclosureReportCol = Get-EnclosureFirmware -Enclosure $_enclosure -Baseline $Baseline -ProgressID 1

                                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Firmware Report return: {0}" -f ($_EnclosureReportCol | Out-String) | Write-Verbose

                                    ForEach ($_item in $_EnclosureReportCol)
                                    {

                                        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding {0} in {1} to Enclosure Firmware collection" -f $_item.Component, $_item.Name | Write-Verbose
                                        
                                        $_item | add-member -Type NoteProperty -Name eg -value $_resource.name

                                        [void]$_FirmwareReportCollection.Add($_item)

                                    }

                                }
                            
                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }

                            }                        

                        }

                    }
                        
                    #Clear Child Write-Progress progress bars
                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Completed Collecting Enclosure Firmware Information - Skipping Write-Progress display."  
                    
                    }
             
                    else 
                    { 
                        
                        Write-Progress -ParentId 1 -id 2 -activity "Collecting Enclosure Firmware Information" -CurrentOperation "Completed" -Completed 
                    
                    }

                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Completed Collecting Enclosure Group Firmware Information Skipping Write-Progress display."  
                    
                    }
             
                    else 
                    { 
                        
                        Write-Progress -Id 1 -activity "Collecting Enclosure Group Firmware Information" -CurrentOperation "Completed" -Completed 
                    
                    }

                }

                "enclosures" 
                {

                    #Keep track of the number of resources
                    $_P++

                    $_ProgressParams = @{

                        ID = 1;
                        Activity = "Generate Firmware Report";
                        CurrentOperation = ("Processing '{0}' Enclosure" -f $_resource.name);
                        PercentComplete = (($_P / $_ResourceCollection.count) * 100)

                    }

                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    {
                        
                          "[$($MyInvocation.InvocationName.ToString().ToUpper())] Collecting Enclosure Firmware Information - {0}" -f ($_ProgressParams | Out-String) | Write-Verbose
                    }
                    
                    else 
                    { 

                        Write-Progress @_ProgressParams
                    
                    }

                    Try
                    {

                        $_EnclosureReport = Get-EnclosureFirmware -Enclosure $_resource -Baseline $Baseline -ProgressID 1

                        $_EnclosureReport | % {

                            [void]$_FirmwareReportCollection.Add($_)

                        }

                    }

                    Catch
                    {

                        Write-Progress -id 1 -activity "Collecting Enclosure Firmware Information" -CurrentOperation "Completed" -Completed 

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Completed Collecting Enclosure Firmware Information - Skipping Write-Progress display."  
                    
                    }
                
                    else 
                    { 
                        
                        Write-Progress -id 1 -activity "Collecting Enclosure Firmware Information" -CurrentOperation "Completed" -Completed 
                    
                    }

                }

                "server-hardware" 
                { 

                    #Keep track of the number of resources
                    $_P++

                    $_ProgressParams = @{

                        ID = 1;
                        Activity = "Generate Firmware Report";
                        CurrentOperation = ("Processing '{0}' Server(s)" -f $_resource.name);
                        PercentComplete = (($_P / $_ResourceCollection.count) * 100)

                    }

                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    {
                        
                          "[$($MyInvocation.InvocationName.ToString().ToUpper())] Collecting Server Firmware Information - {0}" -f ($_ProgressParams | Out-String) | Write-Verbose
                    }
                    
                    else 
                    { 

                        Write-Progress @_ProgressParams
                    
                    }

                    Try
                    {

                        $_ServerReport = Get-ServerFirmware -Server $_resource -Baseline $Baseline -ProgressID 1

                        $_ServerReport | % {

                            [void]$_FirmwareReportCollection.Add($_)

                        }

                    }

                    Catch
                    {

                        Write-Progress -id 1 -activity "Collecting Server Firmware Information" -CurrentOperation "Completed" -Completed 

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Completed Collecting Server Firmware Information - Skipping Write-Progress display."  
                    
                    }
                
                    else 
                    { 
                        
                        Write-Progress -id 1 -activity "Collecting Server Firmware Information" -CurrentOperation "Completed" -Completed 
                    
                    }
            
                }

                "interconnects" 
                { 

                    #Keep track of the number of resources
                    $_P++

                    $_ProgressParams = @{

                        ID = 1;
                        Activity = "Generate Firmware Report";
                        CurrentOperation = ("Processing '{0}' Interconnects(s)" -f $_resource.name);
                        PercentComplete = (($_P / $_ResourceCollection.count) * 100)

                    }

                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    {
                        
                          "[$($MyInvocation.InvocationName.ToString().ToUpper())] Collecting Interconnect Firmware Information - {0}" -f ($_ProgressParams | Out-String) | Write-Verbose
                    }
                    
                    else 
                    { 

                        Write-Progress @_ProgressParams
                    
                    }

                    Try
                    {

                        $_InterconnectFirmwareReport = Get-InterconnectFirmware -Interconnect $_resource -Baseline $Baseline -ProgressID 1

                        $_InterconnectFirmwareReport | % {

                            [void]$_FirmwareReportCollection.Add($_)

                        }

                    }

                    Catch
                    {

                        Write-Progress -id 1 -activity "Collecting Interconnect Firmware Information" -CurrentOperation "Completed" -Completed 

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Completed Collecting Interconnect Firmware Information - Skipping Write-Progress display."  
                    
                    }
                
                    else 
                    { 
                        
                        Write-Progress -id 1 -activity "Collecting Server Firmware Information" -CurrentOperation "Completed" -Completed 
                    
                    }
           
                }

            }

        }

        Write-Progress -Activity "Firmware collection report complete." -PercentComplete (100) -Status "Finished." -Completed

        if ($Export) 
        { 

            $_Location = '{0}\FirmwareReport_{1}.csv' -f $Location,[DateTime]::Now.ToUniversalTime().ToString('yyyy-MM-ddTHH.mm.ss.ff.fffZzzz').Replace(':','')

            $_FirmwareReportCollection | % { Export-Csv -InputObject $_ -Path $_Location -AppEnd -NoTypeInformation -Encoding UTF8 }
                
        }

        #Display Report
        else 
        {

            Return $_FirmwareReportCollection | ft

        }

    }

}

function Get-EnclosureFirmware 
{

    <#
        Internal-only function.
    #>


    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (
    
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateScript({
            if ($_.category -ne 'enclosures') 
            { 
                
                Throw ("The resource object provided is not an Enclosure Resource. Expected category 'enclosures', recieved '{0}' [{1}]." -f $_.category, $_.name)
            }

            else
            {

                $True

            }
        
        })]
        [PsCustomObject]$Enclosure, 

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [object]$Baseline,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [int]$ProgressID = 0
        
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        #Reset private variables
        $_BaseLinePolicy  = $Null
        $_EnclosureReport = New-Object System.Collections.ArrayList

        #Keep track of the number of Servers
        $_s = 0

        #Keep track of the number of Interconnects
        $_i = 0
        
        #Keep track of the number of OAs
        $_o = 0

        #See if EnclosureObject was passed via Pipeline
        if (-not $PSBoundParameters['Enclosure']) 
        { 
            
            $PipelineInput = $True 
        
        }

    }

    Process 
    {
        
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Object passed via pipeline: $($PipelineInput)"
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Enclosure firmware report for: '$($Enclosure.name)'"

        #Use the Enclosure FwBaseline if it is set
        if (($Enclosure.isFwManaged) -and ($null -eq $Baseline)) 
        { 

            Try
            {

                $BaseLinePolicy = Send-HPOVRequest $Enclosure.fwBaselineUri -Hostname $Enclosure.ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        elseif (($Baseline) -and ($Baseline -is [PsCustomObject]) -and ($Baseline.category -eq "firmware-drivers")) 
        { 
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline resource passed."
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline resource name: $($Baseline.baselineShortName)"
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline resource uri: $($Baseline.uri)"
            $BaseLinePolicy = $Baseline
            
        }
        
        #Check to see if the wrong Object has been passed
        elseif (($Baseline) -and ($Baseline -is [PsCustomObject]) -and ($Baseline.category -ne "firmware-drivers")) 
        { 
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid Baseline resource passed. Generating error."
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidBaselineResouce InvalidArgument 'Baseline' -TargetType 'PSObject' -Message "An invalid Baseline Object was passed. Expected Category type 'firmware-drivers', received '$($Baseline.category)' (Object Name: $($Baseline.name)"
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
        }
        
        elseif (($Baseline) -and ($Baseline -is [string]) -and ($Baseline.StartsWith(($script:fwDriversUri)))) 
        { 
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline URI passed: $Baseline"

            Try
            {

                $BaseLinePolicy = Send-HPOVRequest $Baseline -Hostname $Enclosure.ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
        
        }
        
        #Check to see if the wrong URI has been passed
        elseif (($Baseline) -and ($Baseline -is [string]) -and $Baseline.StartsWith("/rest/") -and ( ! $Baseline.StartsWith(($ApplianceBaselineRepoUri)))) 
        { 
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid Baseline URI passed. Generating error."
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidBaselineValue InvalidArgument 'Baseline' -Message "The wrong Baseline URI was passed. URI must start with '/rest/firmware-drivers/', received '$($Baseline)'"
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)        
            
        }
        
        elseif (($Baseline) -and ($Baseline -is [string])) 
        { 
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline Name passed: $Baseline"

            Try
            {

                #$BaseLinePolicy = Get-HPOVBaseline -name $Baseline

                $FirmwareBaslineName = $Baseline.Clone()

                $BaseLinePolicy = Get-HPOVBaseline -name $Baseline -ErrorAction SilentlyContinue

                If (-not $BaseLinePolicy)
                {

                    $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $FirmwareBaslineName
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Baseline' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
        }
        
        else 
        { 
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Baseline provided."

            $BaseLinePolicy = [PsCustomObject]@{ baselineShortName = "No Policy Set" } 
        
        }

        #Get OA Firmware Information
        foreach ($_oa in $Enclosure.managerBays) 
        {

            $_o ++

            $_ProgressParams = @{

                id               = (2 + $ProgressID);
                ParentId         = 1;
                activity         = "Collecting Onboard Administrator Firmware Information";
                CurrentOperation = ("[{0}/{1}] Processing '{2}'" -f $_o, $Enclosure.managerBays.count, $_oa.role);
                percentComplete  = (($_o / $Enclosure.managerBays.count) * 100) 

            }

            #Handle the call from -Verbose so Write-Progress does not get borked on display.
            if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
            { 
                
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Collecting Onboard Administrator Firmware Information - Skipping Write-Progress display: {0}" -f ($_ProgressParams | Out-String) | Write-Verbose
            
            }
            
            else 
            { 
                
                Write-Progress @_ProgressParams
            
            }

            #If OA is absent report it as such
            if ($_oa.role -eq "OaAbsent") 
            {
                
                $_OAReport = [PSCustomObject]@{ 

                    ApplianceConnection = $_resource.ApplianceConnection.Name
                    Name                = $Enclosure.name; 
                    Device              = $Enclosure.enclosureType; 
                    Component           = "OA Bay $($_oa.bayNumber) Absent"; 
                    Installed           = "N/A"; Baseline = "N/A" ; 
                    BaselinePolicy      = "N/A"; 
                    Compliance          = "N/A" 

                }
            
            }
            
            else 
            {

                if ($BaseLinePolicy.baselineShortName -eq "No Policy Set") 
                { 
                    
                    $BaselineVer = "N/A" 
                    $Compliance  = "N/A" 
                
                }

                else 
                { 
                    
                    $_BaselineVersions = ($BaseLinePolicy.fwComponents | ? swKeyNameList -match "oa" ).componentVersion 

                    $_NewerVersion = $null

                    #Figure out which is the newest, and only display that if multiple ROM versions found
                    foreach ($_version in $_BaselineVersions)
                    {

                        if ($_NewerVersion)
                        {

                            if ($_version -gt $_NewerVersion)
                            {

                                $_NewerVersion = $_version
                            
                            }

                        }

                        else
                        {

                            if ($_version -ge $_oa.fwVersion)
                            {
                            
                                $_NewerVersion = $_version

                            }

                        }

                    }

                    $_BaselineVer = $_NewerVersion
                
                }

                if ($_oa.fwVersion -ne $_BaselineVer)
                { 
                    
                    $Compliance = "Not Compliant" 
                
                }
                 
                else 
                { 
                    
                    $Compliance = "Compliant" 
                
                }

                $_OAReport = [PSCustomObject]@{

                    ApplianceConnection = $_resource.ApplianceConnection.Name
                    Name                = $Enclosure.name; 
                    Device              = $Enclosure.enclosureType; 
                    Component           = "OA Bay $($_oa.bayNumber) $($_oa.role)"; 
                    Installed           = $_oa.fwVersion; 
                    Baseline            = $_BaselineVer ; 
                    BaselinePolicy      = $BaseLinePolicy.baselineShortName; 
                    Compliance          = $Compliance 
                    
                }

            }

            $_OAReport.PSObject.TypeNames.Insert(0,'HPOneView.FirmwareReport')

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding {0} in {1} to Enclosure Firmware collection" -f $_item.Component, $_item.Name | Write-Verbose

            [void]$_EnclosureReport.Add($_OAReport)

        } 

        #Get Server Resource Objects
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Server resources from the enclosure."
        Try
        {

            $Uri = "{0}?filter=locationUri='{1}'" -f $ServerHardwareUri, $Enclosure.uri
            $_Servers = Send-HPOVRequest -Uri $uri -Hostname $Enclosure.ApplianceConnection.Name

        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $_s = 0

        foreach ($_server in $_Servers.members) 
        {

            $_s++

            $_ProgressParams = @{

                id               = (3 + $ProgressID);
                ParentId         = 1;
                activity         = "Collecting Server Firmware Information";
                CurrentOperation = ("[{1}/{2}] Processing '{0}' Server" -f $_server.name, $_s, $_Servers.Count);
                percentComplete  = (($_s / $_Servers.members.count) * 100)

            }

            #Handle the call from -Verbose so Write-Progress does not get borked on display.
            if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
            {
                
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Collecting Server Firmware Information - Skipping Write-Progress display: {0}" -f ($_ProgressParams | Out-String) | Write-Verbose
            
            }
             
            else 
            { 
                
                Write-Progress @_ProgressParams
            
            }

            Try
            {

                $_ServerFirmwareReport = Get-ServerFirmware -Server $_server -Baseline $BaseLinePolicy 

                ForEach ($_item in $_ServerFirmwareReport)
                {

                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding {0} in {1} to Enclosure Firmware collection" -f $_item.Component, $_item.Name | Write-Verbose

                    $_item.PSObject.TypeNames.Insert(0,'HPOneView.FirmwareReport')

                    [void]$_EnclosureReport.Add($_item)

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Interconnect resources from the enclosure."

        Try
        {

            $_Interconnects = ($Enclosure.interconnectBays | ? interconnectUri -ne $Null | % { Send-HPOVRequest $_.interconnectUri -Hostname $Enclosure.ApplianceConnection.Name })

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        

        #Get Interconnect Information
        foreach ($_interconnect in $_Interconnects) 
        {

            $_i++

            $_ProgressParams = @{

                id               = (4 + $ProgressID);
                ParentId         = 1;
                activity         = "Collecting Interconnect Firmware Information";
                CurrentOperation = ("Processing {0}: {1} of {2} Interconnect(s)" -f $_interconnect.name, $_i, $_Interconnects.Count);
                percentComplete  = (($_i / $_Interconnects.Count) * 100) 

            }

            #Handle the call from -Verbose so Write-Progress does not get borked on display.
            if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
            {
                
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Collecting Interconnect Firmware Information - Skipping Write-Progress display: {0}" -f ($_ProgressParams | Out-String) | Write-Verbose
            
            }
             
            else 
            { 
                
                Write-Progress @_ProgressParams
            
            }

            Try
            {

                $_InterconnectReport = Get-InterconnectFirmware -Interconnect $_interconnect -Baseline $BaseLinePolicy

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding {0} in {1} to Enclosure Firmware collection" -f $_InterconnectReport.Component, $_InterconnectReport.Name | Write-Verbose

            $_InterconnectReport.PSObject.TypeNames.Insert(0,'HPOneView.FirmwareReport')

            [void]$_EnclosureReport.Add($_InterconnectReport)

        }

        #Handle the call from -Verbose so Write-Progress does not get borked on display.
        if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
        { 
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Completed Collecting OA/Server/Interconnect Firmware Information - Skipping Write-Progress display."  
        
        }
         
        else 
        { 
        
            Write-Progress -ParentId 1 -id (2 + $ProgressID) -activity "Collecting Onboard Administrator Firmware Information" -CurrentOperation "Completed" -Completed                    
            Write-Progress -ParentId 1 -id (3 + $ProgressID) -activity "Collecting Server Firmware Information" -CurrentOperation "Completed" -Completed
            Write-Progress -ParentId 1 -id (4 + $ProgressID) -activity "Collecting Interconnect Firmware Information" -CurrentOperation "Completed" -Completed

        }

    }

    End 
    {

        Return $_EnclosureReport

    }

}

function Get-ServerFirmware 
{

    <#
        Internal-only function.
    #>


    [CmdletBinding ()]
    Param 
    (
    
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [PsCustomObject]$Server, 

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [object]$Baseline
        
    )


    Begin 
    {

        #See if serverObject was passed via Pipeline
        if (-not $PSBoundParameters['serverObject']) { $PipelineInput = $True }
        
        $_ServerReport = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Object passed via pipeline: $($PipelineInput)"
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Server firmware report for: '$($server.name)'"
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Server Hardware Type"

        #Check if the server hardware type allows firmware management
        Try
        {

            $_sht = Send-HPOVRequest -Uri $Server.serverHardwareTypeUri -Hostname $Server.ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        

        if ($_sht.capabilities -match "FirmwareUpdate") 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Hardware Type supports firmware management."

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline value provided: {0}" -f ($Baseline | Out-String) | Write-Verbose

            #If a bladeserver and that the caller hasn't specified a Baseline, Use the Enclosure FwBaseline if it is set
            if (-not($Baseline))
            { 

                #Check to see if there is a profile
                if ($Server.serverProfileUri) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Baseline provided. Checking Server Profile."

                    Try
                    {

                        $_ServerProfile = Send-HPOVRequest $Server.serverProfileUri -Hostname $Server.ApplianceConnection.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    #Then check if a Baseline is attached there
                    if ($_ServerProfile.firmware.manageFirmware) 
                    { 
                    
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Profile has baseline attached. Getting baseline details."

                        Try
                        {

                            $_BaselinePolicy = Send-HPOVRequest $_ServerProfile.firmware.firmwareBaselineUri -Hostname $Server.ApplianceConnection.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Profile Baseline name: $($_BaselinePolicy.name)"

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Profile Baseline name: $($_BaselinePolicy.uri)"

                    }
                    
                    #If not, set $BaselinePolicy to No Policy Set
                    else 
                    {
                        
                        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Profile does not have a baseline attached."

                        $_BaselinePolicy = [PsCustomObject]@{ 
                            
                            baselineShortName = "No Policy Set" 
                        
                        } 

                    }

                }

                else 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Server Profile assigned, which does not have a baseline policy set."

                    $_BaselinePolicy = [PsCustomObject]@{ 
                            
                        baselineShortName = "No Policy Set" 
                        
                    } 

                }
                   
            }

            elseif ($Baseline -is [PSCustomObject])
            {

                if ($Baseline.baselineShortName -eq 'No Policy Set')
                {

                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Baseline provided."

                    $_BaseLinePolicy = [PsCustomObject]@{ baselineShortName = "No Policy Set" } 

                }

                elseif (($Baseline) -and ($Baseline.category -eq "firmware-drivers")) 
                { 
            
                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline resource passed."
                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline resource name: $($Baseline.baselineShortName)"
                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline resource uri: $($Baseline.uri)"

                    $_BaselinePolicy = $Baseline.PSObject.Copy()
                
                }

                #Check to see if the wrong Object has been passed
                elseif (($Baseline) -and ($Baseline.category -ne "firmware-drivers")) 
                { 
            
                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid Baseline resource passed. Generating error."

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentType InvalidArgument 'getserverfirmware' -Message "The wrong Baseline Object was passed. Expected Category type `'firmware-drivers`', received `'$($Baseline.category)`' (Object Name: $($Baseline.name)"

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }


            }            

            elseif (($Baseline) -and ($Baseline -is [string]) -and ($Baseline.StartsWith(($script:fwDriversUri)))) 
            { 
                
                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline URI passed: $Baseline"

                Try
                {

                    $_BaseLinePolicy = Send-HPOVRequest $Baseline -Hostname $Server.ApplianceConnection.Name

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
            
            }

            #Check to see if the wrong URI has been passed
            elseif (($Baseline) -and ($Baseline -is [string]) -and $Baseline.StartsWith("/rest/") -and (-not($Baseline.StartsWith(($ApplianceBaselineRepoUri))))) 
            { 

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid Baseline URI passed. Generating error."
                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentType InvalidArgument 'getserverfirmware' -Message "The wrong Baseline URI was passed. URI must start with '/rest/firmware-drivers/', received '$($Baseline)'"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)        
                
            }

            #Baseline must be a Name
            else
            { 
            
                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline Name passed: $Baseline"

                Try
                {

                    $FirmwareBaslineName = $Baseline.Clone()

                    $_BaseLinePolicy = Get-HPOVBaseline -name $Baseline -ApplianceConnection $Server.ApplianceConnection.Name -ErrorAction SilentlyContinue

                    If (-not $_BaseLinePolicy)
                    {

                        $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $FirmwareBaslineName
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Baseline' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)
                
                }
                
                
            }

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Server ROM Information."

            #Saving SystemROM Information
            $_ServerRomVersion = ($Server.romVersion -replace "/",".").SubString(4)

            #Check Baseline Policy and set Compliance statement
            if ($_BaseLinePolicy.baselineShortName -eq "No Policy Set") 
            { 
                            
                $_BaselineVer = "N/A" 
                $_Compliance  = "N/A"
                                    
            }

            else 
            { 
                            
                $BaselineVer = ($_BaseLinePolicy.fwComponents | ? swKeyNameList -eq $Server.romVersion.SubString(0,3)).componentVersion

                write-verbose "Found Baseline version(s): $($BaselineVer | out-string)"

                $_NewerVersion = $null

                #Figure out which is the newest, and only display that if multiple ROM versions found
                foreach ($_version in $BaselineVer)
                {

                    if ($_NewerVersion)
                    {

                        if ($_version -gt $_NewerVersion)
                        {

                            $_NewerVersion = $_version
                            
                        }

                    }

                    else
                    {

                        if ($_version -ge $_ServerRomVersion)
                        {
                            
                            $_NewerVersion = $_version

                        }

                    }

                }

                $_BaselineVer = $_NewerVersion

                if ($_ServerRomVersion -ne $_BaselineVer) 
                { 
                    
                    $_Compliance = "Not Compliant" 
                
                } 
                
                else 
                { 
                    
                    $_Compliance = "Compliant" 
                
                }                
                 
            }

            $_Report = [PSCustomObject]@{ 
                
                ApplianceConnection = $_resource.ApplianceConnection.Name
                Name           = $Server.name; 
                Device         = $Server.shortModel; 
                Component      = "ROM"; 
                Installed      = $_ServerRomVersion; 
                Baseline       = $_BaselineVer ; 
                BaselinePolicy = $_BaseLinePolicy.baselineShortName; 
                Compliance     = $_Compliance 
            
            }

            [void]$_ServerReport.Add($_Report)

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Server iLO Information."

            #Saving iLO Information
            $_MpFirmwareVersion = $Server.mpFirmwareVersion.SubString(0,4)

            #Check Baseline Policy and set Compliance statement
            if ($_BaseLinePolicy.baselineShortName -eq "No Policy Set") 
            {
                            
                $_BaselineVer = "N/A" 
                $_Compliance = "N/A"
                                    
            }

            else 
            { 
                            
                $_BaselineVersions = ($_BaseLinePolicy.fwComponents | ? swKeyNameList -match $mpModelTable.($Server.mpModel)).componentVersion

                $_NewerVersion = $null

                #Figure out which is the newest, and only display that if multiple ROM versions found
                foreach ($_version in $_BaselineVersions)
                {

                    if ($_NewerVersion)
                    {

                        if ($_version -gt $_NewerVersion)
                        {

                            $_NewerVersion = $_version
                            
                        }

                    }

                    else
                    {

                        if ($_version -ge $_MpFirmwareVersion)
                        {
                            
                            $_NewerVersion = $_version

                        }

                    }

                }

                $_BaselineVer = $_NewerVersion

                if ($_MpFirmwareVersion -ne $_BaselineVer) 
                { 
                    
                    $_Compliance = "Not Compliant" 
                
                } 

                else 
                { 
                    
                    $_Compliance = "Compliant" 
                
                } 
                                
            }

            $_Report = [PSCustomObject]@{ 
                
                ApplianceConnection = $_resource.ApplianceConnection.Name
                Name           = $Server.name; 
                Device         = $Server.shortModel; 
                Component      = "iLO"; 
                Installed      = $_MpFirmwareVersion; 
                Baseline       = $_BaselineVer; 
                BaselinePolicy = $_BaseLinePolicy.baselineShortName; 
                Compliance     = $_Compliance 
            
            }

            [void]$_ServerReport.Add($_Report)

            if ($Server.intelligentProvisioningVersion)
            {

                #Report Intelligent Provisioning version
                $_Report = [PSCustomObject]@{ 
                
                    ApplianceConnection = $_resource.ApplianceConnection.Name
                    Name           = $Server.name; 
                    Device         = $Server.shortModel; 
                    Component      = "Intelligent Provisioning"; 
                    Installed      = $Server.intelligentProvisioningVersion; 
                    Baseline       = 'N/A'; 
                    BaselinePolicy = 'N/A'; 
                    Compliance     = 'N/A'
            
                }

                [void]$_ServerReport.Add($_Report)

            }

        }

        #Server firmware is unmanageable based on its Server Hardware Type
        else 
        { 
            
            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Hardware Type does not support firmware management."      

            [void]$_ServerReport.Add(

                [PSCustomObject]@{ 

                    ApplianceConnection = $_resource.ApplianceConnection.Name
                    Name           = $Server.name; 
                    Device         = $Server.shortModel; 
                    Component      = "N/A"; 
                    Installed      = "N/A"; 
                    Baseline       = "N/A" ; 
                    BaselinePolicy = "Unmanageable" 
                
                }

            )

        }

    }

    End 
    {

        $_ServerReport | % {

            $_.PSObject.TypeNames.Insert(0,'HPOneView.FirmwareReport')

        }

        Return $_ServerReport

    }

}

function Get-InterconnectFirmware 
{

    <#
        Internal-only function.
    #>


    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (
    
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [PsCustomObject]$Interconnect, 

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [object]$Baseline = $Null
        
    )


    Begin 
    {

        $_InterconnectReport = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Interconnect firmware report for: {0}" -f $Interconnect.name | Write-Verbose

        $_InterconnectFirmwareVersion = $Interconnect.firmwareVersion
        
        if (-not($Baseline))
        {



            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline was not provided, checking Logical Interconnect Firmware Baseline set."

            Try
            {

                $_LogicalInterconnect = Send-HPOVRequest $Interconnect.logicalInterconnectUri -Hostname $Interconnect.ApplianceConnection.Name

                $_LogicalInterconnectFirmware = Send-HPOVRequest ($_LogicalInterconnect.uri + '/firmware') -Hostname $Interconnect.ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($_LogicalInterconnectFirmware.sppUri.ToLower() -ne 'unknown')
            {
                
                Try
                {

                    $_BaseLinePolicy = Send-HPOVRequest $_LogicalInterconnectFirmware.sppUri -Hostname $Interconnect.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconenct Firmware Baseline name: {0}" -f $_BaseLinePolicy.name | Write-Verbose

            }

            Else
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline was not provided, checking Enclosure Firmware Baseline set."

                Try
                {

                    $_Enclosure = Send-HPOVRequest $Interconnect.enclosureUri -Hostname $Interconnect.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
            
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Firmware Baseline set: {0}" -f $_Enclosure.isFwManaged | Write-Verbose 

                #Check if the Enclosure has a Firmware Baseline attached
                if ($_Enclosure.isFwManaged -and $_Enclosure.fwBaselineUri)
                { 

                    Try
                    {

                        $_BaseLinePolicy = Send-HPOVRequest $_Enclosure.fwBaselineUri -Hostname $Interconnect.ApplianceConnection.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Firmware Baseline name: {0}" -f $_BaseLinePolicy.name | Write-Verbose

                }

                else 
                { 
            
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Baseline provided."

                    $_BaseLinePolicy = [PsCustomObject]@{ baselineShortName = "No Policy Set" } 
            
                }

            }

        }
        
        elseif ($Baseline -is [PSCustomObject])
        {

            if ($Baseline.baselineShortName -eq 'No Policy Set')
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Baseline provided."

                $_BaseLinePolicy = [PsCustomObject]@{ baselineShortName = "No Policy Set" } 

            }

            elseif (($Baseline) -and ($Baseline.category -eq "firmware-drivers")) 
            { 
            
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline resource passed."
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline resource name: {0}" -f $Baseline.baselineShortName | Write-Verbose 
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline resource uri: {0}" -f $Baseline.uri | Write-Verbose 

                $_BaselinePolicy = $Baseline.PSObject.Copy()
                
            }

            #Check to see if the wrong Object has been passed
            elseif (($Baseline) -and ($Baseline.category -ne "firmware-drivers")) 
            { 
            
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid Baseline resource passed. Generating error."
                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentType InvalidArgument 'Baseline' -TargetType 'PSObject' -Message ("An invalid Baseline Object was passed. Expected Category type 'firmware-drivers', received '{0}' (Object Name: {1})" -f $Baseline.category, $Baseline.name)
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
            }

        }            

        elseif (($Baseline) -and ($Baseline -is [string]) -and ($Baseline.StartsWith(($script:fwDriversUri)))) 
        { 
                
            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Baseline URI passed: $Baseline"

            Try
            {

                $_BaseLinePolicy = Send-HPOVRequest $Baseline -Hostname $Server.ApplianceConnection.Name

            }
                
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
        }

        #Check to see if the wrong URI has been passed
        elseif (($Baseline) -and ($Baseline -is [string]) -and $Baseline.StartsWith("/rest/") -and (-not($Baseline.StartsWith(($ApplianceBaselineRepoUri))))) 
        { 

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid Baseline URI passed. Generating error."
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentType InvalidArgument 'Baseline' -Message "The wrong Baseline URI was passed. URI must start with '/rest/firmware-drivers/', received '$($Baseline)'"
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)        
                
        }

        else 
        { 
                
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Unknown baseline." 
            
        }

        if ($_BaseLinePolicy.baselineShortName -eq "No Policy Set") 
        { 
        
            $_BaselineVer = "N/A"
            $_Compliance = "N/A"

        }

        else 
        { 

            $_BaselineVersions = ($_BaseLinePolicy.fwComponents | ? swKeyNameList -match "vceth").componentVersion

            $_NewerVersion = $null

            #Figure out which is the newest, and only display that if multiple ROM versions found
            foreach ($_version in $_BaselineVersions)
            {

                if ($_NewerVersion)
                {

                    if ($_version -gt $_NewerVersion)
                    {

                        $_NewerVersion = $_version
                            
                    }

                }

                else
                {

                    if ($_version -ge $_InterconnectFirmwareVersion)
                    {
                            
                        $_NewerVersion = $_version

                    }

                }

            }

            $_BaselineVer = $_NewerVersion

            if ($_InterconnectFirmwareVersion -ne $_BaselineVer) 
            { 
                    
                $_Compliance = "Not Compliant" 
                
            } 

            else 
            { 
                    
                $_Compliance = "Compliant" 
                
            } 
                                
        }

        $_Report = [PSCustomObject]@{ 
                
            ApplianceConnection = $_resource.ApplianceConnection.Name;
            Name           = $Interconnect.name; 
            Device         = $Interconnect.model; 
            Component      = 'Interconnect'; 
            Installed      = $_InterconnectFirmwareVersion; 
            Baseline       = $_BaselineVer; 
            BaselinePolicy = $_BaseLinePolicy.baselineShortName; 
            Compliance     = $_Compliance 
            
        }

        [void]$_InterconnectReport.Add($_Report)

    }

    End 
    {

        $_InterconnectReport | % {

            $_.PSObject.TypeNames.Insert(0,'HPOneView.FirmwareReport')

        }

        Return $_InterconnectReport

    }

}

function Enable-HPOVDeviceUid
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Server','Enclosure','Frame','Resource')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Resource']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_ResourceStatusCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        $_RequestCollection = New-Object System.Collections.ArrayList

        if ($PiplineInput)
        {

            "[{0}] Pipeline Input recieved." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

        if ($InputObject -isnot [PSCustomObject])
        {

            $Message = 'The -Resource Parameter value is not an Object. Please use Get-HPOVServer or Get-HPOVEnclosure to provide an allowed resource object.'
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message $Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_PatchRequest = NewObject -PatchOperation

        "[{0}] Turning UID on for: {1} {{2}}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name, $InputObject.category | Write-Verbose

        switch ($InputObject.category)
        {

            {'server-hardware', 'enclosures' -contains $_}
            {

                $_PatchRequest.op = 'replace'
                $_PatchRequest.path  = '/uidState'
                $_PatchRequest.value = 'On'

            }

            default
            {

                $Message = "The -Resource Parameter value is not a supported object, {0}. This Cmdlet only supports 'server-hardware' or 'enclosures'. Please use Get-HPOVServer or Get-HPOVEnclosure to provide an allowed resource object." -f $InputObject.category
                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message $Message
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        [void]$_RequestCollection.Add($_PatchRequest)

        Try
        {

            $_resp = Send-HPOVRequest $InputObject.uri PATCH $_RequestCollection -ApplianceConnection $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        [void]$_ResourceStatusCollection.Add($_resp)

    }

    End 
    {

        Return $_ResourceStatusCollection

    }

}

function Disable-HPOVDeviceUid
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Server','Enclosure','Frame','Resource')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Resource']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ResourceStatusCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($ApplianceConnection.ApplianceType -ne 'Composer')
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. This Cmdlet is only supported with Synergy Composers.' -f $ApplianceConnection.Name)
            $PSCmdlet.WriteError($ErrorRecord)

        }

        $_RequestCollection = New-Object System.Collections.ArrayList

        if ($PiplineInput)
        {

            "[{0}] Pipeline Input recieved." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

        if ($InputObject -isnot [PSCustomObject])
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgument InvalidArgument 'InputObject' -Message "InputObject is not a PSCustomObject."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_PatchRequest = NewObject -PatchOperation

        "[{0}] Turning UID OFF for: {1} {{2}}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name, $InputObject.category | Write-Verbose

        switch ($InputObject.category)
        {

            {'server-hardware', 'enclosures' -contains $_}
            {

                $_PatchRequest.op = 'replace'
                $_PatchRequest.path  = '/uidState'
                $_PatchRequest.value = 'Off'

            }

            default
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidObjectCategory InvalidArgument 'InputObject' -Message "InputObject is not a supported object category. Only 'server-hardware' or 'enclosures' Synergy resources are supported."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        [void]$_RequestCollection.Add($_PatchRequest)

        Try
        {

            $_resp = Send-HPOVRequest $InputObject.uri PATCH $_RequestCollection -ApplianceConnection $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        [void]$_ResourceStatusCollection.Add($_resp)

    }

    End 
    {

        Return $_ResourceStatusCollection

    }

}

function ConvertTo-HPOVImageStreamerConfiguration
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('EnclosureGroup','EG')]
        [Object]$InputObject,

        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [String]$UplinkSetName,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Array]$UplinkPorts = @("Enclosure1:Bay3:Q1.1", "Enclosure1:Bay3:Q2.1", "Enclosure2:Bay6:Q1.1", "Enclosure2:Bay6:Q2.1"),
        
        [Parameter (Mandatory, ParameterSetName = 'default')]
        [ValidateNotNullOrEmpty()]
        [Object]$DeploymentNetwork,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        
        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -gt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList
        $_Collection     = New-OBject System.Collections.ArrayList
        
    }

    Process
    {

        If ($ApplianceConnection.ApplianceType -ne 'Composer')
        {

            $ExceptionMessage = 'The ApplianceConnection {0} ({1}) is not a Synergy Composer. This Cmdlet only support Synergy Composer management appliances.' -f $ApplianceConnection.Name, $ApplianceConnection.ApplianceType
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        Try
        {

            if (-not(Get-HPOVOSDeploymentServer -ApplianceConnection $ApplianceConnection -ErrorAction SilentlyContinue))
            {

                $ExceptionMessage = 'The appliance {0} does not have a Deployment Server. One must be created before attempting to set an Enclosure Group and Logical Interconnect Group policy change.' -f $ApplianceConnection.name
                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.DeploymentServerResourceException OsDeploymentServerNotFound ObjectNotFound 'ApplianceConnect' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $MultipleAssociatedEGs = $False

        "[{0}] InputObject: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | Out-String) | Write-Verbose 

        #Validate InputObject
        if ($InputObject -is [PCustomObject])
        {

            "[{0}] Processing category: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.category | Write-Verbose 

            if ($InputObject.category -eq 'logical-enclosure')
            {

                Try
                {

                    $InputObject = Send-HPOVRequest -Uri $InputObject.enclosureGroupUri -ApplianceConnection $InputObject.ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
            }

            elseif ($InputObject.category -eq 'logical-interconnect-groups')
            {

                #Check to see if the LIG is a member of other EG's via the Index?
                try
                {

                    $IndexResults = Send-HPOVRequest -Uri ('{0}?childUri={1}&name=ENCLOSURE_GROUP_TO_LOGICAL_INTERCONNECT_GROUP' -f $IndexUri, $InputObject.uri)
                    
                    $MultipleAssociatedEGs = $IndexResults.count -gt 1

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($InputObject.category -ne 'enclosure-groups')
            {

                $ErrorRecord = New-ErrorRecord
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        #Look for name?
        else
        {

            Try
            {

                $InputObject = Get-HPOVEnclosureGroup -Name $InputObject -ErrorAction Stop

            }

            catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Process multiple EG's
        if ($MultipleAssociatedEGs)
        {

            $InputObject = New-Object System.Collections.ArrayList

            "[{0}] Processing multiple Enclosure Group associations to Logical Interconnect Group" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

            ForEach ($_Item in $IndexResults)
            {

                Try
                {

                    $EnclosureGroup = Send-HPOVRequest -Uri $_Item.parentUri -Hostname $ApplianceConnection

                    [void]$InputObject.Add($EnclosureGroup)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        #Single EG
        else
        {

            "[{0}] Processing single Enclosure Group associations to Logical Interconnect Group" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
        
        }

        #Process all EG's by removing the LIG association from Bay3 and Bay6 first
        ForEach ($_EnclosureGroup in $InputObject)
        {

            #EG is already configured for Image Streamer, generate error
            if ($_EnclosureGroup.osDeploymentSettings.manageOSDeployment)
            {

                $ExceptionMessage = 'The Enclosure Group {0} is already configured for Image Streamer.' -f $_EnclosureGroup.name
                $ErrorRecord = New-ErrorRecord HPOneView.EnclosureGroupResourceException EnclosureGroupAlreadyConfigured InvalidParameter 'InputObject' -TargetType 'PSObject' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                #Locate LIG within EG at Frame 1, Bay 3 and Frame 2, Bay 6
                ForEach ($_LIGUri in ($_EnclosureGroup.interconnectBayMappings | ? { 3,6 -contains $_.interconnectBay }))
                {

                    Try
                    {

                        $Bay3LIG = Send-HPOVRequest -Uri ($_LigUri | ? interconnectBay -eq 3).logicalInterconnectGroupUri
                        $Bay6LIG = Send-HPOVRequest -Uri ($_LigUri | ? interconnectBay -eq 6).logicalInterconnectGroupUri
                        $AssociatedLig = $Bay3Lig.PSObject.Copy()

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                #LIGs do not match, generate terminating error that it is not supported.
                if ($Bay3Lig.uri -ne $Bay6Lig.uri)
                {

                    $ExceptionMessage = 'The Logical Interconnect Groups assigned to Bays 3 and 6 are not the same policy (Bay3: {0}; Bay6: {1}). Image Streamer is only supported with Redundant Interconnect Modules.' -f $Bay3Lig.name,$Bay6Lig.name
                    $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectGroupResourceException UnsupportedLigConfiguration InvalidOperation 'InputObject' -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                #UPDATE EG
                $ShouldProcessMessage = "Remove Logical Interconnect Group {0} from Enclosure Group on appliance '{1}'" -f $Bay3Lig.name, $InputObject.ApplianceConnection.Name

                if ($PSCmdlet.ShouldProcess($_EnclosureGroup.name, $ShouldProcessMessage)) 
                {

                    #Copy object to then update copy, retain original for use later
                    $UpdateEg = $_EnclosureGroup.PSObject.Copy()

                    #Strip out Bays 3 and 6 from Interconnect Bay Mappings
                    $UpdateEg.interconnectBayMappings | ? { 3,6 -notcontains $_.interconnectBay }

                    #Update EG object on appliance
                    Try
                    {

                        $Results = Send-HPOVRequest -Uri $UpdateEg.uri -Method PUT -Body $UpdateEg -ApplianceConnection $UpdateEg.ApplianceConnection | Wait-HPOVTaskComplete

                        [void]$_Collection.Add($UpdateEg)

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    if ($Results.taskState -ne 'Completed')
                    {

                        $ExceptionMessage = 'The Logical Interconnect Groups update did not complete successfully: {0}' -f [String]::Join(' ', $Results.taskErrors.message)
                        $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectGroupResourceException InvalidUpdateLigResult InvalidResult 'InputObject' -TargetType $_EnclosureGroup.GetType().Name -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                elseif ($PSBoundParameters['WhatIf'])
                {

                    "[{0}] User passed -WhatIf parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                }

            }

            #Update LIG with new Uplink Set
            $ShouldProcessMessage = "Add new Image Streamer Uplink Set {0}" -f $UplinkSetName

            if ($PSCmdlet.ShouldProcess($AssociatedLig.name, $ShouldProcessMessage)) 
            {

                $UplinkSetParams = @{

                    Name        = $UplinkSetName;
                    Type        = 'ImageStreamer';
                    InputObject = $Bay3Lig;
                    Networks    = $DeploymentNetwork;
                    UplinkPorts = $UplinkPorts

                }

                Try
                {

                    $i3SUplinkSetResults = New-HPOVUplinkSet @UplinkSetParams -ApplianceConnection $InputObject.ApplianceConnection | Wait-HPOVTaskComplete

                }

                Catch
                {

                    $PSCmdlet.ThrowterminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] User passed -WhatIf parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            #Update each EG with Deployment Network settings and Bay3 and Bay6 LIG mapping;
            ForEach ($_EnclosureGroupToUpdate in $InputObject)
            {

                #Get EG resource to get updated eTag and modifiedDate values
                Try
                {

                    $UpdatedEg = Get-HPOVEnclosureGroup -Name $_EnclosureGroupToUpdate.name -ApplianceConnection $_EnclosureGroupToUpdate.ApplianceConnection -ErrorAction Stop

                }

                Catch
                {

                    $PSCmdlet.ThrowterminatingError($_)

                }
                
                #Update original object with new eTag and modifiedDate values
                $_EnclosureGroupToUpdate.eTag         = $UpdatedEg.eTag.Copy()
                $_EnclosureGroupToUpdate.modifiedDate = $UpdatedEg.modifiedDate.Copy()
                
                Try
                {

                    Send-HPOVRequest -Uri $_EnclosureGroupToUpdate.uri -Method PUT -Body $_EnclosureGroupToUpdate -ApplianceConnection $_EnclosureGroupToUpdate.ApplianceConnection | Wait-HPOVTaskComplete

                }

                Catch
                {

                    $PSCmdlet.ThrowterminatingError($_)

                }

            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Show-HPOVUtilization
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeLine)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Resource')]
        [Object]$InputObject,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin
    {

        #Throw "Not implemented"

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #Key off of ApplianceConnection for Pipeline Input
        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            Try
            {

                $Resource.ApplianceConnection = Test-HPOVAuth $Resource.ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $errorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($errorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process
    {

        ForEach ($_resource in $InputObject)
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing object: {0}" -f $_resource.name | Write-Verbose 

            switch ($_resource.category)
            {

                'server-profiles'
                {

                    $_uri = $_resource.serverHardwareUri + '/utilization'

                }

                'server-hardware'
                {

                    $_uri = $_resource.uri + '/utilization'

                }

            }

            #Check to see if the resource is eligable for performance monitoring.

            Try
            {

                $_UtilizationData = Send-HPOVRequest -uri $_uri -Hostname $_resource.ApplianceConnection.Name

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            switch ($_resource.category)
            {

                'server-hardware'
                {

                    $_UtilizationObj = New-Object HPOneView.ServerUtilization($_resource.name, $_resource.uri, [HPOneView.Library.ApplianceConnection]$_resource.ApplianceConnection)

                }

                'enclosures'
                {

                    $_UtilizationObj = New-Object HPOneView.EnclosureUtilization($_resource.name, $_resource.uri, [HPOneView.Library.ApplianceConnection]$_resource.ApplianceConnection)

                }

                default
                {

                    #Resource is unsupported, generate error

                }

            }

            ForEach ($_item in $_UtilizationData.metricList)
            {
            
                switch ($_item.metricName)
                {
            
                    'AmbientTemperature'
                    {
            
                        $_total = 0
                        $_count = 0
                        $_item.metricSamples | % { $_[1] | % { $_total += $_; $_count++ } }
            
                        $_UtilizationObj.AmbientTemperatureAverage = [Math]::Round(($_total / $_count), 2)
                        $_UtilizationObj.AmbientTemperature = $_item.metricCapacity
                    
                    }
            
                    'AveragePower'
                    {
            
                        $_total = 0
                        $_count = 0
                        ($_item.metricSamples | % { $_[1] | % { $_total += $_; $_count++ } })
                    
                        $_UtilizationObj.PowerAverage = [Math]::Round(($_total / $_count), 2)
                        
                    }

                    'CpuAverageFreq'
                    {

                        $_total = 0
                        $_count = 0
                        ($_item.metricSamples | % { $_[1] | % { $_total += $_; $_count++ } })

                        $_UtilizationObj.CpuAverage = [Math]::Round(($_total / $_count), 2)

                    }

                    'CpuUtilization'
                    {


                    }
            
                    'PeakPower'
                    {
                    
                        $_PeakValue = 0
            
                        ForEach ($_Sample in $_item.metricSamples)
                        {
            
            
                            if ($_Sample[1] -gt $_PeakValue)
                            {
            
                                $_PeakValue = $_Sample[1]
            
                            }
            
                        }
            
                        $_UtilizationObj.PowerPeak = $_PeakValue
                    
                    }
            
                }
            
                
                
            }

            $_UtilizationObj

        }

    }

    End
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

#######################################################
# Storage Systems and Volume Management:
#

function Get-HPOVStorageSystem 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Name")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "Name")]
        [ValidateNotNullOrEmpty()]
        [Alias ('SystemName')]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Name")]
        [ValidateNotNullOrEmpty()]
        [string]$Hostname,

        [Parameter (Mandatory = $false, ParameterSetName = "Serial")]
        [ValidateNotNullOrEmpty()]
        [Alias ('SN')]
        [string]$SerialNumber,

        [Parameter (Mandatory = $false, ParameterSetName = "Name")]
        [Parameter (Mandatory = $false, ParameterSetName = "Serial")]
        [ValidateSet ('StoreVirtual', 'StoreServ')]
        [string]$Family,

        [Parameter (Mandatory = $false, ParameterSetName = "Name")]
        [Parameter (Mandatory = $false, ParameterSetName = "Serial")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "Name")]
        [Parameter (Mandatory = $false, ParameterSetName = "Serial")]
        [Alias ('Report')]
        [switch]$List

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        if ($PSBoundParameters['List'])
        {

            Write-Warning "The -List parameter has been deprecated."

        }

        $_StorageSystemCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            $uri = $StorageSystemsUri + '?sort:asc'

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            if ($Name)
            { 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filtering for Name property"

                $_method = 'eq'

                if ($Name.Contains('*'))
                {

                    $Name = $Name.Replace("*","%25").Replace("&","%26") 

                    $_method = 'matches'

                }
                
                
                $uri += "&filter=name {0} '{1}'" -f $_method, $Name
                        
            }

            elseif ($Hostname)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filtering for Hostname property"

                $_method = 'eq'

                if ($Hostname.Contains('*'))
                {

                    $Hostname = $Hostname.Replace("*","%25").Replace("&","%26") 

                    $_method = 'matches'

                }

                $uri += "&filter=hostname {0} '{1}'" -f $_method, $Hostname

            }

            if ($Family)
            {

                $uri += "&filter=family EQ '{0}'" -f $Family

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting list of Storage Systems"

            Try
            {

                $_StorageSystems = Send-HPOVRequest -Uri $uri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($SerialNumber)
            {

                [Array]$_StorageSystems.members = $_StorageSystems.members | ? { $_.deviceSpecificAttributes.serialNumber -eq $SerialNumber }

            }

            #Generate Terminating Error if resource not found
            if (-not($_StorageSystems.members.Count -gt 0) -and ($Name -or $SerialNumber -or $Hostname)) 
            {
                
                if ($Name) 
                { 
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Woops! No '$Name' Storage System found."
                    $ExceptionMessage = "No Storage System with '{0}' system name found. Please check the name or use Add-HPOVStorageSystem to add the Storage System." -f $Name
                        
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageSystemResourceException StorageSystemResourceNotFound ObjectNotFound 'Name' -Message $ExceptionMessage

                }

                elseif ($Hostname) 
                { 
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Woops! No '$Hostname' Storage System found."
                    $ExceptionMessage = "No Storage System with '{0}' system name found. Please check the name or use Add-HPOVStorageSystem to add the Storage System." -f $Hostname
                        
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageSystemResourceException StorageSystemResourceNotFound ObjectNotFound 'Hostname' -Message $ExceptionMessage

                }

                elseif ($SerialNumber) 
                { 
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Woops! No Storage System with '$SerialNumber' serial number found."
                    $ExceptionMessage = "No Storage System with '{0}' serial number found. Please check the name or use Add-HPOVStorageSystem to add the Storage System." -f $SerialNumber
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageSystemResourceException StorageSystemResourceNotFound ObjectNotFound 'SerialNumber' -Message $ExceptionMessage

                }
                    
                #Generate Terminating Error
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                $_StorageSystems.members | % {

                    $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.System')

                    if ($_.ports)
                    {

                        $_.ports | % { 
                            
                            #This is temporary
                            Add-Member -InputObject $_ -NotePropertyName ApplianceConnection -NotePropertyValue $_.ApplianceConnection

                            $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.System.Port') 

                        }

                    }

                    if ($_.deviceSpecificAttributes.discoverdPools) { $_.deviceSpecificAttributes.discoverdPools | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.System.Pool')} }
                    if ($_.deviceSpecificAttributes.managedPools) { $_.deviceSpecificAttributes.managedPools | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.System.Pool')} }

                    $_

                }    

            }    

        }
         
    }

    End 
    {

        Write-Verbose "Done."

    }

}

function Update-HPOVStorageSystem 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Name','StorageSystem')]
        [Object]$InputObject,
        
        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }    

        $_StorageSystemRefreshCollection = New-OBject System.Collections.ArrayList
    
    }

    Process 
    { 

        ForEach ($_system in $InputObject) 
        {

            switch ($_system.gettype().name) 
            {

                "String" 
                { 
                    

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] System Name was provided, calling Get-HPOVStorageSystem."

                    Try
                    {

                        $_system = Get-HPOVStorageSystem $_system

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                }

                "PSCustomObject" 
                {
                
                    if ($_system.category -eq "storage-systems") 
                    {
                    
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage System resource object provided"
                        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage System Name: {0}" -f $_system.name | Write-Verbose
                        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage System URI: {0}"  -f $_system.uri  | Write-Verbose

                    }

                    else 
                    {

                        #Wrong category, generate error
                        $ErrorRecord = New-ErrorRecord HPOneView.StorageSystemResourceException WrongCategoryType InvalidResult 'InputObject' -TargetType 'PSObject' -Message ("The '{0}' is the wrong value. Only 'storage-systems' category is allowed. Please check the value and try again." -f $_system.category)#-verbose
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                default 
                {                         
                    
                    #Wrong category, generate error
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageSystemResourceException UnsupportedDataType InvalidArgument 'InputObject' -TargetType $_system.GetType().Name -Message ("The {0} is unsupported. Only [System.String], [System.Array] of [System.String] or [System.Management.Automation.PSCustomObject] are allowed. Please check the value and try again." -f $_system.Gettype().Name )
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                        
                }

            }

            #Update object to refresh state
            $_system.refreshState = "RefreshPending"

            Try
            {

                $_results = Send-HPOVRequest $_system.uri PUT $_system -Hostname $_system.ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
            [void]$_StorageSystemRefreshCollection.Add($_results)

        }
   
    }

    End 
    {

        Return $_StorageSystemRefreshCollection

    }

}

function Add-HPOVStorageSystem 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'StoreServe')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'StoreServe')]
        [Parameter (Mandatory, ParameterSetName = 'StoreVirtual')]
        [ValidateNotNullOrEmpty()]
        [string]$Hostname,

        [Parameter (Mandatory = $False, ParameterSetName = 'StoreServe')]
        [Parameter (Mandatory = $False, ParameterSetName = 'StoreVirtual')]
        [ValidateNotNullOrEmpty()]
        [PSCredential]$Credential,
         
        [Parameter (Mandatory = $False, ParameterSetName = 'StoreServe')]
        [Parameter (Mandatory = $False, ParameterSetName = 'StoreVirtual')]
        [ValidateNotNullOrEmpty()]
        [string]$Username,

        [Parameter (Mandatory = $False, ParameterSetName = 'StoreServe')]
        [Parameter (Mandatory = $False, ParameterSetName = 'StoreVirtual')]
        [ValidateNotNullOrEmpty()]
        [Object]$Password,

        [Parameter (Mandatory = $false, ParameterSetName = 'StoreServe')]
        [Parameter (Mandatory = $false, ParameterSetName = 'StoreVirtual')]
        [ValidateSet ('StoreServ', 'StoreVirtual')]
        [String]$Family = 'StoreServ',

        [Parameter (Mandatory = $false, ParameterSetName = 'StoreServe')]
        [ValidateNotNullOrEmpty()]
        [String]$Domain = 'NO DOMAIN',

        [Parameter (Mandatory = $false, ParameterSetName = 'StoreServe')]
        [ValidateNotNullOrEmpty()]
        [Hashtable]$Ports,

        [Parameter (Mandatory, ParameterSetName = 'StoreVirtual')]
        [ValidateNotNullOrEmpty()]
        [Hashtable]$VIPS,

        [Parameter (Mandatory = $false, ParameterSetName = 'StoreServe')]
        [ValidateNotNullOrEmpty()]
        [Hashtable]$PortGroups,

        [Parameter (Mandatory = $false, ParameterSetName = 'StoreServe')]
        [Parameter (Mandatory = $false, ParameterSetName = 'StoreVirtual')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

        if ($Password -is [SecureString])
        {

            $Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

        if ($PSBoundParameters['Credential'])
        {

            $Username = $Credential.Username
            $Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential.Password))

        }

        if (-not($PSBoundParameters['Credential']) -and -not($PSBoundParameters['Username']))
        {

            $ExceptionMessage = "Credentials are required in order to add a storage system. Please use either the -Credential or -Username parameter to supply a valid account to authenticate with."
            $ErrorRecord = New-ErrorRecord InvalidOperationException MissingCredentialParameter InvalidArgument 'Auth' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if (-not($PSBoundParameters['Password']) -and $PSBoundParameters['Username'])
        {

            $ExceptionMessage = "Credentials are required in order to add a storage system. Please use the Password parameter to supply a String or SecureString value. Or use the Credential parameter to supply a PSCredential object."
            $ErrorRecord = New-ErrorRecord InvalidOperationException MissingPasswordParameter InvalidArgument 'Password' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ((-not $PSBoundParameters['VIPS']) -and $Family -eq 'StoreVirtual')
        {

            $ExceptionMessage = "Adding a StoreVirtual resource requires you to provide the VIP or VIPS and associated Ethernet Network."
            $ErrorRecord = New-ErrorRecord InvalidOperationException MissingVIPSParameter InvalidArgument 'VIPS' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
        }

    }
     
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing appliance: $($_appliance.Name)"

            $_storagesystemcredentials = NewObject -StorageSystemCredentials

            $_storagesystemcredentials.hostname = $hostname
            $_storagesystemcredentials.username = $username
            $_storagesystemcredentials.password = $password
            $_storagesystemcredentials.family   = $StorageSystemFamilyTypeEnum[$Family]


            Try
            {

                $_storageSystemDiscoveryTask = Send-HPOVRequest -Uri $StorageSystemsUri -Method POST -Body $_storagesystemcredentials -Hostname $_appliance.Name | Wait-HPOVTaskComplete

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }            

            if ($_storageSystemDiscoveryTask.taskState -eq "Completed") 
            {

                Try
                {
                    
                    $_connectedStorageSystem = Send-HPOVRequest -Uri $_storageSystemDiscoveryTask.associatedResource.resourceUri -Hostname $_appliance.Name
                
                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }        

                "[{0}] Connected Storage System Object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_connectedStorageSystem | ConvertTo-Json -Depth 99 -Compress) | Write-Verbose

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($_connectedStorageSystem.name)' Storage System."

                $_connectedStorageSystem.PSObject.TypeNames.Insert(0,'HPOneView.Storage.System')

                #Display Storage System details
                if (-not $PesterTest) { $_connectedStorageSystem | Out-Host }
                
                if ($_connectedStorageSystem.deviceSpecificAttributes.discoveredPools)
                {

                    $_connectedStorageSystem.deviceSpecificAttributes.discoveredPools | % { 
                        
                        $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.System.DiscoveredPool') 

                    }

                    #Display Storage System Unmanaged Pool details
                    if (-not $PesterTest) { $_connectedStorageSystem.deviceSpecificAttributes.discoveredPools | Sort domain,name | Out-Host }

                }

                if ($_connectedStorageSystem.ports)
                {

                    $_connectedStorageSystem.ports | % { 
                        
                        #This is temporary
                        Add-Member -InputObject $_ -NotePropertyName ApplianceConnection -NotePropertyValue $_connectedStorageSystem.ApplianceConnection

                        $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.System.Port') 

                    }

                    #Display Storage System Unmanaged Port details
                    if (-not $PesterTest) { $_connectedStorageSystem.ports | Out-Host }
                    
                }

                #Check if ISCSI paramset first, and handle ports
                if ($PSCmdlet.ParameterSetName -eq 'StoreVirtual' -or $Family -eq 'StoreVirtual')
                {

                    ForEach ($_VIP in $VIPS.GetEnumerator())
                    {

                        #Validate the Network associated with the VIP is an Ethernet resource
                        if ($_VIP.Value.category -ne 'ethernet-networks')
                        {

                            $ExceptionMessage = "The provided VIP {0} and associated Network {1} is not an allowed Ethernet network resource." -f $_VIP.Name, $_VIP.Value.name
                            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidVIPNetwork InvalidArgument 'VIPS' -TargetType $VIPS.GetType().Name -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        if ($_connectedStorageSystem.ports | ? name -eq $_VIP.Name)
                        {

                            $_StoragePort = ($_connectedStorageSystem.ports | ? name -eq $_VIP.Name).PSObject.Copy()
                            $_IndexOf     = $_connectedStorageSystem.ports.name.IndexOf($_StoragePort.name)

                        }
                        
                        else
                        {

                            $ExceptionMessage = "The provided VIP {0} name was not found to be present on the StoreVirtual system: {1}." -f $_VIP.Name, [String]::Join(', ', $_connectedStorageSystem.ports.name)
                            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidVIPName InvalidArgument 'VIPS' -TargetType $VIPS.GetType().Name -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        $_StoragePort.expectedNetworkUri  = $_VIP.Value.uri
                        $_StoragePort.expectedNetworkName = $_VIP.Value.name
                        $_StoragePort.mode                = 'Managed'

                        $_connectedStorageSystem.ports[$_IndexOf] = $_StoragePort

                    }

                }

                else
                {

                    #Handle Host Port configuration
                    if ($PSBoundParameters['Ports'])
                    {

                        ForEach ($_port in $Ports.GetEnumerator())
                        {

                            "[{0}] Processing '{1}' Port" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_port.name | Write-Verbose

                            if ($_connectedStorageSystem.ports | ? name -eq $_port.Name)
                            {

                                $_StoragePort = ($_connectedStorageSystem.ports | ? name -eq $_port.Name).PSObject.Copy()
                                $_IndexOf     = $_connectedStorageSystem.ports.name.IndexOf($_StoragePort.name)

                                "[{0}] Found port: '{1}' [{2}]" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_StoragePort.Name, $_IndexOf | Write-Verbose

                            }
                            
                            else
                            {

                                "[{0}] Cleaning up storage system" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                Try
                                {

                                    $reply = Send-HPOVRequest -uri $_connectedStorageSystem.uri -method DELETE -Hostname $_appliance.Name | Wait-HPOVTaskComplete

                                }
                                
                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }        

                                $ExceptionMessage = "The provided host port {0} name was not found to be present on the StoreServ system. Available host ports are: {1}." -f $_port.Name, [String]::Join(', ', $_connectedStorageSystem.ports.name)
                                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidVIPName InvalidArgument 'Ports' -TargetType $Ports.GetType().Name -Message $ExceptionMessage
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                            # First get the network. Will error if network does not exist
                            switch ($_port.value.GetType().Name)
                            {

                                'String'
                                {
                                
                                    if ($_port.value -ne 'Auto' -and $null -ne $_port.value)
                                    {

                                        Try
                                        {

                                            '[{0}] Looking in idex for {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_port.value | Write-Verbose

                                            $uri = '{0}?filter=name:"{1}"&category:fc-networks&category:fcoe-networks' -f $IndexUri, $_port.value 
                                            
                                            $_resp = Send-HPOVRequest -Uri $uri -ApplianceConnection $_appliance.Name

                                        }

                                        Catch
                                        {

                                            $PSCmdlet.ThrowTerminatingError($_)

                                        }

                                        #Error, as we couldn't find a unique FC/FCoE resource from the name via the Index
                                        if ($_resp.count -gt 1)
                                        {

                                            $Message     = "The provided Storage Port Network Resource name {0} was found via the index as the name of {1} resources. Please make sure you are specifying a unique FC or FCoE resource name." -f $_port.value, $_resp.count 
                                            $ErrorRecord = New-ErrorRecord InvalidOperationException NonUniqueStoragePortFabricName InvalidResult 'Ports' -TargetType $Ports.GetType().Name -Message $Message
                                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                        }

                                        elseif ($_resp.count -eq 0)
                                        {

                                            $Message     = "The provided Storage Port Network Resource name {0} was not found via the index. Please verify the FC or FCoE Network exists." -f $_port.Value
                                            $ErrorRecord = New-ErrorRecord InvalidOperationException StorageSystemPortNetworkNotFound ObjectNotFound 'Ports' -TargetType $Ports.GetType().Name -Message $Message
                                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                        }

                                        Try
                                        {

                                            '[{0}] Getting full network object {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_port.value | Write-Verbose

                                            $_sNet = Send-HPOVRequest -Uri $_resp.members.uri

                                        }
                                        
                                        Catch
                                        {

                                            $PSCmdlet.ThrowTerminatingError($_)

                                        }

                                    }
                                    
                                    else 
                                    {
                                    
                                        $_snet = [PScustomObject]@{

                                            expectedNetorkUri = 'Auto';
                                            name              = 'Auto';

                                        }

                                    }
                                
                                }

                                'PSCustomObject'
                                {

                                    if ('fc-networks', 'fcoe-networks' -contains $_port.value.category)
                                    {

                                        $_snet = [PScustomObject]@{

                                            expectedNetorkUri = $_port.value.uri;
                                            name              = $_port.value.name

                                        }

                                    }

                                    elseif ($_port.value.category -eq 'fc-sans')
                                    {

                                        $_snet = [PScustomObject]@{

                                            expectedNetorkUri = $_port.value.associatedNetworks.uri;
                                            name              = $_port.value.associatedNetworks.name

                                        }
                                        
                                    }

                                }

                                default
                                {

                                    $Message     = "The provided Storage Port Network value is not a supported object type, {0}. Please verify the FC or FCoE Network exists." -f $_port.value.GetType().FullName
                                    $ErrorRecord = New-ErrorRecord InvalidOperationException StorageSystemPortNetworkNotFound ObjectNotFound 'Ports' -TargetType $Ports.GetType().Name -Message $Message
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                            }                    

                            #update the ports Expected SAN/Network property
                            if ($_sNet.expectedNetorkUri -eq 'Auto' -and $null -eq $_StoragePort.actualSanUri)
                            {

                                $_StoragePort.mode = 'AutoSelectExpectedSan'

                            }

                            elseif ($_sNet.expectedNetorkUri -ne 'Auto' -and $null -eq $_StoragePort.actualSanUri)
                            {

                                $_StoragePort.expectedNetworkUri  = $_sNet.expectedNetorkUri
                                $_StoragePort.expectedNetworkName = $_sNet.name
                                $_StoragePort.mode                = 'Managed'

                            }

                            if ($PSBoundParameters['PortGroups'])
                            {

                                if ($PortGroups.Get_Item($_port.Name))
                                {

                                    "[{0}] Found '{1}' Port Group for '{2}' port." -f $MyInvocation.InvocationName.ToString().ToUpper(), $PortGroups.Get_Item($_port.Name), $_port.Name | Write-Verbose

                                    $_StoragePort.groupName = $PortGroups.Get_Item($_port.Name)

                                    #Remove the PortGroup item from the Hashtable so we can Process left overs later
                                    $PortGroups.Remove($_port.Name)

                                }

                            }

                            $_connectedStorageSystem.ports[$_IndexOf] = $_StoragePort
                            
                        }

                    }

                    #Process any of the leftover portgroup collection
                    if ($PortGroups)
                    {

                        "[{0}] {1} PortGroups remain to be configured." -f $MyInvocation.InvocationName.ToString().ToUpper(), $PortGroups.Count | Write-Verbose

                        ForEach ($_pg in $PortGroups.GetEnumerator())
                        {

                            "[{0}] Processing {1} Port for PortGroup assignment." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_pg.Name, $_pg.Value | Write-Verbose

                            if ($_connectedStorageSystem.ports | ? name -eq $_pg.Name)
                            {

                                $_port = $_connectedStorageSystem.ports | ? name -eq $_pg.Name

                                "[{0}] Found {1} -> {2}." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_pg.Name, $_pg.Value | Write-Verbose

                                $_connectedStorageSystem.ports[($_connectedStorageSystem.ports.IndexOf($_port))].groupName = $_pg.Value

                            }

                            else
                            {

                                "[{0}] {1} was not found in the unmanagedPorts collection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_pg.Name | Write-Verbose

                            }

                        }

                    }            

                    #"[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding {0} managed ports. {1} remaining unmanaged ports to be claimed later." -f $_managedPorts.count,$_connectedStorageSystem.unmanagedPorts.count | Write-Verbose

                    #Validate the $Domain Parameter exists in the list of unmanaged domains returned in the connect call
                    if ($_connectedStorageSystem.deviceSpecificAttributes.discoveredDomains -ccontains $Domain)                
                    {

                        "[{0}] Found Virtual Domain '{1}'." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Domain| Write-Verbose

                        #The domain exists, update the managedDomain property
                        $_connectedStorageSystem.deviceSpecificAttributes.managedDomain = $_connectedstoragesystem.deviceSpecificAttributes.discoveredDomains | ? { $_ -eq $Domain }

                        [Array]$_connectedStorageSystem.deviceSpecificAttributes.discoveredDomains = @($_connectedStorageSystem.deviceSpecificAttributes.discoveredDomains | ? { $_ -ne $Domain })

                    }

                    else 
                    {

                        "[{0}] Domain '{1}' not found (name is Case Sensitive). Cleaning up." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Domain | Write-Verbose

                        Try
                        {

                            $reply = Send-HPOVRequest -uri $_connectedStorageSystem.uri -method DELETE -Hostname $_appliance.Name

                        }
                        
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }        

                        $ErrorRecord = New-ErrorRecord InvalidOperationException StorageDomainResourceNotFound ObjectNotFound 'Domain' -Message "Storage Domain '$Domain' not found (name is Case Sensitive). Please check the storage domain exist on the storage system."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

            }

            else 
            {

                #ERROR
                $_connectedStorageSystem | Out-Host

                if ($_storageSystemDiscoveryTask.taskErrors.errorCode -eq 'STRM_RESOURCE_ALREADY_PRESENT' -or -not $_storageSystemDiscoveryTask.associatedResource.resourceUri)
                {

                    "[{0}] {1} {2} {3}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_storageSystemDiscoveryTask.taskErrors.details, $_storageSystemDiscoveryTask.taskErrors.recommEndedActions, $_storageSystemDiscoveryTask.taskErrors.errorCode| Write-Verbose

                    $ErrorRecord = New-ErrorRecord InvalidOperationException $_storageSystemDiscoveryTask.taskErrors[0].errorCode InvalidResult 'StoragSystem' -Message ($_storageSystemDiscoveryTask.taskErrors[0].message + ' ' + $_storageSystemDiscoveryTask.taskErrors[0].recommEndedActions)
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                else
                {

                    "[{0}] Task error occurred. Cleaning Up." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    Try
                    {

                        $reply = Send-HPOVRequest -uri $_connectedStorageSystem.uri -method DELETE -Hostname $_appliance.Name | Wait-HPOVTaskComplete

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }        

                    "[{0}] Generating error message." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                
                    $ErrorRecord = New-ErrorRecord InvalidOperationException $_storageSystemDiscoveryTask.taskErrors[0].errorCode InvalidResult 'Add-HPOVStorageSystem' -Message "$($_storageSystemDiscoveryTask.taskErrors[0].message)"
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            "[{0}] Sending request to finalize adding Storage System to appliance" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Try
            {

                $task = Send-HPOVRequest -method PUT -body $_connectedStorageSystem -uri $_connectedStorageSystem.uri -Hostname $_appliance.Name

            }

            Catch
            {
                
                $task = $null
                
                $PSCmdlet.ThrowTerminatingError($_)

            }            

            if ($PSBoundParameters['Async'])
            {

                $task

            }

            else
            {

                $task | Wait-HPOVTaskComplete

            }

        }
        
    }

    End 
    {

        '{0} Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }
   
}

function Remove-HPOVStorageSystem 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default",SupportsShouldProcess,ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri","name","StorageSystem")]
        [object]$InputObject,

        [Parameter (Mandatory = $false)]
        [switch]$force,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList
        $_StorageSystemCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomObject]) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing input"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage System Object provided: $($InputObject | FL * | Out-String)"

            If ('storage-systems' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject:$($InputObject.Name)" -TargetType PSObject -Message "The Storage System resource object provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_StorageSystemCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject:$($InputObject.Name)" -TargetType PSObject -Message "The Storage System resource object is not an expected category type [$($InputObject.category)]. The allowed resource category type is 'storage-systems'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count))"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Storage System Name $($StorageSystem)"

                Try
                {

                    $_StorageSystem = Get-HPOVStorageSystem $InputObject -ApplianceConnection $_appliance

                    $_StorageSystem | % {

                        [void]$_StorageSystemCollection.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_StorageSystemCollection.count) Storage System object resources to remove."

        #Process Storage Resources
        ForEach ($_storagesystem in $_StorageSystemCollection)
        {

            if ($PSCmdlet.ShouldProcess($_storagesystem.ApplianceConnection.Name,"Remove Storage System '$($_storagesystem.name)' from appliance")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Storage System '$($_storagesystem.name)' from appliance '$($_storagesystem.ApplianceConnection.Name)'."

                if ($PSboundParameters['force'])
                {

                    $_storagesystem.uri += "?force=true"

                }

                Try
                {

                    $_resp = Send-HPOVRequest -Uri $_storagesystem.Uri -Method DELETE -Hostname $_storagesystem.ApplianceConnection.Name -AddHeader @{'If-Match' = '*'}

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Get-HPOVStoragePool 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('pool', 'PoolName')]
        [string]$Name,

        [Parameter (Mandatory = $false, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ('systemName', 'system')]
        [object]$StorageSystem,    

        [Parameter (Mandatory = $false)]
        [switch]$Managed,

        [Parameter (Mandatory = $false)]
        [switch]$Unmanaged,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $colStoragePools = New-Object System.Collections.ArrayList

    }

    Process 
    {

        #Check if StorageSystem is a PSCustomObject
        if ($StorageSystem -is [PSCustomObject] -and $StorageSystem.category -eq 'storage-systems')
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] StorageSystem Object provided. Using ApplianceConnection property of object."

            $ApplianceConnection = $StorageSystem.ApplianceConnection

        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance Connection: $($_appliance.Name)"

            if ($PSBoundParameters['Label'])
            {

                $_uri = '{0}?category=storage-pools&query=labels:{1}' -f $IndexUri, $Label

                Try
                {

                    $_storagePools = Send-HPOVRequest -Uri $_uri -ApplianceConnection $_appliance.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                ForEach ($_member in $_storagePools.members)
                {

                    Try
                    {

                        #Get the full object
                        $_member = Send-HPOVRequest -Uri $_member.uri -ApplianceConnection $_appliance.Name
                        
                        $_member.PSObject.TypeNames.Insert(0,'HPOneView.Storage.System.Pool')

                        $_member

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                "[{0}] Getting list of Storage Pools" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $uri = "{0}?sort:dsc" -f $StoragePoolsUri

                if ($PSBoundParameters['Name'])
                {
                
                    "[{0}] Pool name was provided: '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose

                    $Name = $Name -replace ("[*]","%25") -replace ("[&]","%26")

                    $uri += "&filter=name matches '$Name'"

                }

                if ($PSBoundParameters['Managed'])
                {
                
                    "[{0}] Filtering for unmanaged pools." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $uri += "&filter=isManaged EQ true"

                }

                if ($PSBoundParameters['Unmanaged'])
                {
                
                    "[{0}] Filtering for unmanaged pools." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $uri += "&filter=isManaged EQ false"

                }

                #Send the query
                Try
                {

                    $_storagePools = Send-HPOVRequest -Uri $uri -ApplianceConnection $_appliance.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                    
                if ($PSBoundParameters['StorageSystem'])
                {

                    if ($StorageSystem -is [String] -and (-not($storageSystem.startswith($StorageSystemsUri))))
                    { 
            
                        "[{0}] Storage system name was provided: '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StorageSystem | Write-Verbose

                        Try
                        {

                            $StorageSystem = Get-HPOVStorageSystem -SystemName $StorageSystem -ApplianceConnection $_appliance.Name -ErrorAction Stop

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
                
                        if (-not($StorageSystem.uri))
                        {
                    
                            "[{0}] Storage system {1} does not exist on the appliance" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StorageSystem | Write-Verbose
                
                            $ErrorRecord = New-ErrorRecord InvalidOperationException StorageSystemResourceNotFound ObjectNotFound 'StorageSystem' -Message "Storage system '$StorageSystem' not found. Please check the name and try again."

                            #Generate Terminating Error
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)    

                        }
                
                    }

                    elseif ($StorageSystem -is [PsCustomObject] -and $StorageSystem.category -eq "storage-systems") 
                    { 
            
                        "[{0}] StorageSystem Object provided" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                        "[{0}] StorageSystem Name: '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StorageSystem.name | Write-Verbose
                        "[{0}] StorageSystem Uri: '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StorageSystem.uri | Write-Verbose

                    }

                    $_storagePools.members = $_storagePools.members | ? storageSystemUri -eq $StorageSystem.uri

                }
                    
                if ($_storagePools.members)
                {
                
                    ForEach ($_member in $_storagePools.members)
                    {

                        "[{0}] Adding Storage System '{1}' to collection" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_member.name | Write-Verbose 

                        $_member.PSObject.TypeNames.Insert(0,'HPOneView.Storage.System.Pool')

                        $_member

                    }
                
                }

                elseif ((-not $_storagePools.members) -and $Name)
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage Pool '$Name' not found."
                    
                    $ExceptionMessage = "Storage Pool '{0}' not found on '{1}' appliance connection. Please check the name and try again." -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord InvalidOperationException StoragePoolResourceNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)    

                }

                else
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Storage Pools found."

                }
            
            }

        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | write-verbose 

    }

}

function Add-HPOVStoragePool 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Hostname', 'name')]
        [object]$StorageSystem,

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [Alias ('PoolName', 'spName', 'cpg')]
        [array]$Pool,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSboundParameters['StorageSystem']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

    }
     
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing appliance: $($_appliance.Name)"
        
            ForEach ($_pool in $Pool)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$_pool'"

                #Validate StroageSystem Parameter object
                if ($StorageSystem -is [PSCustomObject] -and $StorageSystem.ApplianceConnection.Name -ne $_appliance.Name)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.StoragePoolResourceException InvalidateStorageSystemApplianceConnection InvalidArgument 'StorageSystem' -TargetType 'PSObject' -Message "The -StorageSystem object does not appear to originate [$($StorageSystem.ApplianceConnection.Name)] from the same provided ApplianceConnection [$($_appliance.Name)]"
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                elseif ($StorageSystem -is [PsCustomObject] -and $StorageSystem.category -eq "storage-systems") 
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage System resource object was provided: $($StorageSystem | out-string)"
                    
                    $_StorageSystem = $StorageSystem.PSObject.Copy()
                    
                }
                
                #else the PsCustomObject is not the correct Category type, so error.
                elseif ($StorageSystem -is [PsCustomObject]) 
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneView.StoragePoolResourceException InvalidResourceCategoryValue InvalidArgument 'StorageSystem' -TargetType 'PSObject' -Message "The -StorageSystem Parameter value is the wrong resource type ($($StorageSystem.category)). The correct resource category 'storage-systems' is allowed. Please check the value and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                #Do not allow an array
                elseif ($StorageSystem -is [Array]) 
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.StoragePoolResourceException ArrayNotAllow InvalidArgument 'StorageSystem' -TargetType 'PSObject' -Message "The -StorageSystem Parameter only accepts [System.String] or [System.Management.Automation.PSCustomObject] value. Please correct the value and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                else 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage System Name is passed $($StoragSystem)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting list of Storage Systems"

                    Try
                    {

                        $_storagesystem = Get-HPOVStorageSystem -SystemName $StorageSystem -ApplianceConnection $_appliance.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    #Generate Terminating Error if Storage System resource not found
                    if (-not($_storagesystem)) 
                    {
                            
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Woops! No '$StorageSystem' Storage System found."

                        $ErrorRecord = New-ErrorRecord HPOneView.StoragePoolResourceException StorageSystemResourceNotFound ObjectNotFound 'StorageSystem' -Message "No Storage System with '$StorageSystem' system name found. Please check the name or use Add-HPOVStorageSystem to add the Storage System."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }
                    
                }

                #Get the list of unmanaged and managed pools in the managed domain
                Try
                {
                    
                    $_Results = Send-HPOVRequest ("{0}?filter=name EQ '{1}'" -f $_storagesystem.storagePoolsUri, $_pool) -Hostname $_appliance.Name
                    [PSCustomObject]$_PoolFound = $_Results.members[0]

                    "[{0}] Storage Pool object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_PoolFound | Out-String) | Write-Verbose

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if (-not $_PoolFound)
                {

                    #Storage pool resource does not exist in the existing managed list or in the unmanaged list in the managed domain
                    "[{0}] No Storage pool resource with '{1}' found in the managed Storage System." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_pool | Write-Verbose

                    $ErrorRecord = New-ErrorRecord HPOneView.StoragePoolResourceException StorageSystemResourceNotFound ObjectNotFound 'PoolName' -Message "No Storage pool resource with '$_pool' found in the managed Storage System."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                elseif ($_PoolFound.isManaged)
                {

                    "[{0}] Storage pool resource '{1}' already exists in the managed list." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_pool | Write-Verbose

                    $ErrorRecord = New-ErrorRecord HPOneView.StoragePoolResourceException StoragePoolResourceExists ResourceExists 'PoolName' -Message "Storage pool resource '$_pool' already exists in the managed list."
                    $PSCmdlet.WriteError($ErrorRecord) #"Storage pool resource '$p' already exists"

                }

                else
                {

                    #Good here... Add the storage pool
                    $_PoolFound.isManaged = $true
                    
                    #add the pool to array of pools to manage
                    Try
                    {

                        Send-HPOVRequest -Uri $_PoolFound.uri -method PUT -body $_PoolFound -Hostname $_PoolFound.ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                }

            }

        }

    }

    End  
    {

        write-verbose "End Block"

        Return $colStatus

    }

}

function Remove-HPOVStoragePool 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default",SupportsShouldProcess,ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "StorageSystem")]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri", "name", 'StoragePool')]
        [Object]$InputObject,

        [Parameter (Mandatory, ParameterSetName = "StorageSystem")]
        [ValidateNotNullOrEmpty()]
        [Alias ("storage")]
        [Object]$StorageSystem,
        
        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [Parameter (Mandatory = $False, ParameterSetName = "StorageSystem")]
        [switch]$Force,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "StorageSystem")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection        = New-Object System.Collections.ArrayList
        $_StoragePoolCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomObject]) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing input"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage Pool Object provided: $($InputObject | FL * | Out-String)"

            If ('storage-pools' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject:$($InputObject.Name)" -TargetType PSObject -Message "The Storage Pool resource object provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_StoragePoolCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject:$($InputObject.Name)" -TargetType PSObject -Message "The Storage Pool resource object is not an expected category type [$($StoragePool.category)]. The allowed resource category type is 'storage-pools'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count))"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Storage Pool Name $($InputObject)"

                Try
                {

                    $_StoragePool = Get-HPOVStoragePool $InputObject -ApplianceConnection $_appliance -ErrorAction Stop

                    $_StoragePool | % {

                        [void]$_StoragePoolCollection.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

    }

    End 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_StoragePoolCollection.count) Storage Pool object resources to remove."

        #Process Storage Resources
        ForEach ($_storagepool in $_StoragePoolCollection)
        {

            if ($PSCmdlet.ShouldProcess($_storagepool.ApplianceConnection.Name,"Remove Storage Pool '$($_storagepool.name)' from appliance")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting Storage Pool '$($_storagepool.name)' to 'Unmanaged' on appliance '$($_storagepool.ApplianceConnection.Name)'."

                Try
                {

                    $_storagepool.isManaged = $false

                    $_resp = Send-HPOVRequest -Uri $_storagepool.Uri -Method PUT -Body $_storagepool -Hostname $_storagepool.ApplianceConnection

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Get-HPOVStorageVolumeTemplate 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('TemplateName')]
        [string]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $False)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_StorageVolumeTemplateCollection = New-Object System.Collections.ArrayList

    }

    Process 
    { 

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_appliance.Name) Appliance Connection [of $($ApplianceConnection.Count)]"

            if ($PSBoundParameters['Label'])
            {

                $_uri = '{0}?category:storage-volume-templates&query=labels:{1}' -f $IndexUri, $Label

                Try
                {

                    $_StorageVolumeTemplates = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                    #Loop through all found members and get full SVT object
                    ForEach ($_memeber in $_StorageVolumeTemplates.members)
                    {

                        Try
                        {

                            $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                        

                        $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.Storage.VolumeTemplate')

                        $_memeber

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                $uri = '{0}?filter=isRoot EQ false' -f $StorageVolumeTemplateUri

                if ($PSboundParameters['Name']) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Name provided: '$Name'"

                    $_method = 'eq'

                    if ($Name.Contains('*'))
                    {

                        $Name = $Name.Replace('*','%25').Replace('?','%26')

                        $_method = 'matches'

                    }

                    $uri += "&filter=name {0} '{1}'" -f $_method.ToLower(), $Name

                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting list of Storage Volume Templates"

                Try
                {

                    $_StorageVolumeTemplates = Send-HPOVRequest -Uri $uri -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                #Generate Terminating Error if resource not found
                if (-not($_StorageVolumeTemplates.members) -and $Name)
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] '$_StorageVolumeTemplates' Storage Volume Template not found."
                    
                    $ExceptionMessage = "No Storage Volume with '{0}' name found on '{1}' appliance connection. Please check the name or use New-HPOVStorageVolumeTemplate to create the volume template." -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord InvalidOperationException StorageVolumeResourceNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                elseif (-not($_StorageVolumeTemplates)) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Storage Volume Templates found."

                }

                else
                {

                    $_StorageVolumeTemplates.members | % {

                        $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.VolumeTemplate')

                        $_

                    }

                }

            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
    
    }

}

function New-HPOVStorageVolumeTemplate 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "StoreVirtual")]
        [ValidateNotNullOrEmpty()]
        [Alias ('TemplateName')]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [ValidateNotNullOrEmpty()]
        [string]$Description,

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "StoreVirtual")]
        [ValidateNotNullOrEmpty()]
        [object]$StoragePool,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockStoragePool,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [object]$SnapshotStoragePool,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [switch]$LockSnapShotStoragePool,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [ValidateNotNullOrEmpty()]
        [object]$StorageSystem,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "StoreVirtual")]
        [ValidateScript({$_ -ge 1})]
        [Alias ("size")]
        [int64]$Capacity,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockCapacity,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$Full,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [ValidateSet ('Thin','Full','TPDD')]
        [String]$ProvisionType,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockProvisionType,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$Shared,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockProvisionMode,

        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [ValidateSet ('NetworkRaid0None','NetworkRaid5SingleParity','NetworkRaid10Mirror2Way','NetworkRaid10Mirror3Way','NetworkRaid10Mirror4Way','NetworkRaid6DualParity')]
        [String]$DataProtectionLevel,

        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockProtectionLevel,

        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$EnableAdaptiveOptimization,

        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockAdaptiveOptimization,

        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = "StoreVirtual")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSboundParameters['StoragePool']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

        if ($PSBoundParameters['Full'])
        {

            Write-Warning 'The -Full parameter isbeing deprecated. Please update your scripts to use the -ProvisionType parameter instead.'

        }

    }

    Process 
    {

        if ($StoragePool -isnot [PSCustomObject])
        {

            Try
            {

                "[{0}] Getting and validating StoragePool parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_StoragePool = GetStoragePool -InputObject $StoragePool -StorageSystem $StorageSystem -ApplianceConnection $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        else
        {

            "[{0}] StoragePool object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StoragePool.name | Write-Verbose
            "[{0}] StoragePool object category: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StoragePool.category | Write-Verbose
            "[{0}] StoragePool object URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StoragePool.uri | Write-Verbose
            $_StoragePool = $StoragePool.PSObject.Copy()

        }

        #Get Root Volume Template from Storage System
        Try
        {

            "[{0}] Getting storage system root volume template." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
            $_Uri = '{0}/templates?filter=isRoot EQ true' -f $_StoragePool.storageSystemUri
            $_RootTemplate = (Send-HPOVRequest -Uri $_Uri -Hostname $ApplianceConnection).members[0]

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        "[{0}] Root template: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_RootTemplate.name | Write-Verbose
        "[{0}] Root template family: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_RootTemplate.family | Write-Verbose

        switch ($_RootTemplate.family)
        {

            'StoreServ'
            {

                if ($PSBoundParameters['DataProtectionLevel'] -or $PSBoundParameters['LockProtectionLevel'])
                {

                    $ExceptionMessage = "The Storage System family of the Storage Pool, {0}, is not a StoreVirtual system. DataProtectionLevel is only supported with StoreVirtual class of storage systems." -f $_StoragePool.name
                    $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'DataProtectionLevel' -TargetType $DataProtectionLevel.gettype().Name -Message $ExceptionMessage
                
                    #Generate Terminating Error
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                }

                if ($PSBoundParameters['EnableAdaptiveOptimization'] -or $PSBoundParameters['LockAdaptiveOptimization'])
                {

                    $ExceptionMessage = "The Storage System family of the Storage Pool, {0}, is not a StoreVirtual system. EnableAdaptiveOptimization is only supported with StoreVirtual class of storage systems." -f $_StoragePool.name
                    $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'EnableAdaptiveOptimization' -TargetType $EnableAdaptiveOptimization.gettype().Name -Message $ExceptionMessage
                
                    #Generate Terminating Error
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                }

                $_svt = NewObject -StoreServVolumeTemplate

                if ($PSboundParameters['SnapShotStoragePool'])
                {

                    Try
                    {

                        $_SnapShotStoragePool = GetStoragePool -InputObject $SnapShotStoragePool -StorageSystem $StorageSystem -ApplianceConnection $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)
                        
                    }

                    "[{0}] Setting snapshot storage pool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_SnapShotStoragePool.uri | Write-Verbose

                    $_svt.properties.snapshotPool.default = $_SnapShotStoragePool.uri

                }

                else 
                {            

                    if ($_svt.family -eq 'StoreServ')
                    {

                        "[{0}] No SnapShotStoragePool resource provided. Setting Snapshot Pool to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_StoragePool.name | Write-Verbose

                        $_svt.properties.snapshotPool.default = $_StoragePool.uri

                    }

                }

                if ($PSBoundParameters['LockStoragePool'])
                {

                    "[{0}] Locking Snapshot Storage Pool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockSnapshotStoragePool.IsPresent | Write-Verbose

                    $_svt.properties.snapshotPool.meta.locked = $LockSnapshotStoragePool.IsPresent

                }

            }

            'StoreVirtual'
            {

                if ($PSBoundParameters['SnapShotStoragePool'])
                {

                    $ExceptionMessage = "The Storage System family of the Storage Pool, {0}, is not a StoreServ system. Snapshots are only supported with StoreServ class of storage systems." -f $_StoragePool.name
                    $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'StoragePool' -TargetType $StoragePool.gettype().Name -Message $ExceptionMessage
                
                    #Generate Terminating Error
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                }

                $_svt = NewObject -StoreVirtualVolumeTemplate

                #Set AdaptiveOptimization and RedundancyMode
                if ($PSBoundParameters['DataProtectionLevel'])
                {

                    $_DataProtectionLevel = $_RootTemplate.properties.dataProtectionLevel.enum | ? { $_ -eq $DataProtectionLevel }

                    if (-not $_DataProtectionLevel)
                    {

                        $ExceptionMessage = "The requested data protection level, {0}, is not supported with the storage system. Please correct the value with one of the following options: {1}" -f $DataProtectionLevel, ([String]::Join(', ', $_RootTemplate.properties.dataProtectionLevel.enum))
                        $ErrorRecord = New-ErrorRecord ArgumentException UnsupportedProtectionLevelValue InvalidArgument 'DataProtectionLevel' -TargetType $DataProtectionLevel.gettype().Name -Message $ExceptionMessage
                    
                        #Generate Terminating Error
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                    }

                    "[{0}] Setting StoreVirtual data protection level: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_DataProtectionLevel | Write-Verbose

                    $_svt.properties.dataProtectionLevel.default = $_DataProtectionLevel

                }

                if ($PSBoundParameters['LockProtectionLevel'])
                {

                    "[{0}] Locking Protection Level: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockProtectionLevel.IsPresent | Write-Verbose

                    $_svt.properties.dataProtectionLevel.meta.locked = $LockProtectionLevel.IsPresent

                }

                if ($PSBoundParameters['EnableAdaptiveOptimization'])
                {

                    "[{0}] Setting Adaptive optimization default value: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $EnableAdaptiveOptimization.IsPresent | Write-Verbose

                    $_svt.properties.isAdaptiveOptimizationEnabled.default = $EnableAdaptiveOptimization.IsPresent

                }

                if ($PSBoundParameters['LockAdaptiveOptimization'])
                {

                    "[{0}] Locking Adaptive optimization: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockAdaptiveOptimization.IsPresent | Write-Verbose

                    $_svt.properties.isAdaptiveOptimizationEnabled.meta.locked = $LockAdaptiveOptimization.IsPresent

                }

            }

        }

        #Set common values here
        $_svt.name            = $Name
        $_svt.description     = $description
        $_svt.rootTemplateUri = $_RootTemplate.uri

        switch ($PSBoundParameters.Keys)
        {

            'Capacity'
            {

                "[{0}] Setting capacity default value: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [int64]($capacity * 1GB) | Write-Verbose

                $_svt.properties.size.default = [int64]($capacity * 1GB)

            }

            'LockCapacity'
            {

                "[{0}] Locking capacity: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockCapacity.IsPresent | Write-Verbose

                $_svt.properties.size.meta.locked = $LockCapacity.IsPresent

            }

            'StoragePool'
            {

                "[{0}] Setting Storage Pool default value: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_StoragePool.uri | Write-Verbose

                $_svt.properties.storagepool.default = $_StoragePool.uri

            }

            'LockStoragePool'
            {

                "[{0}] Locking Storage Pool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockStoragePool.IsPresent | Write-Verbose

                $_svt.properties.storagepool.meta.locked = $LockStoragePool.IsPresent

            }

            'Full'
            {

                "[{0}] Setting Provisioning Type to Full: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Full.IsPresent | Write-Verbose

                $_svt.properties.provisioningType.default = if ($Full.IsPresent) { 'Full' } else { 'Thin' }
                
            }

            'ProvisionType'
            {

                "[{0}] Setting Provisioning Type to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StorageVolumeProvisioningTypeEnum[$ProvisionType] | Write-Verbose

                $_svt.properties.provisioningType.default = $StorageVolumeProvisioningTypeEnum[$ProvisionType]


            }

            'LockProvisionType'
            {

                "[{0}] Locking provisioning type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockProvisionType.IsPresent | Write-Verbose

                $_svt.properties.provisioningType.meta.locked = $LockProvisionType.IsPresent

            }

            'Shared'
            {

                "[{0}] Setting Provisioning Type to Full: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Shared.IsPresent | Write-Verbose

                $_svt.properties.isShareable.default = $Shared.IsPresent
                
            }

            'LockProvisionMode'
            {

                "[{0}] Locking provisioning type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockProvisionType.IsPresent | Write-Verbose

                $_svt.properties.isShareable.meta.locked = $LockProvisionType.IsPresent

            }

        }

        #Send the request
        Try
        {

            $_resp = Send-HPOVRequest -method POST -uri $StorageVolumeTemplateUri -body $_svt -Hostname $ApplianceConnection.Name
            $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Storage.VolumeTemplate')

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        $_resp

    }

    End
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Set-HPOVStorageVolumeTemplate 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "StoreVirtual")]
        [Alias('SVT','Template')]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [ValidateNotNullOrEmpty()]
        [Alias ('TemplateName')]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [ValidateNotNullOrEmpty()]
        [string]$Description,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [object]$SnapshotStoragePool,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [switch]$LockSnapShotStoragePool,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [ValidateNotNullOrEmpty()]
        [object]$StorageSystem,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "StoreVirtual")]
        [ValidateScript({$_ -ge 1})]
        [Alias ("size")]
        [int64]$Capacity,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockCapacity,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$Thin,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$Full,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockProvisionType,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [bool]$Shared,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockProvisionMode,

        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [ValidateSet ('NetworkRaid0None','NetworkRaid5SingleParity','NetworkRaid10Mirror2Way','NetworkRaid10Mirror3Way','NetworkRaid10Mirror4Way','NetworkRaid6DualParity')]
        [String]$DataProtectionLevel,

        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockProtectionLevel,

        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$EnableAdaptiveOptimization,

        [Parameter (Mandatory = $false, ParameterSetName = "StoreVirtual")]
        [switch]$LockAdaptiveOptimization,

        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = "StoreVirtual")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process 
    {

        #Get Source Volume resource
        Switch ($InputObject.GetType().Name) 
        {

            "String" 
            { 
                 
                #Parameter is correct URI
                if ($InputObject.StartsWith($StorageVolumeTemplatesUri))
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage Volume Template URI provided by caller: $InputObject"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting volume resource object" 

                    Try
                    {

                        $_InputObject = Send-HPOVRequest -Uri $InputObject -hostname $ApplianceConnection

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                            
                }

                #Parameter is incorrect URI value
                elseif ($InputObject.StartsWith("/rest")) 
                {

                    #Invalid Parameter value, generate terminating error.
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeTemplateResourceException InvalidArgumentValue InvalidArgument 'InputObject' -Message "Invalid InputObject parameter value: $($InputObject | out-string). Please correct and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                #Parameter is Storage Pool name
                else 
                {
                                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage Volume Name provided by caller."

                    Try
                    {

                        $_InputObject = Get-HPOVStorageVolumeTemplate -Name $InputObject -ApplianceConnection $ApplianceConnection -ErrorAction Stop

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }
                
            }

            "PSCustomObject" 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage Volume Template Object provided by caller."

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($InputObject | FL * | Out-String)"

                #Validate the object
                if ('storage-volume-templates' -ne $InputObject.category)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeTemplateResourceException InvalidStorageVolumeTemplateCategory InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "Invalid InputObject parameter value. Expected Resource Category 'storage-volume-templates', received '$($InputObject.category)'."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $_InputObject = $InputObject.PSObject.Copy()
                
            }

        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] ORIGINAL Storage Volume object properties: $($InputObject | out-string)"

        switch ($_InputObject.family)
        {

            'StoreServ'
            {

                if ($PSBoundParameters['DataProtectionLevel'] -or $PSBoundParameters['LockProtectionLevel'])
                {

                    $ExceptionMessage = "The Storage System family of the volume template, {0}, is not a StoreVirtual system. DataProtectionLevel is only supported with StoreVirtual class of storage systems." -f $_InputObject.name
                    $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'DataProtectionLevel' -TargetType $DataProtectionLevel.gettype().Name -Message $ExceptionMessage
                
                    #Generate Terminating Error
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                }

                if ($PSBoundParameters['EnableAdaptiveOptimization'] -or $PSBoundParameters['LockAdaptiveOptimization'])
                {

                    $ExceptionMessage = "The Storage System family of the volume template, {0}, is not a StoreVirtual system. EnableAdaptiveOptimization is only supported with StoreVirtual class of storage systems." -f $_InputObject.name
                    $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'EnableAdaptiveOptimization' -TargetType $EnableAdaptiveOptimization.gettype().Name -Message $ExceptionMessage
                
                    #Generate Terminating Error
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                }

                if ($PSboundParameters['SnapShotStoragePool'])
                {

                    Try
                    {

                        $_SnapShotStoragePool = GetStoragePool -InputObject $SnapShotStoragePool -StorageSystem $StorageSystem -ApplianceConnection $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)
                        
                    }

                    Try
                    {

                        $_StoragePool = Send-HPOVRequest -Uri $_InputObject.storagePoolUri -Hostname $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    if ($_StoragePool.storageSystemUri -ne $_SnapShotStoragePool.storageSystemUri)
                    {

                        $ExceptionMessage = "The Storage Pool and SnapShot Storage Pool are not from the same Storage System. please correct the SnapshotStoragePool parameter value."
                        $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidSnapshotStoragePoolLocation InvalidOperation 'SnapShotStoragePool' -TargetType 'PSObject' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    "[{0}] Setting snapshot storage pool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_SnapShotStoragePool.uri | Write-Verbose

                    $_InputObject.properties.snapshotPool.default = $_SnapShotStoragePool.uri

                }

                if ($PSBoundParameters['LockStoragePool'])
                {

                    "[{0}] Locking Snapshot Storage Pool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockSnapshotStoragePool.IsPresent | Write-Verbose

                    $_InputObject.properties.snapshotPool.meta.locked = $LockSnapshotStoragePool.IsPresent

                }

            }

            'StoreVirtual'
            {

                if ($PSBoundParameters['SnapShotStoragePool'])
                {

                    $ExceptionMessage = "The Storage System family of the Storage Pool, {0}, is not a StoreServ system. Snapshots are only supported with StoreServ class of storage systems." -f $_StoragePool.name
                    $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'SnapShotStoragePool' -TargetType $SnapShotStoragePool.gettype().Name -Message $ExceptionMessage
                
                    #Generate Terminating Error
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                }

                #Set AdaptiveOptimization and RedundancyMode
                if ($PSBoundParameters['DataProtectionLevel'])
                {

                    $_DataProtectionLevel = $_InputObject.properties.dataProtectionLevel.enum | ? { $_ -eq $DataProtectionLevel }

                    if (-not $_DataProtectionLevel)
                    {

                        $ExceptionMessage = "The requested data protection level, {0}, is not supported with the storage system. Please correct the value with one of the following options: {1}" -f $DataProtectionLevel, ([String]::Join(', ', $_InputObject.properties.dataProtectionLevel.enum))
                        $ErrorRecord = New-ErrorRecord ArgumentException UnsupportedProtectionLevelValue InvalidArgument 'DataProtectionLevel' -TargetType $DataProtectionLevel.gettype().Name -Message $ExceptionMessage
                    
                        #Generate Terminating Error
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                    }

                    "[{0}] Setting StoreVirtual data protection level: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_DataProtectionLevel | Write-Verbose

                    $_InputObject.properties.dataProtectionLevel.default = $_DataProtectionLevel

                }

                if ($PSBoundParameters['LockProtectionLevel'])
                {

                    "[{0}] Locking Protection Level: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockProtectionLevel.IsPresent | Write-Verbose

                    $_InputObject.properties.dataProtectionLevel.meta.locked = $LockProtectionLevel.IsPresent

                }

                if ($PSBoundParameters['EnableAdaptiveOptimization'])
                {

                    "[{0}] Setting Adaptive optimization default value: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $EnableAdaptiveOptimization.IsPresent | Write-Verbose

                    $_InputObject.properties.isAdaptiveOptimizationEnabled.default = $EnableAdaptiveOptimization.IsPresent

                }

                if ($PSBoundParameters['LockAdaptiveOptimization'])
                {

                    "[{0}] Locking Adaptive optimization: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockAdaptiveOptimization.IsPresent | Write-Verbose

                    $_InputObject.properties.isAdaptiveOptimizationEnabled.meta.locked = $LockAdaptiveOptimization.IsPresent

                }

            }

        }

        switch ($PSBoundParameters.Keys)
        {

            'Name'
            {

                $_InputObject.name = $Name

            }

            'Description'
            {

                $_InputObject.description = $description

            }

            'Capacity'
            {

                "[{0}] Setting capacity default value: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [int64]($Capacity * 1GB) | Write-Verbose

                $_InputObject.properties.size.default = [int64]($Capacity * 1GB)

            }

            'LockCapacity'
            {

                "[{0}] Locking capacity: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockCapacity.IsPresent | Write-Verbose

                $_InputObject.properties.size.meta.locked = $LockCapacity.IsPresent

            }

            'LockStoragePool'
            {

                "[{0}] Locking Storage Pool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockStoragePool.IsPresent | Write-Verbose

                $_InputObject.properties.storagepool.meta.locked = $LockStoragePool.IsPresent

            }

            'Full'
            {

                "[{0}] Setting Provisioning Type to Full: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Full.IsPresent | Write-Verbose

                $_InputObject.properties.provisioningType.default = if ($Full.IsPresent) { 'Full' } else { 'Thin' }
                
            }

            'Thin'
            {

                "[{0}] Setting Provisioning Type to Thin: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Thin.IsPresent | Write-Verbose

                $_InputObject.properties.provisioningType.default = if ($Thin.IsPresent) { 'Full' } else { 'Thin' }
                
            }

            'LockProvisionType'
            {

                "[{0}] Locking provisioning type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockProvisionType.IsPresent | Write-Verbose

                $_InputObject.properties.provisioningType.meta.locked = $LockProvisionType.IsPresent

            }

            'Shared'
            {

                "[{0}] Setting Provisioning Type to Full: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Shared.IsPresent | Write-Verbose

                $_InputObject.properties.isShareable.default = $Shared.IsPresent
                
            }

            'LockProvisionMode'
            {

                "[{0}] Locking provisioning type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LockProvisionType.IsPresent | Write-Verbose

                $_InputObject.properties.isShareable.meta.locked = $LockProvisionType.IsPresent

            }

        }
        
        "[{0}] Updated Storage Volume Template object properties: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_InputObject | out-string) | Write-Verbose

        "[{0}] Sending updated storage volume template to appliance." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        Try
        {

            $Resp = Send-HPOVRequest -Uri $_InputObject.uri -Method PUT -Body $_InputObject -Hostname $ApplianceConnection

            $Resp.PSObject.TypeNames.Insert(0,'HPOneView.Storage.VolumeTemplate')

            $Resp

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVStorageVolumeTemplate 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default",SupportsShouldProcess,ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('uri', 'name', 'templateName')]
        [Object]$Template,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [switch]$Force
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
                
        if (-not($PSBoundParameters['Template'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList
        $_SVTCollection  = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SVT Object provided: $($Template | FL * | Out-String)"

            If ($Template.category -eq 'storage-volume-templates')
            {

                If (-not($Template.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "Template:$($Template.Name)" -TargetType PSObject -Message "The Template resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_SVTCollection.Add($Template)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "Template:$($Template.Name)" -TargetType PSObject -Message "The Template resource is not an expected category type [$($Template.category)]. Allowed resource category type is 'storage-volume-templates'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            foreach ($_svt in $Template) 
            {

                #SVT passed is a URI
                if (($_svt -is [String]) -and [System.Uri]::IsWellFormedUriString($_svt,'Relative')) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received URI: $($_svt)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting SVT object"

                    if (($ApplianceConnection | Measure-Object).Count -gt 1)
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value when using a Storage Volume Template URI value. Please correct this and try again.'
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Try
                    {

                        $_svtObject = Send-HPOVRequest $_svt -ApplianceConnection $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    [void]$_SVTCollection.Add($_svtObject)

                }

                #SVT passed is the Name
                elseif (($_svt -is [string]) -and (-not($_svt.startsWith("/rest")))) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received SVT Name $($_svt)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting SVT object from Get-HPOVStorageVolumeTemplate"

                    ForEach ($_appliance in $ApplianceConnection)
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$_appliance' Appliance Connection [of $($ApplianceConnection.count)]"

                        Try
                        {

                            $_svtObject = Get-HPOVStorageVolumeTemplate $_svt -ApplianceConnection $ApplianceConnection -ErrorAction Stop

                        }

                        Catch
                        {
                            
                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        $_svtObject | % {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding '$($_.name)' SVT to collection."

                            [void]$_SVTCollection.Add($_)

                        }

                    }

                }

                #SVT passed is the object
                elseif ($_svt -is [PSCustomObject] -and $_svt.category -ieq 'storage-volume-templates') 
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SVT Object provided: $($_svt | FL * | out-string)"

                    [void]$_SVTCollection.Add($_svt)
                
                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Template' -TargetType 'PSObject' -Message "Invalid SVT Parameter: $($_svt | FL * | Out-String)"
                    $PSCmdlet.WriteError($ErrorRecord)

                }

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_SVTCollection.count) SVT resources to remove."

        #Process SVT Resources
        ForEach ($_svtObject in $_SVTCollection)
        {

            if ($PSCmdlet.ShouldProcess($_svtObject.name,"Remove SVT from appliance '$($_svtObject.ApplianceConnection.Name)'")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing SVT '$($_svtObject.name)' from appliance '$($_svtObject.ApplianceConnection.Name)'."

                Try
                {
                    
                    if ($PSBoundParameters['Force'])
                    {

                        $_svtObject.uri += "?force=true"

                    }

                    $_resp = Send-HPOVRequest $_svtObject.Uri DELETE -Hostname $_svtObject.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Get-HPOVStorageVolumeTemplatePolicy 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (
    
        [Parameter (Mandatory = $False)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_SVTPolicyCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($_appliance.Name)' Appliance Connection [of $($ApplianceConnection.Count)]"
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting global setting value."

            Try
            {

                $_Policy = Send-HPOVRequest $applStorageVolumeTemplateRequiredPolicy -Hostname $_appliance

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_Policy.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.GlobalSetting')

            [void]$_SVTPolicyCollection.Add($_Policy)

        }

    }

    End
    {

        Return $_SVTPolicyCollection

    }

}

function Set-HPOVStorageVolumeTemplatePolicy 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding ()]
    Param 
    (
    
        [Parameter (Mandatory, ParameterSetName = "Enable")]
        [switch]$Enable,
              
        [Parameter (Mandatory, ParameterSetName = "Disable")]
        [switch]$Disable,

        [Parameter (Mandatory = $False, ParameterSetName = "Enable")]
        [Parameter (Mandatory = $False, ParameterSetName = "Disable")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_SVTPolicyCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($_appliance.Name)' Appliance Connection [of $($ApplianceConnection.Count)]"

            $_request = NewObject -GlobalSetting

            $_request.name = 'StorageVolumeTemplateRequired'

            switch ($PSCmdlet.ParameterSetName) 
            {

                'Enable' 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User requested to ENABLE the policy"

                    $_request.value = 'true'

                }

                'Disable' 
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User requested to DISABLE the policy"
                    
                    $_request.value = 'false'
            
                }

            }

            try
            {

                $_updatedpolicy = Send-HPOVRequest $applStorageVolumeTemplateRequiredPolicy PUT $_request -Hostname $_appliance 

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_updatedpolicy.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.GlobalSetting')

            [void]$_SVTPolicyCollection.Add($_updatedpolicy)

        }
        
    }

    End 
    {

        Return $_SVTPolicyCollection

    }

}

function Get-HPOVStorageVolume 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "InputObject")]
        [ValidateNotNullOrEmpty()]
        [Alias ('ServerProfile', 'ServerProfileTemplate')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('VolumeName')]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [switch]$Available,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "InputObject")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
        #$volumeCollection = New-Object System.Collections.ArrayList

    }

    Process 
    { 

        "[{0}] ParameterSetName: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PSCmdlet.ParameterSetName | Write-Verbose
        
        if ($InputObject)
        {

            "[{0}] InputObject category: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.category | Write-Verbose

            switch ($InputObject.category)
            {

                'server-profiles'
                {

                    "[{0}] Processing Server Profile: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose
                    "[{0}] Storage Volume Attachments: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.sanStorage.volumeAttachments.Count | Write-Verbose
                    
                    ForEach ($_VolumeAttachment in $InputObject.sanStorage.volumeAttachments)
                    {

                        Try
                        {

                            $_StorageVolume = Send-HPOVRequest -Uri $_VolumeAttachment.volumeUri -HostName $InputObject.ApplianceConnection

                            $_StorageVolume.PSobject.TypeNames.Insert(0,'HPOneView.Storage.Volume')

                            $_StorageVolume

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                }

                'storage-systems'
                {

                    "[{0}] Processing Storage System: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                    "[{0}] Getting associated Storage Pools with system" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    Try
                    {

                        $_Uri = "{0}?filter=storageSystemUri EQ '{1}'&filter=isManaged EQ true" -f $StoragePoolsUri, $InputObject.uri
                        $_AssociatedPools = Send-HPOVRequest -Uri $_Uri -Hostname $InputObject.ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    "[{0}] Associated Storage Pools with system: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_AssociatedPools.count | Write-Verbose

                    if ($_AssociatedPools.members)
                    {

                        ForEach ($_AssociatedPool in $_AssociatedPools.members)
                        {

                            "[{0}] Getting associated storage volumes with pool: " -f $MyInvocation.InvocationName.ToString().ToUpper(), $_AssociatedPool.name | Write-Verbose

                            Try
                            {

                                $_Uri = "{0}?filter=storagePoolUri EQ '{1}'" -f $StorageVolumesUri, $_AssociatedPool.uri
                                $_AssociatedVols = Send-HPOVRequest -Uri $_Uri -Hostname $InputObject.ApplianceConnection

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                            "[{0}] Associated storage vols with pool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_AssociatedVols.count | Write-Verbose

                            if ($_AssociatedVols.members)
                            {

                                $_AssociatedVols.members | % {

                                    $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.Volume')
                                    $_

                                }

                            }

                        }

                    }

                }

                'storage-pools'
                {

                    "[{0}] Processing Storage Pool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                    Try
                    {

                        $_Uri = "{0}?filter=storagePoolUri EQ '{1}'" -f $StorageVolumesUri, $InputObject.uri
                        $_AssociatedVols = Send-HPOVRequest -Uri $_Uri -Hostname $InputObject.ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    if ($_AssociatedVols.members)
                    {

                        $_AssociatedVols.members | % {

                            $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.Volume')
                            $_

                        }

                    }

                }

                default
                {

                    $ExceptionMessage = "The InputObject parameter value is not supported. Only Server Profile, Storage System and Storage Pool objects are supports."
                    $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'InputObject' -TargetType $InputObject.gettype().Name -Message $ExceptionMessage
                
                    #Generate Terminating Error
                    #$PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

        }

        else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                if ($PSBoundParameters['Label'])
                {

                    "[{0}] Searching for volumes with label associatedl: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Label | Write-Verbose

                    $_uri = '{0}?category:storage-volume&query=labels:{1}' -f $IndexUri, $Label

                    Try
                    {

                        $_StorageVolumeTemplates = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                        #Loop through all found members and get full SVT object
                        ForEach ($_memeber in $_StorageVolumeTemplates.members)
                        {

                            Try
                            {

                                $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }                        

                            $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.Storage.VolumeTemplate')

                            $_memeber

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                else
                {

                    if ($Name)
                    {

                        $Name = $Name.Replace("*","%25").Replace("?","%26") 

                    }
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting list of Storage Volumes"

                    if ($Name -and -not $Available) 
                    { 
                    
                        $uri = "{0}?filter=name matches '{1}'" -f $StorageVolumesUri, $Name    

                    }
                    
                    elseif ($Name -and $Available) 
                    {
                    
                        $uri = "{0}?filter=name matches '{1}'&count=1000" -f $AttachableStorageVolumesUri, $Name
                    
                    }
                    
                    elseif (-not $Name -and $Available) 
                    {
                    
                        $uri = $AttachableStorageVolumesUri + '?count=1000' 
                        
                    }
                    
                    else 
                    {
                    
                        $uri = $StorageVolumesUri 
                        
                    }
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Query: $($uri)"

                    #Send the query
                    Try
                    {

                        $storageVolumes = Send-HPOVRequest -Uri $uri -appliance $_appliance

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    #Generate Terminating Error if resource not found
                    if (-not($storageVolumes.members))
                    {
                        
                        if ($Name) 
                        { 
                            
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] '$Name' Storage Volume found."

                            $ExceptionMessage = "No Storage Volume with '{0}' name found on '{1}' appliance connection. Please check the name or use New-HPOVStorageVolume to create the volume." -f $Name, $_appliance.Name
                            $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException StorageVolumeResourceNotFound ObjectNotFound 'Name' -Message $ExceptionMessage 
                            $PSCmdlet.WriteError($ErrorRecord)

                        }

                        else 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Storage Volumes found."

                        }
                                
                    }
                        
                    else 
                    {

                        $storageVolumes.members | % { 

                            $_.PSObject.TypeNames.Insert(0,"HPOneView.Storage.Volume") 
                            
                            $_
                            
                        }     

                        if ($Available) 
                        {
                        
                            Write-Verbose "Done. $($storageVolumes.count) attachable storage volume(s) found on $($_appliance.name)." 
                            
                        }
                        
                        else 
                        {
                        
                            Write-Verbose "Done. $($storageVolumes.count) storage volume(s) found on $($_appliance.name)." 
                            
                        }
                        
                    }

                }    

            }

        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVStorageVolumeSnapShot
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Name', 'Volume')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process 
    { 
        
        #Generate error Volume is not an object
        if (-not($InputObject -is [PSCustomObject]) -and $InputObject.category -ne 'storage-volumes')
        {

            $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStorageVolumeResource InvalidArgument 'Volume' -TargetType $Volume.GetType().Name -Message "The provided Volume Parameter value is not a supported type or object. Please provide a Storage Volume resource object and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }


        "[{0}] Processing Storage Volume: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

        $uri = $InputObject.uri + '/snapshots'

        #Send the query
        Try
        {

            $_VolumeSnapshots = Send-HPOVRequest -Uri $uri -appliance $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not($_VolumeSnapshots.members))
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Storage Volume Snapshots found."

        }

        else 
        {

            $_VolumeSnapshots.members | % { 

                $_.PSObject.TypeNames.Insert(0,"HPOneView.Storage.VolumeSnapshot") 
                    
                $_
                    
            }     

        }

    }

    End 
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function New-HPOVStorageVolumeSnapshot
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Volume')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false)]
        [String]$Name = '{volumeName}_{timestamp}',

        [Parameter (Mandatory = $false)]
        [String]$Description,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
    }

    Process 
    { 

        #Generate error Volume is not an object
        if ($InputObject -isnot [PSCustomObject] -and $InputObject.category -ne 'storage-volumes')
        {

            $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStorageVolumeResource InvalidArgument 'Volume' -TargetType $Volume.GetType().Name -Message "The provided Volume Parameter value is not a supported type or object. Please provide a Storage Volume resource object and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        "[{0}] Processing Storage Volume: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

        #Validate the volume is a support volume to create a snapshot of
        #Get Storage Pool and associated SS
        Try
        {

            $_AssociatedPool = Send-HPOVRequest -Uri $InputObject.storagePoolUri -Hostname $ApplianceConnection
            $_AssociatedSS   = Send-HPOVRequest -Uri $_AssociatedPool.storageSystemUri -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        #Validate SS family
        if ($_AssociatedSS.family -ne 'StoreServ')
        {

            $ExceptionMessage = "The Storage System {0} family ({1}) of the associated storage volume, {2}, is not a StoreServ system. Volume snapshots are supported with StoreServ class of storage systems." -f $_AssociatedSS.name, $_AssociatedPool.name, $InputObject.name
            $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'DataProtectionLevel' -TargetType $DataProtectionLevel.gettype().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $uri = $InputObject.uri + '/snapshots'

        #Send the query
        Try
        {

            $_VolSnapshot = NewObject -VolSnapshot

            $_VolSnapshot.name        = $Name
            $_VolSnapshot.description = $Description

            $_VolumeSnapshotResp = Send-HPOVRequest -Uri $uri -Method POST -Body $_VolSnapshot -appliance $ApplianceConnection

        }

        Catch
        {

            #Return any task resources at this point, then generate error
            $_VolumeSnapshotCollection

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not $PSBoundParameters['Async'])
        {

            $_VolumeSnapshotResp | Wait-HPOVTaskComplete

        }

        else
        {

            $_VolumeSnapshotResp

        }

    }

    End 
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVStorageVolumeSnapshot
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Snapshot')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false)]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_VolumeSnapshotCollection = New-Object System.Collections.ArrayList
        $_TaskCollection           = New-Object System.Collections.ArrayList

    }

    Process 
    { 
        
        #Generate error Snapshot is not an object or correct object
        if (-not($InputObject -is [PSCustomObject]) -and $InputObject.category -ne 'storage-volumes' -and (-not($InputObject -match '/snapshots/')))
        {

            $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStorageVolumeResource InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message "The provided Volume Snapshot Parameter value is not a supported type or object. Please provide a Storage Volume Snapshot resource object and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received Storage Volume Snapshot: {0}" -f $InputObject.name | Write-Verbose

        [void]$_VolumeSnapshotCollection.Add($InputObject)

    }

    End 
    {

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing {0} Storage Volume Snapshot resources to remove." -f $_VolumeSnapshotCollection.count | Write-Verbose 

        #Process Resources
        ForEach ($_resource in $_VolumeSnapshotCollection)
        {

            if ($PSCmdlet.ShouldProcess($_resource.ApplianceConnection.Name,("remove volume snapshot '{0}'" -f $_resource.name))) 
            {

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing resource '{0}' from appliance '{1}'." -f $_resource.name,$_resource.ApplianceConnection.Name | Write-Verbose 

                Try
                {
                    
                    $_resp = Send-HPOVRequest -uri $_resource.Uri -Method DELETE -Hostname $_resource.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            if (-not $PSBoundParameters['Async'])
            {

                $_resp | Wait-HPOVTaskComplete

            }

            else
            {

                $_resp

            }

        }

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function ConvertTo-HPOVStorageVolume
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty ()]
        [Alias ('Snapshot')]
        [Object]$InputObject,

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty ()]
        [String]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty ()]
        [String]$Description,

        [Parameter (Mandatory = $false)]
        [ValidateSet ('Private', 'Shared')]
        [String]$SharingMode,

        [Parameter (Mandatory = $false)]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty ()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_VolumeSnapshotTaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    { 
        
        #Generate error Snapshot is not an object or correct object
        if (-not($InputObject -is [PSCustomObject]) -and $InputObject.category -ne 'storage-volumes' -and (-not($InputObject -match '/snapshots/')))
        {

            $ExceptionMessage = "The provided InputObject parameter value is not a supported type or object. Please provide a Storage Volume Snapshot resource object and try again."
            $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStorageSnapshotResource InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        "[{0}] Processing Storage Volume Snapshot: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

        $_ConvertSnapshotToVol                        = NewObject -ConvertSnapshotToVol
        $_ConvertSnapshotToVol.properties.name        = $Name
        $_ConvertSnapshotToVol.properties.description = $Description
        $_ConvertSnapshotToVol.snapshotUri            = $InputObject.uri
        
        #Get parent volume snapshotUri value
        Try
        {

            $_ParentVol = Send-HPOVRequest -Uri $InputObject.storageVolumeUri -Hostname $InputObject.ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $_ConvertSnapshotToVol.properties.snapshotPool     = $_ParentVol.deviceSpecificAttributes.snapshotPoolUri
        $_ConvertSnapshotToVol.properties.storagePool      = $_ParentVol.storagePoolUri
        $_ConvertSnapshotToVol.properties.provisioningType = $_ParentVol.provisioningType

        if (-not $_ParentVol.volumeTemplateUri) 
        {

            #Need to get root template from system via storage pool
            try
            {

                $_AssociatedPool = Send-HPOVRequest -Uri $_ParentVol.storagePoolUri -Hostname $InputObject.ApplianceConnection.Name

                "[{0}] Getting storage system root volume template." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                $_Uri = '{0}/templates?filter=isRoot EQ true' -f $_AssociatedPool.storageSystemUri
                $_RootTemplate = (Send-HPOVRequest -Uri $_Uri -Hostname $InputObject.ApplianceConnection.Name).members[0]

                $_ConvertSnapshotToVol.templateUri = $_RootTemplate.uri

            }

            catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        else
        {

            $_ConvertSnapshotToVol.templateUri = $_ParentVol.volumeTemplateUri    
            
        }

        if (-not $PSBoundParameters['SharingMode'])
        {

            $_ConvertSnapshotToVol.properties.isShareable = $_ParentVol.isShareable

        }

        else
        {

            $_ConvertSnapshotToVol.properties.isShareable = $SharingMode.IsPresent

        }
        
        #Send the query
        Try
        {

            $_VolumeSnapshotResp = Send-HPOVRequest -Uri $StorageVolumeFromSnapshotUri -Method POST -Body $_ConvertSnapshotToVol -appliance $InputObject.ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not $PSBoundParameters['Async'])
        {

            $_VolumeSnapshotResp | Wait-HPOVTaskComplete

        }

        else
        {

            $_VolumeSnapshotResp

        }

    }

    End 
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function New-HPOVStorageVolume 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "default")]
        [Parameter (Mandatory, ParameterSetName = "template")]
        [ValidateNotNullOrEmpty()]
        [Alias ("VolumeName")]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "template")]
        [ValidateNotNullOrEmpty()]
        [string]$Description,

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("pool","poolName")]
        [object]$StoragePool,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "template")]
        [ValidateNotNullOrEmpty()]
        [object]$SnapshotStoragePool,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [object]$StorageSystem,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "template")]
        [ValidateSet ('NetworkRaid0None','NetworkRaid5SingleParity','NetworkRaid10Mirror2Way','NetworkRaid10Mirror3Way','NetworkRaid10Mirror4Way','NetworkRaid6DualParity')]
        [String]$DataProtectionLevel,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "template")]
        [switch]$EnableAdaptiveOptimization,

        [Parameter (Mandatory, ParameterSetName = "template")]
        [ValidateNotNullOrEmpty()]
        [Alias ('template','svt')]
        [object]$VolumeTemplate,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "template")]
        [ValidateScript({$_ -ge 1})]
        [Alias ("size")]
        [int64]$Capacity,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "template")]
        [ValidateSet ('Thin', 'Full', 'TPDD')]
        [String]$ProvisionType,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "template")]
        [switch]$Full,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "template")]
        [switch]$Shared,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "template")]
        [switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "template")]
        [ValidateNotNullorEmpty()]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['StoragePool']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        if ($PSBoundParameters['Full'])
        {

            Write-Warning "The -Full parameter is being deprecated for -ProvisionType. Please update your script(s) to use the new parameter."

        }

    }

    Process 
    {

        #Check to see if Storage Volume Template Global Setting is enabled
        Try
        {

            "[{0}] Checking for SVT Global Policy." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_storageVolumeTemplateRequiredGlobalPolicy = (Send-HPOVRequest $applStorageVolumeTemplateRequiredPolicy -Hostname $ApplianceConnection).value

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        if ($_storageVolumeTemplateRequiredGlobalPolicy -ieq "True" -and (-not $PSBoundParameters['VolumeTemplate'] -or -not $VolumeTemplate))
        { 
        
            $ExceptionMessage = "Storage Volumes cannot be created without providing a Storage Volume Template due to global policy setting. Please provide a Storage Volume Template and try again."
            $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException StorageVolumeTemplateRequired InvalidArgument 'VolumeTemplate' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
        
        }

        #Figure out what type of VOlume we will create
        if ($PSBoundParameters['VolumeTemplate'] -or $VolumeTemplate)
        {

            if ($VolumeTemplate.category -ne 'storage-volume-templates')
            {

                $ExceptionMessage = "The value provided for VolumeTemplate is not the allowed resource type, storage-volume-templates."
                $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeTemplateResourceException InvalidStorageVolumeTemplateResource InvalidArgument 'VolumeTemplate' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            "[{0}] Storage Volume Template provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $VolumeTemplate.name | Write-Verbose
            "[{0}] Storage Volume Template family: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $VolumeTemplate.family | Write-Verbose

            switch ($VolumeTemplate.family)
            {

                'StoreVirtual'
                {

                    $_newVolume = NewObject -StoreVirtualStorageVolume

                }

                'StoreServ'
                {

                    $_newVolume = NewObject -StoreServStorageVolume

                }

            }

            $_Family = $VolumeTemplate.family

        }
        
        #Storage Pool was provided
        else
        {

            "[{0}] No Storage Volume Template provided. Processing StoragePool." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if ($StoragePool -is [String])
            {

                "[{0}] Locating storage pool resource: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StoragePool | Write-Verbose

                Try
                {

                    $StoragePool = GetStoragePool -Name $StoragePool -StorageSystem $StorageSystem -ApplianceConnection $ApplianceConnection

                }
            
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            #Get Storage System
            Try
            {

                $_StorageSystem = Send-HPOVRequest -Uri $StoragePool.storageSystemUri -Hostname $StoragePool.ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_StoragePool = $StoragePool.PSObject.Copy()

            $_StoragePool | Add-Member -NotePropertyName family -NotePropertyValue $_StorageSystem.family

            "[{0}] Storage Pool family: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_StoragePool.family | Write-Verbose

            switch ($_StoragePool.family)
            {

                'StoreVirtual'
                {

                    $_newVolume = NewObject -StoreVirtualStorageVolume

                }

                'StoreServ'
                {

                    $_newVolume = NewObject -StoreServStorageVolume

                }

            }

            $_Family = $_StoragePool.family

            #Need to get the root ST since none was provided
            Try
            {

                $Uri = "{0}/templates?query=isRoot EQ true" -f $_StoragePool.storageSystemUri
                $RootSVT = Send-HPOVRequest -Uri $Uri -ApplianceConnection $ApplianceConnection
                $VolumeTemplate = $RootSVT.members[0]

            }
        
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        "[{0}] Setting volume template uri: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $VolumeTemplate.uri | Write-Verbose

        $_newVolume.templateUri = $VolumeTemplate.uri

        switch ($_newVolume.properties.GetEnumerator().name)
        {

            'name'
            {

                "[{0}] Setting volume name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose
                $_newvolume.properties.name = $Name

            }

            'description'
            {

                "[{0}] Setting volume description: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Description | Write-Verbose
                $_newvolume.properties.description = $Description

            }

            'storagePool'
            {

                #If SVT enforces, set it
                if ($VolumeTemplate.properties.storagePool.meta.locked -or -not $PSBoundParameters['StoragePool'])
                {

                    "[{0}] Volume Template enforces StoragePool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $VolumeTemplate.properties.storagePool.default | Write-Verbose

                    $_newvolume.properties.storagePool = $VolumeTemplate.properties.storagePool.default
                    
                }

                else
                {

                    "[{0}] Setting StoragePool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_StoragePool.uri | Write-Verbose

                    $_newvolume.properties.storagePool = $_StoragePool.uri

                }

            }

            'snapshotPool'
            {

                if ($_Family -ne 'StoreVirtual')
                {

                    "[{0}] Family is StoreServ, attempting to set snapshot pool" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    #If SVT enforces, set it
                    if ($VolumeTemplate.properties.snapshotPool.meta.locked)
                    {

                        "[{0}] Volume Template enforces Snapshot StoragePool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $VolumeTemplate.properties.snapshotPool.default | Write-Verbose

                        $_newvolume.properties.snapshotPool = $VolumeTemplate.properties.snapshotPool.default
                        
                    }

                    else
                    {

                        if ($PSBoundParameters['SnapshotStoragePool'])
                        {

                            if ($SnapshotStoragePool -is [String])
                            {

                                try
                                {

                                    $SnapshotStoragePool = GetStoragePool -Name $StoragePool -StorageSystem $StorageSystem -ApplianceConnection $ApplianceConnection

                                }

                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }

                            }

                            "[{0}] Setting StoragePool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_StoragePool.uri | Write-Verbose
                            
                            $_newvolume.properties.snapshotPool = $SnapshotStoragePool.uri

                        }

                        else
                        {

                            "[{0}] Setting StoragePool: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_StoragePool.uri | Write-Verbose

                            $_newvolume.properties.snapshotPool = $StoragePool.uri

                        }                        

                    }

                }

                else
                {

                    if ($PSBoundParameters['SnapshotStoragePool'])
                    {

                        $ExceptionMessage = "The Storage System family of the Storage Pool, {0}, is not a StoreServ system. Snapshots are only supported with StoreServ class of storage systems." -f $_StoragePool.name
                        $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'SnapShotStoragePool' -TargetType $SnapShotStoragePool.gettype().Name -Message $ExceptionMessage
                    
                        #Generate Terminating Error
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                    }

                }

            }

            'dataProtectionLevel'
            {

                if ($_Family -eq 'StoreVirtual')
                {

                    if ($VolumeTemplate.properties.dataProtectionLevel.meta.locked -or (-not $PSBoundParameters['DataProtectionLevel'] -and -not $VolumeTemplate.properties.dataProtectionLevel.meta.locked))
                    {

                        "[{0}] Volume Template enforces DataProtectionLevel: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $VolumeTemplate.properties.dataProtectionLevel.default | Write-Verbose

                        $_newvolume.properties.dataProtectionLevel = $VolumeTemplate.properties.dataProtectionLevel.default

                    }
                    
                    else
                    {

                        $_DataProtectionLevel = $VolumeTemplate.properties.dataProtectionLevel.enum | ? { $_ -eq $DataProtectionLevel }

                        if (-not $_DataProtectionLevel)
                        {

                            $ExceptionMessage = "The requested data protection level, {0}, is not supported with the storage system. Please correctthe value with one of the following options: {1}" -f $DataProtectionLevel, ([String]::Join(', ', $VolumeTemplate.properties.dataProtectionLevel.enum))
                            $ErrorRecord = New-ErrorRecord ArgumentException UnsupportedProtectionLevelValue InvalidArgument 'DataProtectionLevel' -TargetType $DataProtectionLevel.gettype().Name -Message $ExceptionMessage
                        
                            #Generate Terminating Error
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                        }

                        $_newvolume.properties.dataProtectionLevel = $_DataProtectionLevel

                    }

                }

                else
                {

                    if ($PSBoundParameters['DataProtectionLevel'])
                    {

                        $ExceptionMessage = "The Storage System family of the Storage Pool, {0}, is not a StoreVirtual system. Data Protection for volumes is defined within the StoreServ Common Provisioning Group (CPG)." -f $_StoragePool.name
                        $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'DataProtectionLevel' -TargetType $DataProtectionLevel.gettype().Name -Message $ExceptionMessage
                    
                        #Generate Terminating Error
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                    }

                }

            }

            'isAdaptiveOptimizationEnabled'
            {

                if ($_Family -eq 'StoreVirtual')
                {

                    if ($VolumeTemplate.properties.isAdaptiveOptimizationEnabled.meta.locked -or (-not $PSBoundParameters['EnableAdaptiveOptimization'] -and -not $VolumeTemplate.properties.isAdaptiveOptimizationEnabled.meta.locked))
                    {

                        "[{0}] Volume Template enforces AdaptiveOptimizationEnabled: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $VolumeTemplate.properties.isAdaptiveOptimizationEnabled.default | Write-Verbose

                        $_newvolume.properties.isAdaptiveOptimizationEnabled = $VolumeTemplate.properties.isAdaptiveOptimizationEnabled.default

                    }
                    
                    else
                    {

                        $_newvolume.properties.isAdaptiveOptimizationEnabled = $EnableAdaptiveOptimization.IsPresent

                    }

                }

                else
                {

                    if ($PSBoundParameters['EnableAdaptiveOptimization'])
                    {

                        $ExceptionMessage = "The Storage System family of the Storage Pool, {0}, is not a StoreVirtual system. Adaptive Optimization is only available with StoreVirtual." -f $_StoragePool.name
                        $ErrorRecord = New-ErrorRecord ArgumentException InvalidArgumentType InvalidArgument 'EnableAdaptiveOptimization' -TargetType $EnableAdaptiveOptimization.gettype().Name -Message $ExceptionMessage
                    
                        #Generate Terminating Error
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                    }

                }

            }

            'size'
            {

                if ($VolumeTemplate.properties.size.meta.locked -or (-not $PSBoundParameters['Capacity'] -and -not $VolumeTemplate.properties.size.meta.locked))
                {

                    "[{0}] Volume Template enforces volume capacity: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $VolumeTemplate.properties.size.default | Write-Verbose

                    $_newvolume.properties.size = $VolumeTemplate.properties.size.default

                }
                
                else
                {

                    $_newvolume.properties.size = $Capacity * 1GB

                }

            }

            'provisioningType'
            {

                if ($VolumeTemplate.properties.provisioningType.meta.locked -or (-not $PSBoundParameters['Full'] -and -not $PSBoundParameters['ProvisionType'] -and -not $VolumeTemplate.properties.provisioningType.meta.locked))
                {

                    "[{0}] Volume Template enforces volume provisioningType: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $VolumeTemplate.properties.provisioningType.default | Write-Verbose
                    $_newvolume.properties.provisioningType = $VolumeTemplate.properties.provisioningType.default

                }
                
                else
                {

                    if ($PSBoundParameters['ProvisionType'])
                    {

                        "[{0}] Setting volume provisioningType via ProvisionType param: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StorageVolumeProvisioningTypeEnum[$ProvisionType] | Write-Verbose

                        $_newvolume.properties.provisioningType = $StorageVolumeProvisioningTypeEnum[$ProvisionType]

                    }

                    elseif ($PSBoundParameters['Full'])
                    {

                        "[{0}] Setting volume provisioningType via full param: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StorageVolumeProvisioningTypeEnum['Full'] | Write-Verbose

                        $_newvolume.properties.provisioningType = $StorageVolumeProvisioningTypeEnum['Full']

                    }

                    else
                    {

                        "[{0}] Setting volume provisioningType via not full param: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StorageVolumeProvisioningTypeEnum['Thin'] | Write-Verbose

                        $_newvolume.properties.provisioningType = $StorageVolumeProvisioningTypeEnum['Thin']

                    }

                }

            }

            'isShareable'
            {

                if ($VolumeTemplate.properties.isShareable.meta.locked -or (-not $PSBoundParameters['Shared'] -and -not $VolumeTemplate.properties.isShareable.meta.locked))
                {

                    "[{0}] Volume Template enforces volume provisioningType: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $VolumeTemplate.properties.provisioningType.default | Write-Verbose

                    $_newvolume.properties.isShareable = $VolumeTemplate.properties.isShareable.default

                }
                
                else
                {

                    $_newvolume.properties.isShareable = $Shared.IsPresent

                }

            }

        }

        #Send the request
        Try
        {

            $_Resp = Send-HPOVRequest -Uri $StorageVolumesUri -Method POST -Body $_newVolume -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-Not $PSBoundParameters['Async'])
        {

            $_Resp | Wait-HPOVTaskComplete

        }

        else
        {

            $_Resp

        }

    }

    End 
    {
        
        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function GetStoragePool
{

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("pool","poolName",'Name', 'StoragePool')]
        [Object]$InputObject,

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [object]$StorageSystem,

        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [object]$ApplianceConnection

    )

    Process
    {

        switch ($InputObject.Gettype().Name) 
        {

            "String" 
            { 
                        
                #Parameter is correct URI
                if ($InputObject.StartsWith($StoragePoolsUri))
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] StoragePool URI provided by caller."
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request." 
                                                       
                    Try
                    {

                        $_sp = Send-HPOVRequest -Uri $InputObject -Hostname $ApplianceConnection.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                                
                            
                }

                #Parameter is incorrect URI value
                elseif ($InputObject.StartsWith("/rest")) 
                {

                    #Invalid Parameter value, generate terminating error.
                    $ExceptionMessage = "Invalid StoragePool Parameter value: {1}. Please correct and try again." -f $InputObject
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidArgumentValue InvalidArgument 'InputObject' -Message 
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                #Parameter is Storage Pool name
                else 
                {
                                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] StoragePool Name provided by caller."
                                
                    #Get specific storage pool from provided StorageSystem
                    if ($InputObject) 
                    { 

                        #First look for the StorageSystem Parameter value, and get the StoragePool by filtering on the StorageSystem value.
                        Try
                        {
                                        
                            $_sp = Get-HPOVStoragePool -Name $InputObject -StorageSystem $StorageSystem -ApplianceConnection $ApplianceConnection -ErrorAction Stop
                                        
                        }
                                    
                        Catch
                        {
                                    
                            $PSCmdlet.ThrowTerminatingError($_)
                                    
                        }

                    }

                    else 
                    {
                                        
                        Try
                        {
                                            
                            $_sp = Get-HPOVStoragePool -Name $InputObject -ApplianceConnection $ApplianceConnection -ErrorAction Stop
                                    
                        }
                                    
                        Catch
                        {
                                    
                            $PSCmdlet.ThrowTerminatingError($_)
                                    
                        }
                                    
                    }
                                    
                    #If multiple Storage Pool Resources are returned that are of the same name, generate error and indicate the -StorageSystem Parameter is needed.
                    #Validate that the storage pool object is unique and not a collection
                    if(($_sp | Measure-Object).Count -gt 1)
                    {
                                    
                        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Multiple Storage Pool resources of the name '$InputObject'. $($_sp.count) resources found."
                                        
                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidStoragePoolResource ObjectNotFound 'InputObject' -TargetType 'Array' -Message "Multiple Storage Pools it the '$tmpStoragePool' name were found. Please use the -StorageSystem Parameter to specify the Storage System the Pool is associated with, or use the Get-HPOVStoragePool cmdlet to get the Storage Pool resource and pass as the -StoragePool Parameter value."
                                        
                        #Generate Terminating Error
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }
                                    
                }

            }

            "PSCustomObject" 
            { 
                        
                #Validate the object
                if ($InputObject.category -eq 'storage-pools') 
                { 
                                
                    #Check the StoragePool object to make sure the ApplianceConnection property matches the ApplianceConnection Parameter from caller
                    if ($InputObject.ApplianceConnection.Name -ne $ApplianceConnection.Name)
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStoragePoolObject InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided StoragePool object does not appear to originate from the same ApplianceConnection specified - ApplianceConnection: $($ApplianceConnection.Name) StorageVolume ApplianceConnection $($StorageVolume.ApplianceConnection.Name)."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }
                                
                    $_sp = $InputObject.PSObject.Copy()
                            
                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStoragePoolCategory InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "Invalid StoragePool Parameter value. Expected Resource Category 'storage-pools', received '$($VolumeTemplate.category)'."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }                        
                        
            }

        }

    }

    End
    {

        Return $_sp

    }

}

function Add-HPOVStorageVolume 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [object]$StorageSystem,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("volid","id","wwn")]
        [string]$VolumeID,

        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [string]$StorageDeviceName,

        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("Name")]
        [string]$VolumeName,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [string]$Description = "",

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$Shared,

        [Parameter (Mandatory = $false, ParameterSetName = "default", ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['StorageSystem']))
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        if ($PSBoundParameters['VolumeID'])
        {

            Write-Warning 'The -VolumeID parameter is now deprecated and is no longer used.'

        }

    }

    Process 
    {


        $_addVolume = NewObject -AddStorageVolume
        $_addVolume.deviceVolumeName = $StorageDeviceName
        $_addVolume.name             = $VolumeName
        $_addVolume.description      = $Description
        $_addVolume.isShareable      = $Shared.IsPresent

        Switch ($StorageSystem.GetType().Name) 
        {

            "String" 
            {
                            
                if ($StorageSystem.StartsWith($StorageSystemsUri))
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] StorageSystem URI provided by caller."
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request."   
                                         
                    Try
                    {

                        $_ss = Send-HPOVRequest -Uri $StorageSystem -Hostname $ApplianceConnection.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                }

                elseif ($StorageSystem.StartsWith("/rest")) 
                {

                    #Invalid Parameter value, generate terminating error.
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidArgumentValue InvalidArgument 'StorageSystem' -Message "Invalid StorageSystem Parameter value: $($StorageSystem | out-string)"
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                else 
                {
                                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] StorageSystem Name provided by caller."
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request."

                    #Get the storage volume template resource. Terminating error will throw from the Get-* if no resource is found.
                    Try
                    {

                        $_ss = Get-HPOVStorageSystem -SystemName $StorageSystem -ApplianceConnection $ApplianceConnection
                    
                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            "PSCustomObject" 
            {

                #Validate the object
                if ($StorageSystem.category -eq 'storage-systems' -and $StorageSystem.ApplianceConnection.Name -eq $ApplianceConnection.Name) 
                { 
                    
                    "[{0}] Storage System Object provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($StorageSystem.name) | Write-Verbose

                    $_ss = $StorageSystem.PSObject.Copy()
                
                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStorageSystemCategory InvalidArgument 'StorageSystem' -TargetType PSObject -Message "Invalid StorageSystem Parameter value. Expected Resource Category 'storage-systems', received '$($VolumeTemplate.category)'."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            default 
            {
            
                $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStorageSystemObject InvalidArgument 'StorageSystem' -TargetType $StorageSystem.GetType().Name -Message "Invalid StorageSystem Parameter value object type. Only [PSCustomObject] or [String] values are allowed."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }
        
        }

        $_addVolume.storageSystemUri = $_ss.uri

        "[{0}] Add Storage Volume Object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_addVolume | Out-String) | Write-Verbose
 
        #Send the request
        Try
        {

            $_Uri = '{0}/from-existing' -f $StorageVolumesUri

            Send-HPOVRequest -Uri $_Uri -Method POST -Body $_addVolume -Hostname $ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        #[void]$colStatus.Add($_resp)
        
    }

    End 
    {

        #Return $colStatus
        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Set-HPOVStorageVolume 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('SourceVolume')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('VolumeName')]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [String]$Description,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateScript ({$_ -ge 1})]
        [Alias ("size")]
        [int64]$Capacity,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Object]$SnapShotStoragePool,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateSet ('NetworkRaid0None','NetworkRaid5SingleParity','NetworkRaid10Mirror2Way','NetworkRaid10Mirror3Way','NetworkRaid10Mirror4Way','NetworkRaid6DualParity')]
        [String]$DataProtectionLevel,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [bool]$PermitAdaptiveOptimization,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [bool]$Shared,

        [Parameter (Mandatory = $false, ParameterSetName = "default", ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        #Get Source Volume resource
        Switch ($InputObject.GetType().Name) 
        {

            "String" 
            { 
                 
                #Parameter is correct URI
                if ($InputObject.StartsWith($StorageVolumesUri))
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage Volume URI provided by caller: $InputObject"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting volume resource object" 

                    Try
                    {

                        $_InputObject = Send-HPOVRequest $InputObject -hostname $ApplianceConnection

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                            
                }

                #Parameter is incorrect URI value
                elseif ($InputObject.StartsWith("/rest")) 
                {

                    #Invalid Parameter value, generate terminating error.
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidArgumentValue InvalidArgument 'InputObject' -Message "Invalid Storage Volume Parameter value: $($InputObject | out-string). Please correct and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                #Parameter is Storage Pool name
                else 
                {
                                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage Volume Name provided by caller."
                                
                    Try
                    {

                        $_InputObject = Get-HPOVStorageVolume $InputObject -ApplianceConnection $ApplianceConnection -ErrorAction Stop

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }
                
            }

            "PSCustomObject" 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Storage Volume Object provided by caller."

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($InputObject | FL * | Out-String)"

                #Validate the object
                if ('storage-volumes' -ne $InputObject.category)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStoragePoolCategory InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "Invalid Storage Volume Parameter value. Expected Resource Category 'storage-volumes', received '$($InputObject.category)'."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }    

                $_InputObject = $InputObject.PSObject.Copy()
                
            }

        }

        "[{0}] ORIGINAL Storage Volume object properties: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | out-string) | Write-Verbose

        #Get the Storage Pool object to identify the family
        Try
        {

            $_AssociatedStoragePool = Send-HPOVRequest -Uri $InputObject.storagePoolUri -Hostname $InputObject.ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        #Get the SVT associated with the Volume
        if ($InputObject.volumeTemplateUri)
        {

            Try
            {

                $_SVT = Send-HPOVRequest -Uri $InputObject.volumeTemplateUri -Hostname $InputObject.ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }    

            "[{0}] Volume is associated with Volume Template: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_SVT.name | Write-Verbose

        }            

        #Volume Object updates
        switch ($PSboundParameters.keys) 
        {

            'Name'
            { 
                
                $_InputObject.name = $Name 
            
            }

            'Description'
            { 
                
                $_InputObject.description = $Description 
            
            }

            'Capacity' 
            { 

                if (-not $_SVT.properties.size.meta.locked)
                {

                    [int64]$_Capacity = $Capacity * 1GB

                    if ([int64]$_Capacity -gt [int64]$InputObject.provisionedCapacity) 
                    { 
                        
                        $_InputObject.provisionedCapacity = $_Capacity 
                    
                    }

                    #Generate Terminating Error
                    else 
                    { 
                    
                        $ExceptionMessage = "Invalid 'capacity' Storage Volume Parameter value. The value '{0}' is less than the original volume size '{1}'. Volume capacity cannot be reduced, only increased." -f [int64]$capacity, [int64]$InputObject.provisionedCapacity
                        $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStorageVolumeCapacityValue InvalidArgument 'Capacity' -TargetType 'Int' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                    }

                }
            
                else
                {

                    $ExceptionMessage = "The associated Storage Volume Template does not allow modifying the Storage Volumes capacity."
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException UnableToModifyCapacity PermissionDenied 'Capacity' -TargetType 'Int' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }                

            }

            'SnapShotStoragePool'
            {

                if (-not $_SVT.properties.snapshotPool.meta.locked -and $_AssociatedStoragePool.family -ne 'StoreVirtual')
                {

                    Try
                    {

                        $_SnapShotStoragePool = GetStoragePool -StoragePool $SnapShotStoragePool -ApplianceConnection $SnapShotStoragePool.ApplianceConnection
                        
                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                    $_InputObject.deviceSpecificAttributes.snapshotPoolUri = $_SnapShotStoragePool.uri

                }
            
                elseif ($_SVT.properties.snapshotPool.meta.locked)
                {

                    $ExceptionMessage = "The associated Storage Volume Template does not allow modifying the Snapshot Storage Pool resource."
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException UnableToModifySnapshotStoragePool PermissionDenied 'SnapShotStoragePool' -TargetType $SnapShotStoragePool.GetType().Name -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                elseif ($_AssociatedStoragePool.family -eq 'StoreVirtual')
                {

                    $ExceptionMessage = "The associated Storage System family is a StoreVirtual system. Snapshot Storage Pool assignment is not supported."
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException UnsupportedStorageSystemFamily InvalidOperation 'SnapShotStoragePool' -TargetType $SnapShotStoragePool.GetType().Name -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            'Shared'
            { 
                
                if (-not $_SVT.properties.isShareable.meta.locked)
                {

                    $_InputObject.shareable = [Bool]$Shared 

                }
            
                else
                {

                    $ExceptionMessage = "The associated Storage Volume Template does not allow modifying the shareability of the Storage Volume resource."
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException UnableToModifyCapacity PermissionDenied 'Shared' -TargetType $Shared.GetType().Name -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }                
            
            }

            'DataProtectionLevel'
            {

                $_InputObject.deviceSpecificProperties.dataProtectionLevel = $DataProtectionLevelEnum[$DataProtectionLevel]

            }

            'PermitAdaptiveOptimization'
            {

                $_InputObject.deviceSpecificProperties.isAdaptiveOptimizationEnabled = $PermitAdaptiveOptimization

            }
            
        }
        
        "[{0}] Updated Storage Volume object properties: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_InputObject | FL * | out-string) | Write-Verbose

        "[{0}] Sending updated storage volume to appliance." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        Try
        {

            Send-HPOVRequest -Uri $_InputObject.uri -Method PUT -Body $_InputObject -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
       
    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVStorageVolume 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess,ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('uri', 'name', 'StorageVolume')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Switch]$ExportOnly,

        [Parameter (Mandatory = $false)]
        [Switch]$Async,
    
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_TaskCollection    = New-Object System.Collections.ArrayList
        $_VolumeCollection  = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomObject])
        {

            "[{0}] Storage Volume Object provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | FL * | Out-String) | Write-Verbose

            If ($InputObject.category -eq 'storage-volumes')
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject:$($InputObject.Name)" -TargetType PSObject -Message "The Storage Volume resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_VolumeCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject:$($InputObject.Name)" -TargetType PSObject -Message "The Storage Volume resource is not an expected category type [$($StorageVolume.category)]. Allowed resource category type is 'storage-volumes'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            foreach ($_vol in $InputObject) 
            {

                #Volume passed is a URI
                if (($_vol -is [String]) -and [System.Uri]::IsWellFormedUriString($_vol,'Relative')) 
                {

                    "[{0}] Received URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_vol | Write-Verbose
                    "[{0}] Getting Volume object" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    if (($ApplianceConnection | Measure-Object).Count -gt 1)
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value when using a Storage Volume Template URI value. Please correct this and try again.'
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Try
                    {

                        $_volObject = Send-HPOVRequest -Uri $_vol -ApplianceConnection $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    [void]$_VolumeCollection.Add($_volObject)

                }

                #Volume passed is the Name
                elseif (($_vol -is [string]) -and (-not($_vol.startsWith("/rest")))) 
                {

                    "[{0}] Received Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_vol | Write-Verbose
                    "[{0}] Getting Volume object" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    ForEach ($_appliance in $ApplianceConnection)
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$_appliance' Appliance Connection [of $($ApplianceConnection.count)]"

                        Try
                        {

                            $_volObject = Get-HPOVStorageVolume -Name $_vol -ApplianceConnection $_appliance -ErrorAction Stop

                        }

                        Catch
                        {
                            
                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        $_volObject | % {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding '$($_.name)' Volume to collection."

                            [void]$_VolumeCollection.Add($_)

                        }

                    }

                }

                #Volume passed is the object
                elseif ($_vol -is [PSCustomObject] -and $_vol.category -ieq 'storage-volumes') 
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Volume Object provided: $($_vol | FL * | out-string)"

                    [void]$_VolumeCollection.Add($_vol)
                
                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "Invalid Volume Parameter: $($_vol | FL * | Out-String)"
                    $PSCmdlet.WriteError($ErrorRecord)

                }

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing {$($_VolumeCollection.count)} Volume resources to remove."

        #Process Volume Resources
        ForEach ($_volObject in $_VolumeCollection)
        {

            if ((-not($PSBoundParameters['ExportOnly'])) -and $PSCmdlet.ShouldProcess($_volObject.name,"Remove Storage Volume from appliance '$($_volObject.ApplianceConnection.Name)'")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Volume '$($_volObject.name)' and Export from appliance '$($_volObject.ApplianceConnection.Name)'."

                Try
                {
                    
                    if ($PSBoundParameters['Force'])
                    {

                        $_volObject.uri += "?force=true"

                    }

                    $_resp = Send-HPOVRequest -Uri $_volObject.Uri -Method DELETE -Hostname $_volObject.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if (-not $PSBoundParameters['Async'])
                {

                    $_resp | Wait-HPOVTaskComplete

                }

                else
                {

                    $_resp

                }

            }

            elseif ($PSBoundParameters['ExportOnly'] -and $PSCmdlet.ShouldProcess($_volObject.name,"Remove Storage Volume from appliance '$($_volObject.ApplianceConnection.Name)'")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Volume Export '$($_volObject.name)' from appliance '$($_volObject.ApplianceConnection.Name)'."

                Try
                {
                    
                    $_uri = '{0}?suppressDeviceUpdates=true' -f $_volObject.Uri

                    if ($PSBoundParameters['Force'])
                    {

                        $_uri += "&force=true"

                    }                    

                    $_resp = Send-HPOVRequest -Uri $_uri -Method DELETE -Hostname $_volObject.ApplianceConnection.Name #-addHeader @{exportOnly = [bool]$ExportOnly}

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if (-not $PSBoundParameters['Async'])
                {

                    $_resp | Wait-HPOVTaskComplete

                }

                else
                {

                    $_resp

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            

        }

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVSanManager 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('SanManager')]
        [string]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $SanManagerCollection = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($Connection in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($Connection.Name)' Appliance (of $($Appliance.Count))"

            $uri = '{0}?sort=name:asc' -f $fcSanManagersUri

            if ($Name)
            {
                
                $uri = '{0}&query=name like "{1}"' -f $uri, $Name.Replace("*","%25").Replace("&","%26")

            }

            #Send Request
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting list of SAN Managers"

            Try
            {

                $_sanManagers = Send-HPOVRequest $uri -Hostname $Connection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            #Generate Terminating Error if resource not found
            if (-not($_sanManagers.members) -and $Name) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Requested Managed SAN '$($SanManager)' not found on $($Connection.Name)."

                $ExceptionMessage = "Request SAN Manager '{0}' not found on '{1}'. Please check the name and try again." -f $Name, $Connection.Name 
                $ErrorRecord = New-ErrorRecord InvalidOperationException SanManagerResourceNotFound ObjectNotFound 'SanManager' -Message $ExceptionMessage
                    
                #Generate Terminating Error
                $PSCmdlet.WriteError($ErrorRecord)

            }
            
            elseif (-not($_sanManagers.members)) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No SAN Managers found."
                        
            }

            else 
            {

                $_sanManagers.members | % { 
                    
                    $_.PSObject.TypeNames.Insert(0,"HPOneView.Storage.SanManager") 
                
                    [void]$SanManagerCollection.Add($_)
                
                }

            }

        }

    }

    End 
    {

        Return $SanManagerCollection

    }

}

function Add-HPOVSanManager 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "BNA")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory, ParameterSetName = "BNA")]
        [ValidateSet ("Brocade","BNA","Brocade Network Advisor","HP","HPE","Cisco")]
        [string]$Type,

        [Parameter (Mandatory, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory, ParameterSetName = "BNA")]
        [ValidateNotNullOrEmpty()]
        [string]$Hostname,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory = $false, ParameterSetName = "BNA")]
        [ValidateNotNullOrEmpty()]
        [ValidateRange(1,65535)]
        [int]$Port = 0,
         
        [Parameter (Mandatory, ParameterSetName = "BNA")]
        [ValidateNotNullOrEmpty()]
        [string]$Username,

        [Parameter (Mandatory, ParameterSetName = "BNA")]
        [ValidateNotNullOrEmpty()]
        [Object]$Password,

        [Parameter (Mandatory, ParameterSetName = "HPCisco")]
        [string]$SnmpUserName,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [ValidateSet ("None","AuthOnly","AuthAndPriv")]
        [ValidateNotNullOrEmpty()]
        [string]$SnmpAuthLevel = "None",

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [ValidateSet ("sha","md5")]    
        [ValidateNotNullOrEmpty()]
        [string]$SnmpAuthProtocol,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [ValidateNotNullOrEmpty()]
        [Object]$SnmpAuthPassword,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [ValidateSet ("aes-128","des56","3des")]    
        [ValidateNotNullOrEmpty()]
        [string]$SnmpPrivProtocol,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [ValidateNotNullOrEmpty()]
        [Object]$SnmpPrivPassword,

        [Parameter (Mandatory = $false, ParameterSetName = "BNA")]
        [switch]$UseSsl,
        
        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory = $false, ParameterSetName = "BNA")]
        [switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory = $false, ParameterSetName = "BNA")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $TaskCollection = New-Object System.Collections.ArrayList

        if ($SnmpAuthLevel -eq "AuthOnly" -and 
            (-not $SnmpAuthProtocol -or 
            -not $SnmpAuthPassword)) 
        {

            #Generate Terminateing error
            $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException MissingRequiredParameters InvalidArgument 'Add-HPOVSanManager' -Message "The -SnmpAuthLevel Parameter was set to 'AuthOnly', but did not include both -SnmpAuthProtocol and -SnmpAuthPassword Parameters."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($SnmpAuthLevel -eq "AuthAndPriv" -and (
            -not $SnmpAuthProtocol -or 
            -not $SnmpAuthPassword -or 
            -not $SnmpPrivProtocol -or 
            -not $SnmpPrivPassword )) 
        {

            #Generate Terminateing error
            $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException MissingRequiredParameters InvalidArgument 'Add-HPOVSanManager' -Message "The -SnmpAuthLevel Parameter was set to 'AuthAndPriv', but did not include -SnmpAuthProtocol, -SnmpAuthPassword, -SnmpPrivProtocol and -SnmpPrivPassword Parameters."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
        }

        #Cisco MDS/Nexus SNMP Auth Parameter validation
        if ($type -eq 'Cisco' -and $SnmpAuthLevel -eq 'None')
        {

            $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException UnsupportedSnmpAuthLevel InvalidArgument 'SnmpAuthLevel' -Message "The -SnmpAuthLevel Parameter value $($SnmpAuthLevel) is invalid for configuring a Cisco SAN Manager. Please specify either 'AuthOnly' or 'AuthAndPriv' and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Cisco MDS/Nexus SNMP Auth Parameter validation
        if ($type -eq 'Cisco' -and $SnmpPrivProtocol -eq '3DES')
        {

            $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException UnsupportedSnmpPrivProtocol InvalidArgument 'SnmpPrivProtocol' -Message "The -SnmpPrivProtocol Parameter value $($SnmpPrivProtocol) is invalid for configuring a Cisco SAN Manager. Please specify either 'des56' or 'aes-128' and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($Password -is [System.Security.SecureString])
        {

            $Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

        if ($SnmpPrivPassword -is [SecureString])
        {

            $SnmpPrivPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SnmpPrivPassword))

        }

        if ($SnmpAuthPassword -is [SecureString])
        {

            $SnmpAuthPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SnmpAuthPassword))

        }

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_appliance.Name) (of $($ApplianceConnection.Count))"

            if ($Type -eq 'HP') { $Type = 'HPE' }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SAN Manager Type requested: $Type"

            #Basic SAN Manager Object
            $_sanmanager = NewObject -SanManager

            $_sanmanagerhostconnectinfo = NewObject -SanManagerConnectInfo
            $_sanmanagerhostconnectinfo.name = "Host"
            $_sanmanagerhostconnectinfo.Value = $Hostname
            [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)

            #Get SAN Manager Providers
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting available SAN Manager Providers"

            Try
            {

                $_SanManagerProviders = Send-HPOVRequest $FcSanManagerProvidersUri -Hostname $_appliance.Name

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            switch ($type) 
            {
                
                { @('Brocade','BNA','Brocade Network Advisor') -contains $_ } 
                { 
                    
                    if ($Port -eq 0) 
                    { 
                        
                        $Port = 5989 
                    
                    }

                    $_SanManagerProviderUri = ($_SanManagerProviders.members | ? name -eq 'Brocade San Plugin').deviceManagersUri

                    $_sanmanagerhostconnectinfo = NewObject -SanManagerConnectInfo
                    $_sanmanagerhostconnectinfo.name = "Username"
                    $_sanmanagerhostconnectinfo.Value = $Username
                    [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)

                    $_sanmanagerhostconnectinfo = NewObject -SanManagerConnectInfo
                    $_sanmanagerhostconnectinfo.name = "Password"
                    $_sanmanagerhostconnectinfo.Value = $Password
                    [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)

                    $_sanmanagerhostconnectinfo       = NewObject -SanManagerConnectInfo
                    $_sanmanagerhostconnectinfo.name  = "UseSsl"
                    $_sanmanagerhostconnectinfo.Value = [bool]$UseSsl
                    [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)
                    
                    $_sanmanagerhostconnectinfo       = NewObject -SanManagerConnectInfo
                    $_sanmanagerhostconnectinfo.name  = "Port"
                    $_sanmanagerhostconnectinfo.Value = $Port
                    [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)

                }

                { @("HPE","Cisco") -contains $_ } 
                { 

                    if ($Port -eq 0) 
                    { 
                        
                        $Port = 161 
                    
                    }

                    $_SanManagerProviderUri = ($_SanManagerProviders.members | ? name -eq ($Type + ' San Plugin')).deviceManagersUri

                    $_sanmanagerhostconnectinfo       = NewObject -SanManagerConnectInfo
                    $_sanmanagerhostconnectinfo.name  = "SnmpPort"
                    $_sanmanagerhostconnectinfo.Value = [int]$Port
                    [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)

                    $_sanmanagerhostconnectinfo       = NewObject -SanManagerConnectInfo
                    $_sanmanagerhostconnectinfo.name  = "SnmpUserName"
                    $_sanmanagerhostconnectinfo.Value = $SnmpUserName
                    [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)

                    $_sanmanagerhostconnectinfo       = NewObject -SanManagerConnectInfo
                    $_sanmanagerhostconnectinfo.name  = "SnmpAuthLevel"
                    $_sanmanagerhostconnectinfo.Value = $FcSanManagerSnmpAuthLevel[$SnmpAuthLevel].ToUpper()
                    [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)

                    if ($SnmpAuthLevel -ne "None")
                    {

                        $_sanmanagerhostconnectinfo       = NewObject -SanManagerConnectInfo
                        $_sanmanagerhostconnectinfo.name  = "SnmpAuthProtocol"
                        $_sanmanagerhostconnectinfo.Value = $SnmpAuthProtocol.ToUpper()
                        [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)

                        $_sanmanagerhostconnectinfo       = NewObject -SanManagerConnectInfo
                        $_sanmanagerhostconnectinfo.name  = "SnmpAuthString"
                        $_sanmanagerhostconnectinfo.Value = $SnmpAuthPassword
                        [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)
                        
                    }

                    if ($SnmpAuthLevel -eq "AuthAndPriv")
                    {

                        $_sanmanagerhostconnectinfo       = NewObject -SanManagerConnectInfo
                        $_sanmanagerhostconnectinfo.name  = "SnmpPrivProtocol"
                        $_sanmanagerhostconnectinfo.Value = $FcSanManagerSnmpPrivProtocol[$SnmpPrivProtocol].ToUpper()
                        [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)

                        $_sanmanagerhostconnectinfo       = NewObject -SanManagerConnectInfo
                        $_sanmanagerhostconnectinfo.name  = "SnmpPrivString"
                        $_sanmanagerhostconnectinfo.Value = $SnmpPrivPassword
                        [void]$_sanmanager.connectionInfo.Add($_sanmanagerhostconnectinfo)

                    }

                }

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SAN Manager Provider URI: $($_SanManagerProviderUri)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New SAN Manager Request: $($_sanmanager.connectionInfo | out-string)"

            try 
            {
            
                $resp = Send-HPOVRequest $_SanManagerProviderUri POST $_sanmanager -Hostname $_appliance.Name

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received async task, calling Wait-HPOVTaskComplete"

                $resp = Wait-HPOVTaskComplete $resp

            }

            catch 
            {

                if ($_.FullyQualifiedErrorId -eq 'RESOURCE_CONFLICT_ERROR')
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException SanManagerAlreadyExists ResourceExists 'Hostname' -Message "The SAN Manager $($Hostname) already exists on appliance $($_appliance.Name)." -InnerException $_.Exception

                }

                else
                {

                    $ErrorRecord = $_

                }
                
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            [void]$TaskCollection.Add($resp)

        }

    }

    End
    {

        Return $TaskCollection

    }

}

function Set-HPOVSanManager 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'BNA')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "BNA")]
        [Alias ('name','Resource')]
        [ValidateNotNullOrEmpty()]
        [object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory = $false, ParameterSetName = "BNA")]
        [ValidateNotNullOrEmpty()]
        [string]$Hostname,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory = $false, ParameterSetName = "BNA")]
        [ValidateNotNullOrEmpty()]
        [ValidateRange(1,65535)]
        [int]$Port = 0,
         
        [Parameter (Mandatory, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory, ParameterSetName = "BNA")]
        [ValidateNotNullOrEmpty()]
        [string]$Username,

        [Parameter (Mandatory, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory, ParameterSetName = "BNA")]
        [ValidateNotNullOrEmpty()]
        [Object]$Password,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [string]$SnmpUserName,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [ValidateSet ("None","AuthOnly","AuthAndPriv")]
        [ValidateNotNullOrEmpty()]
        [string]$SnmpAuthLevel = "None",

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [ValidateSet ("sha","md5")]    
        [ValidateNotNullOrEmpty()]
        [string]$SnmpAuthProtocol,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [ValidateNotNullOrEmpty()]
        [Object]$SnmpAuthPassword,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [ValidateSet ("aes-128","des56","3des")]    
        [ValidateNotNullOrEmpty()]
        [string]$SnmpPrivProtocol,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [ValidateNotNullOrEmpty()]
        [Object]$SnmpPrivPassword,

        [Parameter (Mandatory = $false, ParameterSetName = "BNA")]
        [switch]$EnableSsl,

        [Parameter (Mandatory = $false, ParameterSetName = "BNA")]
        [switch]$DisableSsl,

        [Parameter (Mandatory = $false, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory = $false, ParameterSetName = "BNA")]
        [switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "HPCisco")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "BNA")]
        [ValidateNotNullorEmpty()]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_ResourceUpdateStatus = New-Object System.Collections.ArrayList

    }

    Process
    {

        switch ($InputObject.GetType().Name)
        {

            'PSCustomObject'
            {

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Object received: {0}" -f ($InputObject | Out-String) | Write-Verbose

                #Generate error if wrong resource type
                if ($InputObject.category -ne 'fc-device-managers')
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException InvalidSanManagerResource InvalidArgument 'InputObject' -TargetType 'PSObject' -Message ("The provided Resource object is not a SAN Manager resource. Expected resource category 'fc-device-managers'. Received reource category {0}. Please check the value and try again." -f $InputObject.category)

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                #Generate error if wrong resource type
                if (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException InvalidSanManagerResource InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided Resource object is missing the required ApplianceConnection property. Please check the value and try again."

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            'String'
            {

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting SAN Manager by resource Name: {0}" -f $InputObject | Write-Verbose

                Try
                {

                    $InputObject = Get-HPOVSanManager $InputObject -ApplianceConnection $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                

            }

        }

        $_UpdatedSanManager = [PSCustomObject]@{
            connectionInfo = New-Object System.Collections.ArrayList
        }

        switch ($PSBoundParameters.keys)
        {

            'Hostname'
            {

                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "Host"; value = $Hostname})

            }

            'Port'
            {
            
                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "Port"; value = $Port})
                    
            }

            'Username'
            {
            
                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "Username"; value = $Username})
            
            }

            'Password'
            {

                if ($Password -is [SecureString])
                {

                    $Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

                }

                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "Password"; value = $Password})

            }

            'SnmpUserName'
            {

                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "SnmpUserName"; value = $SnmpUserName})

            }

            'SnmpAuthLevel'
            {

                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "SnmpAuthLevel"; value = $SnmpAuthLevel})

            }
            
            'SnmpAuthProtocol'
            {

                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "SnmpAuthProtocol"; value = $SnmpAuthProtocol})

            }
            
            'SnmpAuthPassword'
            {

                if ($SnmpAuthPassword -is [SecureString])
                {

                    $SnmpAuthPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SnmpAuthPassword))

                }

                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "SnmpAuthPassword"; value = $SnmpAuthPassword})

            }
            
            'SnmpPrivProtocol'
            {

                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "SnmpPrivProtocol"; value = $SnmpPrivProtocol})

            }
            
            'SnmpPrivPassword'
            {

                if ($SnmpPrivPassword -is [SecureString])
                {

                    $SnmpPrivPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SnmpPrivPassword))

                }

                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "SnmpPrivPassword"; value = $SnmpPrivPassword})

            }
            
            'DisableSsl'
            {

                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "UseSsl"; value = $false})

            }
            
            'EnableSsl'
            {

                [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "UseSsl"; value = $true})

            }

        }

        #Add missing ConnectionInfo properties to complete request
        if (-not $PSBoundParameters['Hostname'])
        {

            [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "Host"; value = ($InputObject.connectionInfo | ? Name -eq Host).value})

        }

        if (-not $PSBoundParameters['Port'])
        {

            [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "Port"; value = ($InputObject.connectionInfo | ? Name -eq Port).value})
            
        }

        if (-not $PSBoundParameters['EnableSsl'] -and -not $PSBoundParameters['DisableSsl'] -and $InputObject.providerDisplayName -eq 'Brocade Network Advisor')
        {

            [void]$_UpdatedSanManager.connectionInfo.Add(@{name = "UseSsl"; value = ($InputObject.connectionInfo | ? Name -eq UseSsl).value})
            
        }

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updated SAN Manager: {0}" -f ($_UpdatedSanManager | out-string) | Write-Verbose 

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

        Try
        {

            $resp = Send-HPOVRequest $InputObject.uri PUT $_UpdatedSanManager -ApplianceConnection $InputObject.ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not $PSBoundParameters['Async'])
        {

            $resp = $resp | Wait-HPOVTaskComplete 

        }
     
        [void]$_ResourceUpdateStatus.Add($resp)
           
    }
        
    End
    {
        return $_ResourceUpdateStatus

    }

}

function Update-HPOVSanManager 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Name','SANManager')]
        [Object]$InputObject,
        
        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection -is [HPOneView.Appliance.Connection]) -and (-not($ApplianceConnection -is [System.String])) -and (-not($PipelineInput)))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException InvalidApplianceConnectionDataType InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter is not type [HPOneView.Appliance.Connection] or [System.String]. Please correct this value and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif (($ApplianceConnection | Measure-Object).Count -gt 1 -and (-not($PipelineInput)))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value. Please correct this and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif (-not($PipelineInput))
        {

            Try 
            {
    
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -TargetType $ApplianceConnection.GetType().Name -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_.Exception)

            }

        }

        $_SanManagerRefreshCollection = New-OBject System.Collections.ArrayList
    
    }

    Process 
    {

        $request = [PsCustomObject]@{refreshState = "RefreshPending"}

        #Validate input object type
        #Checking if the input is System.String and is NOT a URI
        if ($InputObject -is [string]) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SANManager Name: $($SANManager)"

            Try
            {

                $SANManager = Get-HPOVSanManager $SANManager -Hostname $ApplianceConnection

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Checking if the input is PSCustomObject, and the category type is server-profiles, which could be passed via pipeline input
        elseif (($InputObject -is [System.Management.Automation.PSCustomObject]) -and ($InputObject.category -ieq "fc-device-managers")) 
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] SANManager is an object: {0}" -f $InputObject.name | Write-Verbose 
        
        }

        else 
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message "The Parameter 'InputObject' value is invalid. Please validate the 'InputObject' Parameter value you passed and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($InputObject.isInternal)
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] '{0}' SAN Manager is internal. Skipping." -f $InputObject.name | Write-Verbose 

        }

        else
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Refreshing SAN Manager resource: {0}" -f $InputObject.name | Write-Verbose 
        
            Try
            {

                $_resp = Send-HPOVRequest $InputObject.uri PUT $request -Hostname $ApplianceConnection.Name
        
            }
        
            Catch
            {
        
                $PSCmdlet.ThrowTerminatingError($_)
        
            }

            $_resp

        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVSanManager 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess,ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Name','SanManager')]
        [object]$InputObject,
    
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSboundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection       = New-Object System.Collections.ArrayList
        $_SanManagerCollection = New-Object System.Collections.ArrayList
   
    }

    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomObject]) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] San Manager Object provided: $($InputObject | FL * | Out-String)"

            If ('fc-device-managers' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException InvalidArgumentValue InvalidArgument "SanManager:$($InputObject.Name)" -TargetType PSObject -Message "The SanManager object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_SanManagerCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException InvalidArgumentValue InvalidArgument "SanManager:$($InputObject.Name)" -TargetType PSObject -Message "The SanManager object resource is not an expected category type [$($InputObject.category)]. The allowed resource category type is 'fc-device-managers'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            #Need to handle Name versus URI
            ForEach ($_appliance in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count))"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing SanManager Name $($InputObject)"

                Try
                {

                    $_SanManager = Get-HPOVSanManager $InputObject -ApplianceConnection $_appliance

                    $_SanManager | % {

                        [void]$_SanManagerCollection.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }        

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Begin resource removal Process."

        foreach ($_sm in $_SanManagerCollection) 
        {

            if ($PSCmdlet.ShouldProcess($_sm.name,"Remove SAN Manager from appliance '$($_sm.ApplianceConnection.Name)'"))
            {   
             
                
                Try
                {
                    
                    $_task = Send-HPOVRequest $_sm.uri DELETE -Hostname $_sm.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_task)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Get-HPOVManagedSan 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Fabric')]
        [string]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $ManagedSansCollection = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            if ($PSBoundParameters['Label'])
            {

                $_uri = '{0}?category:fc-sans&query=labels:{1}' -f $IndexUri, $Label

                Try
                {

                    $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                    #Loop through all found members and get full SVT object
                    ForEach ($_memeber in $_IndexMembers.members)
                    {

                        Try
                        {

                            $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                        

                        $_memeber.PSObject.TypeNames.Insert(0,"HPOneView.Storage.ManagedSan")

                        $_memeber

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                $uri = $fcManagedSansUri + '?sort=name:asc'

                if ($Name)
                {

                    $Name = $Name -replace ("[*]","%25") -replace ("[&]","%26")

                    $uri += "&query=lower(name) like '{0}'" -f $Name.ToLower()

                }
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting list of Managed SANs"
                
                Try
                {

                    $_managedSans = Send-HPOVRequest $uri -Hostname $_appliance.Name

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($_managedSans.count -eq 0 -and $Name) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Woops! Requested Managed SAN '$($_managedSans)' not found."
                        
                    $ErrorRecord = New-ErrorRecord InvalidOperationException ManagedSanResourceNotFound ObjectNotFound 'Name' -Message "Request Managed SAN '$($Name)' not found on appliance $($_appliance.Name). Please check the name and try again."
                        
                    #Generate Terminating Error
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                else
                {

                    $_managedSans.members | % { 
                        
                        $_.PSObject.TypeNames.Insert(0,"HPOneView.Storage.ManagedSan")
                    
                        [void]$ManagedSansCollection.Add($_)

                    }

                }

            }

        }

    }

    End 
    {

        return $ManagedSansCollection 
    
    }

}

function Set-HPOVManagedSan 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Enable")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Enable")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Disable")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "DisableAlias")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Fabric','Name','ManagedSan','Resource')]
        [object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "Enable")]
        [Parameter (Mandatory = $false, ParameterSetName = "DisableAlias")]
        [Alias ('ZoningEnable','Enable')]
        [switch]$EnableAutomatedZoning,

        [Parameter (Mandatory = $false, ParameterSetName = "Disable")]
        [Alias ('ZoningDisable','Disable')]
        [switch]$DisableAutomatedZoning,

        [Parameter (Mandatory = $false, ParameterSetName = "Enable")]
        [Parameter (Mandatory = $false, ParameterSetName = "Disable")]
        [Parameter (Mandatory = $false, ParameterSetName = "DisableAlias")]
        [ValidateSet ('NoZoning', 'SingleInitiatorAllTargets','SingleInitiatorSingleStorageSystem','SingleInitiatorSingleTarget')]
        [ValidateNotNullOrEmpty()]
        [string]$ZoningPolicy = 'SingleInitiatorAllTargets',
      
        [Parameter (Mandatory = $false, ParameterSetName = "Enable")]
        [switch]$EnableAliasing,

        [Parameter (Mandatory = $false, ParameterSetName = "DisableAlias")]
        [switch]$DisableAliasing,

        [Parameter (Mandatory = $false, ParameterSetName = "Enable")]
        [ValidateNotNullOrEmpty()]
        [string]$InitiatorNameFormat,

        [Parameter (Mandatory = $false, ParameterSetName = "Enable")]
        [ValidateNotNullOrEmpty()]
        [string]$TargetGroupNameFormat,

        [Parameter (Mandatory = $false, ParameterSetName = "Enable")]
        [ValidateNotNullOrEmpty()]
        [string]$TargetNameFormat,

        [Parameter (Mandatory = $false, ParameterSetName = "Enable")]
        [ValidateNotNullOrEmpty()]
        [string]$ZoneNameFormat,

        [Parameter (Mandatory = $false, ParameterSetName = "Enable")]
        [bool]$UpdateZoneNames,

        [Parameter (Mandatory = $false, ParameterSetName = "Enable")]
        [bool]$UpdateInitiatorAliases,
        
        [Parameter (Mandatory = $false, ParameterSetName = "Enable")]
        [bool]$UpdateTargetAliases,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Enable")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Disable")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "DisableAlias")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Resource']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_ResourceUpdateStatus = New-Object System.Collections.ArrayList

        if ($PSBoundParameters.Keys -Contains 'EnableAutomatedZoning')
        {

            Write-Warning "the -EnableAutomatedZoning parameter is being deprecated. Please update your scripts to use the -ZoningPolicy parameter."

        }

        if ($PSBoundParameters.Keys -Contains 'DisableAutomatedZoning')
        {

            Write-Warning "the -DisableAutomatedZoning parameter is being deprecated. Please update your scripts to use the -ZoningPolicy parameter."

        }

    }

    Process 
    {

        switch ($InputObject.GetType().Name)
        {

            'PSCustomObject'
            {

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Object received: {0}" -f ($InputObject | Out-String) | Write-Verbose

                #Generate error if wrong resource type
                if ($InputObject.category -ne 'fc-sans')
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.ManagedSanResourceException InvalidManagedSanResource InvalidArgument 'InputObject' -TargetType 'PSObject' -Message ("The provided Resource object is not a Managed SAN resource. Expected resource category 'fc-sans'. Received reource category {0}. Please check the value and try again." -f $InputObject.category)

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                #Generate error if wrong resource type
                if (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException InvalidSanManagerResource InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided Resource object is missing the required ApplianceConnection property. Please check the value and try again."

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }
                
                if ($InputObject.isInternal)
                {

                    $ExceptionMessage = "The provided Resource object '{0}' is an Internal SAN Manager and unsupported with this Cmdlet. Please check the value and try again." -f $InputObject.name
                    $ErrorRecord = New-ErrorRecord HPOneView.SanManagerResourceException InvalidSanManagerResource InvalidArgument 'InputObject' -TargetType 'PSObject' -Message $ExceptionMessage

                    $PSCmdlet.WriteError($ErrorRecord)

                }

            }

            'String'
            {

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Managed SAN by resource Name: {0}" -f $InputObject | Write-Verbose

                Try
                {

                    $InputObject = Get-HPOVManagedSan $InputObject -ApplianceConnection $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        #Needed in order to support ErrorAction
        if (-not $ErrorRecord)
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '{0}'" -f $InputObject.name | Write-Verbose 

            #Disable zoning
            if ($DisableAutomatedZoning.IsPresent -or $ZoningPolicy -eq 'NoZoning')
            { 
                    
                $InputObject.sanPolicy.zoningPolicy = "NoZoning"

                #Need to disable Aliasing Support as well with the request
                $InputObject.sanPolicy.enableAliasing = $false
                        
            }

            else
            {

                $InputObject.sanPolicy.zoningPolicy = $ZoningPolicy

                if ($EnableAliasing.IsPresent -or $ZoningPolicy -ne 'NoZoning') 
                { 

                    $InputObject.sanPolicy.enableAliasing = $True

                    switch ($PSBoundParameters.Keys)
                    {
                        
                        'InitiatorNameFormat'    { $InputObject.sanPolicy.initiatorNameFormat    = $InitiatorNameFormat }
                        'TargetGroupNameFormat'  { $InputObject.sanPolicy.targetGroupNameFormat  = $TargetGroupNameFormat }
                        'TargetNameFormat'       { $InputObject.sanPolicy.targetNameFormat       = $TargetNameFormat }
                        'ZoneNameFormat'         { $InputObject.sanPolicy.zoneNameFormat         = $ZoneNameFormat }
                        'UpdateZoneNames'        { $InputObject.sanPolicy.renameZones            = $UpdateZoneNames }
                        'UpdateInitiatorAliases' { $InputObject.sanPolicy.renameInitiatorAliases = $UpdateInitiatorAliases }
                        'UpdateTargetAliases'    { $InputObject.sanPolicy.renameTargetAliases    = $UpdateTargetAliases }

                    }                
                        
                }
                
                elseif ($DisableAliasing.IsPresent -or $ZoningPolicy -eq 'NoZoning') 
                { 
                    
                    $InputObject.sanPolicy.enableAliasing = $false 
                
                }

            }

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updated Managed SAN Object: {0}" -f ($InputObject | out-string) | Write-Verbose 

            Try
            {

                $_Resp = Send-HPOVRequest $InputObject.uri PUT $InputObject -Hostname $InputObject.ApplianceConnection.Name

                $_Resp | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.ManagedSan') }

                [void]$_ResourceUpdateStatus.Add($_Resp)

            }

            Catch
            {

                $_ResourceUpdateStatus

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    End 
    {
        
        Return $_ResourceUpdateStatus

    }

}

function Show-HPOVSanEndpoint
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory = $False, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$SAN,

        [Parameter (Mandatory, ParameterSetName = 'WWN')]
        [ValidateNotNullOrEmpty()]
        [String]$WWN,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'WWN')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        
        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_SANEndpointCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        $uri = $SanEndpoints

        if ($SAN)
        {

            switch ($SAN.GetType().Name)
            {


                'String'
                {

                    $uri += '?query=sanName eq "{0}"' -f $SAN

                }

                'PSCustomObject'
                {

                    $uri += '?query=sanName eq "{0}"' -f $SAN.name

                }

            }

            Try
            {

                $_resp = Send-HPOVRequest $uri -Hostname $ApplianceConnection

                $_resp.members | % {

                    $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.San.Endpoint')

                    [void]$_SANEndpointCol.Add($_)

                }

            }

            Catch
            {

              $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        else
        {

            if ($WWN)
            {

                $uri += '?query=wwn eq "{0}"' -f $WWN

            }

            if ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                ForEach ($_appliance in $ApplianceConnection)
                {


                    Try
                    {

                        $_resp = Send-HPOVRequest $uri -Hostname $_appliance

                        $_resp.members | % {

                            $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.San.Endpoint')

                            [void]$_SANEndpointCol.Add($_)

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                }

            }

            else
            {

                Try
                {

                    $_resp = Send-HPOVRequest $uri -Hostname $ApplianceConnection

                    $_resp.members | % {

                        $_.PSObject.TypeNames.Insert(0,'HPOneView.Storage.San.Endpoint')

                        [void]$_SANEndpointCol.Add($_)

                    }

                }

                Catch
                {

                  $PSCmdlet.ThrowTerminatingError($_)

                }

            }
            
        }

    }

    End
    {

        Return $_SANEndpointCol

    }

}

function Get-HPOVSanZone
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName='Default')]

    Param 
    (

        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Object]$ManagedSan,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_FCZoneCollection = New-Object System.Collections.ArrayList

    }

    Process
    {

        if ($PSBoundParameters['ManagedSan'])
        {

            Switch ($ManagedSan.GetType().Name)
            {

                'PSCustomObject'
                {

                    if ($ManagedSan.category -ne 'fc-sans')
                    {

                        $ExceptionMessage = "The ManagedSan resource '{0}' is not an allowed resource category." -f $ManagedSan.category
                        $ErrorRecord = New-ErrorRecord HPOneView.ManagedSanResourceException InvalidManagedSanObject InvalidArgument 'ManagedSan' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)   

                    }

                    else
                    {

                        Try
                        {

                            $_resp = Send-HPOVRequest $ManagedSan.zonesUri -Hostname $ManagedSan.ApplianceConnection.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        ForEach ($_MemberZone in $_resp.members)
                        {

                            $_ZoneObject = NewObject -FCZone

                            $_ZoneObject.PSObject.TypeNames.Insert(0,'HPOneView.Storage.ManagedSan.Zone')

                            $_ZoneObject.Name                = $_MemberZone.name
                            $_ZoneObject.State               = $_MemberZone.state
                            $_ZoneObject.Status              = $_MemberZone.status
                            $_ZoneObject.ManagedSan          = $_MemberZone.sanName
                            $_ZoneObject.Created             = $_MemberZone.created
                            $_ZoneObject.Modified            = $_MemberZone.modified
                            $_ZoneObject.ApplianceConnection = $ManagedSan.ApplianceConnection

                            Try
                            {

                                $_Aliases = Send-HPOVRequest $_MemberZone.AliasesUri -Hostname $ManagedSan.ApplianceConnection.Name

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                            ForEach ($_AliasMember in $_Aliases.members)
                            {

                                $_Alias = NewObject -FCAlias

                                $_Alias.PSObject.TypeNames.Insert(0,'HPOneView.Storage.ManagedSan.Zone.Alias')

                                $_Alias.Name = $_AliasMember.name
                                $_Alias.WWN = $_AliasMember.members

                                [void]$_ZoneObject.Members.Add($_Alias)

                            }

                            [void]$_FCZoneCollection.Add($_ZoneObject)

                        }

                    }

                }
                
                default
                {

                    $ExceptionMessage = "The ManagedSan resource data type '{0}' is not an PSCustomObject." -f $ManagedSan.GetType().FullName
                    $ErrorRecord = New-ErrorRecord HPOneView.ManagedSanResourceException InvalidManagedSanValue InvalidArgument 'ManagedSan' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)   

                }

            }            

        }

        else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Try
                {

                    $_resp = Send-HPOVRequest $FcZonesUri -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                ForEach ($_MemberZone in $_resp.members)
                {

                    $_ZoneObject = NewObject -FCZone

                    $_ZoneObject.PSObject.TypeNames.Insert(0,'HPOneView.Storage.ManagedSan.Zone')

                    $_ZoneObject.Name                = $_MemberZone.name
                    $_ZoneObject.State               = $_MemberZone.state
                    $_ZoneObject.Status              = $_MemberZone.status
                    $_ZoneObject.ManagedSan          = $_MemberZone.sanName
                    $_ZoneObject.Created             = $_MemberZone.created
                    $_ZoneObject.Modified            = $_MemberZone.modified
                    $_ZoneObject.ApplianceConnection = [PSCustomObject]@{Name = $_appliance.Name; ID = $_appliance.ID}

                    Try
                    {

                        $_Aliases = Send-HPOVRequest $_MemberZone.AliasesUri -Hostname $_appliance

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    ForEach ($_AliasMember in $_Aliases.members)
                    {

                        $_Alias = NewObject -FCAlias

                        $_Alias.PSObject.TypeNames.Insert(0,'HPOneView.Storage.ManagedSan.Zone.Alias')

                        $_Alias.Name = $_AliasMember.name
                        $_Alias.WWN = $_AliasMember.members

                        [void]$_ZoneObject.Members.Add($_Alias)

                    }

                    [void]$_FCZoneCollection.Add($_ZoneObject)

                }

            }

        }

    }

    End
    {

        Return $_FCZoneCollection

    }

}

function Get-HPOVDriveEnclosure
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName='Default')]

    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_DriveEnclosureCollection = New-Object System.Collections.ArrayList
            
    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($_appliance.ApplianceType -ne 'Composer')
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. This Cmdlet is only supported with Synergy Composers.' -f $_appliance.Name)
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                if ($PSBoundParameters['Label'])
                {

                    $_uri = '{0}?category:drive-enclosures&query=labels:{1}' -f $IndexUri, $Label

                    Try
                    {

                        $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                        #Loop through all found members and get full SVT object
                        ForEach ($_memeber in $_IndexMembers.members)
                        {

                            Try
                            {

                                $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }                        

                            $_memeber.PSObject.TypeNames.Insert(0,"HPOneView.Storage.DriveEnclosure")

                            $_memeber.driveBays | % { 
                                
                                $_.PSObject.TypeNames.Insert(0,"HPOneView.Storage.DriveEnclosure.DriveBay") 

                                if ($_.drive)
                                {

                                    $_.drive.PSObject.TypeNames.Insert(0,'HPOneView.Storage.DriveEnclosure.DriveBay.Drive')

                                }
                                
                            }

                            $_memeber.ioAdapters | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Storage.DriveEnclosure.IoAdapter") }

                            $_memeber

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                else
                {

                    $uri = $DriveEnclosureUri

                    if ($PSBoundParameters['Name'])
                    {

                        $_operator = '='

                        if ($Name -match '\*' -or $Name -match '\?')
                        {

                            $_operator = 'matches'

                        }

                        $uri += "?filter=name {0} '{1}'&sort:asc" -f $_operator, $name.Replace('*','%25')

                    }

                    Write-Verbose ("[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing {0} Connection" -f $_appliance.Name)

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

                    Try
                    {

                        $_DriveEnclosures = Send-HPOVRequest -uri $uri -Hostname $_appliance.Name

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    if ($_DriveEnclosures.count -eq 0 -and (-not ($Name))) 
                    {  
                        
                        Write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No unmanaged devices found." 
                    
                    }

                    elseif ($_DriveEnclosures.count -eq 0 -and $PSBoundParameters['Name']) 
                    { 

                        Write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($_DriveEnclosures | Out-String)"

                        $ExceptionMessage = "The '{0}' Drive Enclosure resource was not found on '{1}' Appliance. Please check the name and try again." -f $Name, $_appliance.Name
                        $ErrorRecord = New-ErrorRecord HPOneview.UnmanagedDeviceResourceException UnmangedDeviceResouceNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                        $PSCmdlet.WriteError($ErrorRecord)
                            
                    }
                    
                    else
                    {

                        $_DriveEnclosures.members | % {

                            $_.PSObject.TypeNames.Insert(0,"HPOneView.Storage.DriveEnclosure")

                            $_.driveBays | % { 
                                
                                $_.PSObject.TypeNames.Insert(0,"HPOneView.Storage.DriveEnclosure.DriveBay") 

                                if ($_.drive)
                                {

                                    $_.drive.PSObject.TypeNames.Insert(0,'HPOneView.Storage.DriveEnclosure.DriveBay.Drive')

                                }
                                
                            }

                            $_.ioAdapters | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Storage.DriveEnclosure.IoAdapter") }

                            $_

                        }

                    }

                }

            }

        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVAvailableDriveType
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName='Default')]

    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PipelineInput = $true
            
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not $ApplianceConnection)
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
            
    }

    Process 
    {

        if (($ConnectedSessions | ? Name -eq $InputObject.ApplianceConnection.Name).ApplianceType -ne 'Composer')
        {

            $ExceptionMessage = 'The ApplianceConnection {0} is not a Synergy Composer. This Cmdlet is only supported with Synergy Composers.' -f $ApplianceConnection.Name
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
            $PSCmdlet.WriteError($ErrorRecord)

        }

        else
        {

            switch ($InputObject.category)
            {

                'sas-logical-interconnects'
                {

                    $_SasLogicalInterconnect = $InputObject.PSObject.Copy()
                    $InputObject = New-Object System.Collections.ArrayList

                    "[{0}] SAS Logical Interconnect provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_SasLogicalInterconnect.name | Write-Verbose
                    "[{0}] Getting all associated drive enclosures: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_SasLogicalInterconnect.driveEnclosureUris.count | Write-Verbose                

                    ForEach ($_DriveEnclosureUri in $_SasLogicalInterconnect.driveEnclosureUris)
                    {

                        Try
                        {

                            $_DriveEnclosure = Send-HPOVRequest -uri $_DriveEnclosureUri -Hostname $ApplianceConnection

                            $_DriveEnclosure | Add-Member -NotePropertyName sasLogicalInterconnectName -NotePropertyValue $_SasLogicalInterconnect.name

                            [void]$InputObject.Add($_DriveEnclosure)

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                }

                'drive-enclosures'
                {

                    "[{0}] Drive Enclosure provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                    $_uri = "{0}?category=sas-logical-interconnects&start=0&count=-1&name=DRIVE_ENCLOSURE_TO_SAS_LOGICAL_INTERCONNECT&parentUri={1}" -f $IndexAssociatedResourcesUri, $InputObject.uri

                    Try
                    {

                        $_AssociatedLogicalInterconnect = Send-HPOVRequest -uri $_uri -Hostname $ApplianceConnection

                        $InputObject | Add-Member -NotePropertyName sasLogicalInterconnectName -NotePropertyValue $_AssociatedLogicalInterconnect.members[0].childResource.name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                default
                {

                    #Generate error due to invalid object
                    if ($Inputobject -is [PSCustomObject])
                    {

                        $_InputObjectName = $InputObject.name

                    }

                    else
                    {

                        $_InputObjectName = $InputObject

                    }

                    $ExceptionMessage = "The specified '{0}' InputObject parameter value is not supported type. Only SAS Logical Interconnect or Disk Drive resources are allowed." -f $_InputObjectName
                    $ErrorRecord = New-ErrorRecord HPOneView.InputObjectResourceException InvalidInputObjectResource InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            ForEach ($_DriveEnclosure in $InputObject)
            {

                "[{0}] Processing drive enclosure: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_DriveEnclosure.name | Write-Verbose

                $_uri = "{0}?category=drives&start=0&count=-1&userQuery='{1} AND available=yes'" -f $IndexUri, $_DriveEnclosure.uri

                Try
                {

                    $_AvailableDrives = Send-HPOVRequest -uri $_uri -Hostname $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                $_TempDriveCollection = New-Object System.Collections.ArrayList

                ForEach ($_MemberDrive in $_AvailableDrives.members)
                {

                    $_AvailableDrive = $null

                    '[{0}] Collecting: {1} Type {2} Capacity' -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_MemberDrive.attributes.interfaceType + $_MemberDrive.attributes.mediaType), $_MemberDrive.attributes.capacityInGb | Write-Verbose

                    #Filter for the number of drives based on combined interfaceType and interfaceMedia
                    [Array]$NumberOfDrives = $_AvailableDrives.members | ? { $_.attributes.interfaceType -eq $_MemberDrive.attributes.interfaceType -and $_.attributes.mediaType -eq $_MemberDrive.attributes.mediaType -and $_.attributes.capacityInGb -eq $_MemberDrive.attributes.capacityInGb }
                    
                    #Create temporary drive object to store values for compare and new object
                    $_DriveAttributes = [PSCustomObject]@{Type = ($_MemberDrive.attributes.interfaceType + $_MemberDrive.attributes.mediaType); Count = $NumberOfDrives.Count; Capacity = [Convert]::ToInt32($_MemberDrive.attributes.capacityInGb)}
                    
                    if ((-not ($_TempDriveCollection.Type | ? { $_ -contains $_DriveAttributes.Type})) -or (($_TempDriveCollection.Type | ? { $_ -contains $_DriveAttributes.Type}) -and -not ($_TempDriveCollection | ? { $_.Capacity -contains $_DriveAttributes.Capacity})))
                    {

                        '[{0}] Adding drive type {1} and capacity {2} to collection' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_DriveAttributes.Type, $_DriveAttributes.Capacity | Write-Verbose

                        $_AvailableDrive = New-Object HPOneView.Storage.AvailableDriveType($_DriveAttributes.Type, 
                                                                                           $_DriveAttributes.Capacity,
                                                                                           $_DriveAttributes.Count,
                                                                                           $_DriveEnclosure.name, 
                                                                                           $_DriveEnclosure.sasLogicalInterconnectName,                                                                                             
                                                                                           $ApplianceConnection)

                        [Void]$_TempDriveCollection.Add($_AvailableDrive)

                    }

                }

                $_TempDriveCollection | Sort Type, Capacity

            }

        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

#######################################################
# Unmanaged Devices:
#

function Get-HPOVUnmanagedDevice 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName='Default')]

    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ('report')]
        [Switch]$List,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        if ($PSBoundParameters['List'])
        {

            Write-Warning "The List Parameter has been deprecated. The CMDLET will now display object data in Format-List view."

        }

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_UnmanagedDevicesCollection = New-Object System.Collections.ArrayList

        $uri = $UnmanagedDevicesUri

        if ($PSBoundParameters['Name'])
        {

            if ($Name.Contains('*'))
            {

                $uri += "&filter=name matches '{0}'" -f $Name.Replace('*','%25')

            }

            else
            {

                $uri += "&filter=name EQ '{0}'" -f $Name

            }

        }

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($PSBoundParameters['Label'])
            {

                $_uri = '{0}?category:unmanaged-devices&query=labels:{1}' -f $IndexUri, $Label

                Try
                {

                    $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                    #Loop through all found members and get full SVT object
                    ForEach ($_memeber in $_IndexMembers.members)
                    {

                        Try
                        {

                            $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                        

                        $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.UnmanagedResource')

                        $_memeber

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

                Try
                {

                    $_UnmanagedDevices = Send-HPOVRequest $uri -Hostname $_appliance.Name

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($_UnmanagedDevices.count -eq 0 -and (-not($Name))) 
                {  
                    
                    Write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No unmanaged devices found." 
                
                }

                elseif ($_UnmanagedDevices.count -eq 0 -and $Name)
                {


                    Write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($_UnmanagedDevices | Out-String)"

                    $ExceptionMessage = "The '{0}' Unmanaged Device resource was not found on '{1}' Appliance. Please check the name and try again." -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneview.UnmanagedDeviceResourceException UnmangedDeviceResouceNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                else
                {

                    $_UnmanagedDevices.members | % {

                        $_.PSObject.TypeNames.Insert(0,"HPOneView.UnmanagedResource")

                        $_

                    }

                }

            }
            
        }            

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function New-HPOVUnmanagedDevice 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName='Default')]

    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$Model,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [int]$Height = 1,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [int]$MaxPower,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$MacAddress,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateScript({if (-not([Net.IPAddress]::TryParse($_,[ref]$null))) { Throw 'The provided IPv4Address value does not appear to be a valid IPv4 Address.' } else { $True }})]
        [string]$IPv4Address,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateScript({if (-not([Net.IPAddress]::TryParse($_,[ref]$null))) { Throw 'The provided IPv6Address value does not appear to be a valid IPv6 Address.' } else { $True }})]
        [string]$IPv6Address,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_UnmanagedDeviceCreateResults = New-Object System.Collections.ArrayList
    }

    Process 
    {
        
        $_NewDevice = NewObject -UnmanagedDevice

        [string]$_NewDevice.name        = $Name
        [string]$_NewDevice.model       = $Model
        [int]$_NewDevice.height         = $Height
        [string]$_NewDevice.mac         = $MacAddress
        [string]$_NewDevice.IPv4Address = $IPv4Address
        [string]$_NewDevice.IPv6Address = $IPv6Address
        [int]$_NewDevice.maxPwrConsumed = $MaxPower

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Unmanaged Device: $($newDevice)"

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

        Try
        {

            $_resp = Send-HPOVRequest $unmanagedDevicesUri POST $_NewDevice -Hostname $ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $_resp | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.UnmanagedResource") }

        [void]$_UnmanagedDeviceCreateResults.Add($_resp)

    }

    End
    {

        Return $_UnmanagedDeviceCreateResults

    }

}

function Remove-HPOVUnmanagedDevice 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default",SupportsShouldProcess,ConfirmImpact = 'High')]

    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri","name")]
        [object]$UnmanagedDevice,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$force,
    
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['UnmanagedDevice'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection            = New-Object System.Collections.ArrayList
        $_UnmanagedDeviceCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User Object provided: $($Name | FL * | Out-String)"

            If ('unmanaged-devices' -contains $UnmanagedDevice.category)
            {

                If (-not($UnmanagedDevice.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.UnmanagedDeviceResourceException InvalidArgumentValue InvalidArgument "UnmanagedDevice:$($UnmanagedDevice.Name)" -TargetType PSObject -Message "The UnmanagedDevice object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_UnmanagedDeviceCollection.Add($UnmanagedDevice)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "UnmanagedDevice:$($UnmanagedDevice.Name)" -TargetType PSObject -Message "The UnmanagedDevice object resource is not an expected category type [$($UnmanagedDevice.category)]. The allowed resource category type is 'unmanaged-devices'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count))"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Unmanaged Device Name $($UnmanagedDevice)"

                Try
                {

                    $_UnmanagedDevice = Get-HPOVUnmanagedDevice $UnmanagedDevice -ApplianceConnection $_appliance

                    $_UnmanagedDevice | % {

                        [void]$_UnmanagedDeviceCollection.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_UnmanagedDeviceCollection.count) object resources to remove."

        #Process Unmanaged Device Resources
        ForEach ($_device in $_UnmanagedDeviceCollection)
        {

            if ($PSCmdlet.ShouldProcess($_device.ApplianceConnection.Name,"Remove Unmanaged Device '$($_device.name)' from appliance")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Unmanaged Device '$($_device.name)' from appliance '$($_device.ApplianceConnection.Name)'."

                Try
                {

                    $_resp = Send-HPOVRequest $_device.Uri DELETE -Hostname $_device.ApplianceConnection.Name

                    $_resp | Add-Member -NotePropertyName Name -NotePropertyValue $_device.name

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

#######################################################
# Power Delivery Devices
#

# // TODO: DEVELOP DOCUMENTATION TEST
function Get-HPOVPowerDevice 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
        $_Collection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Try
            {

                $ipdus = Send-HPOVRequest $powerDevicesUri -appliance $_appliance #($powerDevicesUri + "?filter=`"name matches '$name'`"")

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }            


                #name model deviceType
                #---- ----- ----------
                #172.18.8.11, PDU 1, L1 HP AC Module, Single Phase, Intlgnt HPIpduAcModule
                #172.18.8.11, PDU 1, L2 HP AC Module, Single Phase, Intlgnt HPIpduAcModule
                #172.18.8.11, PDU 1, L3 HP AC Module, Single Phase, Intlgnt HPIpduAcModule
                #172.18.8.13, PDU 1, L1 HP AC Module, Single Phase, Intlgnt HPIpduAcModule
                #172.18.8.13, PDU 1, L2 HP AC Module, Single Phase, Intlgnt HPIpduAcModule
                #172.18.8.13, PDU 1, L3 HP AC Module, Single Phase, Intlgnt HPIpduAcModule
                #172.18.8.14, PDU 1, L1 HP AC Module, Single Phase, Intlgnt HPIpduAcModule
                #172.18.8.11, PDU 1 HP INTELLIGENT MOD PDU 3PH 24A NA/JPN HPIpduCore
                #172.18.8.11, PDU 1, L4 LoadSegment
                #172.18.8.11, PDU 1, L5 LoadSegment
                #172.18.8.11, PDU 1, L6 Managed Ext. Bar HPIpduOutletBar
                #172.18.8.11, PDU 1, L6,Outlet1 Managed Ext. Bar Outlet HPIpduOutlet
                #172.18.8.11, PDU 1, L6,Outlet2 Managed Ext. Bar Outlet HPIpduOutlet
                #172.18.8.11, PDU 1, L6,Outlet3 Managed Ext. Bar Outlet HPIpduOutlet
                #172.18.8.11, PDU 1, L6,Outlet4 Managed Ext. Bar Outlet HPIpduOutlet
                #172.18.8.11, PDU 1, L6,Outlet5 Managed Ext. Bar Outlet HPIpduOutlet
                #172.18.8.13, PDU 1 HP INTELLIGENT MOD PDU 3PH 24A NA/JPN HPIpduCore
                #172.18.8.13, PDU 1, L4 LoadSegment
                #172.18.8.13, PDU 1, L5 LoadSegment
                #172.18.8.13, PDU 1, L6 LoadSegment
                #172.18.8.14, PDU 1 HP INTELLIGENT MOD PDU 3PH 24A NA/JPN HPIpduCore
                #172.18.8.14, PDU 1, L2 LoadSegment
                #172.18.8.14, PDU 1, L3 LoadSegment
                #172.18.8.14, PDU 1, L4 LoadSegment
                #172.18.8.14, PDU 1, L5 LoadSegment
                #172.18.8.14, PDU 1, L6 LoadSegment


            $ipdus.members | % { 
                
                switch ($_.deviceType)
                {

                    'HPIpduCore'
                    {

                        $_.psobject.typenames.Insert(0,"HPOneView.PowerDeliveryDevice")

                    }

                    'HPIpduOutlet'
                    {}

                    'LoadSegment'
                    {}

                }
                
            }    

            if ($Name) 
            { 

                $ipdus.members | ? name -eq $Name | % { [void]$_Collection.Add($_) }

            }

            else 
            { 

                $ipdus.members | % { [void]$_Collection.Add($_) }

            }

        }

    }

    End 
    {

        if (-not ($_Collection) -and $Name) 
        {

            $ErrorRecord = New-ErrorRecord HPOneView.PowerDeliveryDeviceException ResourceNotFound ObjectNotFound "Name" -Message "The specific '$name' iPDU was not found."
            $PSCmdlet.WriteError($ErrorRecord)

        }

        Write-Verbose "Done. $($_Collection.count) Power Delivery Device(s) found."

        Return $_Collection
        
    }

}

function Add-HPOVPowerDevice 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = "High")]
    Param 
    (

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Hostname,
         
        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Username,

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Password,

        [Parameter (Mandatory = $false)]
        [switch]$Force,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            if  ($ApplianceConnection.Count -gt 1)
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value. Please correct this and try again.'
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        #Locate the Enclosure Group specified
        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Starting"

        $_import = NewObject -PowerDeliveryDeviceAdd
        
        $_import.hostname = $hostname
        $_import.username = $username
        $_import.password = $password
        $_import.force    = $Force.IsPresent

        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Sending request to add iPDU."

        Try
        {

            $_resp = Send-HPOVRequest $powerDevicesDiscoveryUri POST $_import -Hostname $ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        #Wait for task to get into Starting stage
        Try
        {

            $_resp = Wait-HPOVTaskStart $_resp

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
            
        write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Task response: $($_resp | out-string)"

        #Check to see if the task errored, which should be in the Task Validation stage
        if ($_resp.taskState -ne "Running" -and $_resp.taskState -eq "Error" -and $_resp.stateReason -eq "ValidationError") 
        {

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Task error found $($resp.taskState) $($resp.stateReason) "

            if ($_resp.taskerrors | Where-Object { $_.errorCode -eq "PDD_IPDU_TRAPRECEIVERACCOUNT_TAKEN" }) 
            {
                        
                $_errorMessage = $_resp.taskerrors | Where-Object { $_.errorCode -eq "PDD_IPDU_TRAPRECEIVERACCOUNT_TAKEN" }

                $_externalManagerIP = $_errorMessage.data.mgmtSystemIP

                Try
                {

                    $_externalManagerFQDN = [System.Net.DNS]::GetHostByAddress($_externalManagerIP)

                }

                Catch
                {

                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Couldn't resolve $_externalManagerIP to FQDN [$($_.Exception.Message)]."

                    $_externalManagerFQDN = [PSCustomObject]@{HostName = $_externalManagerIP}

                }
                

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - Found iPDU '$Hostname' is already being managed by $_externalManagerIP."

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - $_externalManagerIP resolves to $($_externalManagerFQDN.HostName | out-string)"

                write-warning "iPDU '$Hostname' is already claimed by another management system $_externalManagerIP ($($_externalManagerFQDN.HostName))."

                if ($force -and $PSCmdlet.ShouldProcess($Hostname,"iPDU is already claimed by another management system $_externalManagerIP ($($_externalManagerFQDN.HostName)). Force add?")) 
                {
                            
                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - iPDU is being claimed due to user chosing YES to force add."

                    $import.force = $true

                    Try
                    {
                        
                        $_resp = Send-HPOVRequest $script:powerDevicesDiscoveryUri POST $_import -Hostnamme $ApplianceConnection.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                elseif ($PSCmdlet.ShouldProcess($Hostname,"iPDU is already claimed by another management system $_externalManagerIP ($($_externalManagerFQDN.HostName)). Force add?")) 
                {
                            
                    write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] - iPDU is being claimed due to user chosing YES to force add."

                    $import.force = $true

                    Try
                    {
                        
                        $_resp = Send-HPOVRequest $script:powerDevicesDiscoveryUri POST $_import -Hostnamme $ApplianceConnection.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                else 
                {

                    if ($PSBoundParameters['whatif'].ispresent) 
                    { 
                            
                        write-warning "-WhatIf was passed, would have force added '$Hostname' iPDU to appliance."

                        $_resp = $null
                            
                    }

                    else 
                    {

                        #If here, user chose "No", End Processing

                        write-warning "Not importing iPDU, $Hostname."

                        $_resp = $Null

                    }

                }

            }

            else 
            {

                $_errorMessage = $_resp.taskerrors

                if ($_errorMessage -is [System.Collections.IEnumerable]) 
                { 
                        
                    #Loop to find a Message value that is not blank.
                    $displayMessage = $_errorMessage | ? { $_.message }

                    $ErrorRecord = New-ErrorRecord InvalidOperationException $displayMessage.errorCode InvalidResult 'Add-HPOVPowerDevice' -Message $displayMessage
                
                }
                        
                else 
                { 
                    
                    $ErrorRecord = New-ErrorRecord InvalidOperationException $errorMessage.errorCode InvalidResult 'Add-HPOVPowerDevice' -Message ($_errorMessage.details + " " + $_errorMessage.message) 
                
                }

                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }
    
        [void]$colStatus.Add($_resp)
    
    }

    End
    {

        Return $colStatus

    }

}

# // TODO: DEVELOP DOCUMENTATION TEST
function New-HPOVPowerDevice
{

    Throw "Not implemented."

}

function Remove-HPOVPowerDevice 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default",SupportsShouldProcess,ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri","name")]
        [object]$PowerDevice,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$force,
    
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['PowerDevice'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection        = New-Object System.Collections.ArrayList
        $_PowerDeviceCollection = New-Object System.Collections.ArrayList
   
    }

    Process 
    {

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] PowerDevice Object provided: $($PowerDevice | FL * | Out-String)"

            If ('power-devices' -contains $PowerDevice.category)
            {

                If (-not($PowerDevice.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.PowerDeviceResourceException InvalidArgumentValue InvalidArgument "PowerDevice:$($PowerDevice.Name)" -TargetType PSObject -Message "The PowerDevice object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_PowerDeviceCollection.Add($PowerDevice)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.PowerDeviceResourceException InvalidArgumentValue InvalidArgument "PowerDevice:$($PowerDevice.Name)" -TargetType PSObject -Message "The PowerDevice object resource is not an expected category type [$($PowerDevice.category)]. The allowed resource category type is 'power-devices'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count))"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Power Device Name $($PowerDevice)"

                Try
                {

                    $_PowerDevice = Get-HPOVPowerDevice $PowerDevice -ApplianceConnection $_appliance

                    $_PowerDevice | % {

                        [void]$_PowerDeviceCollection.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Begin resource removal Process."

        foreach ($_PowerDevice in $_PowerDeviceCollection) 
        {

            if ($PSCmdlet.ShouldProcess($_PowerDevice.name,"Remove Power Device from appliance '$($_PowerDevice.ApplianceConnection.Name)'"))
            {   
             
                
                Try
                {
                    
                    $_task = Send-HPOVRequest $_PowerDevice.uri DELETE -Hostname $_PowerDevice.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_task)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection


    }

}

function Get-HPOVPowerPotentialDeviceConnection 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri","name")]
        [object]$PowerDevice,
    
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['PowerDevice'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_PowerDeviceCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] PowerDevice Object provided: $($PowerDevice | FL * | Out-String)"

            If ('power-devices' -contains $PowerDevice.category)
            {

                If (-not($PowerDevice.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.PowerDeviceResourceException InvalidArgumentValue InvalidArgument "PowerDevice:$($PowerDevice.Name)" -TargetType PSObject -Message "The PowerDevice object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Try
                {

                    $_resp = Send-HPOVRequest ($powerDevicePotentialConnections + $PowerDevice.uri)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

                if ($_resp)
                {

                    $_resp | % { 
                        
                        $_.PSObject.TypeNames.Insert(0,'HPOneView.PowerDevice.PotentialPowerConnection')
                    
                        [void]$_PowerDeviceCollection.Add($_)

                    }

                }

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.PowerDeviceResourceException InvalidArgumentValue InvalidArgument "PowerDevice:$($PowerDevice.Name)" -TargetType PSObject -Message "The PowerDevice object resource is not an expected category type [$($PowerDevice.category)]. The allowed resource category type is 'power-devices'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count))"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Power Device Name $($PowerDevice)"

                Try
                {

                    $_PowerDevice = Get-HPOVPowerDevice $PowerDevice -ApplianceConnection $_appliance

                    $_resp = $_PowerDevice | % { Send-HPOVRequest ($powerDevicePotentialConnections + $_.uri) }

                    $_resp | % {

                        $_.PSObject.TypeNames.Insert(0,'HPOneView.PowerDevice.PotentialPowerConnection')

                        [void]$_PowerDeviceCollection.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

    }

    End 
    {

        Return $_PowerDeviceCollection

    }

}

# // TODO: DEVELOP DOCUMENTATION TEST
function Add-HPOVPowerDeviceConnection
{

    Throw "Not implemented."

}

#######################################################
# Networking and Connections
#

function New-HPOVNetwork 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Ethernet")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "FC")]
        [Parameter (Mandatory, ParameterSetName = "FCOE")]
        [Parameter (Mandatory, ParameterSetName = "VLANIDRange")]
        [Parameter (Mandatory, ParameterSetName = "Ethernet")]
        [string]$Name, 

        [Parameter (Mandatory, ParameterSetName = "FC")]
        [Parameter (Mandatory, ParameterSetName = "FCOE")]
        [Parameter (Mandatory = $false, ParameterSetName = "VLANIDRange")]
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [ValidateSet ("Ethernet", "FC", "FibreChannel", "Fibre Channel", "FCoE")]
        [string]$Type = "Ethernet",
        
        [Parameter (Mandatory, ParameterSetName = "FCOE")]
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")] 
        [validaterange(1,4095)]
        [int32]$VlanId,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")] 
        [object]$Subnet,

        [Parameter (Mandatory, ParameterSetName = "VLANIDRange")]
        [string]$VlanRange,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")] 
        [Parameter (Mandatory = $false, ParameterSetName = "VLANIDRange")]
        [ValidateSet ('Untagged','Tagged','Tunnel', IgnoreCase = $False)]
        [string]$VLANType = "Tagged", 

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "VLANIDRange")]
        [ValidateSet ("General", "Management", "VMMigration", "FaultTolerance", 'ISCSI', IgnoreCase = $False)]
        [string]$Purpose = "General", 

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "VLANIDRange")]
        [boolean]$SmartLink = $true, 

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "VLANIDRange")]
        [boolean]$PrivateNetwork = $false, 

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "VLANIDRange")]
        [Parameter (Mandatory = $false, ParameterSetName = "FCOE")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [validaterange(2,20000)]
        [int32]$TypicalBandwidth = 2500, 
        
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "VLANIDRange")]
        [Parameter (Mandatory = $false, ParameterSetName = "FCOE")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [validaterange(100,20000)]
        [int32]$MaximumBandwidth = 20000, 

        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [int32]$LinkStabilityTime = 30, 

        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [boolean]$AutoLoginRedistribution = $False,

        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [ValidateSet ("FabricAttach","FA", "DirectAttach","DA")]
        [string]$FabricType = "FabricAttach",

        [Parameter (Mandatory = $false, ParameterSetName = "FC", ValueFromPipeline)]
        [Parameter (Mandatory = $false, ParameterSetName = "FCOE", ValueFromPipeline)] 
        [ValidateNotNullOrEmpty()]
        [object]$ManagedSan,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "FCOE")]
        [Parameter (Mandatory = $false, ParameterSetName = "VLANIDRange")]
        [Parameter (Mandatory = $false, ParameterSetName = "importFile")]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "FCOE")]
        [Parameter (Mandatory = $false, ParameterSetName = "VLANIDRange")]
        [Parameter (Mandatory = $false, ParameterSetName = "importFile")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory, ParameterSetName = "importFile")]
        [Alias ("i", "import")]
        [string]$ImportFile

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

    }
     
    Process 
    {

        #Validate Ethernet VLAN ID Setting if Type = 'Tagged'
        if ($PSBoundParameters['VLANType'] -eq 'Tagged' -and (-not($PSBoundParameters['VLANID'])))
        {

            #Generate Error
            $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidNetworkTypeOperation InvalidOperation 'VLANType' -Message "The -VLANType Parameter was used to specify a 'Tagged' Network, however the -VLANID Parameter was not provided. Please provide a VLANID to the Network resource you are creating."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Validate Ethernet VLAN ID Setting if Network Type is FCoE
        if ($PSBoundParameters['Type'] -eq 'FCoE' -and (-not($PSBoundParameters['VlanId'])))
        {

            #Generate Error
            $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidNetworkTypeOperation InvalidOperation 'Type' -Message "The -Type Parameter was used to specify a 'FCoE' Network, however the -VLANID Parameter was not provided. Please provide a VLANID to the Network resource you are creating."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($_appliance.ApplianceType -eq 'Composer' -and $VlanID -eq 1)
            {

                #Generate Error
                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException ReservedVlanID InvalidOperation 'VlanID' -Message "The VLAN ID 1 is reserved and cannot be used. Please provide a different VLAN ID to the Network resource you are creating."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resolved Parameter Set Name: $($PSCmdlet.ParameterSetName)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing CMDLET for '$($_appliance.name)' appliance."

            If ($ImportFile) 
            {

                try 
                {

                    $network = [string]::Join("", (gc $importfile -ErrorAction Stop)) | convertfrom-json -ErrorAction Stop

                }

                catch [System.Management.Automation.ItemNotFoundException] 
                {

                    $ErrorRecord = New-ErrorRecord System.Management.Automation.ItemNotFoundException InputFileNotFound ObjectNotFound 'New-HPOVNetwork' -Message "$importFile not found. Please check the filename or path is valid and try again."
                        
                    #Generate Terminating Error
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                catch [System.ArgumentException] 
                {

                    $ErrorRecord = New-ErrorRecord System.ArgumentException InvalidJSON ParseError 'New-HPOVNetwork' -Message "JSON incorrect or invalid within '$importFile' input file."
                        
                    #Generate Terminating Error
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }
            
            else
            {
            
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network Type Requested: $($Type)"

                switch ($Type) 
                {

                    "Ethernet" 
                    {

                        if (-not($PSBoundParameters['vlanRange'])) 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating '$name' Ethernet Network"

                            $Network = NewObject -EthernetNetwork

                            $Network.vlanId              = $VlanId
                            $Network.ethernetNetworkType = $VLANType
                            $Network.purpose             = $EthernetNetworkPurposeEnum[$Purpose]
                            $Network.name                = $Name
                            $Network.smartLink           = $SmartLink
                            $Network.privateNetwork      = $PrivateNetwork

                            if ($PSBoundParameters['Subnet'])
                            {

                                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Subnet {0} was provided, validating." -f $Subnet.netowrkId | Write-Verbose

                                #Genrate Error
                                if (-not($Subnet -is [PSCustomObject]))
                                {

                                    $Message = 'The Subnet Parameter value is not an Object. Please provide a valid Object by using the Get-HPOVAddressPoolSubnet Cmdlet.'
                                    $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidSubnetValue InvalidArgument 'Subnet' -TargetType $Subnet.Gettype().Name -Message $Message
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                #Genrate Error, invalid object type
                                if ($Subnet.category -ne 'id-range-IPv4-subnet')
                                {

                                    $Message = "The Subnet Parameter value is not a valid 'id-range-IPv4-subnet' Object. The object category provided was {0}. Please provide a valid Object by using the Get-HPOVAddressPoolSubnet Cmdlet." -f $Subnet.category
                                    $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidSubnetObject InvalidArgument 'Subnet' -TargetType 'PSObject' -Message $Message
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                #Invalid object for the appliance connection
                                if ($Subnet.ApplianceConnection.Name -ne $_appliance.Name)
                                {

                                    $Message = "The Subnet Parameter value is missing the 'ApplianceConnection' property. Please provide a valid Object by using the Get-HPOVAddressPoolSubnet Cmdlet."
                                    $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidNetworkTypeOperation InvalidOperation 'Subnet' -TargetType 'PSObject' -Message $Message
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                $network.subnetUri = $Subnet.uri

                            }

                        }

                        else 
                        {
                    
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating bulk '$name' + '$vlanRange' Ethernet Networks"

                            $network = NewObject -BulkEthernetNetworks

                            $network.vlanIdRange                = $vlanRange
                            $network.purpose                    = $purpose
                            $network.namePrefix                 = $Name
                            $network.smartLink                  = $smartLink
                            $network.privateNetwork             = $privateNetwork
                            $network.bandwidth.typicalBandwidth = $typicalBandwidth
                            $network.bandwidth.maximumBandwidth = $maximumBandwidth
                                    
                        }

                    }
                    
                    { @("FC","FibreChannel","Fibre Channel") -contains $_ } 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating '$name' FC Network"

                        $network = NewObject -FCNetwork

                        $network.name                    = $Name
                        $network.linkStabilityTime       = $linkStabilityTime
                        $network.autoLoginRedistribution = $autoLoginRedistribution
                        $network.fabricType              = $FCNetworkFabricTypeEnum[$FabricType]
                        $network.connectionTemplateUri   = $null

                        Try
                        {

                            $network.managedSanUri  = if ($ManagedSan) { (VerifyManagedSan $ManagedSan $_appliance) } else { $null }

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        #If maxbandiwdth value isn't specified, 10Gb is the default value, must change to 8Gb
                        if ( $maximumBandwidth -eq 10000 ){ $maximumBandwidth = 8000 }

                    }

                    "FCOE" 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating '$name' FCOE Network"

                        $network = NewObject -FCoENetwork

                        $network.name                  = $Name
                        $network.vlanId                = $vlanId
                        $network.connectionTemplateUri = $null
                        
                        Try
                        {

                            $network.managedSanUri = if ($ManagedSan) { (VerifyManagedSan $ManagedSan $_appliance) } else { $null }

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                }
            
            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network Object: $($network | fl | out-string)"
            
            foreach($net in $network) 
            {

                if ($net.type.StartsWith('ethernet-networks') -and $net.type -ne 'ethernet-networkV300') { $net.type = 'ethernet-networkV300' }

                if ($net.defaultTypicalBandwidth) 
                { 
                    
                    $typicalBandwidth = $net.defaultTypicalBandwidth 
                    $net = $net | Select * -ExcludeProperty defaultTypicalBandwidth
                
                }
                
                if ($net.defaultMaximumBandwidth) 
                { 
                    
                    $maximumBandwidth = $net.defaultMaximumBandwidth 
                    $net = $net | Select * -ExcludeProperty defaultMaximumBandwidth

                }

                if ($net.typicalBandwidth) { $typicalBandwidth = $net.typicalBandwidth }
                if ($net.maximumBandwidth) { $maximumBandwidth = $net.maximumBandwidth }
                if ($PSBoundParameters['ImportFile'] -and $net.fabricUri) { $net.fabricUri = $null }
                if ($PSBoundParameters['ImportFile'] -and $net.subnetUri) { $net.subnetUri = $null }
                if ($PSBoundParameters['ImportFile'] -and [Array]$net.scopeUris -gt 0) { [Array]$net.scopeUris = @() }
                if ($PSBoundParameters['ImportFile'] -and $net.connectionTemplateUri) { [Array]$net.connectionTemplateUri = $null }

                switch ($net.type) 
                {

                    {$_ -match "bulk-ethernet-network"}
                    {
                        
                        "[{0}] Creating bulk '{1}' + '{2}' Ethernet Networks" -f $MyInvocation.InvocationName.ToString().ToUpper(), $name, $vlanRange | Write-Verbose

                        $netUri = $EthNetworksUri + "/bulk"

                        break

                    }

                    {$_ -match "ethernet-network"}
                    {

                        "[{0}] Creating {1} Ethernet Network" -f $MyInvocation.InvocationName.ToString().ToUpper(), $net.name | Write-Verbose

                        $netUri = $EthNetworksUri

                        $net = $net | select * -ExcludeProperty uri

                    }

                    {$_ -match "fc-network"}
                    {

                        "[{0}] Creating {1} FC Network" -f $MyInvocation.InvocationName.ToString().ToUpper(), $net.name | Write-Verbose

                        $netUri = $FcNetworksUri

                        $net = $net | select * -ExcludeProperty uri

                    }

                    {$_ -match "fcoe-network"}
                    {

                        "[{0}] Creating {1} FCoE Network" -f $MyInvocation.InvocationName.ToString().ToUpper(), $net.name | Write-Verbose

                        $netUri = $FCoENetworksUri

                        $net = $net | select * -ExcludeProperty uri

                    }

                    #Should never get here. If so, this is an internal error we need to fix.
                    default 
                    {

                        $ErrorRecord = New-ErrorRecord System.ArgumentException InvalidNetworkType InvalidType 'type' -Message "(INTERNAL ERROR) The Network Resource Type $($net.type) is invalid for '$($net.name)' network."
                        
                        #Generate Terminating Error
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                $objStatus = [pscustomobject]@{ 
                    
                    Name      = $net.Name; 
                    Status    = $Null; 
                    Details   = $Null;
                    Exception = $Null;
                
                }

                #Check if Network Type is Direct Attach and if ManagedFabric Parameter is being called at the same time.
                if (($fabricType -eq "DirectAttach" -or $fabricType -eq "DA") -and $managedfabric) 
                { 

                    $objStatus.Details = "You specified a DirectAttach Fabric Type and passed the ManagedSan Parameter. The ManagedSan Parameter is to be used for FabricAttach networks only."
                   
                }

                else 
                {
                     
                    Try
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to create '$($net.name)' network."

                        $task = Send-HPOVRequest $netUri POST $net -Hostname $_appliance 
                    
                    }    
                    
                    Catch
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Exception caught when trying to create '$($net.name)' network."

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Exception: $($_.Exception.Message.ToString())"

                        $objStatus.Status    = "Failed"
                        $objStatus.Details   = $_.exception.message
                        $objStatus.Exception = $_

                    }

                }

                if (-not $task.Uri) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Create Network Object '$($net.name)' request was rejected."

                    $objStatus.Status = "Failed"
                    
                    #Do not want to overwrite the details value from the Fabric Type check above.
                    if ($task) { $objStatus.Details = $task }

                }

                else 
                { 
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Create Network Object '$($net.name)' creating. Monitor task."

                    #Wait for the network to be created
                    Try
                    {

                        $task = Wait-HPOVTaskComplete $task #-Appliance $_appliance

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    $objStatus.Status  = $task.taskState
                    $objStatus.Details = $task

                }

                [void] $colStatus.add($objStatus) #| Out-Null

                #Update Bandwidth allocation if set to different than default values
                if (($typicalBandwidth -or $maximumBandwidth) -and (-not($objStatus.Status -eq "Failed")) -and $net.type -ne 'bulk-ethernet-network' ) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting bandwidth to network object"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Network object to retrieve ConnectionTemplate URI"

                    #Get network resource URI
                    Try
                    {

                        $net = Send-HPOVRequest $task.associatedResource.resourceUri -Hostname $_appliance

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] ConnectionTemplate URI '$($net.connectionTemplateUri)'"

                    if ($net -and $net.connectionTemplateUri) 
                    {

                        $ctUri = $net.connectionTemplateUri
                        
                        Try
                        {

                            $ct = Send-HPOVRequest $ctUri -Hostname $_appliance

                            if ($typicalBandwidth) { $ct.bandwidth.typicalBandwidth = $typicalBandwidth }

                            if ($maximumBandwidth) { $ct.bandwidth.maximumBandwidth = $maximumBandwidth }

                            $void = Send-HPOVRequest $ct.uri PUT $ct -Hostname $ct.ApplianceConnection.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }        

                    }

                }

            }

        }

    }

    End 
    {

        if ($colStatus | ? { $_.Status -ne "Completed" }) 
        { 
            
            write-error "One or more networks failed the creation attempt!" 
        
        }

        Return $colStatus
        
    }

}

function VerifyManagedSan 
{

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Object]$managedSan,

        [Parameter (Mandatory)]    
        [ValidateNotNullorEmpty()]    
        [object]$Appliance
    
    )
    
    Process 
    {

        if ($managedSan -eq "" -or $Null -eq $ManagedSan) 
        {
           
            $managedSanUri = $Null

        }

        elseif ($managedSan -is [PSCustomObject] -and $managedSan.category -eq 'fc-sans') 
        { 
                    
            $managedSanUri = $managedSan.uri
                        
        }

        elseif ($managedSan -is [PSCustomObject] -and -not ($managedSan.category -eq 'fc-sans')) 
        { 
                    
            $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidManagedSanUri InvalidArgument 'managedSan' -Message "The Managed SAN object category provided '$($managedSan.category)' is not the the expected value of 'fc-sans'. Please verify the Parameter value and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)   
                        
        }
                   
        elseif ($managedSan -is [String] -and $managedSan.StartsWith('/rest/')) 
        { 
                    
            $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidManagedSanUri InvalidArgument 'managedSan' -Message "The Managed SAN Uri provided '$managedSan' is incorrect. Managed SAN URI must Begin with '/rest/fc-sans/managed-sans'."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)                       
                    
        }
                    
        elseif ($managedSan -is [String] -and (-not($managedSan.StartsWith($script:fcManagedSansUri)))) 
        {

            #Get ManagedSan object
            Try { $managedSanUri = (Get-HPOVManagedSan $managedSan -appliance $Appliance).uri }

            #If specified ManagedSan object does not exist, generate trappable error
            catch 
            {
        
                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidManagedSanName InvalidArgument 'managedSan' -Message "The Managed SAN Name provided '$managedSan' was not found."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)   

            }

        }

        else 
        {

            $managedSanUri = $managedSan

        }

        Return $managedSanUri

    }

}

function Get-HPOVNetwork 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (ParameterSetName = 'Default', ValueFromPipeline, Mandatory = $false)]
        [ValidateNotNullOrEmpty ()]
        [SupportsWildcards ()]
        [String]$Name,
        
        [Parameter (ParameterSetName = 'Default', Mandatory = $false)]
        [Parameter (ParameterSetName = 'Label', Mandatory = $false)]
        [ValidateSet ("Ethernet", "FC", "FibreChannel", "FCOE")]
        [String]$Type,

        [Parameter (ParameterSetName = 'Default', Mandatory = $false)]
        [Parameter (ParameterSetName = 'Label', Mandatory = $false)]
        [ValidateSet ("General", "Management", "VMMigration", "FaultTolerance", "ISCSI")]
        [String]$Purpose,

        [Parameter (ParameterSetName = 'Default', Mandatory = $false)]
        [ValidateNotNullOrEmpty ()]
        [HPOneView.Appliance.ScopeCollection]$Scope,

        [Parameter (ParameterSetName = 'Label', Mandatory = $false)]
        [ValidateNotNullOrEmpty ()]
        [String]$Label,
        
        [Parameter (ParameterSetName = 'Default', Mandatory = $false)]
        [Parameter (ParameterSetName = 'Label', Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),
        
        [Parameter (ParameterSetName = 'Default', Mandatory = $false)]
        [Parameter (ParameterSetName = 'Label', Mandatory = $false)]
        [Alias ("x", "export")]
        [ValidateScript ({split-path $_ | Test-Path})]
        [String]$exportFile
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['type']))
        {
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] -Type Parameter wasn't provided. Specifying all Network Resource Types."

            [Array]$type = "Ethernet","FibreChannel","FCOE"

        }

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $NetworkCollection = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($Connection in $ApplianceConnection)
        {

            if ($PSBoundParameters['Purpose'])
            {

                $Type = 'Ethernet'

            }

            $Found = New-Object System.Collections.ArrayList

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Connection.Name, $ApplianceConnection.Count | Write-Verbose

            if ($PSBoundParameters['Label'])
            {

                switch ($Type)
                {

                    "Ethernet" { $_category += 'category=ethernet-networks&'}
                    
                    "FibreChannel" { $_category += 'category=fc-networks&'}
                    
                    "FCOE" { $_category += 'category=fcoe-networks&'}

                }

                $_uri = '{0}?{1}sort=name:asc&query=labels:{2}' -f $IndexUri, $_category, $Label

                Try
                {

                    $IndexResources = Send-HPOVRequest -Uri $_uri -Hostname $Connection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                ForEach ($_member in $IndexResources.members)
                {

                    Try
                    {

                        $_member = Send-HPOVRequest -Uri $_member.uri -Hostname $Connection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)
                        
                    }

                    switch ($_member.category)
                    {

                        'ethernet-networks'
                        {

                            $_member.psobject.typenames.Insert(0,"HPOneView.Networking.EthernetNetwork")  

                        }

                        'fc-networks'
                        {

                            $_member.psobject.typenames.Insert(0,"HPOneView.Networking.FibreChannelNetwork")  

                        }

                        'fcoe-networks'
                        {

                            $_member.psobject.typenames.Insert(0,"HPOneView.Networking.FCoENetwork")  

                        }

                    }

                    "[{0}] Adding '{1}' to found collection" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_member.Name | Write-Verbose
                    
                    [void]$Found.Add($_member)

                }

            }

            else
            {

                switch($type) 
                {

                    { @("FC", "FibreChannel") -contains $_ } 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing FibreChannel Networks."

                        $Uri = $FcNetworksUri + "?sort=name:ascEnding"

                        if ($PSBoundParameters['Name']) 
                        { 
                            
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Looking for '$($Name)' Fibre Channel Network resources."

                            $Uri =  "{0}&filter=name matches '{1}'" -f $Uri, $Name.replace("*","%25").Replace("&","%26")

                        }

                        if ($PSBoundParameters['Scope'])
                        {

                            $Uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri

                        }

                        Try
                        {

                            $Networks = Send-HPOVRequest -uri $Uri -Hostname $Connection

                        }
                        
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        #Add to final collection arraylist
                        if ($Networks.members) 
                        { 
                            
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding results to collection"

                            $Networks.members | % { 

                                $_.psobject.typenames.Insert(0,"HPOneView.Networking.FibreChannelNetwork")  

                                "[{0}] Adding '{1}' to found collection" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_.Name | Write-Verbose

                                [void]$Found.Add($_)
                            
                            } 

                        }

                    }

                    { @("Ethernet") -contains $_ } 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Ethernet Network resources."

                        $Uri = $EthNetworksUri + "?sort=name:ascEnding"

                        if ($PSBoundParameters['Name']) 
                        { 
                            
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Looking for '$($Name)' Ethernet Network resources."

                            $Uri =  "{0}&filter=name matches '{1}'" -f $Uri, $Name.replace("*","%25").Replace("&","%26")

                        }

                        if ($PSBoundParameters['Scope'])
                        {

                            $Uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri

                        }

                        if ($PSBoundParameters['Purpose'])
                        {

                            $Uri += "&filter=purpose='{0}'" -f $Purpose

                        }

                        Try
                        {

                            $Networks = Send-HPOVRequest -uri $Uri -Hostname $Connection

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                
                        
                        #Add to final collection arraylist
                        if ($Networks.members) 
                        { 

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding results to collection"

                            $Networks.members | % { 

                                $_.psobject.typenames.Insert(0,"HPOneView.Networking.EthernetNetwork")  

                                "[{0}] Adding '{1}' to found collection" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_.Name | Write-Verbose

                                [void]$Found.Add($_)

                            } 

                        }

                    }

                    { @("FCoE") -contains $_ }
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Looking for FCoE Network resources."

                        $Uri = $FCoENetworksUri + "?sort=name:ascEnding"

                        if ($PSBoundParameters['Name']) 
                        { 
                            
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Looking for '$($Name)' Fibre Channel Network resources."

                            $Uri =  "{0}&filter=name matches '{1}'" -f $Uri, $Name.replace("*","%25").Replace("&","%26")

                        }

                        if ($PSBoundParameters['Scope'])
                        {

                            $Uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri

                        }

                        Try
                        {

                            $Networks = Send-HPOVRequest -uri $Uri -Hostname $Connection

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                

                        #Add to final collection arraylist
                        if ($Networks.members) 
                        { 

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding results to collection"

                            $Networks.members | % { 

                                $_.psobject.typenames.Insert(0,"HPOneView.Networking.FCoENetwork")  

                                "[{0}] Adding '{1}' to found collection" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_.Name | Write-Verbose
                            
                                [void]$Found.Add($_)
                            
                            } 

                        }

                    }

                }

            }

            #If network not found, report error
            if ($Found.Count -eq 0 -and $Name)
            { 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network Resource Name was provided, yet no results were found. Generate Error."

                $ExceptionMessage = "The specified '{0}' Network resource was not found on '{1}' appliance connection. Please check the name and try again." -f $Name, $Connection.Name 
                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException NetworkResourceNotFound ObjectNotFound "Name" -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

            $Found | % { 

                "[{0}] Adding '{1}' to final collection" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_.Name | Write-Verbose
            
                [void]$NetworkCollection.Add($_)
            
            } 

        }

    }

    End 
    {

        if ($NetworkCollection) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Results returned "

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Networks Found: $($NetworkCollection | fl * | out-string ) "

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Network resource Connection Template Object to add bandwidth values to network objects."

            ForEach ($NetObject in $NetworkCollection) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($NetObject.Name)' Network resource."

                if ($NetObject.connectionTemplateUri) 
                {

                    Try
                    {

                        $ct = Send-HPOVRequest -uri $NetObject.connectionTemplateUri -Hostname $NetObject.ApplianceConnection.Name

                    }

                    Catch
                    {

                      $PSCmdlet.ThrowTerminatingError($_)

                    }                    
            
                    Add-Member -InputObject $NetObject -NotePropertyName defaultMaximumBandwidth -NotePropertyValue $ct.bandwidth.maximumBandwidth -Force 
                    Add-Member -InputObject $NetObject -NotePropertyName defaultTypicalBandwidth -NotePropertyValue $ct.bandwidth.typicalBandwidth -Force

                }
        
            }

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. {0} network resource(s) found." -f $NetworkCollection.Count | Write-Verbose 
            
            if ($exportFile) 
            { 
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Exporting JSON to $($exportFile)"
            
                $NetworkCollection | Sort type,name | convertto-json > $exportFile
            
            }
            
            else
            {

                $NetworkCollection | Sort type,name
            
            }
        
        }

        #No networks found
        else
        { 
            
            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Network resources found." 
        
        }

    }

}

function Set-HPOVNetwork 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Ethernet")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [Alias ('net','Network')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [string]$Prefix,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [string]$Suffix,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [ValidateNotNullOrEmpty()]
        [ValidateSet ("General", "Management", "VMMigration", "FaultTolerance", "ISCSI")]
        [string]$Purpose,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Bool]$Smartlink, 

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Bool]$PrivateNetwork, 

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [validaterange(2,20000)]
        [int32]$TypicalBandwidth, 
        
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [validaterange(100,20000)]
        [int32]$MaximumBandwidth, 

        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateRange(1,1800)]
        [Alias ('lst')]
        [int32]$LinkStabilityTime, 

        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [Alias ('ald')]
        [Bool]$AutoLoginRedistribution,

        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [Object]$ManagedSan,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Object]$IPv4Subnet,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network resource passed via pipeline."
        
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_NetworksToUpdate = New-Object System.Collections.ArrayList
        $NetCollection     = New-Object System.Collections.ArrayList

    }

    Process 
    {

        #build collection of networks to modify
        foreach ($net in $InputObject) 
        {

            if ($PSBoundParameters['LinkStabilityTime'] -and $net.category -eq 'fcoe-networks')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'LinkStabilityTime' -TargetType 'Int' -Message "The -LinkStabilityTime Parameter is not supported with FCoE Network resources, only FibreChannel network resources. Please check your call and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if ($PSBoundParameters['AutoLoginRedistribution'] -and $net.category -eq 'fcoe-networks')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'AutoLoginRedistribution' -TargetType 'Boolean'  -Message "The -AutoLoginRedistribution Parameter is not supported with FCoE Network resources, only FibreChannel network resources. Please check your call and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Check the name Parameter value if the caller inadvertantly provided an object for name Parameter
            if ($name -and ($name -match "category=ethernet-networks" -or $name -match "category=fc-networks" -or $name -match "category=fcoe-networks"))
            { 
            
                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'Name' -Message "The -name Parameter value appears to have been passed the network resource object, which is converted to type [String] and is an invalid operation. Please verify that you provided the Network Name attribute in the -name Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

            elseif ($name -and $name.length -gt 255) 
            {

                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'Name' -Message "The -name Parameter value is greater than 255 characters. Please check the -name Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            switch ($net.Gettype().Name) 
            {

                "PSCustomObject" 
                { 
    
                    if ($net -is [PSCustomObject] -and ($net.category -eq "ethernet-networks" -or $net.category -eq "fc-networks" -or $net.category -eq "fcoe-networks")) 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Collecting $($net.type) $($net.name) resource."

                        #[void]$_NetworksToUpdate.Add($net)

                    }

                    else 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "[$($net.gettype().name)] is an unspported data type. Only [System.String] or [PSCustomObject] or an [Array] of [System.String] or [PSCustomObject] network resources are allowed. Please check the -network Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }
                    
                }

                "String" 
                { 
                
                    #User provided Network 'name' and 1 or more Appliance Connections
                    if ($net -is [String] -and (-not ($net.StartsWith('/rest/'))))
                    {
                    
                        ForEach ($_appliance in $ApplianceConnection)
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting '$($net)' resource from appliance."
                            
                            Try 
                            {

                                $net = Get-HPOVNetwork -Name $net -type $PSCmdlet.ParameterSetName -ApplianceConnection $_appliance -ErrorAction Stop

                            }
                            
                            Catch [HPOneView.NetworkResourceException]
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }
                            
                            if ($net.count -gt 1)
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException NonUniqueNetworkName InvalidResult 'InputObject' -Message "Multiple '$_tempNet' Network resource found with the same name. Please check the value and try again, or provide the Network Resource Object instead of the name."
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }
                    
                            #[void]$_NetworksToUpdate.Add($_tempNet)

                        }
                        
                    }

                    elseif ($net -is [String] -and ($net.StartsWith('/rest/ethernet-networks/') -or $net.StartsWith('/rest/fc-networks/'))) 
                    {
                    
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting '$($net)' resource from appliance."

                        Try
                        {

                            $net = Send-HPOVRequest -URi $net -Appliance $ApplianceConnection

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
                                                
                        #[void]$NetCollection.Add($net)
                    
                    }
                
                }

            }

            #Perform the work
            #Set Specific Network Type settings
            switch ($net.category) 
            {

                "ethernet-networks" 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updateing $($net.name) Ethernet Network."

                    switch ($PSBoundParameters.keys) 
                    {

                        "purpose" 
                        { 
                        
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting network Purpose to: $purpose"
                            $net.purpose = $purpose
                            
                        }

                        "smartlink" 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting smartlink Enabled to: $([bool]$smartlink)"
                            $net.smartlink = [bool]$smartlink

                        }

                        "privateNetwork" 
                        { 

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting privateNetwork Enabled to: $([bool]$privateNetwork)"
                            $net.privateNetwork = [bool]$privateNetwork
                        
                        }

                        'IPv4Subnet'
                        {

                            #Validate the Address Pool
                            Switch ($IPv4Subnet.GetType())
                            {

                                'String'
                                {

                                    if ($IPv4Subnet.StartsWith('/rest/id-pools/ipv4/subnets'))
                                    {

                                        Try
                                        {

                                            $IPv4Subnet = Send-HPOVRequest -Uri $IPv4Subnet -Appliance $ApplianceConnection

                                        }
                                        
                                        Catch
                                        {

                                            $PSCmdlet.ThrowTerminatingError($_)

                                        }

                                    }

                                    elseif ($PSBoundParameters['IPv4Subnet'] -and $null -ne $IPv4Subnet)
                                    {

                                        Try
                                        {

                                            $IPv4Subnet = Get-HPOVAddressPoolSubnet -NetworkID $IPv4Subnet -Appliance $ApplianceConnection -ErrorAction Stop

                                        }
                                        
                                        Catch
                                        {

                                            $PSCmdlet.ThrowTerminatingError($_)

                                        }

                                    }

                                }

                                'PSCustomObject'
                                {

                                    if ($IPv4Subnet.category -ne 'id-range-IPv4-subnet')
                                    {

                                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid IPv4 Address Pool resource object."

                                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolResourceException InvalidIPv4AddressPoolResource InvalidArgument 'IPv4Subnet' -TargetType 'PSObject' -Message "An invalid IPv4 Address Pool resource object was provided. Please verify the Parameter value and try again."
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }

                                }

                            }

                            $net.subnetUri = $IPv4Subnet.uri

                        }

                    }

                }

                "fc-networks" 
                {

                    switch ($PSBoundParameters.keys) 
                    {

                        "LinkStabilityTime" 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting LinkStabilityTime to '$LinkStabilityTime' seconds"

                            if ($net.fabricType -eq 'DirectAttach')
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidFabricOperation InvalidOperation 'LinkStabilityTime' -TargetType $LinkStabilityTime.Gettype().Name -Message ("Cannot set LinkStabilityTime value to a DirectAttach FibreChannel resource, {0}." -f $net.name)
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                            $net.linkStabilityTime = [int]$linkStabilityTime

                        }

                        "AutoLoginRedistribution" 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting AutoLoginRedistribution Enabled to: $([bool]$AutoLoginRedistribution)"

                            if ($net.fabricType -eq 'DirectAttach')
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidFabricOperation InvalidOperation 'AutoLoginRedistribution' -TargetType $AutoLoginRedistribution.Gettype().Name -Message ("Cannot set AutoLoginRedistribution value to a DirectAttach FibreChannel resource, {0}" -f $net.name)
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }
                            
                            $net.autoLoginRedistribution = [bool]$autoLoginRedistribution

                            if ($net.linkStabilityTime -eq 0 -and (-not($LinkStabilityTime)) -and [Bool]$AutoLoginRedistribution)
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidLinkStabilityTimeValue InvalidOperation 'AutoLoginRedistribution' -Message ("The '{0}' FC Network resource is a Direct Attach fabric. The Managed SAN resource cannot be modified." -f $_net.name)
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                        }

                        "managedSan"
                        {

                            if ($net.fabricType -eq 'DirectAttach')
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidFabricOperation InvalidResult 'Network' -Message ("The '{0}' FC Network resource is a Direct Attach fabric. The Managed SAN resource cannot be modified." -f $net.name)
                                $PSCmdlet.WriteError($ErrorRecord)

                            }

                            else
                            {

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing ManagedSAN for FC Network."

                                Try
                                {

                                    $net.managedSanUri = (VerifyManagedSan $managedSan $net.ApplianceConnection.Name)

                                }

                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }

                            }
                            
                        }

                    }

                }

                "fcoe-networks"
                {
                    
                    switch ($PSBoundParameters.keys) 
                    {

                        "managedSan"
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing ManagedSAN for FC Network."
                    
                            $net.managedSanUri = (VerifyManagedSan $managedSan $net.ApplianceConnection.Name)
                            
                        }

                    }

                }

            }

            #Shared Parameters for each Network Type
            if ($PSBoundParameters["name"]) 
            {
            
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network name to '$name'."
    
                #validate name Parameter is [String]
                $net.name = $name
                
            }
    
            if ($PSBoundParameters["prefix"]) 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network name to include '$prefix' prefix to Network Name."
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updated Network Name: $($prefix + $net.name)"
    
                #validate name Parameter is [String]
                $net.name = $prefix + $net.name
                
            }
    
            if ($PSBoundParameters["suffix"]) 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network name to include '$suffix' suffix to Network Name."
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updated Network Name: $($net.name + $suffix)"
    
                #validate name Parameter is [String]
                $net.name += $suffix
                
            }
    
            if ($PSBoundParameters["typicalBandwidth"] -or $PSBoundParameters["maximumBandwidth"]) 
            {
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network bandwidth assignment."

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Connection Template resource."

                Try
                {

                    $ct = Send-HPOVRequest $net.connectionTemplateUri -Appliance $net.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                } 
                
                if ($PSBoundParameters["maximumBandwidth"]) 
                {
                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Original Maximum bandwidth assignment: $($ct.bandwidth.maximumBandwidth)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Maximum bandwidth assignment: $maximumBandwidth"

                    $ct.bandwidth.maximumBandwidth = $maximumBandwidth
    
                }

                if($PSBoundParameters["typicalBandwidth"]) 
                {
    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Original Typical bandwidth assignment: $($ct.bandwidth.typicalBandwidth)"
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Typical bandwidth assignment: $typicalBandwidth"

                    $ct.bandwidth.typicalBandwidth = $typicalBandwidth
                    
                }
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Connection Template: $($ct | out-string)"

                Try
                {

                    $ct = Send-HPOVRequest $ct.uri PUT $ct -Appliance $ct.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
    
            }

            $net = $net | select * -ExcludeProperty defaultTypicalBandwidth, defaultMaximumBandwidth, created, modified

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network Resource object: $($net | FL * | out-string)"
            Try
            {

                $resp = Send-HPOVRequest $net.uri PUT $net -Appliance $net.ApplianceConnection.Name
            
            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $resp            

        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

} 

function Remove-HPOVNetwork 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('uri', 'name', 'network','Resource')]
        [System.Object]$InputObject,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [switch]$Force

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Resource'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection    = New-Object System.Collections.ArrayList
        $_NetworkCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network Object provided: $($InputObject | FL * | Out-String)"

            If ('ethernet-networks','fc-networks','fcoe-networks' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "Network:$($InputObject.Name)" -TargetType PSObject -Message "The Network resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_NetworkCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "Network:$($InputObject.Name)" -TargetType PSObject -Message "The Network resource is not an expected category type [$($InputObject.category)]. Allowed resource category types are 'ethernet-networks', 'fc-networks', or 'fcoe-networks'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            foreach ($net in $InputObject) 
            {

                #Network passed is a URI
                if (($net -is [String]) -and [System.Uri]::IsWellFormedUriString($net,'Relative')) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received URI: $($net)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Network Name"

                    Try
                    {

                        $net = Send-HPOVRequest $net -ApplianceConnection $ApplianceConnection

                    }

                    Catch
                    {

                      $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                }

                #Network passed is the Name
                elseif (($net -is [string]) -and (!$net.startsWith("/rest"))) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received Network Name $($net)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Network object from Get-HPOVNetwork"
                    
                    # // NEED APPLIANCE NAME HERE with If Condition
                    $net = Get-HPOVNetwork $net -ApplianceConnection $ApplianceConnection

                    if ($network.count -gt 1 ) 
                    { 

                        $ErrorRecord = New-ErrorRecord InvalidOperationException NetworkResourceNameNotUnique InvalidResult 'Remove-HPOVNetwork' -Message "Invalid Network Parameter: $net"
                        $PSCmdlet.WriteError($ErrorRecord)                
                    
                    }

                }

                #Network passed is the object
                elseif ($net -is [PSCustomObject] -and ($net.category -ieq 'ethernet-networks' -or $net.category -ieq 'fc-networks' -or $net.category -ieq 'fcoe-networks')) 
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network Object provided: $($net | FL * | out-string)"
                
                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Network' -TargetType 'PSObject' -Message "Invalid Network Parameter: $($net | FL * | Out-String)"
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                [void]$_NetworkCollection.Add($InputObject)

            }

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_NetworkCollection.count) Network resources to remove."

        #Process Network Resources
        ForEach ($_network in $_NetworkCollection)
        {

            if ($PSCmdlet.ShouldProcess($_network.name,"Remove Network from appliance '$($_network.ApplianceConnection.Name)'")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Network '$($_network.name)' from appliance '$($_network.ApplianceConnection.Name)'."

                Try
                {
                    
                    if ($PSBoundParameters['Force'])
                    {

                        $_network.uri += "?force=true"

                    }

                    $_resp = Send-HPOVRequest $_network.Uri DELETE -Hostname $_network.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function New-HPOVNetworkSet 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory)]
        [String]$Name,

        [Parameter (Mandatory)]
        [Alias ('networkUris')]
        [Object]$Networks,

        [Parameter (Mandatory = $False)]
        [Alias ('untagged','native','untaggedNetworkUri')]
        [Object]$UntaggedNetwork,

        [Parameter (Mandatory = $False)]
        [int32]$TypicalBandwidth = 2500,

        [Parameter (Mandatory = $False)]
        [int32]$MaximumBandwidth = 10000,
    
        [Parameter (Mandatory = $False)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_NetSetStatusCol = New-Object System.Collections.ArrayList    

    }
    
    Process 
    {


        "[{0}] Processing '{1}' Appliance Connection" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ApplianceConnection.Name | Write-Verbose

        "[{0}] Building NetworkSet '{1}' object." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose

        $_NewNetSet = Newobject -NetworkSet

        $_NewNetSet.name = $Name

        # Validate Networks if they are objects, and ApplianceConnection prop matches $_connection.Name value
        ForEach ($_net in $Networks)
        {

            switch ($_net.GetType().Name)
            {

                'String'
                {

                    #URI provided
                    if ($_net.StartsWith($ethNetworksUri))
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network resource is [String] and URI. Getting resource object."

                        try
                        {

                            $_net = Send-HPOVRequest -Uri $_net -Hostname $ApplianceConnection.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                    #Name provided
                    else
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network resource is [String] and Name. Getting resource object."

                        try
                        {

                            $_originalnet = $_net.Clone()

                            $_net = Get-HPOVNetwork -Name $_net -ApplianceConnection $ApplianceConnection.Name -ErrorAction Stop

                            if ($_net.count -gt 1)
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException MultipleNetworkResourcesFound LimitsExceeded 'Networks' -Message "Network '$_originalnet' is not a unique resource name, as multiple Network resources were found. Please correct the Parameter value and try again."
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                }

                'PSCustomObject'
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Object: $($_net | fl * | Out-String)"

                    #Object must have the ApplianceConnection NoteProperty
                    if (-not($_net.ApplianceConnection))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException MissingApplianceConnectionNoteProperty InvalidArgument 'Networks' -TargetType 'PSObject' -Message "Network '$($_net.name)' does not contain the required 'ApplianceConnection' NoteProperty. Network objects must be retrieved from the appliance either using their unique URI or with Get-HPOVNetwork. Please correct the Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    elseif ($_net.ApplianceConnection.Name -ne $ApplianceConnection.Name)
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException ApplianceConnetionDoesNotMatchObject InvalidArgument 'Networks' -TargetType 'PSObject' -Message "Network '$($_net.name)' 'ApplianceConnection' NoteProperty {$($_net.ApplianceConnection.Name)}does not match the Appliance Connection currently Processing {$($ApplianceConnection.Name)}. Network objects must be retrieved from the appliance either using their unique URI or with Get-HPOVNetwork. Please correct the Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if ($_net.category -ne 'ethernet-networks')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException UnsupportedResourceCategory InvalidArgument 'Networks' -TargetType 'PSObject' -Message "Network '$($_net.name)' category {$($_net.category)} is not the supported type, 'ethernet-networks'. Network objects must be retrieved from the appliance either using their unique URI or with Get-HPOVNetwork using the -Type Ethernet Parameter. Please correct the Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                default
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException UnsupportedParameterValueType InvalidType 'Networks' -TargetType $_Net.GetType().Name -Message "The provided Networks Parameter value type '$($_Net.GetType().Name)' is not supported. Only String (Name or URI) or PSCustomObject types are allowed and supported. Please correct the Parameter value and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            [void]$_NewNetSet.networkUris.Add($_net.uri)

        }

        if ($PSboundParameters['UntaggedNetwork'])
        {

            # Validate UntaggedNetwork if it is an object, and ApplianceConnection prop matches $_connection.Name value
            switch ($UntaggedNetwork.GetType().Name)
            {

                'String'
                {

                    #URI provided
                    if ($UntaggedNetwork.StartsWith($ethNetworksUri))
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] UntaggedNetwork resource is [String] and URI. Getting resource object."

                        try
                        {

                            $UntaggedNetwork = Send-HPOVRequest -Uri $UntaggedNetwork -Hostname $ApplianceConnection.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                    #Name provided
                    else
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] UntaggedNetwork resource is [String] and Name. Getting resource object."

                        try
                        {

                            $UntaggedNetwork = Get-HPOVNetwork -Name $UntaggedNetwork -ApplianceConnection $ApplianceConnection.Name -ErrorAction Stop

                            if ($UntaggedNetwork.count -gt 1)
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException MultipleNetworkResourcesFound LimitsExceeded 'UntaggedNetwork' Message "Network '$_originalnet' is not a unique resource name, as multiple Network resources were found. Please correct theParameter value and try again."
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                }

                'PSCustomObject'
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Object: $($UntaggedNetwork | fl * | Out-String)"

                    #Object must have the ApplianceConnection NoteProperty
                    if (-not($UntaggedNetwork.ApplianceConnection))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException MissingApplianceConnectionNoteProperty InvalidArgument 'UntaggedNetwork' TargetType 'PSObject' -Message "Network '$($UntaggedNetwork.name)' does not contain the required 'ApplianceConnection' NoteProperty. Networkobjects must be retrieved from the appliance either using their unique URI or with Get-HPOVNetwork. Please correct the Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    elseif ($UntaggedNetwork.ApplianceConnection.Name -ne $ApplianceConnection.Name)
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException ApplianceConnetionDoesNotMatchObject InvalidArgument 'UntaggedNetwork' TargetType 'PSObject' -Message "Network '$($UntaggedNetwork.name)' 'ApplianceConnection' NoteProperty {$($UntaggedNetwork.ApplianceConnection.Name)}does notmatch the Appliance Connection currently Processing {$($ApplianceConnection.Name)}. Network objects must be retrieved from the appliance either using their unique URI or with Get-HPOVNetwork. Please correct the Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if ($UntaggedNetwork.category -ne 'ethernet-networks')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException UnsupportedResourceCategory InvalidArgument 'UntaggedNetwork' -TargetType'PSObject' -Message "Network '$($UntaggedNetwork.name)' category {$($UntaggedNetwork.category)} is not the supported type, 'ethernet-networks'. Network objects must be retrieved from the appliance either using their unique URI or with Get-HPOVNetwork using the -Type Ethernet Parameter.Please correct the Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                default
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException UnsupportedParameterValueType InvalidType 'UntaggedNetwork' -TargetType    $UntaggedNetwork.GetType().Name -Message "The provided UntaggedNetwork Parameter value type '$($UntaggedNetwork.GetType().Name)' is not supported. Only String (Name or URI) or PSCustomObject types are allowed and supported. Please correct the Parameter value and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            $_NewNetSet.nativeNetworkUri = $UntaggedNetwork.uri

        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network Set object: $($_NewNetSet | out-string)"

        #Caller is requesting different bandwidth settings. Need to handle async task to create network set.
        if ($PSBoundParameters['TypicalBandwidth'] -or $PSBoundParameters['MaximumBandwidth']) 
        {

            try 
            {

                $_task = Send-HPOVRequest -Uri $networkSetsUri -Method POST -Body $_NewNetSet -Hostname $ApplianceConnection.Name | Wait-HPOVTaskComplete

                if ($_task.taskStatus -eq "Created") 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network Set was successfully created"
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network Set bandwidth"
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Requested Typical bandwidth: $($typicalBandwidth)"
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Requested Maximum bandwidth: $($maximumBandwidth)"

                    #Get Network Set Object
                    Try
                    {

                        $_NetSetObj = Send-HPOVRequest -Uri $_task.associatedResource.resourceUri -Hostname $ApplianceConnection.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                        
                    # Update the associated connection template with max & typical bandwidth settings
                    Try
                    {

                        $_ct = Send-HPOVRequest -Uri $_NetSetObj.connectionTemplateUri -Hostname $ApplianceConnection.Name

                    }
                        
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                        

                    if ($PSBoundParameters['typicalBandwidth']) { $_ct.bandwidth.typicalBandwidth = $typicalBandwidth }

                    if ($PSBoundParameters['maximumBandwidth']) { $_ct.bandwidth.maximumBandwidth = $maximumBandwidth }
                        
                    #Update Connection Template Object
                    Try
                    {

                        $_ct = Send-HPOVRequest -Uri $_ct.uri -Method PUT -Body $_ct -Hostname $ApplianceConnection.Name

                    }
                        
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    #Get Network Set Object after CT has been updated
                    Try
                    {

                        $_NetSetObj = Send-HPOVRequest -Uri $_NetSetObj.uri -Hostname $ApplianceConnection.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                        
                }

            }

            catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            [void]$_NetSetStatusCol.Add($_NetSetObj)

        }

        else 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request with default bandwidth."

            Try
            {

                $_task = Send-HPOVRequest -Uri $networkSetsUri -Method POST -Body $_NewNetSet -Hostname $ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            [void]$_NetSetStatusCol.Add($_task)

        }

    }

    End 
    {

        #Return Network Set collection status/objects
        Return $_NetSetStatusCol

    }

}

function Get-HPOVNetworkSet 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (ParameterSetName = "Default", Mandatory = $false)]
        [Parameter (ParameterSetName = "Export", Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (ParameterSetName = "Default", Mandatory = $false)]
        [Parameter (ParameterSetName = "Export", Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,

        [Parameter (ParameterSetName = "Label", Mandatory = $false)]
        [Parameter (ParameterSetName = "Export", Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Label,
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "Label")]
        [Parameter (Mandatory = $false, ParameterSetName = "Export")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (ParameterSetName = "Label", Mandatory = $false)]
        [Parameter (ParameterSetName = "Export", Mandatory = $false)]
        [Alias ("x", "export")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$ExportFile

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_NetworkSetCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($Connection in $ApplianceConnection)
        {

            if ($PSBoundParameters['Label'])
            {

                $_uri = '{0}?category:network-sets&query=labels:{1}' -f $IndexUri, $Label

                Try
                {

                    $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                    #Loop through all found members and get full SVT object
                    ForEach ($_memeber in $_IndexMembers.members)
                    {

                        Try
                        {

                            $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        if ($_memeber.connectionTemplateUri) 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Network Set resource Connection Template Object to add bandwidth values to network objects."

                            Try
                            {

                                $ct = Send-HPOVRequest -uri $_memeber.connectionTemplateUri -Hostname $Connection

                            }
                        
                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                            Add-Member -InputObject $_memeber -NotePropertyName maximumBandwidth -NotePropertyValue $ct.bandwidth.maximumBandwidth -Force 
                            Add-Member -InputObject $_memeber -NotePropertyName typicalBandwidth -NotePropertyValue $ct.bandwidth.typicalBandwidth -Force

                        }

                        $_memeber.PSObject.TypeNames.Insert(0,"HPOneView.Networking.NetworkSet")  

                        $_memeber

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($Connection.Name)' Appliance (of $($ApplianceConnection.Count))"

                $uri = $networkSetsUri + "?sort=name:asc"

                if ($PSBoundParameters['Name'])
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filtering for Network Set name: $name"

                    $uri += "&filter=name matches '{0}'" -f $Name.Replace("*","%25")

                }

                if ($PSBoundParameters['Scope'])
                {

                    $Uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri
                
                }

                Try
                {

                    $_NetSets = Send-HPOVRequest $uri -Hostname $Connection

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                #Add to final collection arraylist
                if ($_NetSets.members) 
                { 
                            
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding results to collection"

                    $_NetSets.members | % { 

                        if ($_.connectionTemplateUri) 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Network Set resource Connection Template Object to add bandwidth values to network objects."

                            Try
                            {

                                $ct = Send-HPOVRequest -uri $_.connectionTemplateUri -Hostname $Connection

                            }
                        
                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                            Add-Member -InputObject $_ -NotePropertyName maximumBandwidth -NotePropertyValue $ct.bandwidth.maximumBandwidth -Force 
                            Add-Member -InputObject $_ -NotePropertyName typicalBandwidth -NotePropertyValue $ct.bandwidth.typicalBandwidth -Force

                        }

                        $_.PSObject.TypeNames.Insert(0,"HPOneView.Networking.NetworkSet")  

                        [void]$_NetworkSetCollection.Add($_)
                            
                    } 

                }
                
            }

        }

    }

    End 
    {

        #If network not found, report error
        if ((-not($_NetworkSetCollection)) -and $Name)
        { 

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network Set Resource Name was provided, yet no results were found. Generate Error."

            $ErrorRecord = New-ErrorRecord HPOneView.NetworkSetResourceException NetworkSetResourceNotFound ObjectNotFound "Name" -Message "The specified '$name' Network Set resource was not found. Please check the name and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($_NetworkSetCollection) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Results returned "

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network Sets Found: $($_NetworkSetCollection | fl * | out-string ) "

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. {0} network set resource(s) found." -f $_NetworkSetCollection.Count | Write-Verbose 
            
            if ($exportFile) 
            { 
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Exporting JSON to $($exportFile)"
            
                $_NetworkSetCollection | convertto-json > $exportFile
            
            }
            
            else
            {

                Return $_NetworkSetCollection
            
            }
        
        }

        #No network sets found
        else
        { 
            
            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Network set resources found." 
        
        }

    }

}

function Set-HPOVNetworkSet 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullorEmpty()]
        [Alias ('NetSet')]
        [Object]$NetworkSet,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Object]$Networks,

        [Parameter (Mandatory = $False)]
        [Alias ('untagged','native','untaggedNetworkUri')]
        [ValidateNotNullorEmpty()]
        [Object]$UntaggedNetwork,

        [Parameter (Mandatory = $false)]
        [validaterange(2,20000)]
        [int32]$TypicalBandwidth, 
        
        [Parameter (Mandatory = $false)]
        [validaterange(100,20000)]
        [int32]$MaximumBandwidth,

        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose
        
        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['NetworkSet']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                #Check for URI Parameters with multiple appliance connections
                if($ApplianceConnection.Count -gt 1)
                {

                    if ($NetworkSet -is [String] -and ($NetworkSet.StartsWith($networkSetsUri))) 
                    {
                    
                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'NetworkSet' -Message "The NetworkSet Parameter as URI is unsupported with multiple appliance connections. Please check the -NetworkSet Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
                    }

                    if (($Networks -is [string] -and $Networks.startswith($ethNetworksUri)) -or ($Networks -is [Array] -and ($Networks | % { $_.startswith($ethNetworksUri) })))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'Networks' -TargetType $Networks.GetType().Name -Message "Networks Parameter contains 1 or more URIs that are unsupported with multiple appliance connections. Please check the -networks Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if ($UntaggedNetwork -is [string] -and $UntaggedNetwork.startswith($ethNetworksUri)) 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'Set-HPOVNetworkSet' -Message "Untaggednetwork Parameter as URI is unsupported with multiple appliance connections. Please check the -untaggednetwork Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        #Process Network Set input object is the correct resource and data type.
        switch ($NetworkSet.Gettype().Name) 
        {

            "PSCustomObject" 
            { 
    
                if ($NetworkSet.category -eq "network-sets")
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($NetworkSet.type) $($NetworkSet.name) resource."

                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'NetworkSet' -TargetType 'PSObject' -Message "The provided NetworkSet resource contains an unsupported category type, '$($NetworkSet.category)'. Only 'network-sets' resources are allowed. Please check the -NetworkSet Parameter value and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }
                
            }

            "String" 
            { 
                
                if (-not ($NetworkSet.StartsWith($networkSetsUri)))
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting '$($NetworkSet)' resource from appliance."

                    Try
                    {

                        $NetworkSet = Get-HPOVNetworkSet $NetworkSet -appliance $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                        

                }

                elseif ($netSet.StartsWith($networkSetsUri))
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting '$($netSet)' resource from appliance."

                    Try
                    {

                        $NetworkSet = Send-HPOVRequest $NetworkSet -appliance $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                }
                
            }

            default
            {
                    
                $ErrorRecord = New-ErrorRecord HPOneView.NetworkSetResourceException InvalidArgumentValue InvalidArgument 'NetworkSet' -TargetType $NetworkSet.GetType().Name -Message "[$($netSet.gettype().name)] is an unsupported data type. Only [System.String] or [PSCustomObject] Network Set resources are allowed. Please check the -NetworkSet Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        $_UpdatedNetSet = $NetworkSet.PSObject.Copy()

        #Process Network Set Name change
        if ($PSBoundParameters["Name"]) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network Set name to '$name'."

            $_UpdatedNetSet.name = $name
            
        }

        if ($PSBoundParameters["Networks"]) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($Networks.count) network resources"

            $i = 1

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Clearing out existing networkUris."

            $_UpdatedNetSet.networkUris = New-Object System.Collections.ArrayList

            foreach ($_net in $Networks) 
            {

                switch ($_net.GetType().Name)
                {

                    'String'
                    {

                        if ($_net.startswith($ethNetworksUri)) 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network [$i] is a URI: $_net"

                            Try
                            {

                                [void]$_UpdatedNetSet.networkUris.Add((Send-HPOVRequest $UntaggedNetwork -Hostname $ApplianceConnection).uri)

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                        }

                        elseif ($_net -is [string]) 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network [$i] is a Name: $_net"

                            Try
                            {

                                $_networkObject = Get-HPOVNetwork $_net -type Ethernet -appliance $ApplianceConnection

                                [void]$_UpdatedNetSet.networkUris.Add($_networkObject.uri)

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }
                                
                        }

                    }

                    'PSCustomObject'
                    {

                        if ($_net.category -eq "ethernet-networks") 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network [$i] is a type [PsCustomObject]"
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network [$i] Name: $($_net.name)"
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network [$i] uri: $($_net.uri)"

                        }

                        else 
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'Networks' -TargetType $_Net.GetType().Name -Message "Network '$($_net.name)' is not a supported type '$($_net.gettype().fullname)'. Network resource must be either [System.String] or [PsCustomObject]. Please correct the Parameter value and try again."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        [void]$_UpdatedNetSet.networkUris.Add($_net.uri)

                    }

                    default
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'Networks' -TargetType $_Net.GetType().Name -Message "The provided Network is not a supported type '$($_net.gettype().fullname)'. Network resource must be either [System.String] or [PsCustomObject]. Please correct the Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                $i++
                    
            }

        }

        if ($PSBoundParameters["UntaggedNetwork"])
        {

            switch ($UntaggedNetwork.GetType().Name)
            {

                'String'
                {

                    if ($UntaggedNetwork.startswith($ethNetworksUri)) 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Untagged Network is a URI: $UntaggedNetwork"

                        Try
                        {

                            $_UpdatedNetSet.nativeNetworkUri = (Send-HPOVRequest $UntaggedNetwork -Hostname $ApplianceConnection).uri

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                    elseif ($UntaggedNetwork -is [string]) 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Untagged Network is a Name: $UntaggedNetwork"

                        Try
                        {

                            $_networkObject = Get-HPOVNetwork $UntaggedNetwork -type Ethernet -appliance $ApplianceConnection

                            $_UpdatedNetSet.nativeNetworkUri = $_networkObject.uri

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
                                
                    }

                }

                'PSCustomObject'
                {

                    if ($UntaggedNetwork.category -eq "ethernet-networks") 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Native Network is a type [PsCustomObject]"
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Native Network Name: $($UntaggedNetwork.name)"
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Native Network uri: $($UntaggedNetwork.uri)"

                    }

                    else 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'UntaggedNetwork' -TargetType $UntaggedNetwork.GetType().Name -Message "The UntaggedNetwork '$($UntaggedNetwork.name)' is not a supported type '$($UntaggedNetwork.gettype().fullname)'. Network resource must be either [System.String] or [PsCustomObject]. Please correct the Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    $_UpdatedNetSet.nativeNetworkUri = $UntaggedNetwork.uri

                }

                default
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'UntaggedNetwork' -TargetType $UntaggedNetwork.GetType().Name -Message "The provided UntaggedNetwork is not a supported type '$($UntaggedNetwork.gettype().fullname)'. Network resource must be either [System.String] or [PsCustomObject]. Please correct the Parameter value and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

        }

        #Process Network Set Bandwidth assignment change
        if ($PSBoundParameters["TypicalBandwidth"] -or $PSBoundParameters["MaximumBandwidth"]) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network bandwidth assignment."

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Network Set Connection Template."
                
            Try
            {

                $_ct = Send-HPOVRequest $_UpdatedNetSet.connectionTemplateUri -appliance $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
                
            if ($PSBoundParameters["MaximumBandwidth"]) 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Original Maximum bandwidth assignment: $($_ct.bandwidth.maximumBandwidth)"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Maximum bandwidth assignment: $MaximumBandwidth"

                $_ct.bandwidth.maximumBandwidth = $MaximumBandwidth

            }

            if($PSBoundParameters["TypicalBandwidth"]) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Original Typical bandwidth assignment: $($_ct.bandwidth.typicalBandwidth)"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Typical bandwidth assignment: $TypicalBandwidth"

                $_ct.bandwidth.typicalBandwidth = $TypicalBandwidth
                    
            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Connection Template: $($_ct | out-string)"

            Try
            {

                $_ct = Send-HPOVRequest $_UpdatedNetSet.connectionTemplateUri PUT $_ct -appliance $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_UpdatedNetSet = $_UpdatedNetSet | select * -ExcludeProperty typicalBandwidth, maximumBandwidth, created, modified, state, status
            
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network Resource object: $($_UpdatedNetSet | out-string)"

        Try
        {

            $_results = Send-HPOVRequest $_UpdatedNetSet.Uri PUT $_UpdatedNetSet -appliance $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        [void]$_TaskCollection.Add($_results)

    }

    End 
    {

        Return $_TaskCollection

    }

}

function Remove-HPOVNetworkSet 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default" ,SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (
        
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri","name")]
        [Object]$NetworkSet,

        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose
        
        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['NetworkSet']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                #Check for URI Parameters with multiple appliance connections
                if($ApplianceConnection.Count -gt 1)
                {

                    if (($NetworkSet -is [String] -and ($NetworkSet.StartsWith($networkSetsUri))) -or ($NetworkSet -is [Array] -and ($NetworkSet | % { $_.startswith($networkSetsUri) }))) 
                    {
                    
                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'NetworkSet' -Message "The NetworkSet Parameter as URI is unsupported with multiple appliance connections. Please check the -NetworkSet Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
                    }

                }


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_NetSetsToRemoveCol = New-Object System.Collections.ArrayList

        $_TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing pipeline input objects."

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received object: $($NetworkSet | fl * | Out-String)"

            if ($NetworkSet.category -ne 'network-sets')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.NetworkSetResourceException InvalidArgumentValue InvalidArgument 'NetworkSet' -TargetType 'PSObject' -Message "The provided Network Set {$($NetworkSet.Name)} is an unsupported object category, '$($NetworkSet.category)'. Only 'network-sets' category objects are supported. please chceck the Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            [void]$_NetSetsToRemoveCol.Add($NetworkSet)

        }

        Else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_appliance.Name) appliance connection (of $($ApplianceConnection.Count))."

                Try
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Network Set object from Get-HPOVNetworkSet."

                    $NetworkSet = Get-HPOVNetworkSet $NetworkSet -ApplianceConnection $_appliance

                    [void]$_NetSetsToRemoveCol.Add($NetworkSet)

                }

                Catch
                {


                    $PSCmdlet.ThrowTerminatingError($_)
                }

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Begin resource removal Process."

        foreach ($_NetSet in $_NetSetsToRemoveCol) 
        {

            if ($PSCmdlet.ShouldProcess($_NetSet.name,"Remove Network Set from appliance '$($_NetSet.ApplianceConnection.Name)'"))
            {   
             
                
                Try
                {
                    
                    $_task = Send-HPOVRequest $_NetSet.uri DELETE -Hostname $_NetSet.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_task)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Get-HPOVAddressPool 
{  

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateSet ('vmac', 'vwwn', 'vsn', 'IPv4', 'all')]
        [Array]$Type = "all",
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Requested Address Pool type: $($Type) "

        if ($Type -ieq "all") { $Type = @("VMAC", "VWWN", "VSN", "IPv4") }

        $_AddressPoolCollection = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            switch ($Type) 
            {

                'IPv4'
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Retrieve IPv4 Address Pool details."
                
                    #Get the VMAC Pool object
                    Try
                    {

                        $_IPv4Pool = Send-HPOVRequest $ApplianceIPv4PoolsUri -Hostname $_appliance.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    $_IPv4Pool | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AddressPool") } 
                    
                    [void]$_AddressPoolCollection.Add($_IPv4Pool)

                }

                "vmac" 
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Retrieve VMAC Address Pool details."
                
                    #Get the VMAC Pool object
                    Try
                    {

                        $_VMACPool = Send-HPOVRequest $ApplianceVmacPoolsUri -Hostname $_appliance.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    $_VMACPool | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AddressPool") } 
                    
                    [void]$_AddressPoolCollection.Add($_VMACPool)

                }

                "vwwn" 
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Retrieve VWWN Address Pool details."    
            
                    #Get the VWWN Pool object
                    Try
                    {

                        $_VWWNPool = Send-HPOVRequest $ApplianceVwwnPoolsUri -Hostname $_appliance.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    $_VWWNPool | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AddressPool") } 
                    
                    [void]$_AddressPoolCollection.Add($_VWWNPool)

                }
                
                "vsn" 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Retrieve VSN Address Pool details."

                    #Get the VSN Pool object
                    Try
                    {

                        $_VWWNPool = Send-HPOVRequest $ApplianceVsnPoolsUri -Hostname $_appliance.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    $_VWWNPool | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AddressPool") } 
                    
                    [void]$_AddressPoolCollection.Add($_VWWNPool)

                }

            }

        }

    }

    End 
    {

        return $_AddressPoolCollection 

    }

}

function Get-HPOVAddressPoolRange 
{  

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [ValidateSet ('IPv4', 'vmac', 'vwwn', 'vsn', 'all')]
        [Alias('Pool')]
        [Object]$Type = 'all',

        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = "Pipeline")]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Pipeline")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSCmdlet.ParameterSetName -eq 'Pipeline')
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_RangeList = New-Object System.Collections.ArrayList
                    
    }

    Process 
    {

        if ($PipelineInput -or $PSBoundParameters['InputObject'])
        {

            if (($InputObject.category -match "id-pool-" -or $InputObject.category -eq 'id-range-IPV4-subnet') -and $InputObject.ApplianceConnection) 
            {

                foreach ($_RangeUri in $InputObject.rangeUris) 
                {

                    Try
                    {

                        $_rangeObject = Send-HPOVRequest $_RangeUri -Hostname $InputObject.ApplianceConnection.Name

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    $_rangeObject | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AddressPoolRange") } 
                    
                    [void]$_RangeList.Add($_rangeObject)

                }

            }

            elseif ($InputObject.category -match "id-pool-" -and -not($InputObject.ApplianceConnection))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException MissingApplianceConnectionProperty InvalidArgument 'InputObject' 'PSObject' -Message "The InputObject Parameter value does not contain an ApplianceConnection property. Did this object come from Get-HPOVAddressPool or Send-HPOVRequest? Please correct the Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            else 
            {
            
                $ExceptionMessage = "The InputObject Parameter value is not a valid Poll ID object. Object Category '{0}', expected 'id-pool-vmac', 'id-pool-vwwn', or 'id-pool.vsn'. Please correct the Parameter value and try again." -f $InputObject.category
                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType 'PSObject' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

        }

        else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Try
                {

                    $_AddressPoolCol = Get-HPOVAddressPool -Type $Type -ApplianceConnection $_appliance.Name -ErrorAction Stop

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                foreach ($_AddressPool in $_AddressPoolCol) 
                {

                    ForEach ($_RangUri in $_AddressPool.rangeUris)
                    {

                        Try
                        {

                            $_rangeObject = Send-HPOVRequest $_RangUri -Hostname $_AddressPool.ApplianceConnection.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        $_rangeObject | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AddressPoolRange") } 

                        [void]$_RangeList.Add($_rangeObject)

                    }

                }

            }

        }    

    }

    End 
    {

        Return $_RangeList

    }

}

function Get-HPOVAddressPoolSubnet
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (
    
        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$NetworkId,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_SubnetCollection = New-Object System.Collections.ArrayList
                    
    }

    Process 
    {

        $uri = $ApplianceIPv4SubnetsUri

        if ($PSBoundParameters['NetworkId'])
        {

            $uri += "?filter=networkId='$NetworkId'"

        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($_appliance.ApplianceType -ne 'Composer')
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. This Cmdlet is only supported with Synergy Composers.' -f $_appliance.Name)
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                Try
                {

                    $_IPv4SubnetPool = Send-HPOVRequest $uri -ApplianceConnection $_appliance.Name

                    $_IPv4SubnetPool.members | % { 
                    
                        $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.IPv4AddressSubnet") 
                
                        [void]$_SubnetCollection.Add($_)

                    } 

                }

                Catch
                {

                    $_SubnetCollection

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($NetworkId -and -not $_IPv4SubnetPool.members)
                {

                    $ExceptionMessage = "The NetworkID {0} was not found on appliance {1}." -f $NetworkId, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolResourceException ResourceNotFound ObjectNotFound 'NetworkId' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }        

            }

        }

    }

    End 
    {

        Return $_SubnetCollection

    }

}

function New-HPOVAddressPoolSubnet
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (
    
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Net.IPAddress]$NetworkId,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$SubnetMask,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Net.IPAddress]$Gateway,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [String]$Domain,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Array]$DNSServers,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #Validate Parameters before auth
        if (($SubnetMask -lt 1 -or $SubnetMask -gt 32) -and ($SubnetMask -notmatch $IPSubnetAddressPattern))
        {

            $Exceptionmessage = "The provided SubnetID {0} does not appear to be a valid Subnet Mask." -f $SubnetMask
            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolResourceException InvalidIPv4SubnetMask InvalidArgument 'SubnetMask' -TargetType 'String' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_SubnetCollection = New-Object System.Collections.ArrayList
                    
    }

    Process
    {

        #Calculate the CIDR bit value to the SubnetMask Address
        if ($PSBoundParameters['SubnetMask'].Length -le 2)
        {

            Try
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Converting Subnet CIDR Bit value to Subnet Mask Address."

                [Int64]$_Int64Value = ([convert]::ToInt64(('1' * $SubnetMask + '0' * (32 - $SubnetMask)), 2))

                $SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($_Int64Value / 16777216)).ToString(),
                                                    ([math]::Truncate(($_Int64Value % 16777216) / 65536)).ToString(),
                                                    ([math]::Truncate(($_Int64Value % 65536)/256)).ToString(),
                                                    ([math]::Truncate($_Int64Value % 256)).ToString()

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ExcludedIPSubnetIDBin  = (([Net.IPAddress]$ExcludedIPSubnetID).IPAddressToString -split '\.' | ForEach-Object {[System.Convert]::ToString($_,2).PadLeft(8,'0')}) -join ""
        $_ExcludedIPSubnetEndBin = (([Net.IPAddress]$ExcludedIPSubnetEnd).IPAddressToString -split '\.' | ForEach-Object {[System.Convert]::ToString($_,2).PadLeft(8,'0')}) -join ""
        $_NetworIdDecBin         = (([Net.IPAddress]$NetworkId.IPAddressToString).IPAddressToString -split '\.' | ForEach-Object {[System.Convert]::ToString($_,2).PadLeft(8,'0')}) -join ""

        "[{0}] NetworkID overlaps with Reserved Address: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), (($_NetworIdDecBin -eq $_ExcludedIPSubnetIDBin) -or (($_NetworIdDecBin -ge $_ExcludedIPSubnetIDBin) -and ($_NetworIdDecBin -le $_ExcludedIPSubnetEndBin))) | Write-Verbose
        "[{0}] {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_NetworIdDecBin -eq $_ExcludedIPSubnetIDBin) | Write-Verbose
        "[{0}] {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), (($_NetworIdDecBin -ge $_ExcludedIPSubnetIDBin) -and ($_NetworIdDecBin -le $_ExcludedIPSubnetEndBin)) | Write-Verbose

        "{0}" -f $_NetworIdDecBin | Write-Verbose
        "{0}" -f $_ExcludedIPSubnetIDBin | Write-Verbose
        "{0}" -f $_ExcludedIPSubnetEndBin | Write-Verbose

        #"[{0}] {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_NetworkIdBin -le $_ExcludedIPSubnetEndBin) | Write-Verbose

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($_appliance.ApplianceType -ne 'Composer')
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. This Cmdlet is only supported with Synergy Composers.' -f $_appliance.Name)
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                #if ($_connection.ApplianceType -eq 'Composer' -and (($_NetworkIdBin -eq $_ExcludedIPSubnetIDBin) -or (($_NetworkIdBin -ge $_ExcludedIPSubnetIDBin) -and ($_NetworkIdBin -le $_ExcludedIPSubnetEndBin))))
                if (($_NetworIdDecBin -eq $_ExcludedIPSubnetIDBin) -or (($_NetworIdDecBin -ge $_ExcludedIPSubnetIDBin) -and ($_NetworIdDecBin -le $_ExcludedIPSubnetEndBin)))
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] The calculated SubnetID overlaps with the reserved IP Address range, 172.30.254.0/24."

                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolResourceException InvalidIPv4AddressPoolResource InvalidArgument 'NetworkId' -TargetType 'System.Net.IPAddress' -Message ("The provided SubnetID {0} overlaps with the reserved {1} subnet. Please choose a different IPv4 SubnetID." -f $NetworkId, $ExcludedIPSubnetID.IPAddressToString)
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $_NewSubnet = NewObject -IPv4Subnet

                $_NewSubnet.networkId  = $NetworkId.IPAddressToString
                $_NewSubnet.subnetmask = $SubnetMask
                $_NewSubnet.gateway    = $Gateway.IPAddressToString
                $_NewSubnet.domain     = $Domain
            
                if ($PSBoundParameters['DnsServers'])
                {

                    $DnsServers | % { 

                        [void]$_NewSubnet.dnsServers.Add($_)

                    }

                }

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Defining new IPv4 Subnet object: {0}" -f ($_NewSubnet | fl * | Out-String) | Write-Verbose 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

                Try
                {

                    $_resp = Send-HPOVRequest $ApplianceIPv4SubnetsUri POST $_NewSubnet -Hostname $_appliance.Name

                    $_resp.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.IPv4AddressSubnet")

                    [void]$_SubnetCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
    
    }

    End
    {

        Return $_SubnetCollection

    }

}

function Set-HPOVAddressPoolSubnet
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'IPv4')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "IPv4")]
        [Alias ('Subnet','IPv4Subnet')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "IPv4")]
        [ValidateScript({ [string]::IsNullOrEmpty($_) -or
            $_ -match [Net.IPAddress]$_})]
        [Net.IPAddress]$SubnetMask,

        [Parameter (Mandatory = $false, ParameterSetName = "IPv4")]
        [ValidateScript({ [string]::IsNullOrEmpty($_) -or
            $_ -match [Net.IPAddress]$_})]
        [Net.IPAddress]$Gateway,

        [Parameter (Mandatory = $false, ParameterSetName = "IPv4")]
        [ValidateNotNullorEmpty()]
        [String]$Domain,

        [Parameter (Mandatory = $false, ParameterSetName = "IPv4")]
        [ValidateNotNullorEmpty()]
        [Array]$DNSServers,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName , ParameterSetName = "IPv4")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {
            
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_SubnetCollection = New-Object System.Collections.ArrayList
                    
    }

    Process
    {

        #Validate IPv4Subnet object
        if ($InputObject.category -ne 'id-range-IPv4-subnet')
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid IPv4 Address Pool resource object."

            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolResourceException InvalidIPv4AddressPoolResource InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "An invalid IPv4 Address Pool resource object was provided. Please verify the Parameter value and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }
        
        switch ($PSBoundParameters.keys)
        {

            'SubnetMask'
            {

                $InputObject.subnetMask = $SubnetMask.IPAddressToString

            }

            'Gateway'
            {

                $InputObject.gateway = $Gateway.IPAddressToString

            }

            'Domain'
            {

                $InputObject.domain = $Domain

            }

            'DNSServers'
            {

                $InputObject.DNSServers = New-Object System.Collections.ArrayList

                $DNSServers | % { [void]$InputObject.DNSServers.Add($_) }

            }

        }

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Defining new IPv4 Subnet object: {0}" -f ($InputObject | fl * | Out-String) | Write-Verbose 

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

        Try
        {

            $_resp = Send-HPOVRequest $InputObject.uri PUT $InputObject -Hostname $ApplianceConnection.Name

            $_resp.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.IPv4AddressSubnet")

            [void]$_SubnetCollection.Add($_resp)

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
    
    }

    End
    {

        Return $_SubnetCollection

    }

}

function Remove-HPOVAddressPoolSubnet 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "IPv4",SupportsShouldProcess,ConfirmImpact = 'High')]
    Param 
    (
        
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "IPv4")]
        [Alias ('Subnet')]
        [ValidateNotNullorEmpty()]
        [Object]$IPv4Subnet,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName , ParameterSetName = "IPv4")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose
        
        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['IPv4Subnet']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_IPv4SubnetPoolsToRemoveCol = New-Object System.Collections.ArrayList

        $_TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing pipeline input objects."

        }

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received object: {0}" -f ($IPv4Subnet | fl * | Out-String) | Write-Verbose

        if ($IPv4Subnet.category -ne 'id-range-IPv4-subnet')
        {

            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressSubnetException InvalidArgumentValue InvalidArgument 'IPv4Subnet' -TargetType 'PSObject' -Message "The provided IPv4Subnet {$($IPv4Subnet.Name)} is an unsupported object category, '$($IPv4Subnet.category)'. Only 'id-range-IPv4-subnet' category objects are supported. Please chceck the Parameter value and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        [void]$_IPv4SubnetPoolsToRemoveCol.Add($IPv4Subnet)

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Begin resource removal Process."

        foreach ($_Subnet in $_IPv4SubnetPoolsToRemoveCol) 
        {

            if ($PSCmdlet.ShouldProcess($_Subnet.ApplianceConnection.Name,("Remove IPv4 SubnetID '{0}'" -f $_Subnet.networkId)))
            {   
             
                
                Try
                {
                    
                    $_task = Send-HPOVRequest $_Subnet.uri DELETE -Hostname $_Subnet.ApplianceConnection.Name

                    [void]$_TaskCollection.Add($_task)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function New-HPOVAddressPoolRange 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "IPv4")]
        [Alias ('Subnet')]
        [ValidateNotNullorEmpty()]
        [Object]$IPv4Subnet,
    
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "Custom")]
        [ValidateSet ('vmac', 'vwwn', 'vsn')]
        [String]$PoolType,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "Custom")]
        [ValidateSet ("Generated", "Custom")]
        [String]$RangeType = "Generated",

        [Parameter (Mandatory, ParameterSetName = "IPv4")]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory, ParameterSetName = "Custom")]
        [Parameter (Mandatory, ParameterSetName = "IPv4")]
        [ValidateNotNullorEmpty()]
        [String]$Start,

        [Parameter (Mandatory, ParameterSetName = "Custom")]
        [Parameter (Mandatory, ParameterSetName = "IPv4")]
        [ValidateNotNullorEmpty()]
        [String]$End,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [Parameter (Mandatory = $False, ParameterSetName = "Custom")]
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "IPv4")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    { 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSCmdlet.ParameterSetName -eq 'IPv4' -and (-not($PSBoundParameters['IPv4Subnet'])))
        {

            $PipelineInput = $True

        }
        
        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_Collection = New-Object System.Collections.ArrayList

        #Validate Parameter options here
        if ($PSCmdlet.ParameterSetName -eq 'Custom' -and $RangeType -ne 'Custom')
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException LogicalInterconnectUriNoApplianceConnection InvalidArgument 'RangeType' -Message "Custom Address Range was provided, but the RangeType Parameter value was not set to 'Custom'. Please check to make sure your call is correct, and try again.."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Generate error when defining custom range and not a specific appliance
        if ($PSCmdlet.ParameterSetName -eq 'Custom' -and $ApplianceConnection.count -gt 1)
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException LogicalInterconnectUriNoApplianceConnection InvalidArgument 'ApplianceConnection' -Message "A Custom Address Range was provided with no Appliance Connection specified. Custom Address Pool Ranges should be unique per appliance connection. Please specify an Appliance Connection and try your call again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }
    
    }

    Process 
    {

        if ($PSCmdlet.ParameterSetName -eq 'IPv4')
        {

            #Validate IPv4Subnet value
            if ($IPv4Subnet.category -ne 'id-range-IPv4-subnet')
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid IPv4 Address Pool resource object."

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolResourceException InvalidIPv4AddressPoolResource InvalidArgument 'IPv4Subnet' -TargetType 'PSObject' -Message "An invalid IPv4 Address Pool resource object was provided. Please verify the Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if (-not [HPOneView.Appliance.AddressPool]::IsInSameSubnet($Start,$IPv4Subnet.networkId,$IPv4Subnet.subnetMask))
            {

                "[{0}] The Start address value {1} is not within the Subnet Network ID {2}." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Start, $IPv4Subnet.networkId | Write-Verbose

                $Exceptionmessage = "The Start address value {0} is not within the Subnet Network ID {1}\{2}." -f $Start, $IPv4Subnet.networkId, $IPv4Subnet.subnetMask

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolResourceException InvalidIPv4AddressPoolResource InvalidArgument 'Start' -TargetType 'PSObject' -Message $Exceptionmessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if (-not [HPOneView.Appliance.AddressPool]::IsInSameSubnet($End,$IPv4Subnet.networkId,$IPv4Subnet.subnetMask))
            {

                "[{0}] The End address value {1} is not within the Subnet Network ID {2}." -f $MyInvocation.InvocationName.ToString().ToUpper(), $End, $IPv4Subnet.networkId | Write-Verbose

                $Exceptionmessage = "The End address value {0} is not within the Subnet Network ID {1}\{2}." -f $End, $IPv4Subnet.networkId, $IPv4Subnet.subnetMask

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolResourceException InvalidIPv4AddressPoolResource InvalidArgument 'End' -TargetType 'PSObject' -Message $Exceptionmessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Create Pool Range, then assign to Subnet
            $_newRange = NewObject -IDPoolRange
            $_newRange.name         = $Name
            $_newRange.startAddress = $Start
            $_newRange.endAddress   = $End
            $_newRange.subnetUri    = $IPv4Subnet.uri

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Range Object: $($_newRange | FL * | out-string)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

            Try
            {

                $_resp = Send-HPOVRequest $ApplianceIPv4PoolRangesUri POST $_newRange -Hostname $ApplianceConnection.Name

                $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.AddressPoolRange')

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            
            [void]$_Collection.Add($_resp)

        }

        else
        {
                    
            ForEach ($_appliance in $ApplianceConnection)
            {

                "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

                #Get the correct URI to request a new Generated Address Range
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating new $($PoolType) type address range"

                switch ($PoolType) 
                {

                    "vmac" 
                    { 
            
                        $_newGenRangeUri  = $script:ApplianceVmacGenerateUri
                        $_newPoolRangeUri = $script:ApplianceVmacPoolRangesUri

                    }

                    "vwwn" 
                    { 
            
                        $_newGenRangeUri  = $script:ApplianceVwwnGenerateUri
                        $_newPoolRangeUri = $script:ApplianceVwwnPoolRangesUri
                
                    }

                    "vsn" 
                    { 
            
                        $_newGenRangeUri  = $script:ApplianceVsnPoolGenerateUri
                        $_newPoolRangeUri = $script:ApplianceVsnPoolRangesUri
            
                    }

                }

                switch ($RangeType) 
                {

                    "Generated" 
                    {
                    
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Generating new address range"
                
                        #sEnd the request, and remove the fragmentType property as it's not a valid JSON pfield for the request.
                        Try
                        {

                            $_newRange = Send-HPOVRequest $_newGenRangeUri -Hostname $_appliance.Name | Select-Object -Property * -excludeproperty fragmentType

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        $_newRange | add-member -NotePropertyName type -NotePropertyValue "Range"
                        $_newRange | add-member -NotePropertyName rangeCategory -NotePropertyValue "GENERATED"

                    }
                
                    "Custom" 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating custom new address range"
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Starting Address: $($Start)"
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] End Address: $($End)"

                        switch ($PoolType) 
                        {
                        
                            "vmac" 
                            {
                            
                                if (-not($Start -match ($macAddressPattern))) 
                                { 
                                
                                    $ExceptionMessage = "The provided Start address {0} does not conform to a valid MAC Address value." -f $Start

                                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolRangeException InvalidMacStartAddress InvalidArgument 'Start' -Message $ExceptionMessage 
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                if (-not($End -match ($macAddressPattern))) 
                                { 
                                
                                    $ExceptionMessage = "The provided End address {0} does not conform to a valid MAC Address value." -f $End

                                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolRangeException InvalidMacendAddress InvalidArgument 'End' -Message $ExceptionMessage 
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                                }

                             }
                        
                            "vwwn" 
                            {
                        
                                if (-not($Start -match ($wwnAddressPattern))) 
                                { 
                                
                                    $ExceptionMessage = "The provided Start address {0} does not conform to a valid WWN Address value." -f $Start

                                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolRangeException InvalidWwnStartAddress InvalidArgument 'Start' -Message $ExceptionMessage 
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                                }

                                if (-not($End -match ($wwnAddressPattern))) 
                                { 
                                
                                    $ExceptionMessage = "The provided End address {0} does not conform to a valid WWN Address value." -f $End

                                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolRangeException InvalidWwnendAddress InvalidArgument 'End' -Message $ExceptionMessage 
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                                }
                        
                            }

                            "vsn" 
                            {
                        
                                if (-not $Start.StartsWith('VCU')) 
                                { 
                                
                                    $ExceptionMessage = "The provided Start address {0} does not conform to a valid Serial Number value." -f $Start

                                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolRangeException InvalidSerialNumberStartAddress InvalidArgument 'Start' -Message $ExceptionMessage 
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                                }

                                if (-not $End.StartsWith('VCU')) 
                                { 
                                
                                    $ExceptionMessage = "The provided End address {0} does not conform to a valid Serial Number value." -f $End

                                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressPoolRangeException InvalidSerialNumberendAddress InvalidArgument 'End' -Message $ExceptionMessage 
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                                }
                        
                            }

                        }
                    
                        $_newRange = NewObject -IDPoolRange

                        $_newRange.startAddress = $Start
                        $_newRange.endAddress   = $End
                
                    }

                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Range Object: $($_newRange | FL * | out-string)"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

                Try
                {

                    $_resp = Send-HPOVRequest $_newPoolRangeUri POST $_newRange -Hostname $_appliance.Name

                    $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.AddressPoolRange')

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                [void]$_Collection.Add($_resp)

            }

        }

    }

    End
    {

        return $_Collection

    }

}

function Remove-HPOVAddressPoolRange
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (
        
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [Alias ('AddressPool')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName , ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose
        
        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_AddressPoolsToRemoveCol = New-Object System.Collections.ArrayList

        $_TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing pipeline input objects."

        }

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received object: {0}" -f ($InputObject | fl * | Out-String) | Write-Verbose

        if ($InputObject.category -notmatch 'id-range-')
        {

            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AddressSubnetException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided InputObject {$($InputObject.Name)} is an unsupported object category, '$($InputObject.category)'. Only 'id-range-VMAC', 'id-range-VWWN', 'id-range-VSN' or 'id-range-IPv4-subnet' category objects are supported."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        [void]$_AddressPoolsToRemoveCol.Add($InputObject)

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Begin resource removal Process."

        foreach ($_Pool in $_AddressPoolsToRemoveCol) 
        {

            if ($PSCmdlet.ShouldProcess($_Pool.ApplianceConnection.Name,("Remove address pool range 'Start:{0} (End:{1})'" -f $_Pool.startAddress, $_Pool.endAddress)))
            {   
             
                
                Try
                {
                    
                    Send-HPOVRequest $_Pool.uri DELETE -Hostname $_Pool.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] Caller passed -WhatIf Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] Caller selected NO to confirmation prompt." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        #Return $_TaskCollection

    }

}

#######################################################
# Interconnects and Uplinks
#

function Get-HPOVInterconnectType 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Name')]
    Param
    (
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Name')]
        [ValidateNotNullorEmpty()]
        [string]$Name,

        [Parameter (Mandatory, ParameterSetName = 'PartNumber')]
        [ValidateNotNullorEmpty()]
        [string]$PartNumber,

        [Parameter (Mandatory = $false, ParameterSetName = 'Name')]
        [Parameter (Mandatory = $false, ParameterSetName = 'PartNumber')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    { 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $Collection = New-Object System.Collections.ArrayList
        $NotFound   = New-Object System.Collections.ArrayList
    
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            $uri = $interconnectTypesUri + "?sort=name:descEnding"

            if ($PSboundParameters['Name']) 
            { 
                
                $uri += "&filter=name='$name'" 
            
            }
            
            elseif ($PSboundParameters['PartNumber']) 
            {
                
                $uri += "&filter=partNumber='$partNumber'" 
            
            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

            Try
            {

                $resp = Send-HPOVRequest $uri -Appliance $_appliance

            }

            Catch
            {

              $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($resp.count -gt 0)
            {

                $resp.members | Sort-Object name | % {

                    $_interconnectType = $_

                    $_interconnectType | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.InterconnectType')}

                    [void]$Collection.Add($_interconnectType)

                }

            }

            else 
            {

                [Void]$NotFound.Add($_appliance.Name)

            }

        }

    }

    End 
    {

        if (((-not $Collection) -or ($NotFound.count -gt 1)) -and $Name) 
        {

            $Collection

            $ExceptionMessage = "No Interconnect Types with '{0}' name were found on appliance {1}." -f $Name, ($NotFound -join ", ")
            $ErrorRecord = New-ErrorRecord HPOneView.InterconnectResourceException InterconnectTypeNameResourceNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
            $PSCmdlet.WriteError($ErrorRecord)

        }

        elseif (((-not $Collection) -or ($NotFound.count -gt 0)) -and $PartNumber) 
        {

            $Collection

            $ExceptionMessage = "No Interconnect Types with '{0}' nampartnumbere were found on appliance {1}." -f $PartNumber, ($NotFound -join ", ")
            $ErrorRecord = New-ErrorRecord HPOneView.InterconnectTypeResourceException InterconnectTypePartnumberResourceNotFound ObjectNotFound 'PartNumber' -Message $ExceptionMessage
            $PSCmdlet.WriteError($ErrorRecord)

        }

        else 
        { 
        
            return $Collection

        }

    }

}

function Get-HPOVSasInterconnectType 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Name')]
    Param
    (
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Name')]
        [ValidateNotNullorEmpty()]
        [string]$Name,

        [Parameter (Mandatory, ParameterSetName = 'PartNumber')]
        [ValidateNotNullorEmpty()]
        [string]$PartNumber,

        [Parameter (Mandatory = $false, ParameterSetName = 'Name')]
        [Parameter (Mandatory = $false, ParameterSetName = 'PartNumber')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    { 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $Collection = New-Object System.Collections.ArrayList
        $NotFound   = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($_appliance.ApplianceType -ne 'Composer')
            {
    
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is an HPE OneView Virtual Machine Appliance, which does not support SAS Logical Interconnect Group resources.' -f $_appliance.Name)
                $PSCmdlet.WriteError($ErrorRecord)
    
            }    

            else
            {        

                $uri = $SasInterconnectTypeUri  + "?sort=name:descEnding"

                if ($PSboundParameters['Name']) 
                { 
                    
                    $uri += "&filter=name='$name'" 
                
                }
                
                elseif ($PSboundParameters['PartNumber']) 
                {
                    
                    $uri += "&filter=partNumber='$partNumber'" 
                
                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

                Try
                {

                    $resp = Send-HPOVRequest $uri -Appliance $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($resp.count -gt 0)
                {

                    $resp.members | Sort-Object name | % {

                        $_interconnectType = $_

                        $_interconnectType | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.SasInterconnectType')}

                        [void]$Collection.Add($_interconnectType)

                    }

                }

                elseif ($resp.count -eq 0 -and $Name)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.InterconnectResourceException SasInterconnectTypeNameResourceNotFound ObjectNotFound 'Name' -Message "No SAS Interconnect Types with '{0}' name were found on appliance '{1}'." -f $Name, $_appliance.Name
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                elseif ($resp.count -eq 0 -and $PartNumber)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.InterconnectResourceException InterconnectTypePartnumberResourceNotFound ObjectNotFound 'Name' -Message "No SAS Interconnect Types with '{0}' PartNumber were found on appliance '{1}'." -f $PartNumber, $_appliance.Name
                    $PSCmdlet.WriteError($ErrorRecord)

                }

            }

        }

    }

    End 
    {

        return $Collection

    }

}

function Get-HPOVInterconnect 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false)]
        [Alias ("x", "exportFile")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$Export

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $InterconnectCollection   = New-Object System.Collections.ArrayList
        $ApplianceInterconnectCol = New-Object System.Collections.ArrayList
        $NotFound                 = New-Object System.Collections.ArrayList
        
        $InterconnecUris = $SasInterconnectsUri, $InterconnectsUri
        
    }
    
    Process 
    {

        if ($PSBoundParameters['Name'])
        {

            $Name = $Name.Replace("*","%25").Replace("&","%26")

        }    

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($PSBoundParameters['Label'])
            {

                if ($ApplianceConnection.ApplianceType -eq 'Composer')
                {

                    $_uri = '{0}?category:interconnects&query=labels:{1}' -f $IndexUri, $Label
                
                }

                else
                {

                    $_uri = '{0}?category:interconnects&category:sas-interconnects&query=labels:{1}' -f $IndexUri, $Label

                }

                Try
                {

                    $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                    #Loop through all found members and get full SVT object
                    ForEach ($_memeber in $_IndexMembers.members)
                    {

                        Try
                        {

                            $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                        

                        switch ($_memeber.category)
                        {

                            'sas-interconnects'
                            {

                                #Add the Custom TypeName
                                $_memeber.PSObject.TypeNames.Insert(0,"HPOneView.Networking.SasInterconnect") 

                            }

                            'interconnects'
                            {

                                #Add the Custom TypeName
                                $_memeber.PSObject.TypeNames.Insert(0,"HPOneView.Networking.Interconnect") 

                                #Add the Custom Uplink/Stacking Link TypeName
                                $_memeber.ports | ? { $_.portType -eq "Uplink" -or $_.portType -eq "Stacking" } | % { 
                
                                    $_.PSObject.TypeNames.Insert(0,"HPOneView.Networking.Interconnect.UplinkPort") 

                                    $_ | Add-Member -NotePropertyName ApplianceConnection -NotePropertyValue (New-Object HPOneView.Library.ApplianceConnection($_appliance.Name, $_appliance.ConnectionID))
            
                                }
                        
                                #Add the Custom Downlink Link TypeName
                                $_memeber.ports | ? { $_.portType -eq "Downlink" } | % { 
                
                                    $_.PSObject.TypeNames.Insert(0,"HPOneView.Networking.Interconnect.DownlinkPort") 

                                    $_ | Add-Member -NotePropertyName ApplianceConnection -NotePropertyValue (New-Object HPOneView.Library.ApplianceConnection($_appliance.Name, $_appliance.ConnectionID))
            
                                }
                            
                            }

                        }

                        $_memeber

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose        

                ForEach ($_IntTypeUri in $InterconnecUris)
                {
                    
                    if ($ApplianceConnection.ApplianceType -ne 'Composer' -and $_IntTypeUri -eq $SasInterconnectsUri)
                    {
                    
                        "[{0}] Skipping {1} URI, as it isn't supported." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_IntTypeUri | Write-Verbose
                    
                    }

                    else
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to retrieve $_IntTypeUri Interconnects."

                        $_uri = $_IntTypeUri + "?sort=name:asc"

                        if ($Name)
                        {

                            $_uri += "&filter=name matches '{0}'" -f $Name

                        }

                        if ($PSBoundParameters['Scope'])
                        {

                            $Uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri
                        
                        }

                        Try
                        {

                            $_interconnects = Send-HPOVRequest $_uri -hostname $_appliance.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }            

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($_interconnects.count) Interconnects found."

                        if ($_interconnects.members) 
                        {

                            ForEach ($_interconnect in $_interconnects.members)
                            {

                                switch ($_interconnect.category)
                                {

                                    'sas-interconnects'
                                    {

                                        #Add the Custom TypeName
                                        $_interconnect.PSObject.TypeNames.Insert(0,"HPOneView.Networking.SasInterconnect") 

                                    }

                                    'interconnects'
                                    {

                                        #Add the Custom TypeName
                                        $_interconnect.PSObject.TypeNames.Insert(0,"HPOneView.Networking.Interconnect") 

                                        #Add the Custom Uplink/Stacking Link TypeName
                                        $_interconnect.ports | ? { $_.portType -eq "Uplink" -or $_.portType -eq "Stacking" } | % { 
                        
                                            $_.PSObject.TypeNames.Insert(0,"HPOneView.Networking.Interconnect.UplinkPort") 

                                            $_ | Add-Member -NotePropertyName ApplianceConnection -NotePropertyValue (New-Object HPOneView.Library.ApplianceConnection($_appliance.Name, $_appliance.ConnectionID))
                    
                                        }
                                
                                        #Add the Custom Downlink Link TypeName
                                        $_interconnect.ports | ? { $_.portType -eq "Downlink" } | % { 
                        
                                            $_.PSObject.TypeNames.Insert(0,"HPOneView.Networking.Interconnect.DownlinkPort") 

                                            $_ | Add-Member -NotePropertyName ApplianceConnection -NotePropertyValue (New-Object HPOneView.Library.ApplianceConnection($_appliance.Name, $_appliance.ConnectionID))
                    
                                        }
                                
                                    }

                                }

                                [void]$ApplianceInterconnectCol.Add($_interconnect)

                            }

                        }

                        else
                        {

                            "[{0}] Interconnect '{1}' was not found at {2} Endpoint. Adding appliance to notfound collection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name, $_IntTypeUri | Write-Verbose
                            
                            [Void]$NotFound.Add($_appliance.Name)

                        }

                    }
                    
                }

            }

            #Generate final error if name wasn't found on appliance(s)
            if ($NotFound.count -gt 0 -and $Name -and $ApplianceInterconnectCol.count -eq 0) 
            {

                $ErrorRecord = New-ErrorRecord HPOneView.InterconnectResourceException InterconnectNameResourceNotFound ObjectNotFound 'Name' -Message "No Interconnect resources with '$Name' name were found on appliance $($NotFound -join ", ")."
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                $ApplianceInterconnectCol | % { [void]$InterconnectCollection.Add($_) }

            }

        }

    }

    End 
    {

        Write-Verbose "Done. $($InterconnectCollection.count) logical interconnect(s) found."

        "[{0}] NotFound Count: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(),$NotFound.count | Write-Verbose

        if ($Export)
        { 
                
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Exporting to: $($Export)"

            $InterconnectCollection  | convertto-json -Depth 99 | Set-Content -Path $Export -force -encoding UTF8
                
        }

        else
        {

            Return $InterconnectCollection

        }

    }
    
}

function Get-HPOVLogicalInterconnect 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [String]$Label,
        
        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Alias ("x", "ExportFile")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$Export

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $LiCollection = New-Object System.Collections.ArrayList
        $NotFound     = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {
        <#
        $uri = $logicalInterconnectsUri
        $Method = 'eq'
 
        if ($Name)
        {
 
            if ($Name.Contains('*'))
            {
 
                $Name = $Name.Replace.("*","%25")
                $Method = 'matches'
 
            }
 
        }
        #>

        ForEach ($_appliance in $ApplianceConnection)
        {

            $_IndexLookup = $false

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose        

            if ($Name) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconnect name provided: '$Name'"

                #Search Index to workaround a CRM LI filter bug
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Searching index for Logical Interconnect resource."

                # // Uncomment when CRM LI filter bug is fixed.
                #$uri = "{0}?filter=name='{1}'" -f $logicalInterconnectsUri, $Name

                $uri = "{0}?filter=name:'{1}'&category=logical-interconnects&sort=name:asc" -f $IndexUri, $Name

                $_IndexLookup = $true

            }

            if ($PSBoundParameters['Scope'])
            {

                if ($_IndexLookup)
                {

                    $uri += "&query=scope:'{0}'" -f $Scope.Name

                }

                else
                {

                    $uri = "{0}?category=logical-interconnects&query=scope:'{1}'&sort=name:asc" -f $IndexUri, $Scope.Name

                }

                $_IndexLookup = $true

            }

            else 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Logical Interconnect name provided. Looking for all Logical Interconnect resources."
                
                $uri = $LogicalInterconnectsUri

            }

            if ($PSBoundParameters['Label'])
            {

                if ($PSBoundParameters['Name'])
                {

                    $uri += '&query=labels:{0}' -f $Label

                }

                else
                {

                    $uri = "{0}?category:logical-interconnects&sort=name:asc&query=labels:{1}" -f $IndexUri, $Label

                }

                $_IndexLookup = $true

            }

            Try
            {

                $resp = Send-HPOVRequest $uri -Hostname $_appliance.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
                
            if ($resp.count -eq 0 -and $Name) 
            { 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconnect '$name' resource not found on '$($_appliance.Name)'. Adding to notfound collection."

                $ExceptionMessage = "Specified Logical Interconnect '{0}' was not found on '{1}' appliance. Please check the name and try again." -f $Name, $_appliance.Name
                $ErrorRecord = New-ErrorRecord InvalidOperationException LogicalInterconnectGroupNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)  

            }

            elseif ($resp.count -eq 0) 
            { 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Logical Interconnect resources found on '$($_appliance.name)'."

            }

            else 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($resp.count) Logical Interconnect resource(s)."

                ForEach ($_LiObject in $resp.members)
                {

                     "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting LI resource object for {0}." -f $_ligindexitem.name | Write-Verbose

                    Try
                    {

                        if ($_IndexLookup)
                        {

                            $_LiObject = Send-HPOVRequest $_LiObject.uri -Hostname $_appliance.Name

                        }                        

                        $_LiObject.PSobject.TypeNames.Insert(0,"HPOneView.Networking.LogicalInterconnect")  #FORMAT DONE
                        $_LiObject.snmpConfiguration | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnect.SnmpConfiguration') } #FORMAT DONE
                        $_LiObject.snmpConfiguration.trapDestinations | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnect.SnmpConfiguration.Destinations') } #FORMAT DONE
                        $_LiObject.ethernetSettings | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnect.InterconnectSettings') }
                        $_LiObject.telemetryConfiguration | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnect.UtilizationSampleSettings') }
                        $_LiObject.portMonitor | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnect.PortMonitorSettings') }
                    
                        [void]$LiCollection.Add($_LiObject) 

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }
 
            }

        }
   
    }

    End 
    {
        
        Write-Verbose "Done. $($lsws.count) logical interconnect group(s) found." 

        if ($Export)
        {
            
            $LiCollection | convertto-json -Depth 99 | Set-Content -Path $exportFile -force -encoding UTF8 
        
        }
        
        else 
        {

             $LiCollection 
        
        }    

    }

}

function Get-HPOVSasLogicalInterconnect 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [String]$Label,
        
        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Alias ("x", "ExportFile")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$Export

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $LiCollection = New-Object System.Collections.ArrayList
        $NotFound     = New-Object System.Collections.ArrayList

        if (-not $PSBoundParameters['Type'])
        {

            $Type = 'Ethernet', 'FibreChannel', 'SAS'

        }
        
    }
    
    Process 
    {
        
        ForEach ($_appliance in $ApplianceConnection)
        {

            $_IndexLookup = $false

            $uri = $SasLogicalInterconnectsUri

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose        

            if ($PSBoundParameters['Name']) 
            {

                $Method = 'eq'

                if ($Name.Contains('*'))
                {

                    $Name = $Name.Replace('*', '%25')
                    $Method = 'matches'

                }    

                "[{0}] Logical Interconnect name provided: '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose

                $uri = "{0}?filter=name {1} '{2}'" -f $uri, $Method, $Name

            }

            if ($PSBoundParameters['Label'])
            {

                $uri = "{0}?category:logical-interconnects&sort=name:asc&query=labels:{1}" -f $IndexUri, $Label

                if ($PSBoundParameters['Name'])
                {

                    $uri += '&query=name:{0}' -f $Name

                }

                $_IndexLookup = $true

            }

            Try
            {

                $resp = Send-HPOVRequest -Uri $uri -Hostname $_appliance.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
                
            if ($resp.count -eq 0 -and $Name) 
            { 

                "[{0}] Logical Interconnect '{1}' resource not found on '{2}'." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name, $_appliance.Name | Write-Verbose

                $ExceptionMessage = "Specified Logical Interconnect '{0}' was not found on '{1}' appliance. Please check the name and try again." -f $Name, $_appliance.Name
                $ErrorRecord = New-ErrorRecord InvalidOperationException SASLogicalInterconnectGroupNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)  

            }

            elseif ($resp.count -eq 0) 
            { 

                "[{0}] No Logical Interconnect resources found on '{1}'." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            }

            else 
            {

                "[{0})] Found {1} Logical Interconnect resource(s)." -f $MyInvocation.InvocationName.ToString().ToUpper(), $resp.count | Write-Verbose

                ForEach ($_LiObject in $resp.members)
                {

                    Try
                    {

                        if ($_IndexLookup)
                        {

                            "[{0}] Getting LI resource object for {1} (Indexed)." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_LiObject.name | Write-Verbose

                            Try
                            {

                                $_LiObject = Send-HPOVRequest -Uri $_LiObject.uri -Hostname $_appliance.Name

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }                            

                        }                        

                        $_LiObject.PSobject.TypeNames.Insert(0,"HPOneView.Storage.SasLogicalInterconnect")  
                    
                        [void]$LiCollection.Add($_LiObject) 

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }
 
            }

        }
   
    }

    End 
    {
        
        "[{0}] Done. {1} logical interconnect(s) found." -f $MyInvocation.InvocationName.ToString().ToUpper(), $LiCollection.count | Write-Verbose

        if ($Export)
        {
            
            $LiCollection | convertto-json -Depth 99 | Set-Content -Path $ExportFile -force -encoding UTF8 
        
        }
        
        else 
        {

             $LiCollection 
        
        }    

    }

}

function Update-HPOVLogicalInterconnect 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = "Reapply")]
        [ValidateNotNullorEmpty()]
        [Alias ('uri', 'li','name','Resource')]
        [object]$InputObject,
        
        [Parameter (ValueFromPipelineByPropertyName, ParameterSetName = "default", Mandatory = $false)]
        [Parameter (ValueFromPipelineByPropertyName, ParameterSetName = "Reapply", Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory, ParameterSetName = "Reapply")]
        [switch]$Reapply

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_returntasks = New-Object System.Collections.ArrayList
        $_liobjects   = New-Object System.Collections.ArrayList

    }

    Process 
    {

        "[{0}] Processing $($InputObject.count) LI objects." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        foreach ($_li in $InputObject) 
        {
            
            #Name provided
            if (($_li -is [String]) -and (-not($_li.StartsWith($script:logicalInterconnectsUri))))
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] LI Name was provided '$($_li)'"

                #Loop through appliance connections to add LI objects to collection
                ForEach ($_appliance in $ApplianceConnection)
                {

                    Try 
                    {

                        Get-HPOVLogicalInterconnect -Name $_li -ApplianceConnection $_appliance.Name | % { [void]$_liobjects.Add($_) }

                    }
                        
                    Catch
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $_.FullyQualifiedErrorId Error Caught: $($_.Exception.Message)"

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Retrieved $($_liobjects.count) LI Objects"

            }

            elseif (($_li -is [String]) -and ($_li.StartsWith($script:logicalInterconnectsUri))) 
            {

                #User didn't provide an appliance connection during call
                if (-not($PSBoundParameters['ApplianceConnection']) -and $ApplianceConnection.Count -gt 1)
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException LogicalInterconnectUriNoApplianceConnection InvalidArgument 'ApplianceConnection' -Message "A Logical Interconnect URI was provided in the -Resource Parameter, but no Appliance Connection specified. URI's are unique per appliance connection. Please specify an Appliance Connection and try your call again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }
                
                #User provided more than 1 appliance connection, and LI URI, generate error
                elseif ($ApplianceConnection.Count -gt 1)
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException LogicalInterconnectUriMultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message "A Logical Interconnect URI was provided in the -Resource Parameter, with multiple Appliance Connections specified. URI's are unique per appliance connection. Please specify an Appliance Connection and try your call again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] LI URI was provided $($_li)"

                Try 
                {

                    Send-HPOVRequest $_li -HostName $ApplianceConnection.Name | % { [void]$_liobjects.Add($_) }

                }
                        
                Catch
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $_.FullyQualifiedErrorId Error Caught: $($_.Exception.Message)"

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif (($_li -is [PSCustomObject]) -and ($_li.category -ieq 'logical-interconnects')) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] LI Object was provided $($_li | out-string)"

                [void]$_liobjects.Add($_li)

            }

            else 
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Resource' -TargetType $_li.GetType().Name -Message "An invalid Resource object was provided. $($_li.GetType()) $($_li.category) was provided. Only type String or PSCustomObject, and 'logical-interconnects' object category are permitted."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

    }

    End 
    {

        #Loop through liobject collection to perform action
        ForEach ($_liobject in $_liobjects)
        {

            "[{0}] Processing Logical Interconnect: $($_liobject.name)" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if ($PSboundParameters['Reapply'])
            { 

                "[{0}] Reapply LI configuration requested." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    
                if ($PSCmdlet.ShouldProcess($_liobject.name,"Reapply Logical Interconnect configuration. WARNING: Depending on this action, there might be a brief outage."))
                { 

                    Try
                    {

                        "[{0}] Sending request to reapply configuration" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    
                        $uri = $_liobject.uri + "/configuration"

                        $task = Send-HPOVRequest $uri PUT -Hostname $_liobject.ApplianceConnection.Name

                        [void]$_returntasks.Add($task)

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                elseif ($PSBoundParameters['WhatIf'])
                {
                    
                    "[{0}] User included -WhatIf." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                }

                else
                {

                    "[{0}] User cancelled." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                }
                
            }

            else 
            {
                
                #Do not Process LI if consistencyStatus is good.
                if ($_liobject.consistencyStatus -eq 'CONSISTENT')
                {

                    Write-Warning 'Logical Interconnect is Consistent with Policy. Nothing to do.'

                }

                else
                {

                    "[{0}] Update '$($liDisplayName)' Logical Interconnect from parent $($parentLig.name)." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    Try
                    {

                        $_ligname = (Send-HPOVRequest $_liobject.logicalInterconnectGroupUri -HostName $_liobject.ApplianceConnection.Name).Name
                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                        
                    if ($PSCmdlet.ShouldProcess($_liobject.name,"Update Logical Interconnect from Group '$_ligname'. WARNING: Depending on the Update, there might be a brief outage."))
                    {    
                        
                        Try
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

                            $uri = $_liobject.uri + "/compliance"

                            $task = Send-HPOVRequest $uri PUT -Hostname $_liobject.ApplianceConnection.Name

                            [void]$_returntasks.Add($task)

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                    elseif ($PSBoundParameters['WhatIf'])
                    {
                        
                        "[{0}] User included -WhatIf." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        Try
                        {
    
                            Compare-LogicalInterconnect -InputObject $_liobject
    
                        } 
    
                        Catch
                        {
    
                            $PSCmdlet.ThrowTerminatingError($_)
    
                        }
                    
                    }

                    else
                    {

                        "[{0}] User cancelled." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    }

                }

            }

        }

        return $_returntasks

    }

}

# Function Compare-LogicalInterconnect
# {

# [CmdletBinding ()]
# Param
# (

# [Parameter (Mandatory, HelpMessage = "Please provide the Encloure or Logical Interconnect object.")]
# [ValidateNotNullorEmpty()]
# [Object]$InputObject

# )

# Begin
# {

# Try
# {
        
# $UplinkSets = Get-HPOVUplinkSet
# $InterconnectTypes = Get-HPOVInterconnectType
        
# }
        
# Catch
# {
        
# PSCmdlet.ThrowTerminatingError($_)
        
# }

# }

# Process
# {


# $CompareObject = New-Object System.Collections.ArrayList
# $_LogicalInterconnects = New-Object System.Collections.ArrayList #Logical Interconnect Uris; not sure what this is used for yet.
# $Interconnects = New-Object System.Collections.ArrayList #Collection of Interconnects?
# $InterconnectMapTemplate = New-Object System.Collections.ArrayList
# $SideIndicator = @{ Parent = '<='; Child = '=>'; NotEqual = '<=>'}

# function GetUplinkSets ($_LI, $_LIG)
# {

# 'Processing Uplink Set objects' | Write-Verbose #-Verbose
# 'LI: {0} [{1}]' -f $_LI.name,$_LI.uri | Write-Verbose #-Verbose
# 'LIG: {0}' -f $_LIG.name | Write-Verbose #-Verbose
# 'Number of LIG Uplink Sets: {0}' -f $_LIG.uplinkSets.count | Write-Verbose #-Verbose
# 'Number of matched Uplink Sets to LI: {0}' -f ($UplinkSets | ? logicalInterconnectUri -eq $_LI.uri).Count | Write-Verbose #-Verbose
            
# $myLUs = New-Object System.Collections.ArrayList
            
# foreach ($lu in ($UplinkSets | ? logicalInterconnectUri -eq $_LI.uri))
# {

# "Match on: {0}" -f $lu.logicalInterconnectUri | Write-Verbose #-Verbose

# Add-Member -InputObject $lu -MemberType NoteProperty -Name UplinkSetGroup -Value $null -Force
# Add-Member -InputObject $lu -NotePropertyName LogicalInterconnectName -NotePropertyValue $_LI.name
# $lu.UplinkSetGroup = $_LIG.uplinkSets | ? name -eq $lu.name
# Add-Member -InputObject $lu.UplinkSetGroup -NotePropertyName LogicalInterconnectGroupName -NotePropertyValue $_LIG.name
# [void]$myLUs.Add($lu)

# }

# ForEach ($_LigUplinkSet in $_LIG.uplinkSets)
# {

# 'Looking for unprovisioned uplink set: {0}' -f $_LigUplinkSet.name | Write-Verbose #-Verbose

# if (($UplinkSets | ? logicalInterconnectUri -eq $_LI.uri).name -notcontains $_LigUplinkSet.name)
# {

# '{0} is not provisioned.' -f $_LigUplinkSet.name | Write-Verbose #-Verbose

# $MissingUplinkSet = MissingUplinkSetFromLIG
# $MissingUplinkSet.UplinkSetGroup = $_LigUplinkSet
# $MissingUplinkSet.LogicalInterconnectUri = $_LI.uri
# $MissingUplinkSet.LogicalInterconnectName = $_LI.name
# $MissingUplinkSet.LogicalInterconnectGroupName = $_Lig.name
                    
# [void]$myLUs.Add($MissingUplinkSet)
                    
# }

# }

# #Need to add a check here for when the LIG Uplink Set(s) differe from LI, not what matches from LI to global Uplink Sets
# return $myLUs
# }

# function GetPortName ($bay, $portNumber)
# {
            
# 'Getting name for port Bay: {0}; Port Number: {1}' -f $Bay, $PortNumber | Write-Verbose #-Verbose
            

# # This function uses the Interconnect map Group set up in CompareInterconnects
# $InterconnectMapEntry = $InterconnectMapTemplate | ? bayNumber -eq $bay
# "InterconnectType: {0}" -f ($InterconnectMapEntry | FL *) | Write-Verbose #-Verbose

# $InterconnectModuleType = $InterconnectTypes | ? uri -eq $InterconnectMapEntry.InterconnectTypeUri
# "Interconnect Module Type: {0}" -f ($InterconnectModuleType | FL *) | Write-Verbose #-Verbose

# "Uplink Port Name: {0}" -f ($InterconnectModuleType.portInfos | ? portNumber -eq $PortNumber).portName | Write-Verbose #-Verbose
# Return ($InterconnectModuleType.portInfos | ? portNumber -eq $PortNumber).portName

# }

# function CompareNetworks ($lu, $lut)
# {

# 'Examining Networks associated with Uplink Set "{0}"' -f $lu.name | Write-Verbose #-Verbose

# switch ($lu.networkType)
# {

# 'FibreChannel'
# {

# 'Processing Fibre Channel Uplink Set' | Write-Verbose #-Verbose

# if ($lu.fcNetworkUris.Count -ne $lut.networkUris.Count)
# {

# '{0} currently has {1} FC networks, Group has {2}' -f $lu.name, $lu.fcNetworkUris.Count, $lut.networkUris.Count | Write-Verbose
                    
# }

# $diff = Compare-Object -ReferenceObject $lu.fcNetworkUris -DifferenceObject $lut.networkUris

# }

# 'Ethernet'
# {

# 'Processing Ethernet Uplink Set' | Write-Verbose #-Verbose

# if ($lu.networkUris.Count -ne $lut.networkUris.Count)
# {
                        
# '{0} currently has {1} Ethernet networks, Group has {2}' -f $lu.name, $lu.networkUris.Count, $lut.networkUris.Count | Write-Verbose
                        
# }

# $diff = Compare-Object -ReferenceObject $lu.networkUris -DifferenceObject $lut.networkUris

# }

# }
            
# foreach ($d in $diff)
# {

# Try
# {
                
# $net = Send-HPOVRequest $d.InputObject
                
# }
                
# Catch
# {
                
# PSCmdlet.ThrowTerminatingError($_)
                
# }
                
# if ($d.SideIndicator -eq $SideIndicator.Child)
# {

# $_diff = New-Object HPOneView.Library.CompareObject($lu.name,
# $SideIndicator.Parent,
# $net.name,
# $null,
# $lut.LogicalInterconnectGroupName,
# $lu.LogicalInterconnectName,
# 'MISSING_NETWORK')

# [void]$CompareObject.Add($_diff)

# '{0} is currently missing network {1} VLAN {2}' -f $lu.name, $net.name, $net.vlanId | Write-Verbose

# }
                
# else
# {

# $_diff = New-Object HPOneView.Library.CompareObject($lu.name,
# $SideIndicator.Child,
# $null,
# $net.name,
# $lut.LogicalInterconnectGroupName,
# $lu.LogicalInterconnectName,
# 'EXTRA_NETWORK')
# [void]$CompareObject.Add($_diff)

# '{0} currently has extra network {1} VLAN {2}' -f $lu.name, $net.name, $net.vlanId | Write-Verbose

# }

# }

# }

# function CompareLocalNetworks ($li, $lig)
# {

# 'Examining Internal Networks' | Write-Verbose #-Verbose

# if ($li.internalNetworkUris.Count -ne $lig.internalNetworkUris.Count)
# {
                
# '{0} currently has {1} Internal Ethernet networks, Group has {2}' -f $li.name, $li.internalNetworkUris.Count, $lig.internalNetworkUris.Count | Write-Verbose
                
# }

# $diff = Compare-Object -ReferenceObject $lig.internalNetworkUris -DifferenceObject $li.internalNetworkUris

            
# foreach ($d in $diff)
# {

# Try
# {
                
# $net = Send-HPOVRequest $d.InputObject
                
# }
                
# Catch
# {
                
# PSCmdlet.ThrowTerminatingError($_)
                
# }
                
# if ($d.SideIndicator -eq $SideIndicator.Parent)
# {

# $_diff = New-Object HPOneView.Library.CompareObject('InternalNetworks',
# $SideIndicator.Child,
# $net.name,
# $null,
# $lig.name,
# $li.name,
# 'MISSING_NETWORK')

# [void]$CompareObject.Add($_diff)

# '{0} is currently missing internal network {1} VLAN {2}' -f $li.name, $net.name, $net.vlanId | Write-Verbose

# }
                
# else
# {

# $_diff = New-Object HPOneView.Library.CompareObject('InternalNetworks',
# $SideIndicator.Parent,
# $null,
# $net.name,
# $lig.name,
# $li.name,
# 'EXTRA_NETWORK')
# [void]$CompareObject.Add($_diff)

# '{0} currently has extra network {1} VLAN {2}' -f $li.name, $net.name, $net.vlanId | Write-Verbose

# }

# }

# }

# function ComparePorts ($lu, $lut)
# {

# "Comparing ports" | Write-Verbose #-Verbose

# "Uplink Set Port count: {0}" -f $lu.portConfigInfos.Count | Write-Verbose #-Verbose
# "LIG Uplink Set Port count: {0}" -f $lut.logicalPortConfigInfos.Count | Write-Verbose #-Verbose

# if ($lu.portConfigInfos.Count -ne $lut.logicalPortConfigInfos.Count)
# {

# '{0} currently has {1} ports, Group has {2}' -f $lu.name, $lu.portConfigInfos.Count, $lut.logicalPortConfigInfos.Count | Write-Verbose

# }

# #Build array of LU ports
# $luPorts = New-Object System.Collections.ArrayList
# $lutPorts = New-Object System.Collections.ArrayList

# #Process LIG Uplink Set Uplink Ports
# foreach ($upPorts in $lut.logicalPortConfigInfos)
# {

# $Port = [PSCustomObject]@{ type = 'lut.portConfigInfos';bayNumber = $null; portNumber = $null; portName = $null; Speed = $null }

# foreach ($loc in $upPorts.logicalLocation.locationEntries)
# {

# $Port.Speed = $upPorts.desiredSpeed

# if ($loc.type -eq "BAY") { $Port.bayNumber = $loc.relativeValue }

# if ($loc.type -eq "PORT") { $Port.portNumber = $loc.relativeValue }

# }

# $Port.portName = GetPortName $Port.bayNumber $Port.portNumber

# [void]$lutPorts.Add($Port)

# }

# #Process LI Uplink Set Uplink Ports
# foreach ($upPorts in $lu.portConfigInfos)
# {

# $Port = [PSCustomObject]@{ type = 'lu.portConfigInfos';bayNumber = $null; portNumber = $null; portName = $null; Speed = $null }

# foreach ($loc in $upPorts.Location.locationEntries)
# {

# $Port.Speed = $upPorts.desiredSpeed

# if ($loc.type -eq "BAY") { $Port.bayNumber = $loc.Value }

# if ($loc.type -eq "PORT") { $Port.portName = $loc.Value }

# }

# [void]$luPorts.Add($Port)

# }

# $PortLocationDiff = Compare-Object -ReferenceObject $lutPorts -DifferenceObject $luPorts -Property bayNumber, portName

# 'PortLocationDiff Object: {0}' -f ($PortLocationDiff | Out-String) | Write-Verbose #-Verbose

# foreach ($d in $PortLocationDiff)
# {

# $Property = 'Bay{0}:{1}' -f $d.bayNumber, $d.portName

# if ($d.SideIndicator -eq $SideIndicator.Parent)
# {

# $_diff = New-Object HPOneView.Library.CompareObject($lu.name,
# $SideIndicator.Child,
# $Property,
# $null,
# $lut.LogicalInterconnectGroupName,
# $lu.LogicalInterconnectName,
# 'MISSING_UPLINKPORT')
                    
# [void]$CompareObject.Add($_diff)
                    
# '{0} is currently missing port bay {1} port ' -f $lu.name, $d.bayNumber, $d.portName | Write-Verbose
                
# }
                
# elseif ($d.SideIndicator -eq $SideIndicator.Child)
# {

# $_diff = New-Object HPOneView.Library.CompareObject($lu.name,
# $SideIndicator.Parent,
# $null,
# $Property,
# $lut.LogicalInterconnectGroupName,
# $lu.LogicalInterconnectName,
# 'ADDITIONAL_UPLINKPORT')
                    
# [void]$CompareObject.Add($_diff)
                    
# '{0} currently has extra port on bay {1} port {2}' -f $lu.name, $d.bayNumber, $d.portName | Write-Verbose

# }

# }

# $PortSpeedDiff = Compare-Object -ReferenceObject $lutPorts -DifferenceObject $luPorts -Property Speed -PassThru

# 'PortSpeedDiff Object: {0}' -f ($PortSpeedDiff | Out-String) | Write-Verbose #-Verbose

# foreach ($d in $PortSpeedDiff)
# {

# if ($luPorts | ? { $_.bayNumber -eq $d.bayNumber -and $_.portName -eq $d.portName} )
# {

# $Property = '{0}:Bay{1}:{2}' -f $lut.name,$d.bayNumber, $d.portName

# 'luPort Object: {0}' -f (($luPorts | ? { $_.bayNumber -eq $d.bayNumber -and $_.portName -eq $d.portName}) | Out-String) | Write-Verbose #-Verbose

# if ($d.SideIndicator -eq '=>')
# {

# $ParentValue = '{0}' -f $GetUplinkSetPortSpeeds[($lutPorts | ? { $_.bayNumber -eq $d.bayNumber -and $_.portName -eq $d.portName}).Speed]
# $ChildValue = '{0}' -f $GetUplinkSetPortSpeeds[$d.Speed]

# }
                
# elseif ($d.SideIndicator -eq '<=')
# {

# $ParentValue = '{0}' -f $GetUplinkSetPortSpeeds[$d.Speed]
# $ChildValue = '{0}' -f $GetUplinkSetPortSpeeds[($luPorts | ? { $_.bayNumber -eq $d.bayNumber -and $_.portName -eq $d.portName}).Speed]

# }

# $_diff = New-Object HPOneView.Library.CompareObject($Property,
# $SideIndicator.NotEqual,
# $ParentValue,
# $ChildValue,
# $lut.LogicalInterconnectGroupName,
# $lu.LogicalInterconnectName,
# 'LINKSPEED_MISMATCH')
                    
# [void]$CompareObject.Add($_diff)

# '{0} Uplink Port {1}:{2} has different link speed {3} than Group {4}' -f $lut.name, $d.bayNumber, $d.portName, $ParentValue, $ChildValue | Write-Verbose

# }

# }

# }

# function CompareUplinksWithGroup ($lu)
# {

# $lut = $lu.UplinkSetGroup

# if (! $lut)
# {
                
# '"{0}" Uplink Set has no matching LIG Uplink Set. Skipping.' -f $lu.name | Write-Verbose
                
# }

# if ($lu.name -eq 'missing')
# {

# '"{0}" Uplink Set within Logical Interconnect Group "{1}" is not provisioned or missing from Logical Interconnect "{2}"' -f $lut.name, $lu.LogicalInterconnectGroupName, $lu.LogicalInterconnectName | Write-Verbose

# $_diff = New-Object HPOneView.Library.CompareObject('UplinkSets',
# $SideIndicator.Child,
# $lut.name,
# $null,
# $lu.LogicalInterconnectGroupName,
# $lu.LogicalInterconnectName,
# 'MISSING_UPLINKSET')
                
# [void]$CompareObject.Add($_diff)

# }

# else
# {

# 'Comparing {0} Uplink Set with Group' -f $lu.name | Write-Verbose #-Verbose

# 'LU: {0}' -f ($lu | FL * | Out-String) | Write-Verbose #-Verbose
# 'LUT: {0}' -f ($lut | FL * | Out-String) | Write-Verbose #-Verbose

# if ($lu.networkType -ne $lut.networkType)
# {
                    
# $_diff = New-Object HPOneView.Library.CompareObject(($lu.name + ':networkType'),
# $SideIndicator.Parent,
# $lut.networkType,
# $lu.networkType,
# $lut.LogicalInterconnectGroupName,
# $lu.LogicalInterconnectName,
# 'NETWORKTYPE_MISMATCH')
                    
# [void]$CompareObject.Add($_diff)
                    
# '"{0}" current Type "{1}" differs from Group Type "{2}"' -f $lu.name, $lu.networkType, $lut.networkType | Write-Verbose
                
# }

# if ($lu.connectionMode -ne $lut.mode)
# {

# $_diff = New-Object HPOneView.Library.CompareObject('connectionMode',
# $SideIndicator.Parent,
# $lut.mode,
# $lu.connectionMode,
# ($lut.LogicalInterconnectGroupName + ":" + $lut.name),
# ($lu.LogicalInterconnectName + ":" + $lu.name),
# 'CONNECTIONMODE_MISMATCH')

# [void]$CompareObject.Add($_diff)

# '"{0}" current Connection Mode "{1}" differs from Group Connection Mode "{2}"' -f $lu.name, $lu.connectionMode, $lut.mode | Write-Verbose
# }

# if ( $lut.mode -ne 'Auto' -or $lu.connectionMode -ne 'Auto')
# {

# $LutPrimaryPort = [PSCustomObject]@{ bayNumber = $null; portNumber = $null; portName = $null; Speed = $null }
# $LutPrimaryPort.bayNumber = ($lut.primaryPort.locationEntries | ? { $_.type -eq 'Bay' } ).relativeValue
# $LutPrimaryPort.portNumber = ($lut.primaryPort.locationEntries | ? { $_.type -eq 'Port' } ).relativeValue
# $LutPrimaryPort.portName = GetPortName $LutPrimaryPort.bayNumber $LutPrimaryPort.portNumber

# $LuPrimaryPort = [PSCustomObject]@{ bayNumber = $null; portNumber = $null; portName = $null; Speed = $null }
# $LuPrimaryPort.bayNumber = ($lu.primaryPortLocation.locationEntries | ? type -eq 'Bay').value
# $LuPrimaryPort.portName = ($lu.primaryPortLocation.locationEntries | ? type -eq 'Port').value

# $PrimaryPortDiff = Compare-Object -ReferenceObject $LutPrimaryPort -DifferenceObject $LuPrimaryPort -Property portName -PassThru

# 'PrimaryPortDiff Object: {0}' -f ($PrimaryPortDiff | Out-String) | Write-Verbose #-Verbose

# if ($PrimaryPortDiff)
# {

# $_SideIndicator = '<=>'

# $_ParentPrimaryPort = ('BAY{0}:{1}' -f $LutPrimaryPort.bayNumber, $LutPrimaryPort.portName)
# $_ChildPrimaryPort = ('BAY{0}:{1}' -f $LuPrimaryPort.bayNumber, $LuPrimaryPort.portName)

# if (! $LuPrimaryPort.portName)
# {

# $_SideIndicator = '<='
# $_ChildPrimaryPort = $null

# }

# elseif (! $LutPrimaryPort.portName)
# {

# $_SideIndicator = '=>'
# $_ParentPrimaryPort = $null

# }

# $_diff = New-Object HPOneView.Library.CompareObject('PrimaryPort',
# $_SideIndicator,
# $_ParentPrimaryPort,
# $_ChildPrimaryPort,
# ($lut.LogicalInterconnectGroupName + ":" + $lut.name),
# ($lu.LogicalInterconnectName + ":" + $lu.name),
# 'PRIMARYPORT_MISMATCH')

# [void]$CompareObject.Add($_diff)

# '"{0}" current Primary Port "{1}" differs from Group "{2}"' -f $lu.name, $_ChildPrimaryPort, $_ParentPrimaryPort | Write-Verbose

# }

# }


# if ($lu.nativeNetworkUri -ne $lut.nativeNetworkUri)
# {

# 'LU NativeNetworkUri: {0}' -f $lu.nativeNetworkUri | Write-Verbose #-Verbose
# 'LUT NativeNetworkUri: {0}' -f $lut.nativeNetworkUri | Write-Verbose #-Verbose

# $_SideIndicator = $SideIndicator.NotEqual

# if ($lu.nativeNetworkUri)
# {
                        
# $luNativeNetwork = (Send-HPOVRequest $lu.nativeNetworkUri).name
                    
# }

# else
# {
                    
# $luNativeNetwork = "None"
# $_SideIndicator = $SideIndicator.Parent
                    
# }

# if ($lut.nativeNetworkUri)
# {

# $lutNativeNetwork = (Send-HPOVRequest $lut.nativeNetworkUri).name

# }

# else
# {
                    
# $lutNativeNetwork = "None"
# $_SideIndicator = $SideIndicator.Child
                    
# }

# $_diff = New-Object HPOneView.Library.CompareObject(($lu.name + ':nativeNetworkUri'),
# $_SideIndicator,
# $lutNativeNetwork,
# $luNativeNetwork,
# $lut.LogicalInterconnectGroupName,
# $lu.LogicalInterconnectName,
# 'NATIVENETWORK_MISMATCH')
                    
# [void]$CompareObject.Add($_diff)
                    
# '"{0}" current Native Network "{1}" differs from Group Native Network "{2}"' -f $lu.name, $luNativeNetwork, $lutNativeNetwork | Write-Verbose

# }

# CompareNetworks $lu $lut

# ComparePorts $lu $lut

# }

# }

# function CompareInterconnects ($_LogicalInterconnect, $_LogicalInterconnectGroup)
# {

# "Processing Logical Interconnect '{0}' and LIG '{1}'" -f $_LogicalInterconnect.name, $_LogicalInterconnectGroup.name | Write-Verbose #-Verbose

# #Build array of Interconnects in Group
            
# foreach ($InterconnectMapEntryGroup in $_LogicalInterconnectGroup.interconnectMapTemplate.interconnectMapEntryTemplates)
# {

# if ($InterconnectMapEntryGroup.permittedInterconnectTypeUri)
# {

# [void]$InterconnectMapTemplate.Add([PSCustomObject]@{
# bayNumber = ($InterconnectMapEntryGroup.logicalLocation.locationEntries | ? type -eq "BAY").relativeValue;
# InterconnectTypeUri = $InterconnectMapEntryGroup.permittedInterconnectTypeUri
# })
            
# }

# }

# #Build array of Interconnects in logical Interconnect
# $InterconnectMap = New-Object System.Collections.ArrayList

# foreach ($_InterconnectMapEntry in $_LogicalInterconnect.InterconnectMap.interconnectMapEntries)
# {

# if ($_InterconnectMapEntry.permittedInterconnectTypeUri)
# {

# [void]$InterconnectMap.Add([PSCustomObject]@{
# bayNumber = ($_InterconnectMapEntry.location.locationEntries | ? type -eq "Bay").value;
# InterconnectTypeUri = $_InterconnectMapEntry.permittedInterconnectTypeUri
# })

# }

# }

# $diff = Compare-Object -ReferenceObject $InterconnectMapTemplate -DifferenceObject $InterconnectMap -Property bayNumber, InterconnectTypeUri -IncludeEqual

# foreach ($d in $diff)
# {

# 'Processing LI with LIG DIFF' | Write-Verbose #-Verbose

# $InterconnectType = $InterconnectTypes | Where-Object { $_.uri -eq $d.InterconnectTypeUri }

# if ($d.SideIndicator -eq "==")
# {

# 'Expected Interconnect in "{0}" matches Group for Interconnect bay "{1}" type "{2}"' -f $_LogicalInterconnect.name, $d.bayNumber, $InterconnectType.name | Write-Verbose #-Verbose
               
# }
                
# else
# {

# if ($d.SideIndicator -eq $SideIndicator.Parent)
# {

# $_diff = New-Object HPOneView.Library.CompareObject($d.bayNumber,
# $SideIndicator.Child,
# $InterconnectType.name,
# $null,
# $_LogicalInterconnectGroup.name,
# $_LogicalInterconnect.name,
# 'MISSING_MODULE')

# [void]$CompareObject.Add($_diff)

# '"{0}" Logical Interconnect is currently missing expected module "{1}" within Interconnect bay "{2}" ' -f $_LogicalInterconnect.name, $InterconnectType.name, $d.bayNumber | Write-Verbose
# }
                    
# elseif ($d.SideIndicator -eq $SideIndicator.Child)
# {

# $_diff = New-Object HPOneView.Library.CompareObject($d.bayNumber,
# $SideIndicator.Parent,
# $InterconnectType.name,
# $null,
# $_LogicalInterconnectGroup.name,
# $_LogicalInterconnect.name,
# 'EXTRA_MODULE')

# [void]$CompareObject.Add($_diff)

# '"{0}" Logical Interconnect contains an extra module "{1}" within Interconnect bay "{2}" ' -f $_LogicalInterconnect.name, $InterconnectType.name, $d.bayNumber | Write-Verbose
# }

# }

# }

# #Process Ethernet Settings
# $EthernetSettingsProperties = "enableIgmpSnooping", "igmpIdleTimeoutInterval", "enableFastMacCacheFailover", "macRefreshInterval", "enableNetworkLoopProtection", "enablePauseFloodProtection", "enableRichTLV", "enableTaggedLldp"
# $EthernetSettingsDiff = New-Object System.Collections.Arraylist

# if ($_LogicalInterconnectGroup.category -ne 'sas-logical-interconnect-groups')
# {

# ForEach ($Property in $EthernetSettingsProperties)
# {

# if ($_LogicalInterconnectGroup.ethernetSettings.$Property -ne $_LogicalInterconnect.ethernetSettings.$Property)
# {

# $_diff = New-Object HPOneView.Library.CompareObject($Property,
# $SideIndicator.NotEqual,
# $_LogicalInterconnectGroup.ethernetSettings.$Property,
# $_LogicalInterconnect.ethernetSettings.$Property,
# $_LogicalInterconnectGroup.name,
# $_LogicalInterconnect.name,
# 'SETTING_MISMATCH')

# [void]$EthernetSettingsDiff.Add($_diff)
# [void]$CompareObject.Add($_diff)

# }

# }

# ForEach ($diff in $EthernetSettingsDiff)
# {

# 'Logical Interconnect "{0}" Ethernet Setting "{1}" does not match the parent "{2}" setting.' -f $diff.InputObject, $diff.ChildSetting, $diff.ParentSetting | Write-Verbose

# }

# }

# if ($_LogicalInterconnectGroup.category -ne 'sas-logical-interconnect-groups')
# {

# $_diff = Compare-Object -ReferenceObject $_LogicalInterconnectGroup.qosConfiguration.activeQosConfig.configType -DifferenceObject $_LogicalInterconnect.qosConfiguration.activeQosConfig.configType -PassThru

# if ($_diff.SideIndicator -eq $SideIndicator.Parent)
# {

# $_diff = New-Object HPOneView.Library.CompareObject('ActiveQosConfig',
# $SideIndicator.Parent,
# $_LogicalInterconnectGroup.qosConfiguration.activeQosConfig.configType,
# $_LogicalInterconnect.qosConfiguration.activeQosConfig.configType,
# $_LogicalInterconnectGroup.name,
# $_LogicalInterconnect.name,
# 'SETTING_MISMATCH')

# [void]$CompareObject.Add($_diff)

# }

# elseif ($_diff.SideIndicator -eq $SideIndicator.Child)
# {

# $_diff = New-Object HPOneView.Library.CompareObject('ActiveQosConfig',
# $SideIndicator.Child,
# $_LogicalInterconnectGroup.qosConfiguration.activeQosConfig.configType,
# $_LogicalInterconnect.qosConfiguration.activeQosConfig.configType,
# $_LogicalInterconnectGroup.name,
# $_LogicalInterconnect.name,
# 'SETTING_MISMATCH')

# [void]$CompareObject.Add($_diff)
                    
# }

# }

# }

# Function MissingUplinkSetFromLIG
# {

# Return [PSCustomObject] @{

# Name = "missing";
# UplinkSetGroup = $null;
# LogicalInterconnectUri = $null;
# LogicalInterconnectName = $null;
# LogicalInterconnectGroupName = $null

# }

# }

# ##################################################################
# # If InputObject is not a PSCustomObject, assume it is an Enclosure Name
# if ($InputObject -IsNot [System.Management.Automation.PSCustomObject])
# {

# Try
# {
            
# $InputObject = Get-HPOVEnclosure -Name $InputObject
            
# }
            
# Catch
# {
            
# PSCmdlet.ThrowTerminatingError($_)
            
# }

# }

# "InputObject resource: {0} [{1}]" -f $InputObject.name, $InputObject.category | Write-Verbose

# #Loop through all ICM bays of the Enclosure object
# if ($InputObject.category -eq 'enclosures')
# {

# '{0} has {1} interconnect bays which are configured as {2} logical Interconnects' -f $InputObject.name, ($InputObject.interconnectBays | ? interconnectUri).Count, $_LogicalInterconnectUris.Count | Write-Verbose

# $UniqueLIUris = $InputObject.interconnectBays | Select -Property logicalInterconnectUri -Unique | ? { $_.logicalInterconnectUri }

# ForEach ($_uri in $UniqueLIUris.logicalInterconnectUri)
# {

# 'Processing LI URI: {0}' -f $_uri | Write-Verbose

# Try
# {
                
# $_LIObject = Send-HPOVRequest -Uri $_uri
# $_LigObject = Send-HPOVRequest -Uri $_LIObject.logicalInterconnectGroupUri
                    
# $_LIObject | Add-Member -NotePropertyName LogicalInterconnectGroup -NotePropertyValue $_LigObject -Force
# [void]$_LogicalInterconnects.Add($_LIObject)
                
# }
                
# Catch
# {
                
# $PSCmdlet.ThrowTerminatingError($_)
                
# }

# }

# }

# elseif ($InputObject.category -eq 'logical-enclosures')
# {

# #Is this even right? There is a logicalInterconnectUris property. Should that be used, even for C-Class and Synergy?
# ForEach ($_LogicalInterconnectUri in $InputObject.logicalInterconnectUris)
# {

# Try
# {
                
# $_LogicalInterconnect = Send-HPOVRequest -Uri $_LogicalInterconnectUri -Hostname $InputObject.ApplianceConnection
                
# }
                
# Catch
# {
                
# PSCmdlet.ThrowTerminatingError($_)
                
# }

# '{0} has {1} interconnect bays which are configured within the Logical Interconnect' -f $InputObject.name, $InputObject.interconnects.Count | Write-Verbose

# Try
# {
                
# $_LigObject = Send-HPOVRequest -Uri $_LogicalInterconnect.logicalInterconnectGroupUri
                    
# $_LogicalInterconnect | Add-Member -NotePropertyName LogicalInterconnectGroup -NotePropertyValue $_LigObject -Force
# [void]$_LogicalInterconnects.Add($_LogicalInterconnect)
                
# }
                
# Catch
# {
                
# $PSCmdlet.ThrowTerminatingError($_)
                
# }

# }

# }

# elseif ($InputObject.category -eq 'logical-interconnects')
# {

# '{0} has {1} interconnect bays which are configured within the Logical Interconnect' -f $InputObject.name, $InputObject.interconnects.Count | Write-Verbose

# Try
# {
            
# $_LIObject = $InputObject.PSObject.Copy()
# $_LigObject = Send-HPOVRequest -Uri $_LIObject.logicalInterconnectGroupUri
                
# $_LIObject | Add-Member -NotePropertyName LogicalInterconnectGroup -NotePropertyValue $_LigObject -Force
# [void]$_LogicalInterconnects.Add($_LIObject)
            
# }
            
# Catch
# {
            
# $PSCmdlet.ThrowTerminatingError($_)
            
# }

# }

# else
# {

# Write-Error "Unsupported InputObject. Only Enclosure or Logical Interconnect resources are permitted." -ErrorAction Stop

# }

# foreach ($_LI in $_LogicalInterconnects)
# {

# "Logical Interconnect '{0}' has '{1}' Interconnects and is based on Group '{2}'" -f $_LI.name, $_LogicalInterconnect.Interconnects.Count, $_LI.LogicalInterconnectGroup.name | Write-Verbose

# CompareInterconnects $_LI $_LI.LogicalInterconnectGroup

# $lus = GetUplinkSets $_LI $_LI.LogicalInterconnectGroup

# foreach ($lu in $lus)
# {

# CompareUplinksWithGroup $lu

# }

# CompareLocalNetworks $_LI $_LI.LogicalInterconnectGroup
            
# }

# $CompareObject | FT

# }

# End
# {

# "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

# }

# }

# // TODO: REFACTOR, ADD DTO TO APPLIANCE.FORMAT.PS1XML
Function Compare-LogicalInterconnect
{

    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory, HelpMessage = "Please provide the Encloure or Logical Interconnect object.")]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject

    )

    Begin
    {

        $ApplianceConnection = $InputObject.ApplianceConnection

        Try
        {
        
            'Getting all configured Uplink Set objects.' -f $_LigUplinkSet.name | Write-Verbose #-Verbose
            $UplinkSets = Get-HPOVUplinkSet -ApplianceConnection $ApplianceConnection.Name
            
            'Getting all Interconnect Types objects.' -f $_LigUplinkSet.name | Write-Verbose #-Verbose
            $InterconnectTypes = Get-HPOVInterconnectType -ApplianceConnection $ApplianceConnection.Name
        
        }
        
        Catch
        {
        
            $PSCmdlet.ThrowTerminatingError($_)
        
        }

    }

    Process
    {


        $CompareObject            = New-Object System.Collections.ArrayList
        $_LogicalInterconnects    = New-Object System.Collections.ArrayList   #Logical Interconnect Uris; not sure what this is used for yet.
        $InterconnectMap          = New-Object System.Collections.ArrayList   #Collection of Interconnects?
        $InterconnectMapTemplate  = New-Object System.Collections.ArrayList
        $SideIndicator            = @{ Parent = '<='; Child = '=>'; NotEqual = '<=>'}

        function CompareInterconnects ($_LogicalInterconnect, $_LogicalInterconnectGroup) 
        {

            "Processing Logical Interconnect '{0}' and LIG '{1}'" -f $_LogicalInterconnect.name, $_LogicalInterconnectGroup.name | Write-Verbose #-Verbose

            #Build array of expected Interconnects within LIG
            foreach ($InterconnectMapEntryGroup in $_LogicalInterconnectGroup.interconnectMapTemplate.interconnectMapEntryTemplates) 
            {

                if ($InterconnectMapEntryGroup.permittedInterconnectTypeUri) 
                {

                    [void]$InterconnectMapTemplate.Add([PSCustomObject]@{
                        bayNumber           = ($InterconnectMapEntryGroup.logicalLocation.locationEntries | ? type -eq "BAY").relativeValue; 
                        InterconnectTypeUri = $InterconnectMapEntryGroup.permittedInterconnectTypeUri
                    })
            
                }

            }

            
            #$InterconnectMap = New-Object System.Collections.ArrayList
            #Build array of actual Interconnects in LI
            foreach ($_InterconnectMapEntry in $_LogicalInterconnect.InterconnectMap.interconnectMapEntries) 
            {

                if ($_InterconnectMapEntry.permittedInterconnectTypeUri) 
                {

                    [void]$InterconnectMap.Add([PSCustomObject]@{
                        bayNumber           = ($_InterconnectMapEntry.location.locationEntries | ? type -eq "Bay").value; 
                        InterconnectTypeUri = $_InterconnectMapEntry.permittedInterconnectTypeUri
                    })

                }

            }

            $diff = Compare-Object -ReferenceObject $InterconnectMapTemplate -DifferenceObject $InterconnectMap -Property bayNumber, InterconnectTypeUri -IncludeEqual

            foreach ($d in $diff) 
            {

                'Processing LI with LIG DIFF' | Write-Verbose #-Verbose

                $InterconnectType = $InterconnectTypes | Where-Object { $_.uri -eq $d.InterconnectTypeUri }

                if ($d.SideIndicator -eq "==") 
                {

                    'Expected Interconnect in "{0}" matches Group for Interconnect bay "{1}" type "{2}"' -f $_LogicalInterconnect.name,  $d.bayNumber, $InterconnectType.name | Write-Verbose #-Verbose
               
                } 
                
                else 
                {

                    if ($d.SideIndicator -eq $SideIndicator.Parent) 
                    {

                        $_diff = New-Object HPOneView.Library.CompareObject($d.bayNumber,
                                                                            $SideIndicator.Child,
                                                                            $InterconnectType.name,
                                                                            $null,
                                                                            $_LogicalInterconnectGroup.name,
                                                                            $_LogicalInterconnect.name,
                                                                            'MISSING_MODULE')

                        [void]$CompareObject.Add($_diff)

                        '"{0}" Logical Interconnect is currently missing expected module "{1}" within Interconnect bay "{2}" ' -f $_LogicalInterconnect.name, $InterconnectType.name, $d.bayNumber | Write-Verbose
                        
                    }
                    
                    elseif ($d.SideIndicator -eq $SideIndicator.Child)  
                    {

                        $_diff = New-Object HPOneView.Library.CompareObject($d.bayNumber,
                                                                            $SideIndicator.Parent,
                                                                            $InterconnectType.name,
                                                                            $null,
                                                                            $_LogicalInterconnectGroup.name,
                                                                            $_LogicalInterconnect.name,
                                                                            'EXTRA_MODULE')

                        [void]$CompareObject.Add($_diff)

                        '"{0}" Logical Interconnect contains an extra module "{1}" within Interconnect bay "{2}" ' -f $_LogicalInterconnect.name, $InterconnectType.name, $d.bayNumber | Write-Verbose

                    }

                }

            }

            #Process Ethernet Settings
            $EthernetSettingsProperties = "enableIgmpSnooping", "igmpIdleTimeoutInterval", "enableFastMacCacheFailover", "macRefreshInterval", "enableNetworkLoopProtection", "enablePauseFloodProtection", "enableRichTLV", "enableTaggedLldp"
            $EthernetSettingsDiff = New-Object System.Collections.Arraylist

            if ($_LogicalInterconnectGroup.category -ne 'sas-logical-interconnect-groups')
            {

                ForEach ($Property in $EthernetSettingsProperties)
                {

                    if ($_LogicalInterconnectGroup.ethernetSettings.$Property -ne $_LogicalInterconnect.ethernetSettings.$Property)
                    {

                        $_diff = New-Object HPOneView.Library.CompareObject($Property, 
                                                                            $SideIndicator.NotEqual, 
                                                                            $_LogicalInterconnectGroup.ethernetSettings.$Property, 
                                                                            $_LogicalInterconnect.ethernetSettings.$Property, 
                                                                            $_LogicalInterconnectGroup.name,
                                                                            $_LogicalInterconnect.name,
                                                                            'SETTING_MISMATCH')

                        [void]$EthernetSettingsDiff.Add($_diff)
                        [void]$CompareObject.Add($_diff)

                    }

                }

                ForEach ($diff in $EthernetSettingsDiff)
                {

                    'Logical Interconnect "{0}" Ethernet Setting "{1}" does not match the parent "{2}" setting.' -f $diff.InputObject, $diff.ChildSetting, $diff.ParentSetting | Write-Verbose

                }

            # }

            # if ($_LogicalInterconnectGroup.category -ne 'sas-logical-interconnect-groups')
            # {

                #Process QoS
                $_diff = Compare-Object -ReferenceObject $_LogicalInterconnectGroup.qosConfiguration.activeQosConfig.configType -DifferenceObject $_LogicalInterconnect.qosConfiguration.activeQosConfig.configType -PassThru

                if ($_diff.SideIndicator -eq $SideIndicator.Parent)
                {

                    $_diff = New-Object HPOneView.Library.CompareObject('ActiveQosConfig', 
                                                                        $SideIndicator.Parent, 
                                                                        $_LogicalInterconnectGroup.qosConfiguration.activeQosConfig.configType, 
                                                                        $_LogicalInterconnect.qosConfiguration.activeQosConfig.configType, 
                                                                        $_LogicalInterconnectGroup.name,
                                                                        $_LogicalInterconnect.name,
                                                                        'SETTING_MISMATCH')

                    [void]$CompareObject.Add($_diff)

                }

                elseif ($_diff.SideIndicator -eq $SideIndicator.Child)
                {

                    $_diff = New-Object HPOneView.Library.CompareObject('ActiveQosConfig', 
                                                                        $SideIndicator.Child, 
                                                                        $_LogicalInterconnectGroup.qosConfiguration.activeQosConfig.configType, 
                                                                        $_LogicalInterconnect.qosConfiguration.activeQosConfig.configType, 
                                                                        $_LogicalInterconnectGroup.name,
                                                                        $_LogicalInterconnect.name,
                                                                        'SETTING_MISMATCH')

                    [void]$CompareObject.Add($_diff)
                    
                }

            }

        }
        
        function GetUplinkSets ($_LI, $_LIG) 
        {

            'Processing Uplink Set objects' | Write-Verbose #-Verbose
            'LI: {0} [{1}]' -f $_LI.name,$_LI.uri | Write-Verbose #-Verbose
            'LIG: {0}' -f $_LIG.name | Write-Verbose #-Verbose
            'Number of LIG Uplink Sets: {0}' -f $_LIG.uplinkSets.count | Write-Verbose #-Verbose
            'Number of matched Uplink Sets to LI: {0}' -f ($UplinkSets | ? logicalInterconnectUri -eq $_LI.uri).Count | Write-Verbose #-Verbose
            
            if (($UplinkSets | ? logicalInterconnectUri -eq $_LI.uri).Count -gt $_LIG.uplinkSets.Count)
            {

                'Number of Unmatched Uplink Sets to LI: {0}' -f (($UplinkSets | ? logicalInterconnectUri -eq $_LI.uri).Count - $_LIG.uplinkSets.Count) | Write-Verbose #-Verbose

            }

            else
            {

                'Number of Unmatched Uplink Sets to LIG: {0}' -f ($_LIG.uplinkSets.Count - ($UplinkSets | ? logicalInterconnectUri -eq $_LI.uri).Count) | Write-Verbose #-Verbose
            
            }
            
            $myLUs = New-Object System.Collections.ArrayList
            
            'Processing LIG policy for undefined Uplink Sets within LI.' -f $_LigUplinkSet.name | Write-Verbose #-Verbose
            
            ForEach ($_LigUplinkSet in $_LIG.uplinkSets)
            {

                'Looking for unprovisioned LIG Uplink Set: {0}' -f $_LigUplinkSet.name | Write-Verbose #-Verbose

                if (($UplinkSets | ? logicalInterconnectUri -eq $_LI.uri).name -notcontains $_LigUplinkSet.name)
                {

                    '{0} is not provisioned within LI.' -f $_LigUplinkSet.name | Write-Verbose #-Verbose

                    $MissingUplinkSet = NewObject -liUplinkSetObject
                    $MissingUplinkSet.name = "Missing"
                    Add-Member -InputObject $MissingUplinkSet -NotePropertyName UplinkSetGroup -NotePropertyValue $null -Force
                    Add-Member -InputObject $MissingUplinkSet -NotePropertyName LogicalInterconnectName -NotePropertyValue $_LI.name
                    Add-Member -InputObject $MissingUplinkSet.UplinkSetGroup -NotePropertyName LogicalInterconnectGroupName -NotePropertyValue $_LIG.name                   
                    [void]$myLUs.Add($MissingUplinkSet)
                    
                }

            }

            # Inject LIG Uplink Set object into LI for further matching later
            foreach ($lu in ($UplinkSets | ? logicalInterconnectUri -eq $_LI.uri)) 
            {

                "Match on: {0}" -f $lu.logicalInterconnectUri | Write-Verbose #-Verbose

                Add-Member -InputObject $lu -NotePropertyName UplinkSetGroup -NotePropertyValue $null -Force
                Add-Member -InputObject $lu -NotePropertyName LogicalInterconnectName -NotePropertyValue $_LI.name
                $lu.UplinkSetGroup = $_LIG.uplinkSets | ? name -eq $lu.name
                
                # If LIG Uplink Set doesn't exist, add placebo
                if ($null -eq $lu.UplinkSetGroup)
                {

                    'Uplink Set "{0}" is not defined in the LIG.' -f $_LigUplinkSet.name | Write-Verbose #-Verbose
                    
                    $MissingLIGUplinkSet = MissingUplinkSetFromLIG
                    $MissingLIGUplinkSet.UplinkSetGroup               = $_LigUplinkSet
                    $MissingLIGUplinkSet.LogicalInterconnectUri       = $_LI.uri
                    $MissingLIGUplinkSet.LogicalInterconnectName      = $_LI.name
                    $MissingLIGUplinkSet.LogicalInterconnectGroupName = $_Lig.name

                }

                else
                {

                    'Uplink Set "{0}" exists in both LI and LIG.' -f $_LigUplinkSet.name | Write-Verbose #-Verbose

                    Add-Member -InputObject $lu.UplinkSetGroup -NotePropertyName LogicalInterconnectGroupName -NotePropertyValue $_LIG.name

                }
                
                [void]$myLUs.Add($lu)

            }
            
            # Need to add a check here for when the LIG Uplink Set(s) differe from LI, not what matches from LI to global Uplink Sets
            return $myLUs
            
        }

        function GetPortName ($bay, $portNumber) 
        {
            
            'Getting name for port Bay: {0}; Port Number: {1}' -f $Bay, $PortNumber | Write-Verbose #-Verbose
            

            # This function uses the Interconnect map Group set up in CompareInterconnects
            $InterconnectMapEntry = $InterconnectMapTemplate | ? bayNumber -eq $bay
            "InterconnectType: {0}" -f ($InterconnectMapEntry | FL *) | Write-Verbose #-Verbose

            $InterconnectModuleType = $InterconnectTypes | ? uri -eq $InterconnectMapEntry.InterconnectTypeUri
            "Interconnect Module Type: {0}" -f ($InterconnectModuleType | FL *) | Write-Verbose #-Verbose

            "Uplink Port Name: {0}" -f ($InterconnectModuleType.portInfos | ? portNumber -eq $PortNumber).portName | Write-Verbose #-Verbose
            Return ($InterconnectModuleType.portInfos | ? portNumber -eq $PortNumber).portName

        }

        function CompareNetworks ($lu, $lut) 
        {

            'Examining Networks associated with Uplink Set "{0}"' -f $lu.name | Write-Verbose #-Verbose

            switch ($lu.networkType)
            {

                'FibreChannel'
                {

                    'Processing Fibre Channel Uplink Set' | Write-Verbose #-Verbose

                    if ($lu.fcNetworkUris.Count -ne $lut.networkUris.Count) 
                    {

                        '{0} currently has {1} FC networks, Group has {2}' -f $lu.name, $lu.fcNetworkUris.Count, $lut.networkUris.Count | Write-Verbose
                    
                    }
                    
                    if ($null -eq $lut.fcNetworkUris) 
                    {

                        $diff = [PSCustomObject]@{InputObject = $lu.fcNetworkUris; SideIndicator = "=>"}

                    }

                    elseif ($null -eq $lu.fcNetworkUris) 
                    {

                        $diff = [PSCustomObject]@{InputObject = $lut.fcNetworkUris; SideIndicator = "<="}

                    }

                    else
                    {

                        $diff = Compare-Object -ReferenceObject $lu.fcNetworkUris -DifferenceObject $lut.networkUris

                    }

                }

                'Ethernet'
                {

                    'Processing Ethernet Uplink Set' | Write-Verbose #-Verbose

                    if ($lu.networkUris.Count -ne $lut.networkUris.Count) 
                    {
                        
                        '{0} currently has {1} Ethernet networks, Group has {2}' -f $lu.name, $lu.networkUris.Count, $lut.networkUris.Count | Write-Verbose
                        
                    }
                    
                    if ($null -eq $lut.networkUris) 
                    {

                        $diff = [PSCustomObject]@{InputObject = $lu.networkUris; SideIndicator = "=>"}

                    }

                    elseif ($null -eq $lu.networkUris) 
                    {

                        $diff = [PSCustomObject]@{InputObject = $lut.networkUris; SideIndicator = "<="}

                    }

                    else
                    {

                        $diff = Compare-Object -ReferenceObject $lu.networkUris -DifferenceObject $lut.networkUris

                    }                   

                }

            }
            
            foreach ($d in $diff) 
            {

                ForEach ($_uri in $d.InputObject)
                {

                    Try
                    {
                    
                        $net = Send-HPOVRequest -Uri $_uri -Hostname $ApplianceConnection
                    
                    }
                    
                    Catch
                    {
                    
                        $PSCmdlet.ThrowTerminatingError($_)
                    
                    }

                    if ($d.SideIndicator -eq $SideIndicator.Child)
                    {
    
                        $_diff = New-Object HPOneView.Library.CompareObject($lu.name, 
                                                                            $SideIndicator.Parent, 
                                                                            $net.name,
                                                                            $null, 
                                                                            $lut.LogicalInterconnectGroupName,
                                                                            $lu.LogicalInterconnectName,
                                                                            'MISSING_NETWORK')
    
                        [void]$CompareObject.Add($_diff)
    
                        '{0} is currently missing network {1} VLAN {2}' -f $lu.name, $net.name, $net.vlanId | Write-Verbose
    
                    } 
                    
                    else 
                    {
    
                        $_diff = New-Object HPOneView.Library.CompareObject($lu.name, 
                                                                            $SideIndicator.Child, 
                                                                            $null,
                                                                            $net.name, 
                                                                            $lut.LogicalInterconnectGroupName,
                                                                            $lu.LogicalInterconnectName,
                                                                            'EXTRA_NETWORK')
                        [void]$CompareObject.Add($_diff)
    
                        '{0} currently has extra network {1} VLAN {2}' -f $lu.name, $net.name, $net.vlanId | Write-Verbose
    
                    }

                }

            }

        }

        function CompareLocalNetworks ($li, $lig) 
        {

            'Examining Internal Networks' | Write-Verbose #-Verbose

            if ($li.internalNetworkUris.Count -ne $lig.internalNetworkUris.Count) 
            {
                
                '{0} currently has {1} Internal Ethernet networks, Group has {2}' -f $li.name, $li.internalNetworkUris.Count, $lig.internalNetworkUris.Count | Write-Verbose
                
            }

            $diff = Compare-Object -ReferenceObject $lig.internalNetworkUris -DifferenceObject $li.internalNetworkUris

            
            foreach ($d in $diff) 
            {

                Try
                {
                
                    $net = Send-HPOVRequest $d.InputObject
                
                }
                
                Catch
                {
                
                    PSCmdlet.ThrowTerminatingError($_)
                
                }
                
                if ($d.SideIndicator -eq $SideIndicator.Parent) 
                {

                    $_diff = New-Object HPOneView.Library.CompareObject('InternalNetworks', 
                                                                        $SideIndicator.Child, 
                                                                        $net.name,
                                                                        $null,                                                                         
                                                                        $lig.name,
                                                                        $li.name,
                                                                        'MISSING_NETWORK')

                    [void]$CompareObject.Add($_diff)

                    '{0} is currently missing internal network {1} VLAN {2}' -f $li.name, $net.name, $net.vlanId | Write-Verbose

                } 
                
                else 
                {

                    $_diff = New-Object HPOneView.Library.CompareObject('InternalNetworks', 
                                                                        $SideIndicator.Parent, 
                                                                        $null,
                                                                        $net.name, 
                                                                        $lig.name,
                                                                        $li.name,
                                                                        'EXTRA_NETWORK')
                    [void]$CompareObject.Add($_diff)

                    '{0} currently has extra network {1} VLAN {2}' -f $li.name, $net.name, $net.vlanId | Write-Verbose

                }

            }

        }

        function ComparePorts ($lu, $lut) 
        {

            "Comparing ports" | Write-Verbose #-Verbose

            "Uplink Set Port count: {0}" -f $lu.portConfigInfos.Count | Write-Verbose #-Verbose
            "LIG Uplink Set Port count: {0}" -f $lut.logicalPortConfigInfos.Count | Write-Verbose #-Verbose

            if ($lu.portConfigInfos.Count -ne $lut.logicalPortConfigInfos.Count) 
            {

                '{0} currently has {1} ports, Group has {2}' -f $lu.name, $lu.portConfigInfos.Count, $lut.logicalPortConfigInfos.Count | Write-Verbose

            }

            #Build array of LU ports
            $luPorts = New-Object System.Collections.ArrayList
            $lutPorts = New-Object System.Collections.ArrayList

            #Process LIG Uplink Set Uplink Ports
            foreach ($upPorts in $lut.logicalPortConfigInfos) 
            {

                $Port = [PSCustomObject]@{ type = 'lut.portConfigInfos';bayNumber = $null; portNumber = $null; portName = $null; Speed = $null }

                foreach ($loc in $upPorts.logicalLocation.locationEntries) 
                {

                    $Port.Speed = $upPorts.desiredSpeed

                    if ($loc.type -eq "BAY") { $Port.bayNumber = $loc.relativeValue }

                    if ($loc.type -eq "PORT") { $Port.portNumber = $loc.relativeValue }

                }

                $Port.portName = GetPortName $Port.bayNumber $Port.portNumber

                [void]$lutPorts.Add($Port)

            }

            #Process LI Uplink Set Uplink Ports
            foreach ($upPorts in $lu.portConfigInfos) 
            {

                $Port = [PSCustomObject]@{ type = 'lu.portConfigInfos';bayNumber = $null; portNumber = $null; portName = $null; Speed = $null }

                foreach ($loc in $upPorts.Location.locationEntries) 
                {

                    $Port.Speed = $upPorts.desiredSpeed

                    if ($loc.type -eq "BAY") { $Port.bayNumber = $loc.Value }

                    if ($loc.type -eq "PORT") { $Port.portName = $loc.Value }

                }

                [void]$luPorts.Add($Port)

            }

            $PortLocationDiff = Compare-Object -ReferenceObject $lutPorts -DifferenceObject $luPorts -Property bayNumber, portName

            'PortLocationDiff Object: {0}' -f ($PortLocationDiff | Out-String) | Write-Verbose #-Verbose

            foreach ($d in $PortLocationDiff) 
            {

                $Property = 'Bay{0}:{1}' -f $d.bayNumber, $d.portName

                if ($d.SideIndicator -eq $SideIndicator.Parent) 
                {

                    $_diff = New-Object HPOneView.Library.CompareObject($lu.name, 
                                                                        $SideIndicator.Child, 
                                                                        $Property, 
                                                                        $null, 
                                                                        $lut.LogicalInterconnectGroupName,
                                                                        $lu.LogicalInterconnectName,
                                                                        'MISSING_UPLINKPORT')
                    
                    [void]$CompareObject.Add($_diff)
                    
                    '{0} is currently missing port bay {1} port ' -f $lu.name, $d.bayNumber, $d.portName | Write-Verbose
                
                } 
                
                elseif ($d.SideIndicator -eq $SideIndicator.Child)  
                {

                    $_diff = New-Object HPOneView.Library.CompareObject($lu.name, 
                                                                        $SideIndicator.Parent, 
                                                                        $null, 
                                                                        $Property, 
                                                                        $lut.LogicalInterconnectGroupName,
                                                                        $lu.LogicalInterconnectName,
                                                                        'ADDITIONAL_UPLINKPORT')
                    
                    [void]$CompareObject.Add($_diff)
                    
                    '{0} currently has extra port on bay {1} port {2}' -f $lu.name, $d.bayNumber, $d.portName | Write-Verbose

                }

            }

            $PortSpeedDiff = Compare-Object -ReferenceObject $lutPorts -DifferenceObject $luPorts -Property Speed -PassThru

            'PortSpeedDiff Object: {0}' -f ($PortSpeedDiff | Out-String) | Write-Verbose #-Verbose

            foreach ($d in $PortSpeedDiff) 
            {

                if ($luPorts | ? { $_.bayNumber -eq $d.bayNumber -and $_.portName -eq $d.portName} )
                {

                    $Property = '{0}:Bay{1}:{2}' -f $lut.name,$d.bayNumber, $d.portName

                    'luPort Object: {0}' -f (($luPorts | ? { $_.bayNumber -eq $d.bayNumber -and $_.portName -eq $d.portName}) | Out-String) | Write-Verbose #-Verbose

                    if ($d.SideIndicator -eq '=>')
                    {

                        $ParentValue = $null

                        if ($lutPorts | ? { $_.bayNumber -eq $d.bayNumber -and $_.portName -eq $d.portName})
                        {

                            $ParentValue = '{0}' -f $GetUplinkSetPortSpeeds[($lutPorts | ? { $_.bayNumber -eq $d.bayNumber -and $_.portName -eq $d.portName}).Speed]

                        }
                        
                        $ChildValue = '{0}' -f $GetUplinkSetPortSpeeds[$d.Speed]

                    }
                
                    elseif ($d.SideIndicator -eq '<=')
                    {

                        $ChildValue = $null
                        
                        if ($luPorts | ? { $_.bayNumber -eq $d.bayNumber -and $_.portName -eq $d.portName})
                        {

                            $ChildValue = '{0}' -f $GetUplinkSetPortSpeeds[($luPorts | ? { $_.bayNumber -eq $d.bayNumber -and $_.portName -eq $d.portName}).Speed]

                        }

                        $ParentValue = '{0}' -f $GetUplinkSetPortSpeeds[$d.Speed]                        

                    }

                    $_diff = New-Object HPOneView.Library.CompareObject($Property, 
                                                                        $SideIndicator.NotEqual, 
                                                                        $ParentValue, 
                                                                        $ChildValue, 
                                                                        $lut.LogicalInterconnectGroupName,
                                                                        $lu.LogicalInterconnectName,
                                                                        'LINKSPEED_MISMATCH')
                    
                    [void]$CompareObject.Add($_diff)

                    '{0} Uplink Port {1}:{2} has different link speed {3} than Group {4}' -f $lut.name, $d.bayNumber, $d.portName, $ParentValue, $ChildValue | Write-Verbose

                }

            }

        }

        function CompareUplinksWithGroup ($lu) 
        {

            $lut = $lu.UplinkSetGroup

            if (! $lut) 
            {
                
                '"{0}" Uplink Set has no matching LIG Uplink Set. Skipping.' -f $lu.name | Write-Verbose
                
            }

            if ($lu.name -eq 'missing')
            {

                '"{0}" Uplink Set within Logical Interconnect Group "{1}" is not provisioned or missing from Logical Interconnect "{2}"' -f $lut.name, $lu.LogicalInterconnectGroupName, $lu.LogicalInterconnectName | Write-Verbose

                $_diff = New-Object HPOneView.Library.CompareObject('UplinkSets',
                                                                    $SideIndicator.Child, 
                                                                    $lut.name, 
                                                                    $null, 
                                                                    $lu.LogicalInterconnectGroupName,
                                                                    $lu.LogicalInterconnectName,
                                                                    'MISSING_UPLINKSET')
                
                [void]$CompareObject.Add($_diff)

            }

            else 
            {

                'Comparing {0} Uplink Set with Group' -f $lu.name | Write-Verbose #-Verbose

                'LU: {0}' -f ($lu | FL * | Out-String) | Write-Verbose #-Verbose
                'LUT: {0}' -f ($lut | FL * | Out-String) | Write-Verbose #-Verbose

                if ($lu.networkType -ne $lut.networkType) 
                {
                    
                    $_diff = New-Object HPOneView.Library.CompareObject(($lu.name + ':networkType'), 
                                                                        $SideIndicator.Parent, 
                                                                        $lut.networkType, 
                                                                        $lu.networkType,
                                                                        $lut.LogicalInterconnectGroupName,
                                                                        $lu.LogicalInterconnectName,
                                                                        'NETWORKTYPE_MISMATCH')
                    
                    [void]$CompareObject.Add($_diff)
                    
                    '"{0}" current Type "{1}" differs from Group Type "{2}"' -f $lu.name, $lu.networkType, $lut.networkType | Write-Verbose
                
                }

                if ($lu.connectionMode -ne $lut.mode) 
                {

                    $LutPort = $null
                    $LuPort = $null

                    if ($lut.LogicalInterconnectGroupName)
                    {

                        $LutPort = $lut.LogicalInterconnectGroupName + ":" + $lut.name

                    }
                    
                    if ($lu.LogicalInterconnectName)
                    {

                        $LuPort = $lu.LogicalInterconnectName + ":" + $lu.name

                    }
                    
                    $_diff = New-Object HPOneView.Library.CompareObject('connectionMode', 
                                                                        $SideIndicator.Parent, 
                                                                        $lut.mode, 
                                                                        $lu.connectionMode, 
                                                                        $LutPort,
                                                                        $LuPort,
                                                                        'CONNECTIONMODE_MISMATCH')

                    [void]$CompareObject.Add($_diff)

                    '"{0}" current Connection Mode "{1}" differs from Group Connection Mode "{2}"' -f $lu.name, $lu.connectionMode, $lut.mode | Write-Verbose
                    
                }

                if ( $lut.mode -ne 'Auto' -or $lu.connectionMode -ne 'Auto')
                {

                    $LutPrimaryPort = [PSCustomObject]@{ bayNumber = $null; portNumber = $null; portName = $null; Speed = $null }
                    $LutPrimaryPort.bayNumber = ($lut.primaryPort.locationEntries | ? { $_.type -eq 'Bay' } ).relativeValue
                    $LutPrimaryPort.portNumber = ($lut.primaryPort.locationEntries | ? { $_.type -eq 'Port' } ).relativeValue
                    $LutPrimaryPort.portName = GetPortName $LutPrimaryPort.bayNumber $LutPrimaryPort.portNumber

                    $LuPrimaryPort = [PSCustomObject]@{ bayNumber = $null; portNumber = $null; portName = $null; Speed = $null }
                    $LuPrimaryPort.bayNumber = ($lu.primaryPortLocation.locationEntries | ? type -eq 'Bay').value
                    $LuPrimaryPort.portName = ($lu.primaryPortLocation.locationEntries | ? type -eq 'Port').value

                    $PrimaryPortDiff = Compare-Object -ReferenceObject $LutPrimaryPort -DifferenceObject $LuPrimaryPort -Property portName -PassThru

                    'PrimaryPortDiff Object: {0}' -f ($PrimaryPortDiff | Out-String) | Write-Verbose #-Verbose

                    if ($PrimaryPortDiff)
                    {

                        $_SideIndicator = '<=>'

                        $_ParentPrimaryPort = ('BAY{0}:{1}' -f $LutPrimaryPort.bayNumber, $LutPrimaryPort.portName)
                        $_ChildPrimaryPort = ('BAY{0}:{1}' -f $LuPrimaryPort.bayNumber, $LuPrimaryPort.portName)

                        if (! $LuPrimaryPort.portName)
                        {

                            $_SideIndicator = '<='
                            $_ChildPrimaryPort = $null

                        }

                        elseif (! $LutPrimaryPort.portName)
                        {

                            $_SideIndicator = '=>'
                            $_ParentPrimaryPort = $null

                        }

                        $_diff = New-Object HPOneView.Library.CompareObject('PrimaryPort',
                                                                            $_SideIndicator,
                                                                            $_ParentPrimaryPort,
                                                                            $_ChildPrimaryPort, 
                                                                            ($lut.LogicalInterconnectGroupName + ":" + $lut.name),
                                                                            ($lu.LogicalInterconnectName + ":" + $lu.name),
                                                                            'PRIMARYPORT_MISMATCH')

                        [void]$CompareObject.Add($_diff)

                        '"{0}" current Primary Port "{1}" differs from Group "{2}"' -f $lu.name, $_ChildPrimaryPort, $_ParentPrimaryPort | Write-Verbose                

                    }

                }


                if ($lu.nativeNetworkUri -ne $lut.nativeNetworkUri) 
                {

                    'LU NativeNetworkUri: {0}' -f $lu.nativeNetworkUri | Write-Verbose #-Verbose
                    'LUT NativeNetworkUri: {0}' -f $lut.nativeNetworkUri | Write-Verbose #-Verbose

                    $_SideIndicator = $SideIndicator.NotEqual

                    if ($lu.nativeNetworkUri) 
                    { 
                        
                        $luNativeNetwork = (Send-HPOVRequest $lu.nativeNetworkUri).name 
                    
                    }

                    else
                    {
                    
                        $luNativeNetwork = "None"
                        $_SideIndicator = $SideIndicator.Parent
                    
                    }

                    if ($lut.nativeNetworkUri) 
                    {

                        $lutNativeNetwork = (Send-HPOVRequest $lut.nativeNetworkUri).name

                    }

                    else
                    {
                    
                        $lutNativeNetwork = "None"
                        $_SideIndicator = $SideIndicator.Child
                    
                    }

                    $_diff = New-Object HPOneView.Library.CompareObject(($lu.name + ':nativeNetworkUri'), 
                                                                        $_SideIndicator,
                                                                        $lutNativeNetwork, 
                                                                        $luNativeNetwork, 
                                                                        $lut.LogicalInterconnectGroupName,
                                                                        $lu.LogicalInterconnectName,
                                                                        'NATIVENETWORK_MISMATCH')
                    
                    [void]$CompareObject.Add($_diff)
                    
                    '"{0}" current Native Network "{1}" differs from Group Native Network "{2}"' -f $lu.name, $luNativeNetwork, $lutNativeNetwork | Write-Verbose

                }

                CompareNetworks $lu $lut

                ComparePorts $lu $lut

            }

        }
        
        Function MissingUplinkSetFromLIG 
        {

            Return [PSCustomObject] @{

                Name                         = "missing";
                UplinkSetGroup               = $null;
                LogicalInterconnectUri       = $null;
                LogicalInterconnectName      = $null;
                LogicalInterconnectGroupName = $null

            }

        }

        ##################################################################
        # If InputObject is not a PSCustomObject, assume it is an Enclosure Name
        if ($InputObject -IsNot [System.Management.Automation.PSCustomObject])
        {

            Try
            {
            
                $InputObject = Get-HPOVEnclosure -Name $InputObject -ApplianceConnection $ApplianceConnection
            
            }
            
            Catch
            {
            
                PSCmdlet.ThrowTerminatingError($_)
            
            }    

        }

        "InputObject resource: {0} [{1}]" -f $InputObject.name, $InputObject.category | Write-Verbose

        #Loop through all ICM bays of the Enclosure object
        if ($InputObject.category -eq 'enclosures')
        {

            '{0} has {1} interconnect bays which are configured as {2} logical Interconnects' -f $InputObject.name, ($InputObject.interconnectBays | ? interconnectUri).Count, $_LogicalInterconnectUris.Count | Write-Verbose

            $UniqueLIUris = $InputObject.interconnectBays | Select -Property logicalInterconnectUri -Unique | ? { $_.logicalInterconnectUri }  

            ForEach ($_uri in $UniqueLIUris.logicalInterconnectUri)
            {

                'Processing LI URI: {0}' -f $_uri | Write-Verbose

                Try
                {
                
                    $_LIObject = Send-HPOVRequest -Uri $_uri -Hostname $ApplianceConnection
                    $_LigObject = Send-HPOVRequest -Uri $_LIObject.logicalInterconnectGroupUri -Hostname $ApplianceConnection
                    
                    $_LIObject | Add-Member -NotePropertyName LogicalInterconnectGroup -NotePropertyValue $_LigObject -Force
                    [void]$_LogicalInterconnects.Add($_LIObject)
                
                }
                
                Catch
                {
                
                    $PSCmdlet.ThrowTerminatingError($_)
                
                }

            }

        }

        elseif ($InputObject.category -eq 'logical-enclosures')
        {

            #Is this even right? There is a logicalInterconnectUris property. Should that be used, even for C-Class and Synergy?
            ForEach ($_LogicalInterconnectUri in $InputObject.logicalInterconnectUris)
            {

                Try
                {
                
                    $_LogicalInterconnect = Send-HPOVRequest -Uri $_LogicalInterconnectUri -Hostname $ApplianceConnection
                
                }
                
                Catch
                {
                
                    $PSCmdlet.ThrowTerminatingError($_)
                
                }

                '{0} has {1} interconnect bays which are configured within the Logical Interconnect' -f $InputObject.name, $InputObject.interconnects.Count | Write-Verbose

                Try
                {
                
                    $_LigObject = Send-HPOVRequest -Uri $_LogicalInterconnect.logicalInterconnectGroupUri -Hostname $ApplianceConnection
                    
                    $_LogicalInterconnect | Add-Member -NotePropertyName LogicalInterconnectGroup -NotePropertyValue $_LigObject -Force
                    [void]$_LogicalInterconnects.Add($_LogicalInterconnect)
                
                }
                
                Catch
                {
                
                    $PSCmdlet.ThrowTerminatingError($_)
                
                }                

            }

        }

        elseif ($InputObject.category -eq 'logical-interconnects')
        {

            '{0} has {1} interconnect bays which are configured within the Logical Interconnect' -f $InputObject.name, $InputObject.interconnects.Count | Write-Verbose

            Try
            {
            
                $_LIObject = $InputObject.PSObject.Copy()
                $_LigObject = Send-HPOVRequest -Uri $_LIObject.logicalInterconnectGroupUri -Hostname $ApplianceConnection
                
                $_LIObject | Add-Member -NotePropertyName LogicalInterconnectGroup -NotePropertyValue $_LigObject -Force
                [void]$_LogicalInterconnects.Add($_LIObject)
            
            }
            
            Catch
            {
            
                $PSCmdlet.ThrowTerminatingError($_)
            
            }

        }

        else
        {

            Throw "Unsupported InputObject. Only Enclosure or Logical Interconnect resources are permitted."

        }

        #Start the compare process
        foreach ($_LI in $_LogicalInterconnects) 
        {

            "Logical Interconnect '{0}' has '{1}' Interconnects and is based on Group '{2}'" -f $_LI.name, $_LogicalInterconnect.Interconnects.Count, $_LI.LogicalInterconnectGroup.name | Write-Verbose

            #Compare Expected and Actual interconnect map
            CompareInterconnects $_LI $_LI.LogicalInterconnectGroup

            #Collect Uplink Sets from both LIG and LI
            $lus = GetUplinkSets $_LI $_LI.LogicalInterconnectGroup

            foreach ($lu in $lus) 
            {

                # Compare Uplink Sets between LI and LIG, with LIG Uplink Set within LI Uplink Set (LU)
                CompareUplinksWithGroup $lu

            }

            #Compare Local Networks
            CompareLocalNetworks $_LI $_LI.LogicalInterconnectGroup
            
        }

        #Display final object
        $CompareObject

    }

    End
    {

        'Done.' | Write-Verbose

    }

}

function Show-HPOVLogicalInterconnectMacTable 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "MACAddress")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Pipeline")]
        [ValidateNotNullorEmpty()]
        [Alias ("name","li","LogicalInterconnect")]
        [object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "Pipeline")]
        [ValidateNotNullorEmpty()]
        [string]$network,

        [Parameter (Mandatory = $false, ParameterSetName = "MACAddress")]
        [validatescript({if ($_ -match $script:macAddressPattern) {$true} else { throw "The input value '$_' does not match 'aa:bb:cc:dd:ee:ff'. Please correct the value and try again."}})]
        [Alias ("mac")]
        [string]$MacAddress,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "MACAddress")]
        [Parameter (Mandatory = $false, ParameterSetName = "Pipeline")]
        [Alias ("x", "ExportFile")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$Export,
        
        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Parameter (Mandatory = $false, ParameterSetName = "MACAddress")]
        [Parameter (Mandatory = $false, ParameterSetName = "Pipeline", ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
        
        if ($PSCmdlet.ParameterSetName -ne 'Pipeline')
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $MacTables = New-Object System.Collections.ArrayList

    }

    Process 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconnect via PipeLine: $PipelineInput"

        if (-not($InputObject))
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Logical Interconnects provided via Parameter. Getting all LI resources."

            Try
            {

                $InputObject = Get-HPOVLogicalInterconnect

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        ForEach ($li in $InputObject) 
        {

            if ($li -is [PSCustomObject] -and $li.category -eq "logical-interconnects") 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconnect object provided: $($li.name)"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconnect object URI: $($li.uri)"

                $uri = $li.uri +"/forwarding-information-base"

            }

            else 
            {

                #Unsupported type
                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'LogicalInterconnect' -TargetType $li.GetType().Name -Message "The Parameter -LogicalInterconnect contains an invalid Parameter value type, '$($li.gettype().fullname)' is not supported. Only [PSCustomObject] type is allowed."
                $PSCmdlet.WriteError($ErrorRecord)

            }

            #Filter the request for a specific Network
            if ($Network) 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filtering for '$Network' Network Resource"
                
                $_Network = Get-HPOVNetwork $network -ApplianceConnection $li.ApplianceConnection.Name

                $_internalVlanId = $_Nework.internalVlanId

                $uri += "?filter=internalVlan=$_internalVlanId"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $uri"

                Try
                {

                    $resp = (Send-HPOVRequest $uri -Hostname $li.ApplianceConnection.Name).members

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                

            }

            elseif ($MacAddress) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filtering for MAC Address '$MacAddress'"

                $uri += "?filter=macAddress='$MacAddress'"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $uri"

                Try
                {

                    $resp = (Send-HPOVRequest $uri -Hostname $li.ApplianceConnection.Name).members

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

            else 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Generating '$uri' mactable file."

                Try
                {

                    #$MacTableFile = (Send-HPOVRequest -Uri $uri -Metho POST -Hostname $li.ApplianceConnection.Name).members
                    $MacTableFile = Send-HPOVRequest -Uri $uri -Metho POST -Hostname $li.ApplianceConnection.Name

                    "[{0}] MacTable Contents: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($MacTableFile | FL * | Out-String) | Write-Verbose

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                

                if ("Success","Completed" -match $MacTableFile.state -and -not([System.String]::IsNullOrWhiteSpace($MacTableFile))) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($MacTableFile.uri)' mactable file."

                    Try
                    {

                        $resp = Download-MacTable $MacTableFile

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                elseif ([System.String]::IsNullOrWhiteSpace($MacTableFile))
                {

                    $Message = 'The results returned are null. This Cmdlet is not supported with the HPE OneView DCS appliance.'
                    $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidInterconnectFibDataInfo InvalidOperation 'InputObject' -Message $Message
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidInterconnectFibDataInfo InvalidResult 'InputObject' -Message ($macTableFile.state + ": " + $macTableFile.status)
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }


            }

            $resp | % {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding $($_.address) to collection"

                [void]$MacTables.Add($_)

            } 

        }

    }

    End 
    {

        if ($list) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Displaying formatted table."

            if ($name -or $MacAddress) 
            {

                $m = @{Expression={($_.interconnectName -split ",")[0]};Label="Enclosure"},
                     @{Expression={($_.interconnectName -split ",")[1]};Label="Interconnect"},                 
                     @{Expression={$_.networkInterface};Label="Interface"},
                     @{Expression={$_.macAddress};Label="Address"},
                     @{Expression={$_.entryType};Label="Type"},
                     @{Expression={$_.networkName};Label="Network"},
                     @{Expression={$_.externalVlan};Label="VLAN"}

            }

            else 
            {

                $m = @{Expression={$_.Enclosure};Label="Enclosure"},
                     @{Expression={$_.Interconnect};Label="Interconnect"},
                     @{Expression={$_.Interface};Label="Interface"},
                     @{Expression={$_.address};Label="Address"},
                     @{Expression={$_.type};Label="Type"},
                     @{Expression={$_.network};Label="Network"},
                     @{Expression={$_.extVlan};Label="VLAN"},
                     @{Expression={$_.LAGPorts};Label="LAG Ports"}

            }

            $MacTables | sort "Enclosure","Interconnect",macAddress | format-table $m -autosize

        }

        elseif ($PSBoundParameters['Export']) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Exporting to CSV file: $Export"

            $MacTables | sort Enclosure,Interconnect,macAddress | Export-CSV $Export -NoTypeInformation

        }
        else 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Displaying results."

            $MacTables | sort Enclosure,Interconnect,macAddress

        }
        
        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. {0} mac table entry(ies) found." -f $MacTables.Count | write-verbose

    }

}

function Download-MacTable 
{
    
    <#
        .SYNOPSIS
        Download Logical Interconnect MAC Table CSV.
 
        .DESCRIPTION
        This internal helper function will download the MAC Table CSV from a provided Logical Interconnect, parse it and return an array of MAC Table entries.
 
        .Parameter Uri
        [System.String] URI of Logical Interconnect.
 
        .Parameter Hostname
        [System.String] Hostname of Appliance
 
        .INPUTS
        None.
 
        .OUTPUTS
        System.Array
        Array of MAC Table entries.
 
        .LINK
        Get-HPOVLogicalInterconnect
 
        .EXAMPLE
        PS C:\> $encl1li = Get-HPOVLogicalInterconnect Encl1-LI
        PS C:\> Download-MACTable $encl1li
 
        Get the Logical Interconnect 'Encl1-LI' and
                 
    #>


    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [ValidateScript({if ($_.type -eq 'interconnect-fib-data-info') { $true } else {throw "-URI must being with a '/rest/logical-interconnects/' in its value. Please correct the value and try again."}})]
        [Object]$InputObject

    ) 

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        $enc = [System.Text.Encoding]::UTF8

    }
 
    Process
    {    

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Download URI: $($InputObject.uri)"

        [System.Net.httpWebRequest]$fileDownload = RestClient GET $InputObject.uri $InputObject.ApplianceConnection.Name

        $fileDownload.accept               = "application/zip,application/octet-stream,*/*"
        $fileDownload.Headers.Item("auth") = ($ConnectedSessions | ? Name -eq $InputObject.ApplianceConnection.Name).SessionID

        $i = 0
        foreach ($h in $fileDownload.Headers) 
        { 
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Request Header $($i): $($h) = $($fileDownload.Headers[$i])"
            
            $i++
        
        }
        
        Try
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Request: GET $($fileDownload.RequestUri.AbsolutePath | out-string)"
            
            #Get response
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting response"
            [Net.httpWebResponse]$rs = $fileDownload.GetResponse()

            #Display the response status if verbose output is requested
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response Status: $([int]$rs.StatusCode) $($rs.StatusDescription)"

            $i = 0
            foreach ($h in $rs.Headers) 
            { 
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Response Header $($i): $($h) = $($rs.Headers[$i])"
                
                $i++ 
            
            }

            #Request is a redirect to download file contained in the response headers
            $fileName = ($rs.headers["Content-Disposition"].SubString(21)) -replace "`"",""

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filename: $($fileName)"
                                                
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filesize: $($rs.ContentLength)"

            $responseStream = $rs.GetResponseStream()

            #Define buffer and buffer size
            [int] $bufferSize = ($rs.ContentLength*1024)
            [byte[]]$Buffer   = New-Object byte[] ($rs.ContentLength*1024)
            [int] $bytesRead  = 0

            #This is used to keep track of the file upload progress.
            $totalBytesToRead = $rs.ContentLength
            $numBytesRead     = 0
            $numBytesWrote    = 0

            #Read from stream
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Reading HttpWebRequest file stream."
            $responseStream.Read($Buffer, 0, $bufferSize) | out-Null
            
            #Write to output stream
            $outStream = new-object System.IO.MemoryStream (,$Buffer)    

            $source = $outStream.ToArray()
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Decompressing HttpWebRequest file."
            $sr = New-Object System.IO.Compression.GZipStream($outStream,[System.IO.Compression.CompressionMode]::Decompress)
            
            #Reset variable to collect uncompressed result
            $byteArray = New-Object byte[]($source.Length+1024)
            
            #Decompress
            [int]$rByte = $sr.Read($byteArray, 0, $source.Length)

            #Transform byte[] unzip data to string
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Converting Byte array to String Characters."
            $sB = New-Object System.Text.StringBuilder($rByte)
            
            #Read the number of bytes GZipStream read and do not a for each bytes in resultByteArray
            for ([int] $i = 0; $i -lt $rByte; $i++) 
            {

                $sB.AppEnd([char]$byteArray[$i]) | Out-Null

            }
            
        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        Finally
        {

            #Clean up our work
            if ($responseStream) { $responseStream.Close() }
            if ($rs) { $rs.Close() }
            if ($sr) { $sr.Close();$sr.Dispose() }

        }

    }

    End 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Building string array in CSV format"

        $macTableArray = $sb.ToString() -split "`n"
        $header        = "enclosure","interconnect","interface","address","type","network","extVLAN","intVLAN","serverProfile","uplinkSet","LAGPort1","LAGPort2","LAGPort3","LAGPort4","LAG Port5","LAG Port6","LAG Port7","LAG Port8"
        $macTableArray = $macTableArray[1..($macTableArray.count)]

        $e = @{Expression={
             
                 $lagport = $_
                 1..8 | % { if ($lagport."LAGPort$($_)") { $lagport."LAGPort$($_)" } } 
                           
             };name="LAGPorts"}

        $macTable = $macTableArray | ConvertFrom-Csv -Header $header | select "enclosure","interconnect","interface","address","type","network","extVLAN","intVLAN","serverProfile","uplinkSet",$e

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Returning results."

        Return $macTable

    }

}

function Install-HPOVLogicalInterconnectFirmware 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (
        
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [Alias ('name','uri', 'li')]
        [ValidateNotNullorEmpty()]
        [object]$LogicalInterconnect,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateSet ('Update','Activate','Stage')]
        [string]$Method = "Update",

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateSet ('OddEven','Parallel','Serial')]
        [Alias ('Order','ActivateOrder')]
        [string]$EthernetActivateOrder = 'OddEven',

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [int]$EthernetActivateDelay = 5,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateSet ('OddEven','Parallel','Serial')]
        [String]$FCActivateOrder = 'Serial',

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [int]$FCActivateDelay = 5,

        [Parameter (Mandatory, ParameterSetName = "default")]
        [Alias ('spp')]
        [object]$Baseline,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$Force,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($LogicalInterconnect))
        {

            $PipelineInput = $True

        }
        
        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $TaskCollection = New-Object System.Collections.ArrayList
        
    }

    Process 
    {

        if ($PipelineInput -or $LogicalInterconnect -is [PSCustomObject])
        {

            #Validate Logical Interconnect Object Type
            if (-not($LogicalInterconnect -is [PSCustomObject]) -and $LogicalInterconnect.category -ne 'local-interconnects') 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] invalid LogicalInterconnect passed: $($LogicalInterconnect)"

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'INSTALL-HPOVLOGICALINTERCONNECTFIRMWARE' -Message "The 'LogicalInterconnect' Parameter value '$($LogicalInterconnect)' is invalid. Please check the Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
        
            }

        }

        else
        {

            if ($null -eq $ApplianceConnection)
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message 'No Appliance Connection was provided. Please provide a valid ApplianceConnection Object.'
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Looking for Logical Interconnect '$LogicalInterconnect' from Get-HPOVLogicalInterconnect."

            Try
            {
                
                $LogicalInterconnect = Get-HPOVLogicalInterconnect -Name $LogicalInterconnect -ApplianceConnection $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Validating Baseline input value."

        switch ($Baseline.GetType().Name)
        {

            'String'
            {

                Try
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Firmware Baseline name passed: $($Baseline)"

                    $FirmwareBaslineName = $Baseline.Clone()

                    $Baseline = Get-HPOVBaseline -name $Baseline -ApplianceConnection $LogicalInterconnect.ApplianceConnection.Name -ErrorAction SilentlyContinue

                    If (-not $_BaseLinePolicy)
                    {

                        $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $FirmwareBaslineName
                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Baseline' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            'PSCustomObject'
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Firmware Baseline object passed: $($Baseline | FL * | Out-String)"

                if ($Baseline.category -ne 'firmware-drivers')
                {
                    
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException InvalidBaselineObject InvalidArgument 'Baseline' -TargetType 'PSObject' -Message "The Baseline provided in an invalid object. Baseline category value '$($Basline.caetegory)', expected 'firmware-drivers'. Please check the Parameter value and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                }

            }

        }

        $Staging    = $False
        $Activating = $False

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($LogicalInterconnect.name)' Logical Interconnect."

        $_Request = NewObject -LogicalInterconnectBaseline

        $_Request.command                 = $Method
        $_Request.ethernetActivationType  = [String]$EthernetActivateOrder
        $_Request.ethernetActivationDelay = [int]$EthernetActivateDelay
        $_Request.fcActivationType        = [String]$FCActivateOrder
        $_Request.fcActivationDelay       = [int]$FCActivateDelay
        $_Request.sppUri                  = $Baseline.uri
        $_Request.force                   = [bool]$PSBoundParameters['Force']

        switch ($Method) 
        {

            {'Update', 'Stage' -match $_}
            { 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] '$Method' Method called."        
                
                $_Request.command = $Method
                
                
            }

            "Activate" 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] 'Activate' Method called."
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Verifying '$(LogicalInterconnect.name)' LI is in a Staged state."
                
                Try
                {

                    $_FirmwareStatus = Send-HPOVRequest ($LogicalInterconnect.uri + "/firmware") -Hostname $LogicalInterconnect.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                #Validate interconnect firmware update state
                switch ($_FirmwareStatus.state) 
                {
                     
                    'STAGED' 
                    { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] '$($LogicalInterconnect.name)' LI is in the proper '$($_FirmwareStatus.state)' state."

                        #$baselineObj = [pscustomobject] @{ uri = $_FirmwareStatus.sppUri }

                        $_Request.command = 'ACTIVATE'
                        $_Request.sppUri  = $_FirmwareStatus.sppUri

                    }
                        
                    'STAGING'
                     { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] '$($LogicalInterconnect.name)' is currently being staged with firmware. Please wait until the task completes."
                            
                        #Locate and return running task.
                        $_task = Get-HPOVTask -State Running -resource $LogicalInterconnect.name -ApplianceConnection $LogicalInterconnect.ApplianceConnection.Name

                        $_task | ? { $_.taskStatus.StartsWith('Staging') } | % {

                            [void]$TaskCollection.Add($_)

                        }

                        # Flag to skip the command Processing IF block below
                        $Staging = $true
                            
                    }

                    'STAGING_FAILED' 
                    { 
                        
                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidLogicalInterconnectState InvalidResult 'LogicalInterconnect' -Message "The $($LogicalInterconnect.name) Logical Interconnect is in an invalid state ($($_FirmwareStatus.state))in order to issue the Activate command."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                        
                    }

                    'ACTIVATED' 
                    { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] '$($LogicalInterconnect.name)' is already activated."
                        
                        Write-Warning "'$($LogicalInterconnect.name)' is already activated."
                        
                        Return 
                    
                    }

                    'ACTIVATING' 
                    {
                            
                        #Logical Interconnect is already Processing the Activate command.
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] '$($LogicalInterconnect.name)' is already activating. Returning task resource."

                        # Flag to skip the command Processing IF block below
                        $activating = $True
                            
                        #Locate and return running task.
                        $_task = Get-HPOVTask -State Running -resource $LogicalInterconnect.name -ApplianceConnection $LogicalInterconnect.ApplianceConnection.Name

                        $_task | ? { $_.taskStatus.StartsWith('Activating') } | % {

                            [void]$TaskCollection.Add($_)

                        }

                    }

                    'ACTIVATION_FAILED' 
                    { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] '$($LogicalInterconnect.name)' failed a prior activation request. LI is in a valid state to attempt Activation command."

                        #$baselineObj = [pscustomobject] @{ uri = $_FirmwareStatus.sppUri }

                        $_Request.command = 'ACTIVATE'
                        $_Request.sppUri  = $_FirmwareStatus.sppUri
                            
                    }

                    'PARTIALLY_ACTIVATED' 
                    { 
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] '$($LogicalInterconnect.name)' is Partially Activated. LI is in a valid state to attempt Activation command."
                        $baselineObj = [pscustomobject] @{ uri = $_FirmwareStatus.sppUri }
                        
                    }

                    'PARTIALLY_STAGED' 
                    {
                        
                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidLogicalInterconnectState InvalidResult 'LogicalInterconnect' -Message "The $($LogicalInterconnect.name) Logical Interconnect is in an invalid state ($($_FirmwareStatus.state)) in order to issue the Activate command."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                        
                    }

                    'UNINITIALIZED' 
                    { 
                        
                        <# Generate Error that firmware has not been staged #> 
                        $ErrorRecord = New-ErrorRecord InvalidOperationException NoStagedFirmwareFound ObjectNotFound 'LogicalInterconnect' -Message "No staged firmware found for '$($LogicalInterconnect.name)' Logical Interconnect. Use Install-HPOVLogicalInterconnectFirmware -method Stage to first stage the firmware before attempting to Activate."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                    }

                }
                
            }

        }

        #Need to prompt user to update or activate firmware, which could cause an outage.
        if (('Update', 'Stage' -match $Method) -and (-not($Activating)) -and (-not($Staging)))
        {

            Write-Warning 'Module activation may cause a network outage if Activation Order is Parallel.'

            if ($PSCmdlet.ShouldProcess($LogicalInterconnect.name,'update and activate Interconnect modules')) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User was prompted warning and accepted. Sending request."

                Try
                {

                    $_taskResults = Send-HPOVRequest -method PUT -uri ($LogicalInterconnect.uri + "/firmware") -body $_Request -Hostname $LogicalInterconnect.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                    
            }

            else 
            { 
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User was prompted and selected No, cancelling the update for $($LogicalInterconnect.name)" 
            
            }

        }

        #User is staging firmware, no need to prompt.
        elseif (-not($Activating) -and (-not($Staging)))
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Beginning to stage firmware to '$($LogicalInterconnect.name)'."

            Try
            {

                $_taskResults = Send-HPOVRequest -method PUT -uri ($li.uri + "/firmware") -body $_Request -Hostname $LogicalInterconnect.ApplianceConnection.Name

            }

            Catch
            {

              $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        if (-not($PSBoundParameters['Async']))
        {

            Try
            {

                $_taskResults = Wait-HPOVTaskComplete $_taskResults -ApplianceConnection $_taskResults.ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        [void]$TaskCollection.Add($_taskResults)

    }

    End 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Finished, returning results."

        return $TaskCollection

    }


}

function Show-HPOVPortStatistics 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "InterconnectPort")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Pipeline")]
        [Parameter (Mandatory = $false, ParameterSetName = "InterconnectPort")]
        [object]$Port,

        [Parameter (Mandatory, ParameterSetName = "InterconnectPort")]
        [object]$Interconnect,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Pipeline")]
        [Parameter (Mandatory = $false, ParameterSetName = "InterconnectPort")]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSCmdlet.ParameterSetName -eq 'Pipeline')
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Port object provided by pipeline."

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_PortStatsCol = New-Object System.Collections.ArrayList
    
    }

    Process 
    {

        Switch ($PSCmdlet.ParameterSetName) 
        {

            "Pipeline" 
            {

                switch ($Port.GetType().Name)
                {

                    #Do not support String Port values via pipeline, so generate error
                    "String" 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.InterconnectPortResourceException InvalidInterconnectPortParameter InvalidArgument 'Port' -Message "The -Port Parameter only supports Objects via the pipeline. Please refer to the CMDLET help for proper pipeline syntax."

                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)  
                        
                    }

                    "PSCustomObject" 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Port Object provided: $($Port | Out-String)"

                        #Validate the Port Object is type Port
                        if ($Port.category -ne "ports") 
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.InterconnectPortResourceException InvalidInterconnectPortObject InvalidArgument 'Port' -TargetType "PSObject" -Message ("The object for the -Port Parameter is the wrong type: {0}. Expected category 'ports'. Please check the object provided and try again." -f $Port.category )
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                        }

                        Try
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Interconnect resource from Port Object."

                            $_InterconnectUri = $Port.uri.SubString(0,$Port.uri.IndexOf('/ports/' + $Port.portId))

                            $Interconnect = Send-HPOVRequest $_InterconnectUri -ApplianceConnection $Port.ApplianceConnection.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                }

            }

            "InterconnectPort" 
            { 

                switch ($Interconnect.GetType().Name)
                {

                    "String" 
                    {


                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Interconnect object '$Interconnect'"

                        Try
                        {

                            $Interconnect = Get-HPOVInterconnect $Interconnect -ApplianceConnection $ApplianceConnection

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                    "PSCustomObject" 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Interconnect Object provided: $($Interconnect | Out-String)"

                        #Validate the Port Object is type Port
                        if ($Interconnect.category -ne 'interconnects') 
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.InterconnectPortResourceException InvalidInterconnectPortObject InvalidArgument 'Interconnect' -TargetType "PSObject" -Message ("The object for -Interconnect Parameter is the wrong resource category: {0}. Expected type 'interconnects'. Please check the object provided and try again." -f  $Interconnect.category)

                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                        }

                    }

                }

                if ($PSBoundParameters['Port'])
                {

                    if ($Port -is [String])
                    {

                        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filtering for '{0}' within '{1}' Interconnect." -f $Port, $Interconnect.name | Write-Verbose 

                        $_originalport = $Port

                        $Port = $Interconnect.ports | ? portName -like $Port

                        if (-not($Port)) 
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.InterconnectPortResourceException InvalidInterconnectPort InvalidArgument 'Port' -Message ("The the port '{0}' was not found within '{1}'. Available ports within the interconnect are '{2}' Please check the port value and try again." -f $_originalport, $Interconnect.name, ($interconnect.ports.portName -join ",") )

                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                        }

                    }

                    elseif ($Port -is [PSCustomObject])
                    {

                        $_originalport = $Port.PSObject.Copy()

                        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filtering for '{0}' within '{1}' Interconnect." -f $Port.name, $Interconnect.name | Write-Verbose 

                        $Port = $Interconnect.ports | ? portName -like $Port.name

                        if (-not($Port)) 
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.InterconnectPortResourceException InvalidInterconnectPort InvalidArgument 'Port' -TargetType 'PSObject' -Message ("The the port '{0}' was not found within '{1}'. Available ports within the interconnect are '{2}' Please check the port value and try again." -f $_originalport.name, $Interconnect.name, ($interconnect.ports.portName -join ",") )

                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                        }

                    }

                }

            }

        }

        Try
        {

            $_InterconnectStats = Send-HPOVRequest ($Interconnect.uri + "/statistics") -ApplianceConnection $ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        $_InterconnectStats | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Networking.InterconnectStatistics") }

        if ($Port) 
        { 
            
            $_InterconnectStats.portStatistics = $_InterconnectStats.portStatistics | ? { $port.portName -contains $_.portName } 
        
        }

        #Set the specific TypeNames value for Formats to handle
        foreach ($_PortObj in $Interconnect.ports) 
        {

            switch ($_PortObj.configPortTypes) 
            {

                {@("EnetFcoe","Ethernet") -match $_ } 
                {

                    $TypeName    = "HPOneView.Networking.PortStatistics.Ethernet"
                    $SubTypeName = "Ethernet"
                    Break

                }

                "FibreChannel" 
                {

                    $TypeName    = "HPOneView.Networking.PortStatistics.FibreChannel"
                    $SubTypeName = "FibreChannel"
                    Break

                }

            }

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] inserting '{0}' into '{1}' [{2}]" -f $TypeName, $_PortObj.name, ($_PortObj.configPortTypes -join ",") | Write-Verbose 

            ($_InterconnectStats.portStatistics | ? portName -eq $_PortObj.portName ).PSObject.TypeNames.Insert(0,$TypeName)
            ($_InterconnectStats.portStatistics | ? portName -eq $_PortObj.portName ) | Add-Member -NotePropertyName portConfigType -NotePropertyValue $SubTypeName -force
        }

        #Insert sampleInterval from the Interconnect itself. Otherwise, portStatistics doesn't contain the interval.
        $_InterconnectStats.portStatistics | % { Add-Member -InputObject $_ -NotePropertyName sampleInterval -NotePropertyValue $_InterconnectStats.moduleStatistics.portTelemetryPeriod -force }

        $_InterconnectStats.portStatistics | sort-Object portConfigType,portName | % {

            [void]$_PortStatsCol.Add($_)

        }

    }

    End 
    {

        Return $_PortStatsCol

    }

} 

function Get-HPOVLogicalInterconnectGroup 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (ValueFromPipeline, Mandatory, ParameterSetName = 'Pipeline')]
        [Alias('Resource')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateSet ('SAS','VC')]
        [String]$Type,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Pipeline')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ("x", "export")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$exportFile

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSCmdlet.ParameterSetName -eq 'Pipeline')
        {

            $PipelineInput = $True

        }

        Else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $LigCollection = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomObject])
        {

            #Task Resource Object
            if ($InputObject.category -eq 'tasks')
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Task Resource input object."

                if ($InputObject.taskState -eq 'Completed')
                {

                    Try
                    {

                        $_LigObject = Send-HPOVRequest $InputObject.associatedResource.resourceUri -Hostname $InputObject.ApplianceConnection.Name

                        $_LigObject | % { 
                
                            $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnectGroup')    

                            [void]$LigCollection.Add($_) 
                
                        }

                    }

                    Catch
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] API Error Caught: $($_.Exception.Message)"

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                #Generate error
                else
                {

                    $InputObject

                    $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectGroupResourceException TaskFailure InvalidOperation 'InputObject' -Message "The Task object provided by the pipeline did not complete successfully. Please validate the task object resource and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                }

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectGroupResourceException LogicalInterconnectGroupNotFound ObjectNotFound 'InputObject' -Message "The Logical Interconnect Group associated with the pipeline input task object was not found on '$($InputObject.ApplianceConnection.Name)'. Please check the value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

            }

        }

        Else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                $_FoundCollection = New-Object System.Collections.ArrayList

                if ($PSBoundParameters['Label'])
                {

                    $_uri = '{0}?category:logical-interconnect-groups&query=labels:{1}' -f $IndexUri, $Label

                    Try
                    {

                        $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                        #Loop through all found members and get full SVT object
                        ForEach ($_memeber in $_IndexMembers.members)
                        {

                            Try
                            {

                                $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }                        

                            $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnectGroup')    

                            [void]$_FoundCollection.Add($_memeber) 

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                else
                {

                    if (-not($PSBoundParameters['Type']) -and $_appliance.ApplianceType -ne 'Composer')
                    {

                        $Type = 'VC'

                    }

                    elseif (-not $PSBoundParameters['Type'] -and $_appliance.ApplianceType -eq 'Composer')
                    {

                        [Array]$Type = 'VC','SAS'

                    }

                    "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

                    if ($Type -Contains 'SAS')
                    {

                        if ($_appliance.ApplianceType -ne 'Composer')
                        {
                
                            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is an HPE OneView Virtual Machine Appliance, which does not support SAS Logical Interconnect Group resources.' -f $_appliance.Name)
                            $PSCmdlet.WriteError($ErrorRecord)
                
                        }

                        else
                        {

                            $Uri = $SasLogicalInterconnectGroupsUri + "?sort=name:asc"

                            if ($PSboundParameters['Name']) 
                            {

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SAS Logical Interconnect Group name provided: '$Name'"

                                $_method = 'EQ'

                                if ($Name.Contains('*'))
                                {

                                    $_Name = $Name.Replace('*','%25').Clone()

                                    $_method = 'matches'

                                }

                                else
                                {

                                    $_Name = $Name.Clone()
                                }

                                $Uri += "&filter=name {0} '{1}'" -f $_method.ToLower(), $_Name

                            }

                            if ($PSBoundParameters['Scope'])
                            {

                                $Uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri
                            
                            }

                            Try
                            {
                                

                                $_SasLigs = Send-HPOVRequest -Uri $Uri -Hostname $_appliance.Name

                            }

                            Catch
                            {

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] API Error Caught: $($_.Exception.Message)"

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                            if ($_SasLigs.count -eq 0) 
                            { 

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No SAS Logical Interconnect Group resources found on '$($_appliance.Name)'."

                            }

                            else 
                            {

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($_SasLigs.count) SAS Logical Interconnect Group resource(s)."
                
                                $_SasLigs.members | % { 
                
                                    $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.SASLogicalInterconnectGroup')    

                                    [void]$_FoundCollection.Add($_) 
                
                                }

                            }

                        }

                    }

                    if ($Type -Contains 'VC')
                    {

                        $Uri = $LogicalInterconnectGroupsUri + "?sort=name:asc"

                        if ($PSboundParameters['Name']) 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconnect Group name provided: '$Name'"

                            $_method = 'eq'

                            if ($Name.Contains('*'))
                            {

                                $_Name = $Name.Replace('*','%25').Clone()

                                $_method = 'matches'

                            }

                            else
                            {

                                $_Name = $Name.Clone()
                            }

                            $Uri += "&filter=name {0} '{1}'" -f $_method.ToLower(), $_Name

                        }

                        if ($PSBoundParameters['Scope'])
                        {

                            $Uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri
                        
                        }

                        Try
                        {

                            $_VCligs = Send-HPOVRequest -Uri $Uri -Hostname $_appliance.Name

                        }

                        Catch
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] API Error Caught: $($_.Exception.Message)"

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
            
                        if ($_VCligs.count -eq 0) 
                        { 

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No Logical Interconnect Group resources found on '$($_appliance.Name)'."

                        }

                        else 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($_VCligs.count) Logical Interconnect Group resource(s)."
                
                            $_VCligs.members | % { 
                
                                $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnectGroup')    

                                [void]$_FoundCollection.Add($_) 
                
                            }

                        }

                    }

                    #Generate error if no LIG resources were found, yet name was provided.
                    if ($_FoundCollection.count -eq 0 -and $Name) 
                    { 

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconnect Group '$name' resource not found. Generating error"

                        $ExceptionMessage = "Specified Logical Interconnect Group '{0}' was not found on '{1}' appliance connection. Please check the name and try again." -f $Name, $_appliance.Name
                        $ErrorRecord = New-ErrorRecord InvalidOperationException LogicalInterconnectGroupNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                        $PSCmdlet.WriteError($ErrorRecord)  

                    }

                    #Add found members to collection
                    else
                    {

                        $_FoundCollection | % {

                            [void]$LigCollection.Add($_)

                        }

                    } 

                }

            }        

        }

    }

    End 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. $($LigCollection.count) logical interconnect group(s) found."

        if ($exportFile)
        {
            
            $LigCollection | convertto-json -Depth 99 | Set-Content -Path $exportFile -force -encoding UTF8 
        
        }
                
        else 
        {
            
            Return $LigCollection | Sort category,name
        
        }

    }

}

function New-HPOVLogicalInterconnectGroup 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "C7000")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "C7000")]
        [Parameter (Mandatory, ParameterSetName = "Synergy")]
        [ValidateNotNullOrEmpty()]
        [Alias ('ligname')]
        [String]$Name,

        [Parameter (Mandatory, ParameterSetName = "Synergy")]
        [ValidateRange(1,5)]
        [int]$FrameCount = 1,

        [Parameter (Mandatory, ParameterSetName = "Synergy")]
        [ValidateRange(1,3)]
        [int]$InterconnectBaySet,

        [Parameter (Mandatory, ParameterSetName = "Synergy")]
        [ValidateSet ('SEVC40F8','SEVCFC','SAS')]
        [String]$FabricModuleType,

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "C7000")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Synergy")]
        [Hashtable]$Bays,

        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [ValidateSet ('HighlyAvailable','Redundant','ASide','BSide')]
        [String]$FabricRedundancy = 'Redundant',

        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [Alias ("IGMPSnoop")]
        [bool]$EnableIgmpSnooping = $False,
        
        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [ValidateRange(1,3600)]
        [Alias ('IGMPIdle')]
        [int]$IgmpIdleTimeoutInterval = 260,
        
        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Alias ('FastMAC')]
        [bool]$EnableFastMacCacheFailover = $True,
        
        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [ValidateRange(1,30)]
        [Alias ('FastMACRefresh')]
        [int]$MacRefreshInterval = 5,
        
        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [Alias ('LoopProtect')]
        [bool]$EnableNetworkLoopProtection = $True,

        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Alias ('PauseProtect')]
        [bool]$EnablePauseFloodProtection = $True,

        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [bool]$EnableLLDPTagging = $false,

        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [bool]$EnableEnhancedLLDPTLV,        
        
        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [Object]$SNMP,

        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [Array]$InternalNetworks,

        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [Alias ('qos','QosConfig')]
        [Object]$QosConfiguration,

        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [Parameter (Mandatory = $False, ParameterSetName = "Import")]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $False, ParameterSetName = "C7000")]
        [Parameter (Mandatory = $False, ParameterSetName = "Synergy")]
        [switch]$Async,

        [Parameter (Mandatory, ParameterSetName = "Import")]
        [ValidateScript({split-path $_ | Test-Path})]
        [Alias ('i')]
        [object]$Import

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $LigTasks = New-Object System.Collections.ArrayList

    }
    
    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            If ($Import)
            {
            
                write-verbose "Reading input file"

                try 
                {

                    #Open input file, join so we can validate if the JSON format is correct.
                    $lig = [string]::Join("", (gc $import -ErrorAction Stop)) | convertfrom-json -ErrorAction Stop

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] LIG Object to Import: $($lig | ConvertTo-Json -depth 99 | Out-String)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"
                
                    $task = Send-HPOVRequest $logicalInterconnectGroupsUri POST $lig -Appliance $_appliance

                    [void]$LigStatus.Add($task)

                }
            
                #If there was a problem with the input file (format, not syntax) throw error
                catch [System.ArgumentException] 
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Import' -TargetType "PSObject" -Message "JSON Input File is invalid. Please check the contents and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            Else 
            {

                switch ($PSCmdlet.ParameterSetName)
                {

                    'C7000'
                    {

                        $uri = $LogicalInterconnectGroupsUri

                        #Create new LIgObject
                        $lig = NewObject -C7KLig 

                        $lig.ethernetSettings.enableIgmpSnooping          = $EnableIgmpSnooping
                        $lig.ethernetSettings.igmpIdleTimeoutInterval     = $IgmpIdleTimeoutInterval
                        $lig.ethernetSettings.enableFastMacCacheFailover  = $EnableFastMacCacheFailover
                        $lig.ethernetSettings.macRefreshInterval          = $MacRefreshInterval
                        $lig.ethernetSettings.enableNetworkLoopProtection = $EnableNetworkLoopProtection
                        $lig.ethernetSettings.enablePauseFloodProtection  = $EnablePauseFloodProtection
                        $lig.ethernetSettings.enableTaggedLldp            = $EnableLLDPTagging
                        $lig.ethernetSettings.enableRichTLV               = $EnableEnhancedLLDPTLV

                        #Fill in missing bay locations from the input value if needed.
                        $Secondary = @{ 1 = $null; 2 = $null; 3 = $null; 4 = $null; 5 = $null; 6 = $null; 7 = $null; 8 = $null }

                        #check for any duplicate keys
                        $duplicates = $Bays.keys | where { $Secondary.ContainsKey($_) }

                        if ($duplicates) 
                        {

                            foreach ($item in $duplicates) 
                            {

                                $Secondary.Remove($item)

                            }

                        }

                        #join the two hash tables
                        $NewBays = $Bays + $Secondary 

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Bay configuration: $($NewBays | Sort-Object Key -DescEnding | Out-String)"

                        #Assign located Interconnect object URI to device bay mapping.
                        foreach ($_bay in ($NewBays.GetEnumerator() | Sort-Object Key))
                        {

                            $_interconnectObject = $null
                
                               switch ($_bay.value) 
                            {

                                "FlexFabric" 
                                {            

                                    #Get VC FlexFabric interconnect-type URI
                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found VC FF in bay $($_bay.name | out-string)"

                                    $_interconnectObject = Get-HPOVInterconnectType -partNumber "571956-B21" -Appliance $_appliance

                                }

                                "Flex10" 
                                {

                                    #Get VC Flex-10 interconnect-type URI
                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found VC F10 in bay $($_bay.name | out-string)"

                                    $_interconnectObject = Get-HPOVInterconnectType -partNumber "455880-B21" -Appliance $_appliance

                                }

                                "Flex1010D" 
                                {

                                    #Get VC Flex-10/10D interconnect-type URI
                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found VC F1010D in bay $($_bay.name | out-string)"

                                    $_interconnectObject = Get-HPOVInterconnectType -partNumber "638526-B21" -Appliance $_appliance

                                }

                                "Flex2040f8" 
                                {

                                    #Get VC Flex-10/10D interconnect-type URI
                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found VC Flex2040f8 in bay $($_bay.name | out-string)"

                                    $_interconnectObject = Get-HPOVInterconnectType -partNumber "691367-B21" -Appliance $_appliance

                                }

                                "VCFC20" 
                                {

                                    #Get VC Flex-10/10D interconnect-type URI
                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found VC FC 20-port in bay $($_bay.name | out-string)"

                                    $_interconnectObject = Get-HPOVInterconnectType -partNumber "572018-B21" -Appliance $_appliance

                                }

                                "VCFC24" 
                                {

                                    #Get VC Flex-10/10D interconnect-type URI
                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found VC FC 24-port in bay $($_bay.name | out-string)"

                                    $_interconnectObject = Get-HPOVInterconnectType -partNumber "466482-B21" -Appliance $_appliance

                                }

                                "FEX" 
                                {

                                    #Get Cisco Fabric ExtEnder for HP BladeSystem interconnect-type URI
                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found Cisco Fabric ExtEnder for HP BladeSystem in bay $($_bay.name | out-string)"
                            
                                    $_interconnectObject = Get-HPOVInterconnectType -partNumber "641146-B21" -Appliance $_appliance

                                }

                                default 
                                {

                                    $_interconnectObject = $null

                                }
                    
                            }
                
                            $_InterconnectMapEntryTemplate = NewObject -InterconnectMapEntryTemplate

                            $_InterconnectMapEntryTemplate.permittedInterconnectTypeUri = $_interconnectObject.uri;
                            
                            $_LogicalLocationEntry = NewObject -LocationEntry
                            $_LogicalLocationEntry.relativeValue = 1
                            $_LogicalLocationEntry.type          = 'Enclosure'
                            
                            [void]$_InterconnectMapEntryTemplate.logicalLocation.locationEntries.Add($_LogicalLocationEntry)

                            $_LogicalLocationEntry = NewObject -LocationEntry
                            $_LogicalLocationEntry.relativeValue = [String]$_bay.name.ToString().ToLower().Replace('bay',$null)
                            $_LogicalLocationEntry.type          = 'Bay'
                            
                            [void]$_InterconnectMapEntryTemplate.logicalLocation.locationEntries.Add($_LogicalLocationEntry)

                            [void]$lig.interconnectMapTemplate.interconnectMapEntryTemplates.Add($_InterconnectMapEntryTemplate)

                        }

                    }

                    'Synergy'
                    {

                        if ((${Global:ConnectedSessions} | ? Name -EQ $_appliance.Name).ApplianceType -ne 'Composer')
                        {

                            $Message = 'The Appliance {0} is not a Synergy Composer, and this operation is not supported. Only Synergy managed resources are supported with this Cmdlet.' -f $_appliance.Name

                            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.ComposerNodeException UnsupportedMethod InvalidOperation 'ApplianceConnection' -TargetType 'HPOneView.Appliance.Connection' -Message $Message

                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        switch ($FabricModuleType)
                        {

                            'SEVC40F8'
                            {

                                #Used for the POST request below
                                $uri = $LogicalInterconnectGroupsUri

                                #Create new LIgObject
                                $lig = NewObject -SELig 

                                $lig.name                                         = $Name
                                $lig.redundancyType                               = $LogicalInterconnectGroupRedundancyEnum[$FabricRedundancy]
                                $lig.interconnectBaySet                           = $InterconnectBaySet
                                $lig.ethernetSettings.enableIgmpSnooping          = $EnableIgmpSnooping
                                $lig.ethernetSettings.igmpIdleTimeoutInterval     = $IgmpIdleTimeoutInterval
                                $lig.ethernetSettings.enableFastMacCacheFailover  = $EnableFastMacCacheFailover
                                $lig.ethernetSettings.macRefreshInterval          = $MacRefreshInterval
                                $lig.ethernetSettings.enableNetworkLoopProtection = $EnableNetworkLoopProtection
                                $lig.ethernetSettings.enablePauseFloodProtection  = $EnablePauseFloodProtection
                                $lig.ethernetSettings.enableTaggedLldp            = $EnableLLDPTagging
                                $lig.ethernetSettings.enableRichTLV               = $EnableEnhancedLLDPTLV

                                if ($FrameCount -ne $Bays.Count)
                                {

                                    $Message = "The -FrameCount parameter value '{0}' does not match the expected Frame and Fabric Bay configuration in the -Bays parameters, '{1}'." -f $FrameCount, $Bays.Count
                                    $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectGroupResourceException InvalidArgumentValue InvalidArgument 'InternalNetworks' -TargetType 'PSObject' -Message $Message
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                1..$FrameCount | % { [void]$lig.enclosureIndexes.Add($_) }

                            }

                            'SEVCFC'
                            {

                                #Used for the POST request below
                                $uri = $LogicalInterconnectGroupsUri

                                #Create new LIgObject
                                $lig = NewObject -SELig 
                                $lig.name               = $Name
                                $lig.redundancyType     = $LogicalInterconnectGroupRedundancyEnum[$FabricRedundancy]
                                $lig.interconnectBaySet = $InterconnectBaySet
                                [void]$lig.enclosureIndexes.Add('-1')
                                $EnclosureIndex = '-1'

                                #Validate BaySet
                                if ($InterconnectBaySet -eq 3)
                                {

                                    $Message = "The -InterconnectBaySet parameter value '{0}' is not supported. Please choose InterconnectBaySet 1 or 2." -f $InterconnectBaySet
                                    $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectGroupResourceException InvalidArgumentValue InvalidArgument 'InterconnectBaySet' -TargetType 'Int' -Message $Message
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }
                                
                            }

                            'SAS'
                            {

                                #Used for the POST request below
                                $uri = $SasLogicalInterconnectGroupsUri

                                #Create new LIgObject
                                $lig = NewObject -SESASLIG
                                $lig.name  = $Name

                            }
                            
                        }

                        ForEach ($_Entry in ($Bays.GetEnumerator() | Sort-Object Key))
                        {

                            if ($_Entry.Name -Match 'frame')
                            {
                        
                                if ($EnclosureIndex = '-1' -and $FabricModuleType -eq 'SEVCFC')
                                {

                                    [int]$_FrameID = -1

                                }

                                else
                                {

                                    [int]$_FrameID = $_Entry.Name.ToLower().Replace("frame",$null)

                                }
                                

                                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Frame ID: {0}" -f $_FrameID | Write-Verbose

                                ForEach ($_Bay in ($_Entry.Value).GetEnumerator())
                                {

                                    [int]$_BayID = $_Bay.Name.ToString().ToLower().Replace('bay',$null)

                                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Fabric Module for Bay {0} to {1}" -f $_BayID, $_Bay.Value | Write-Verbose 
                        
                                    $_InterconnectBayObject = $null

                                    Try
                                    {

                                        $_InterconnectBayObject = Get-InterconnectBayObject $_Bay $_appliance

                                    }

                                    Catch
                                    {

                                        $PSCmdlet.ThrowTerminatingError($_)

                                    }

                                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting Fabric Module Bay {0} to {1}" -f $_BayID, $_InterconnectBayObject.name | Write-Verbose 

                                    $_InterconnectMapEntryTemplate = NewObject -InterconnectMapEntryTemplate

                                    $_InterconnectMapEntryTemplate.permittedInterconnectTypeUri = $_InterconnectBayObject.uri
                                    $_InterconnectMapEntryTemplate.enclosureIndex               = $_FrameID
                                    
                                    $_LogicalLocationEntry = NewObject -LocationEntry
                                    $_LogicalLocationEntry.relativeValue = $_FrameID
                                    $_LogicalLocationEntry.type          = 'Enclosure'
                                
                                    [void]$_InterconnectMapEntryTemplate.logicalLocation.locationEntries.Add($_LogicalLocationEntry)

                                    $_LogicalLocationEntry = NewObject -LocationEntry
                                    $_LogicalLocationEntry.relativeValue = $_BayID
                                    $_LogicalLocationEntry.type          = 'Bay'
                                    
                                    [void]$_InterconnectMapEntryTemplate.logicalLocation.locationEntries.Add($_LogicalLocationEntry)

                                    [void]$lig.interconnectMapTemplate.interconnectMapEntryTemplates.Add($_InterconnectMapEntryTemplate)
                            
                                }

                            }

                            else
                            {

                                [int]$_BayID = $_Entry.Name.ToString().ToLower().Replace('bay',$null)

                                if ($EnclosureIndex = '-1' -and $FabricModuleType -eq 'SEVCFC')
                                {

                                    [int]$_FrameID = -1

                                }

                                else
                                {

                                    $_FrameID = 1
                                    
                                }                            
                                            
                                $_InterconnectBayObject = $null

                                Try
                                {

                                    $_InterconnectBayObject = Get-InterconnectBayObject $_Entry $_appliance

                                }

                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }

                                if ($_BayID -ne 1 -and $_BayID -ne 4 -and $_InterconnectBayObject.name -match 'SAS')
                                {

                                    $Message = 'The Fabric Module Bay {0} is invalid for the Synergy 12Gb SAS Connection Module. Please specify Fabric Module Bay 1 or 4.' -f $_BayID
                                    $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectGroupResourceException InvalidFabricBayIDforSasInterconnect InvalidArgument 'Bays' -TargetType $_Entry.GetType().Name -Message $Message
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                                }

                                "[{0}] Setting Fabric Module Bay {1} to {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_BayID, $_Entry.Value | Write-Verbose 

                                $_InterconnectMapEntryTemplate = NewObject -InterconnectMapEntryTemplate

                                $_InterconnectMapEntryTemplate.permittedInterconnectTypeUri = $_InterconnectBayObject.uri
                                $_InterconnectMapEntryTemplate.enclosureIndex               = $_FrameID
                                
                                $_LogicalLocationEntry = NewObject -LocationEntry
                                $_LogicalLocationEntry.relativeValue = $_FrameID
                                $_LogicalLocationEntry.type          = 'Enclosure'
                            
                                [void]$_InterconnectMapEntryTemplate.logicalLocation.locationEntries.Add($_LogicalLocationEntry)

                                $_LogicalLocationEntry = NewObject -LocationEntry
                                $_LogicalLocationEntry.relativeValue = $_BayID
                                $_LogicalLocationEntry.type          = 'Bay'
                                
                                [void]$_InterconnectMapEntryTemplate.logicalLocation.locationEntries.Add($_LogicalLocationEntry)

                                [void]$lig.interconnectMapTemplate.interconnectMapEntryTemplates.Add($_InterconnectMapEntryTemplate)

                            }

                        }

                    }

                }
                
                if ($lig.type -notmatch 'sas')
                {

                    #decide what type of QoS Configuration to add to activeQosConfig
                    $lig.qosConfiguration.activeQosConfig = if ($QosConfiguration) 
                    { 

                        if(-not($QosConfiguration -is [PSCustomObject]))
                        {

                            $Message = "The -QosConfiguration Parameter does not contain a valid QOS Configuration Object. Please check the value and try again."
                            $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectGroupResourceException InvalidArgumentValue InvalidArgument 'QosConfiguration' -TargetType $QosConfiguration.Gettype().Name -Message $Message
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }
                    
                        if ($QosConfiguration.type -ne 'QosConfiguration')
                        {

                            $Message = "The -QosConfiguration Parameter value does not contain a valid QOS Configuration Object. OBject type expected 'QosConfiguration', recieved '$($QosConfiguration.type)'. Please check the value and try again."
                            $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectGroupResourceException InvalidArgumentValue InvalidArgument 'QosConfiguration' -TargetType 'PSObject' -Message $Message
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                        }

                        $QosConfiguration 
                
                    } 
                
                    Else 
                    { 
                    
                        NewObject -QosConfiguration 
                
                    }

                    if ($PSBoundParameters['InternalNetworks'])
                    {

                        ForEach ($_network in $InternalNetworks)
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Internal Network Type: $($_network.GetType().Name)"

                            switch ($_network.GetType().Name)
                            {

                                'String'
                                {

                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Internal Network: $_network"

                                    if ($_network.StartsWith($script:ethNetworksUri))
                                    {

                                        Try
                                        {

                                            #Validating object
                                            $_network = Send-HPOVRequest $_network -Hostname $_appliance

                                            #Generate terminating error due to incorrect object from URI isn't the correct type
                                            if ($_network.category -ne 'ethernet-networks')
                                            {

                                                $Message = "The Internal Network '$_network' does not match the allowed value of 'ethernet-networks'. Please specify an Ethernet Network to assign to the Internal Networks property."
                                                $ErrorRecord = New-ErrorRecord HPOneView.LogicalInterconnectGroupResourceException InvalidArgumentValue InvalidArgument 'InternalNetworks' -TargetType 'PSObject' -Message $Message
                                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                            }

                                        }

                                        catch
                                        {

                                            $PSCmdlet.ThrowTerminatingError($_)

                                        }

                                    }

                                    #Get network resource via Get-HPOVNetwork
                                    else
                                    {

                                        try
                                        {

                                            $_network = Get-HPOVNetwork $_network -ApplianceConnection $_appliance

                                        }

                                        catch
                                        {

                                            $PSCmdlet.ThrowTerminatingError($_)

                                        }

                                    }

                                }

                                'PSCustomObject'
                                {

                                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Internal PSObject Network: $($_network | fl * )"

                                    #Throw terminating error if the Internet Network object is not type Ethernet Network
                                    if (-not($_network.category -eq 'ethernet-networks'))
                                    {

                                        $Message = "The Internal Network category for ($_network.name) does not match the allowed value of 'ethernet-networks'."
                                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InternalNetworks' -TargetType 'PSObject' -Message $Message
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                    }

                                    #Error if Netowrk Object does not match the appliance connection we are currently Processing.
                                    if ($_network.ApplianceConnection.Name -ne $_appliance.Name)
                                    {

                                        $Message = "The Internal Network '($_network.name)' Appliance Connection ($($_network.ApplianceConnection.Name)) does not match the current Appliance Connection ($($_appliance.Name)) being Processed."
                                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InternalNetworks' -TargetType 'PSObject' -Message $Message
                                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                                    }

                                }

                            }

                            #Add to URI's to collection
                            [void]$lig.internalNetworkUris.Add($_network.uri)

                        }

                    }

                }            

                if ($PSBoundParameters['Snmp'])
                {

                    $lig.snmpConfiguration = $Snmp

                }

                $lig.name = $Name

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] LIG: $(ConvertTo-Json -Depth 99 $lig | out-string)"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to create '$($lig.name)'..."
            
                Try
                {
                
                    $task = Send-HPOVRequest $uri POST $lig -Hostname $_appliance
                
                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($Async.IsPresent)
                {

                    [void]$LigTasks.Add($task)

                }

                else
                {

                    Try
                    {

                        $_FinalTaskStaus = Wait-HPOVTaskComplete $task

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    [void]$LigTasks.Add($_FinalTaskStaus)

                }        

            }

        }

    }

    End 
    {

        Return $LigTasks

    }

}

function Get-InterconnectBayObject
{

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [System.Collections.DictionaryEntry]$InterconnectBay,
        
        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection

    )

    Process
    {

        switch ($InterconnectBay.Value) 
        {

            'SEVC40f8'
            {            

                $_PartNumber = '794502-B23'
                
            }

            'SEVC16GbFC'
            {

                $_PartNumber = '779227-B21'

            }

            'SE20ILM'
            {

                $_PartNumber = '779218-B21'

            }

            'SE10ILM'
            {

                $_PartNumber = '779215-B21'

            }

            'SE12SAS'
            {

                Try
                {

                    $_interconnectObject = Get-HPOVSasInterconnectType -partNumber "755985-B21" -Appliance $ApplianceConnection

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            default 
            {

                #Should we throw an exception here?
                # $ExceptionMessage = "The specified Interconnect Bay type was not"
                # $ErrorRecord = New-ErrorRecord HPOneView.SnmpTrapDestination InvalidTrapSeverity InvalidArgument 'InterconnectBay' -Message ("The provided SNMP Trap Severity {0} is unsupported. Please check the value, making sure it is one of these values: {1}." -f $_severity, ([System.String]::Join(", ", $SnmpTrapSeverityEnums)))

                # $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                $_interconnectObject = $null

            }
                    
        }

        Try
        {

            '[{0}] Looking for {1} (P/N: {2})' -f $MyInvocation.InvocationName.ToString().ToUpper(), $InterconnectBay.Value, $_Partnumber | Write-Verbose

            if ($Null -ne $_PartNumber)
            {

                $_interconnectObject = Get-HPOVInterconnectType -partNumber $_PartNumber -Appliance $ApplianceConnection

            }
            
        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

    }

    End
    {

        Return $_interconnectObject

    }

}

function New-HPOVSnmpConfiguration
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$ReadCommunity,
        
        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [String]$Contact,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Array]$AccessList,
        
        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Array]$TrapDestinations

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        $_SnmpConfigrationCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        $_SnmpConfig = NewObject -SnmpConfig

        switch ($PSBoundParameters.keys)
        {

            'ReadCommunity'
            {

                $_SnmpConfig.readCommunity = $ReadCommunity

            }

            'Contact'
            {

                $_SnmpConfig.systemContact = $Contact
            
            }

            'AccessList'
            {
            
                ForEach ($_entry in $AccessList)
                {

                    [void]$_SnmpConfig.snmpAccess.Add($_entry)

                }
            
            }

            'TrapDestinations'
            {
            

                ForEach ($_entry in $TrapDestinations)
                {

                    [void]$_SnmpConfig.trapDestinations.Add($_entry)

                }

            }

        }


        $_SnmpConfig.PSObject.TypeNames.Insert(0,'HPOneView.Networking.SnmpConfiguration')

        [void]$_SnmpConfigrationCol.Add($_SnmpConfig)

    }

    End
    {

        Return $_SnmpConfigrationCol

    }

}

function New-HPOVSnmpTrapDestination
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Destination,
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [String]$Community = 'public',

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [ValidateSet ('SNMPv1', 'SNMPv2', IgnoreCase = $False)]
        [String]$SnmpFormat = 'SNMPv1',
        
        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Array]$TrapSeverities,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Array]$VCMTrapCategories,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Array]$EnetTrapCategories,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Array]$FCTrapCategories

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        $_TrapDestinationCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        $_TrapDestination = NewObject -SnmpTrapDestination

        $_TrapDestination.trapDestination    = $Destination
        $_TrapDestination.communityString    = $Community
        $_TrapDestination.trapFormat         = $SnmpFormat

        switch ($PSBoundParameters.keys)
        {

            'TrapSeverities'
            {

                ForEach ($_severity in $TrapSeverities)
                {
                    
                    #Throw error
                    if ($SnmpTrapSeverityEnums -notcontains $_severity)
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.SnmpTrapDestination InvalidTrapSeverity InvalidArgument 'TrapSeverities' -Message ("The provided SNMP Trap Severity {0} is unsupported. Please check the value, making sure it is one of these values: {1}." -f $_severity, ([System.String]::Join(", ", $SnmpTrapSeverityEnums)))

                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                    }

                    $_severity = $_severity.SubString(0,1).ToUpper() + $_severity.SubString(1).tolower()
                    
                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing {0} Trap Severity." -f $_severity  | Write-Verbose 
                    
                    [void]$_TrapDestination.trapSeverities.Add($_severity)

                }

            }

            'VCMTrapCategories'
            {
            
                ForEach ($_category in $VCMTrapCategories)
                {
                    
                    #Throw error
                    if ($SnmpVcmTrapCategoryEnums -notcontains $_category)
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.SnmpTrapDestination InvalidVcmTrapCategory InvalidArgument 'VCMTrapCategories' -Message ("The provided VCM Trap Category {0} is unsupported. Please check the value, making sure it is one of these values: {1}." -f $_category, ([System.String]::Join(", ", $SnmpVcmTrapCategoryEnums)))

                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                    }

                    $_category = $_category.SubString(0,1).ToUpper() + $_category.SubString(1).tolower()
                    
                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing {0} VCM Trap Category." -f $_category  | Write-Verbose 

                    [void]$_TrapDestination.vcmTrapCategories.Add($_category)

                }
            
            }

            'EnetTrapCategories'
            {
            
                ForEach ($_category in $EnetTrapCategories)
                {
                    
                    #Throw error
                    if ($SnmpEneTrapCategoryEnums -notcontains $_category)
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.SnmpTrapDestination InvalidEnetTrapCategory InvalidArgument 'EnetTrapCategories' -Message ("The provided Ethernet Trap Category {0} is unsupported. Please check the value, making sure it is one of these values: {1}." -f $_category, ([System.String]::Join(", ", $SnmpEneTrapCategoryEnums)))

                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                    }

                    if ($_category.StartsWith('port'))
                    {

                        $_category = $_category.SubString(0,1).ToUpper() + $_category.SubString(1,3).tolower() + $_category.SubString(4,1).ToUpper() + $_category.SubString(6).tolower()

                    }

                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing {0} Enet Trap Category." -f $_category  | Write-Verbose 

                    [void]$_TrapDestination.enetTrapCategories.Add($_category)

                }
            
            }

            'FCTrapCategories'
            {
            
                ForEach ($_category in $FCTrapCategories)
                {

                    #Throw error
                    if ($SnmpFcTrapCategoryEnums -notcontains $_category)
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.SnmpTrapDestination InvalidFcTrapCategory InvalidArgument 'FCTrapCategories' -Message ("The provided FC Trap Category {0} is unsupported. Please check the value, making sure it is one of these values: {1}." -f $_category, ([System.String]::Join(", ", $SnmpFcTrapCategoryEnums)))

                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                    }

                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing {0} FC Trap Category." -f $_category  | Write-Verbose 
                    
                    [void]$_TrapDestination.fcTrapCategories.Add($_category)

                }
            
            }

        }

        $_TrapDestination.PSObject.TypeNames.Insert(0,'HPOneView.Networking.SnmpTrapDestination')

        [void]$_TrapDestinationCol.Add($_TrapDestination)

    }

    End
    {

        Return $_TrapDestinationCol

    }

}

function New-HPOVQosConfig
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Passthrough")]
    Param 
    (

        [Parameter (Mandatory = $False, ParameterSetName = "Passthrough")]
        [Parameter (Mandatory, ParameterSetName = "Custom")]
        [ValidateSet ("Passthrough", "CustomNoFCoE", "CustomWithFCoE", IgnoreCase = $False)]
        [String]$ConfigType = "Passthrough",

        [Parameter (Mandatory = $False, ParameterSetName = "Custom")]
        [ValidateSet ("DSCP", "DOT1P", "DOT1P_AND_DSCP", IgnoreCase = $False)]
        [String]$UplinkClassificationType = "DOT1P",

        [Parameter (Mandatory = $False, ParameterSetName = "Custom")]
        [ValidateSet ("DSCP", "DOT1P", "DOT1P_AND_DSCP", IgnoreCase = $False)]
        [String]$DownlinkClassificationType = "DOT1P_AND_DSCP",

        [Parameter (Mandatory = $False, ParameterSetName = "Custom")]
        [System.Collections.ArrayList]$TrafficClassifiers = @()

    )

    Begin
    {

        #Helper CMDLET. Does not require appliance authentication.

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #Validate the caller
        if (($PSBoundParameters['UplinkClassificationType'] -or $PSBoundParameters['DownlinkClassificationType'] -or $PSBoundParameters['TrafficClassifiers']) -and $ConfigType -eq 'Passthrough')
        {

            $ParameterNames = New-Object System.Collections.ArrayList
        
            switch ($PSBoundParameters.Keys)
            {

                'UplinkClassificationType'   { [void]$ParameterNames.Add('UplinkClassificationType') }
                'DownlinkClassificationType' { [void]$ParameterNames.Add('DownlinkClassificationType') }
                'TrafficClassifiers'         { [void]$ParameterNames.Add('TrafficClassifiers') }

            }

            $Message = "ConfigType Parameter value was set to 'Passthrough' and $($ParameterNames -join ", ") Parameter (s) were provided. When choosing 'Passthrough' QOS Config Type, the other Parameters cannot be used."
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'ConfigType' -Message $Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

    }

    Process
    {

        $_QosConfigurationObject            = NewObject -QosConfiguration
        $_QosConfigurationObject.configType = $ConfigType
        
        switch ($ConfigType)
        {

            'CustomNoFCoE'
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Building 'CustomNoFCoE' QOS Configuration."

                if ($PSBoundParameters['TrafficClassifiers'])
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding Custom Traffic Classifiers."

                    $TrafficClassifiers | % { [void]$_QosConfigurationObject.qosTrafficClassifiers.Add($_) }

                }
                
                else 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding Default NoFCoELossless Traffic Classifiers."

                    $_QosConfigurationObject.qosTrafficClassifiers = NewObject -DefaultNoFCoELosslessQosTrafficClassifiers

                }

                $_QosConfigurationObject.uplinkClassificationType   = $UplinkClassificationType
                $_QosConfigurationObject.downlinkClassificationType = $DownlinkClassificationType
            
            }
            
            'CustomWithFCoE'
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Building 'CustomWithFCoE' QOS Configuration."

                if ($PSBoundParameters['TrafficClassifiers'])
                {

                    if ($TrafficClassifiers.Count -gt 6)
                    {

                        $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'TrafficClassifiers' -TargetType 'System.Collections.ArrayList' -Message "The number of provided TrafficClassifiers is exceeded by $($TrafficClassifiers.Count - 2). When defining the QOS Configuration Type to 'CustomWithFCoE', only 6 Custom Traffic Classes are allowed."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    elseif ($TrafficClassifiers.Count -le 6)
                    {

                        1..($TrafficClassifiers.Count - 6) | % { 
                        
                            $_NewBaseTrafficClass = NewObject -BaseTrafficClass
                            
                            $_NewBaseTrafficClass.qosTrafficClass.className += $_

                            [void]$_QosConfigurationObject.qosTrafficClassifiers.Add($_NewBaseTrafficClass) 
                        
                        }

                    }

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding Custom Traffic Classifiers."

                    #Check to make sure caller has not provided 'Best effort' or 'FCoE lossless' Classes
                    $TrafficClassifiers | % { 
                    
                        #Generate Error
                        if ($_.name -eq 'FCoE lossless')
                        {

                            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'TrafficClassifiers' -TargetType 'System.Collections.ArrayList' -Message "The 'FCoE lossless' traffic class is reserved. Please remove it from the TrafficClassifiers Parameter and try again."
                            
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }    
                        
                        #Add to collection
                        [void]$_QosConfigurationObject.qosTrafficClassifiers.Add($_) 
                    
                    }

                    #Add FCoE Class
                    [void]$_QosConfigurationObject.qosTrafficClassifiers.Add((NewObject -FCoELossLessTrafficClass))

                }
                
                else 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding Default With FCoELossless Traffic Classifiers."

                    $_QosConfigurationObject.qosTrafficClassifiers = NewObject -DefaultFCoELosslessQosTrafficClassifiers

                }
                                
                $_QosConfigurationObject.uplinkClassificationType   = $UplinkClassificationType
                $_QosConfigurationObject.downlinkClassificationType = $DownlinkClassificationType

            }

        }

    }

    End
    {

        $_QosConfigurationObject.qosTrafficClassifiers | % { 
            
            if ($_.PSObject.TypeNames -notcontains 'HPOneView.Networking.Qos.TrafficClassifier')    
            {
            
                $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.Qos.TrafficClassifier') 
            
            }
        
        }

        $_QosConfigurationObject.PSObject.TypeNames.Insert(0,'HPOneView.Networking.Qos.Configuration')

        Return $_QosConfigurationObject

    }

}

function New-HPOVQosTrafficClass
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [Alias ('ClassName')]
        [string]$Name,

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [ValidateRange(1,100)]
        [int]$MaxBandwidth,

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [string]$BandwidthShare,
        
        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [int]$EgressDot1pValue,

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [System.Collections.ArrayList]$IngressDot1pClassMapping,
        
        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [System.Collections.ArrayList]$IngressDscpClassMapping,

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [switch]$RealTime,

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [switch]$Enabled

    )

    Begin
    {

        #CMDLET doesn't require auth

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        $NoMatch = New-Object System.Collections.ArrayList
        
        #Validate the IngressDscpClassMapping values caller is providing
        ForEach ($item in $IngressDscpClassMapping)
        {

            if (-not($IngressDscpClassMappingEnum -contains $item))
            {

                [void]$NoMatch.Add($item)

            }

        }

        #Check to make sure caller isn't attempting to create an FCoE lossless Class
        if ($Name -eq "FCoE lossless")
        {

            $Message = "The 'FCoE lossless' Traffic Classifier cannot be modified or created. It is automatically created when using the 'New-HPOVQosConfig' CMDLET."
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Name' -Message $Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($Name -eq "Best effort" -and $PSBoundParameters['MaxBandwidth'] -and $PSBoundParameters.Count -gt 2 -and (-not($PSBoundParameters['verbose']) -or -not($PSBoundParameters['debug']) -or -not($PSBoundParameters['Enabled'])))
        {

            $Message = "The 'Best effort' Traffic Classifier can only be created with providing the 'Name' and 'MaxBandwidth' Parameters."
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Name' -Message $Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($NoMatch)
        {

            $Message = "Invalid IngressDscpClassMapping Parameter values found: $($NoMatch -join ', '). Please remove these values and try again."
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'IngressDscpClassMapping' -TargetType 'Array' -Message $Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

    }

    Process
    {

        $_BaseTrafficClass = NewObject -BaseTrafficClass

        switch ($PSBoundParameters.Keys)
        {

            "Name"
            {

                $_BaseTrafficClass.qosTrafficClass.className = $Name

            }

            "MaxBandwidth"
            {
            
                $_BaseTrafficClass.qosTrafficClass.maxBandwidth = $MaxBandwidth
            
            }

            "BandwidthShare"
            {

                $_BaseTrafficClass.qosTrafficClass.bandwidthShare = $BandwidthShare
                        
            }


            "EgressDot1pValue"
            {
            
                $_BaseTrafficClass.qosTrafficClass.egressDot1pValue = $EgressDot1pValue
            
            }

            "RealTime"
            {
            
                $_BaseTrafficClass.qosTrafficClass.realTime = $RealTime
            
            }
            
            "IngressDot1pClassMapping"
            {

                $IngressDot1pClassMapping | % { [void]$_BaseTrafficClass.qosClassificationMapping.dot1pClassMapping.Add($_) }

            }
            
            "IngressDscpClassMapping"
            {

                $IngressDscpClassMapping | % { [void]$_BaseTrafficClass.qosClassificationMapping.dscpClassMapping.Add($_) }

            }

        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] BaseTrafficClass Object: $($_BaseTrafficClass | fl * | Out-String) $($_BaseTrafficClass.qosTrafficClass | fl * | Out-String) $($_BaseTrafficClass.qosClassificationMapping | fl * | Out-String)"

    }

    End
    {

        $_BaseTrafficClass.PSObject.TypeNames.Insert(0,'HPOneView.Networking.QosTrafficClassifier')

        Return $_BaseTrafficClass

    }

}

function Remove-HPOVLogicalInterconnectGroup 
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("uri","name","Lig",'Resource')]
        [Object]$InputObject,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")] 
        [switch]$force

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Resource'])) 
        {
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_taskcollection = New-Object System.Collections.ArrayList
        $_ligcollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomObject]) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] LIG Object provided: $($InputObject | FL * | Out-String)"

            If ('sas-logical-interconnect-groups','logical-interconnect-groups' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "LIG:$($InputObject.Name)" -TargetType PSObject -Message "The LIG resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_ligcollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "LIG:$($InputObject.Name)" -TargetType PSObject -Message "The LIG resource is not an expected category type [$($InputObject.category)]. Allowed resource category type is 'logical-interconnect-groups'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            foreach ($_lig in $InputObject) 
            {

                #LIG passed is a URI
                if (($_lig -is [String]) -and [System.Uri]::IsWellFormedUriString($_lig,'Relative')) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received URI: $($_lig)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Network Name"

                    if ($ApplianceConnection.count -gt 1)
                    {

                        $ErrorRecord = New-ErrorRecord InvalidOperationException NetworkResourceNameNotUnique InvalidResult 'Resource' -Message "The provided Resource value is an URI, however a specific Appliance Connection was not provided. Please specify an Appliance Connection."
                        $PSCmdlet.WriteError($ErrorRecord)

                    }

                    else
                    {

                        Try
                        {

                            $_resp = Send-HPOVRequest $_lig -Appliance $ApplianceConnection.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        [void]$_ligcollection.Add($_resp)

                    }
                    
                }

                #LIG passed is the Name
                elseif (($_lig -is [string]) -and (-not($_lig.startsWith("/rest/")))) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received LIG Name $($_lig)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting LIG object from Get-HPOVLogicalInterconnectGroup"
                    
                    Try
                    {

                        $_lig = Get-HPOVLogicalInterconnectGroup $_lig -ApplianceConnection $ApplianceConnection.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    [void]$_ligcollection.Add($_lig)

                }

                #LIG passed is the object
                elseif ($_lig -is [PSCustomObject] -and ('sas-logical-interconnect-groups','logical-interconnect-groups' -contains $_lig.category)) 
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] LIG Object provided: $($_lig | FL * | out-string)"

                    [void]$_ligcollection.Add($_lig)
                
                }

                elseif ($_lig -is [PSCustomObject] -and ('sas-logical-interconnect-groups','logical-interconnect-groups' -notcontains $_lig.category))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Resource' -TargetType 'PSObject' -Message "Invalid LIG Parameter: $($_lig | FL * | Out-String)"
                    $PSCmdlet.WriteError($ErrorRecord)

                }

            }

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_ligcollection.count) LIG resources to remove."

        #Process LIG Resources
        ForEach ($_lig in $_ligcollection)
        {
        
            if ($PSCmdlet.ShouldProcess($_lig.name,"Remove Logical Interconnect Group from appliance '$($_lig.ApplianceConnection.Name)'")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing LIG '$($_lig.name)' from appliance '$($_lig.ApplianceConnection.Name)'."

                Try
                {
                    
                    if ($force.IsPresent)
                    {

                        $_lig.uri += "?force=true"

                    }

                    $_resp = Send-HPOVRequest $_lig.Uri DELETE -Hostname $_lig.ApplianceConnection.Name

                    [void]$_taskcollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_taskcollection

    }

}

function Get-HPOVUplinkSet 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Name")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "Name")]
        [ValidateNotNullorEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = "Name")]
        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = "Type")]
        [ValidateNotNullorEmpty()]
        [Alias ('liname')]
        [object]$LogicalInterconnect,

        [Parameter (Mandatory = $false, ParameterSetName = "Type")]
        [ValidateSet ('Ethernet','FibreChannel', IgnoreCase=$False)]
        [string]$Type,
    
        [Parameter (Mandatory = $false, ParameterSetName = "Name")]
        [Parameter (Mandatory = $false, ParameterSetName = "Type")]
        [switch]$Report,

        [Parameter (Mandatory = $false, ParameterSetName = "Name")]
        [Parameter (Mandatory = $false, ParameterSetName = "Type")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "Name")]
        [Parameter (Mandatory = $false, ParameterSetName = "Type")]
        [Alias ("x", "export")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$ExportFile

    )
    
    Begin 
    {

        if ($PSBoundParameters['report'])
        {

            Write-Warning "The Report Parameter has been deprecated. The CMDLET will now display object data in Format-List view."

        }

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_UplinkSetCollection = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        if ($LogicalInterconnect -is [PSCustomObject])
        {

            $ApplianceConnection = $ApplianceConnection | ? { $_.Name -eq $LogicalInterconnect.ApplianceConnection.Name }

        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing '$($_appliance.Name)' Appliance"

            #Looking for UplinkSet Name without LI Object/Resource
            if ($PSCmdlet.ParameterSetName -eq 'Name' -and (-not($PSBoundParameters['LogicalInterconnect']))) 
            {

                if ($PSboundParameters['Name'])
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Uplink Set name provided: '$name'"

                    $name = $name -replace ("[*]","%25") -replace ("[&]","%26")

                    #We will crate a URI that uses filter at the resource URI
                    $uri = $uplinkSetsUri + "?filter=name matches '$name'"

                }

                else
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Looking for all Uplink Sets."

                    $uri = $uplinkSetsUri

                }

                Try
                {

                    $_uplinksets = Send-HPOVRequest -Uri $uri -Method GET -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

                if ($_uplinksets.count -eq 0 -and $Name)
                {

                    #Generate Error if no name was found
                    $ExceptionMessage = "Specified Uplink Set '{0}' was not found on '{1}'. Please check the name and try again." -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord InvalidOperationException UplinkSetResourceNameNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)  

                }

                elseif ($_uplinksets.count -eq 0)
                {

                    "[{0}] No Uplink Sets found for {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

                }

                else
                {

                    $_uplinksets = $_uplinksets.members

                }

            }

            #Looking for LI Object and associated Uplink Sets
            elseif ($PSboundParameters['LogicalInterconnect']) # -and (-not($PSBoundParameters['Name'])))
            {

                #Check the LogicalInterconnect Parameter value type
                switch ($LogicalInterconnect.GetType().Name)
                {
                
                    'PSCustomObject'
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Recieved PSCustomObject for LogicalInterconnect Parameter."

                        if ($LogicalInterconnect.category -eq 'logical-interconnects')
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconnect Object provided: $($LogicalInterconnect | FL * | Out-String)."

                        }
                        
                        else
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid Logical Interconnect Object provided: $($LogicalInterconnect | Out-String)."

                            $ErrorRecord = New-ErrorRecord InvalidOperationException LogicalInterconnectInvalidCategroy InvalidArgument 'LogicalInterconnect' -TargetType 'PSObject' -Message "The provided LogicalInterconnect resource category '$($LogicalInterconnect.category)' does not match the required 'logical-interconnects' value. Please check the Parameter value and try again."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                        }

                    }

                    'String'
                    {

                        #User provided Logical Interconnect Name, look for it on the appliance
                        if (-not($LogicalInterconnect.StartsWith('/rest/')) -or (-not($LogicalInterconnect.StartsWith($logicalInterconnectsUri))))
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Interconnect name provided: 'LogicalInterconnect'."

                            Try
                            {

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Logical Interconnect '$liName'"

                                $LogicalInterconnect = Get-HPOVLogicalInterconnect -Name $LogicalInterconnect -ApplianceConnection $_appliance

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                        }

                        #User didn't provide a Logical Interconnect Resource Name, generate error as URI's are not supported
                        else
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid Logical Interconnect Parameter value provided: $($LogicalInterconnect | Out-String)."

                            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidLogicalInterconnectParameterValue InvalidArgument 'LogicalInterconnect' -TargetType 'PSObject' -Message "The provided LogicalInterconnect resource category '$($LogicalInterconnect.category)' does not match the required 'logical-interconnects' value. Please check the Parameter value and try again."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord) 

                        }
                        
                    }
                
                }

                #Use Index to find associations
                try 
                { 
                
                    $_uplinksets = New-Object System.Collections.ArrayList

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Looking for associated Uplink Sets to Logical Interconnects via Index."

                    Try
                    {

                        $_indexassociatedulinksets = Send-HPOVRequest "/rest/index/associations?parentUri=$($LogicalInterconnect.uri)&name=LOGICAL_INTERCONNECT_TO_UPLINK_SET" -Hostname $_appliance

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                    if ($_indexassociatedulinksets.count -gt 0)
                    {

                        ForEach ($child in $_indexassociatedulinksets.members)
                        {

                            $_uplinksetobject = Send-HPOVRequest $child.childUri -Hostname $_appliance

                            if ($Name)
                            {

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filtering Uplink Sets for '$Name'"
                        
                                if ($Name -match "\*" -or $Name -match "\?")
                                {

                                    if ($_uplinksetobject.name -match $Name)
                                    {

                                        [void]$_uplinksets.Add($_uplinksetobject)

                                    }

                                }

                                else
                                {

                                    if ($_uplinksetobject.name -eq $Name)
                                    {

                                        [void]$_uplinksets.Add($_uplinksetobject)

                                    }

                                }

                            }

                            elseif ($type) 
                            {

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Filtering Uplink Sets for '$type' type." 
                                if ($_uplinksetobject.networkType -eq $type)
                                {

                                    [void]$_uplinksets.Add($_uplinksetobject)

                                }

                            }
                            
                        }
                        
                    }
                    
                    
                    if ($Name -and $_uplinksets.count -eq 0)
                    {
                        
                        #Generate Error if no name was found
                        $ErrorRecord = New-ErrorRecord InvalidOperationException UplinkSetResourceNameNotFound ObjectNotFound 'Name' -Message "Specified Uplink Set '$name' was not found associated with '$($LogicalInterconnect.name)' on '$($_appliance.Name)'. Please check the name and try again."
                        $PSCmdlet.WriteError($ErrorRecord)  

                    }

                    elseif ($type -and $_uplinksets.count -eq 0)
                    {

                        $ErrorRecord = New-ErrorRecord InvalidOperationException UplinkSetResourceTypeNotFound ObjectNotFound 'Type' -Message "Specified Uplink Set Type '$type' was not found associated with '$($LogicalInterconnect.name)' on '$($_appliance.Name)'. Please check the name and try again."
                        $PSCmdlet.WriteError($ErrorRecord)  
                    
                    }

                }

                catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            #Update TypeNames
            if ($_uplinksets.count -gt 0)
            {

                foreach ($_object in $_uplinksets)
                {

                    switch ($_object.networkType)
                    {

                        'Ethernet'     
                        { 

                            $_object.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnect.UplinkSet.Ethernet') 
                            $_object.portConfigInfos | % {
                                
                                Add-Member -InputObject $_ -NotePropertyName ApplianceConnection -NotePropertyValue $_object.ApplianceConnection

                                $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnect.UplinkSet.Ethernet.UplinkPort') 

                            }
                            
                        }

                        'FibreChannel' 
                        { 
                        
                            $_object.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnect.UplinkSet.FibreChannel') 
                            $_object.portConfigInfos | % {
                                
                                Add-Member -InputObject $_ -NotePropertyName ApplianceConnection -NotePropertyValue $_object.ApplianceConnection

                                $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalInterconnect.UplinkSet.FibreChannel.UplinkPort') 

                            }
                        
                        }

                    }

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding '$($_object.name)' to final collection."

                    [void]$_UplinkSetCollection.Add($_object)

                }

            }

        }

    }

    End 
    {
                            
        $_UplinkSetCollection | sort-object -Property networkType,name

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. $($_UplinkSetCollection.count) uplink set(s) found."

    }

}

function New-HPOVUplinkSet 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "PipelineOrObjectEthernet")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "PipelineOrObjectEthernet")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "PipelineOrObjectFibreChannel")]
        [Alias ('li','lig','ligName','Resource')]
        [Object]$InputObject,

        [Parameter (Mandatory, ParameterSetName = "PipelineOrObjectFibreChannel")]
        [Parameter (Mandatory, ParameterSetName = "PipelineOrObjectEthernet")]
        [Alias ('usName')]
        [String]$Name,

        [Parameter (Mandatory, ParameterSetName = "PipelineOrObjectFibreChannel")]
        [Parameter (Mandatory, ParameterSetName = "PipelineOrObjectEthernet")]
        [Alias ('usType')]
        [ValidateSet ("Ethernet", "FibreChannel", "Untagged", "Tunnel", 'ImageStreamer', IgnoreCase = $false)]
        [String]$Type,

        [Parameter (Mandatory = $false, ParameterSetName = "PipelineOrObjectFibreChannel")]
        [Parameter (Mandatory = $false, ParameterSetName = "PipelineOrObjectEthernet")]
        [Alias ('usNetworks')]
        [ValidateNotNullorEmpty()]
        [Array]$Networks,

        [Parameter (Mandatory = $false, ParameterSetName = "PipelineOrObjectEthernet")]
        [Alias ('usNativeEthNetwork','Native','PVID')]
        [ValidateNotNullorEmpty()]
        [Object]$NativeEthNetwork,

        [Parameter (Mandatory = $false, ParameterSetName = "PipelineOrObjectFibreChannel")]
        [Parameter (Mandatory = $false, ParameterSetName = "PipelineOrObjectEthernet")]
        [Alias ('usUplinkPorts')]
        [ValidateScript({($_.Split(","))[0].contains(":")})]
        [Array]$UplinkPorts,

        [Parameter (Mandatory = $false, ParameterSetName = "PipelineOrObjectEthernet")]
        [Alias ('usEthMode')]
        [ValidateSet ("Auto", "Failover", IgnoreCase=$false)]
        [String]$EthMode = "Auto",
        
        [Parameter (Mandatory = $false, ParameterSetName = "PipelineOrObjectEthernet")]
        [ValidateSet ("Short", "Long", IgnoreCase=$false)]
        [String]$LacpTimer = "Short",

        [Parameter (Mandatory = $false, ParameterSetName = "PipelineOrObjectEthernet")]
        [ValidateScript({$_.contains(":")})]
        [String]$PrimaryPort,

        [Parameter (Mandatory = $false, ParameterSetName = "PipelineOrObjectFibreChannel")]
        [ValidateSet ("Auto", "2", "4", "8", IgnoreCase=$false)]
        [String]$fcUplinkSpeed = "Auto",

        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = "PipelineOrObjectEthernet")]
        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = "PipelineOrObjectFibreChannel")]
        [Switch]$Async,
        
        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = "PipelineOrObjectEthernet")]
        [Parameter (Mandatory = $false, ValueFromPipelinebyPropertyName, ParameterSetName = "PipelineOrObjectFibreChannel")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }
    
    Process 
    {

        if (-not $PipelineInput -and $ApplianceConnection.ApplianceType -ne 'Composer' -and $Type -eq 'ImageStreamer')
        {
            
            $Exceptionmessage = 'The ApplianceConnection {0} is not a Synergy Composer. The "ImageStreamer" Type is only supported with HPE Synergy.' -f $ApplianceConnection.Name
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
        }

        else
        {

            $_NewUplinkSetCol = New-Object System.Collections.ArrayList

            #if pipeline object is String and not PSCustomObject, fail the call
            if ($InputObject -is [String] -or (-not($InputObject -is [PSCustomObject])))
            {

                "[{0}] Input Object is an unsupported type: {1}. Generating error." -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.GetType().FullName | Write-Verbose
                
                $ErrorRecord = New-ErrorRecord ArgumentException InvalidParameter InvalidArgument 'Resource' -TargetType 'PSObject' -Message "The -Resource Parameter value type($($InputObject.GetType().Fullname)) provided is not a Logical Interconnect Group object. Please check the value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($InputObject -is [PSCustomObject])
            {

                $InputObject = $InputObject.PSObject.Copy()

            }

            #Validate the resource contains the ApplianceConnection NoteProperty
            if (-not($InputObject.ApplianceConnection))
            {

                "[{0}] Input Object does not contain the ApplianceConnection NoteProperty, generating error." -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.GetType().FullName | Write-Verbose
                
                $ErrorRecord = New-ErrorRecord ArgumentException InvalidParameter InvalidArgument 'Type' -Message "The -Type value 'ImageStreamer' is only available for Synergy resources. Please choose another UplinkSet type."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Determine the resource type; LIG or LI
            switch ($InputObject.category)
            {

                #Uplink Sets are created differently for LI Resources
                'logical-interconnects'
                {

                    # //TODO Need to validate the LIG Enclosure type is a Synergy Frame if UplinkSet Type is 'ImageStreamer'
                    if ($Type -eq 'Imagestreamer' -and $InputObject.enclosureType -notmatch 'SY')
                    {

                        $ErrorRecord = New-ErrorRecord ArgumentException InvalidParameter InvalidArgument 'Resource' -TargetType 'PSObject' -Message "The -Resource Parameter value does not contain the ApplianceConnection object property. Please validate the object was retrieved from Get-HPOVLogicalInterconnectGroup or a resource URI via Send-HPOVRequest."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    "[{0}] Provided LI Resource Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose
                    "[{0}] Provided LI Resource Category: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.category | Write-Verbose
                    "[{0}] Provided LI Resource URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.uri | Write-Verbose

                    #Init Uplink Set Objects
                    $_liUplinkSetObject  = NewObject -liUplinkSetObject

                    $_liUplinkSetObject.name = $Name
                
                    if ($EthMode)
                    {

                        $_liUplinkSetObject.connectionMode = $EthMode

                        if ($EthMode -eq 'Failover' -and $PSBoundParameters['LacpTimer'])
                        {

                            $ErrorRecord = New-ErrorRecord ArgumentException InvalidParameter InvalidArgument 'LacpTimer' -Message "The -LacpTimer Parameter value is not supported when -EthMode is set to Failover."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                    if ($EthMode -eq 'Auto' -and $PSBoundParameters['LacpTimer'])
                    {

                        $_liUplinkSetObject.lacpTimer = $LacpTimer

                    }

                    # Add Logical Interconnect object URI to Uplink Set Object
                    $_liUplinkSetObject.logicalInterconnectUri = $InputObject.uri

                    # Get list of interconnects within LI resource
                    $_liInterconnects = $InputObject.interconnectMap.interconnectMapEntries
                
                    "[{0}] Uplink Ports to Process: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [System.String]::Join(', ', $UplinkPorts) | Write-Verbose

                    # Loop through requested Uplink Ports
                    $port              = New-Object System.Collections.ArrayList
                    $uslogicalLocation = New-Object System.Collections.ArrayList

                    foreach ($_p in $UplinkPorts)
                    {

                        # Split string to get bay and port
                        $_p = $_p.Split(':')

                        # Synergy uplink config
                        if ($_p.Count -ge 3)
                        {

                            '[{0}] Port configuration is Synergy Ethernet' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            # This is causing an issue with getting the frame ID, which should not be the enclosureUri
                            # [string]$EnclosureID = $InputObject.enclosureUris[$_p[0].TrimStart('enclosureEnclosure')-1]
                            [string]$EnclosureID = $_p[0].TrimStart('enclosureEnclosure')

                            # remove bay so we just have the ID
                            $bay = $_p[1].ToLower().TrimStart('bayBay') -replace " ",$null
                            
                            # Get faceplate portName (Need to make sure Synergy Uplink Port format which uses : instead of . for subport delimiter is replaced correctly)
                            $uplinkPort = $_p[2]

                            if ($_p.Count -eq 4)
                            {

                                $uplinkPort = '{0}.{1}' -f $uplinkPort, $_p[3]

                            }

                            '[{0}] Processing Frame "{1}", Bay "{2}", Port "{3}"' -f $MyInvocation.InvocationName.ToString().ToUpper(), $EnclosureID, $bay, $uplinkPort | Write-Verbose

                            "[{0}] Looking for Interconnect URI for Bay {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $bay | Write-Verbose

                            # Loop through Interconnect Map Entry Template items looking for the provided Interconnet Bay number
                            ForEach ($l in ($InputObject.interconnectMap.interconnectMapEntries | ? enclosureIndex -eq $EnclosureID)) 
                            { 
    
                                if ($l.location.locationEntries | ? { $_.type -eq "Bay" -and $_.relativeValue -eq $bay }) 
                                {

                                    $permittedIcUri = $l.permittedInterconnectTypeUri

                                    "[{0}]] Found permitted Interconnect Type URI {1} for Bay {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $permittedIcUri, $bay | Write-Verbose

                                }

                            }

                        }

                        else
                        {

                            '[{0}] Port configuration is not Synergy Ethernet' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            #Set the Enclosure ID value. FC type needs to be -1
                            if ($Type -eq 'FibreChannel' -and $InputObject.enclosureType -match 'SY')
                            {

                                '[{0}] Setting EnclosureID to -1 for Synergy FibreChannel' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                [String]$EnclosureID = -1

                            }

                            else
                            {

                                [string]$EnclosureID = $InputObject.enclosureUris

                            }        

                            #remove bay so we just have the ID
                            $bay = $_p[0].ToLower().TrimStart('bayBay') -replace " ",$null
                            
                            #Get faceplate portName
                            $uplinkPort = $_p[1]

                            '[{0}] Processing Bay "{1}", Port "{2}"' -f $MyInvocation.InvocationName.ToString().ToUpper(), $bay, $uplinkPort | Write-Verbose

                            "[{0}] Looking for Interconnect URI for Bay {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $bay | write-verbose

                            #Loop through Interconnect Map Entry Template items looking for the provided Interconnet Bay number
                            ForEach ($l in $InputObject.interconnectMap.interconnectMapEntries) 
                            { 

                                #$found = $l.logicalLocation.locationEntries | ? { $_.type -eq "Bay" -and $_.relativeValue -eq $bay }
                                                                
                                if ($l.location.locationEntries | ? { $_.type -eq "Bay" -and $_.value -eq $bay }) 
                                {
                                        
                                    $permittedIcUri = $l.permittedInterconnectTypeUri

                                    "[{0}]] Found permitted Interconnect Type URI {1} for Bay {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $permittedIcUri, $bay | write-verbose

                                }

                            } 

                        }

                        # Generate error that Interconnect could not be found from the LI
                        if ($null -eq $permittedIcUri)
                        {

                            $ExceptionMessage = 'The Interconnect Bay ID {0} could not be identified within the provided Logical Interconnect resource object.' -f $bay
                            $ErrorRecord = New-ErrorRecord HPOneView.UplinkSetResourceException UnsupportedLogicalInterconnectResource InvalidArgument 'InputObject' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                        }
                        
                        # Get Interconnect Type object in order to get relative port ID
                        Try
                        {

                            $_interconnecttype = Send-HPOVRequest -Uri $permittedIcUri -Hostname $InputObject.ApplianceConnection.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
                    
                        #Validate the Interconnect has capable Uplink Ports
                        if (-not ($_interconnecttype.portInfos | ? uplinkCapable))
                        {

                            $ExceptionMessage = "The Interconnect/Fabric module in 'BAY{0}' has no uplink capable ports. Please check the value and try again." -f $bay, $uplinkPort
                            $ErrorRecord = New-ErrorRecord HPOneView.UplinkSetResourceException UnsupportedInterconnectResource InvalidArgument 'UplinkPorts' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        'Looking for {0} port in portInfos Interconnect property.' -f $uplinkPort | Write-Verbose #.Replace('.',':') | Write-Verbose

                        #Translate the port number
                        $_portRelativeValue = $_interconnecttype.portInfos | ? { $_.portName.Replace(':','.') -eq $uplinkPort } 

                        #Didn't find relative port number, so generate terminating error
                        if (-not $_portRelativeValue) 
                        {

                            $ExceptionMessage = "The provided uplink port 'BAY{0}:{1}' is an invalid port ID. Did you mean 'X{2}'? Please check the value and try again." -f $bay, $uplinkPort, $uplinkPort
                            $ErrorRecord = New-ErrorRecord HPOneView.UplinkSetResourceException InvalidUplinkPortID InvalidArgument 'port' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        #Make sure the port found is uplinkCapable
                        if (-not $_portRelativeValue.uplinkCapable) 
                        {

                            $ExceptionMessage = "The provided uplink port 'BAY{0}:{1}' is not uplink capable. Please check the value and try again." -f $bay,$uplinkPort
                            $ErrorRecord = New-ErrorRecord HPOneView.UplinkSetResourceException UnsupportedUplinkPort InvalidArgument 'UplinkPorts' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        #Add uplink port
                        $_location = NewObject -UplinkSetLocation

                        $_EnclosureLocation       = NewObject -UplinkSetLocationEntry
                        $_EnclosureLocation.type  = 'Enclosure'
                        $_EnclosureLocation.value = $EnclosureId
                        [void]$_location.location.locationEntries.Add($_EnclosureLocation)

                        $_BayLocation       = NewObject -UplinkSetLocationEntry
                        $_BayLocation.type  = 'Bay'
                        $_BayLocation.value = [int]$bay
                        [void]$_location.location.locationEntries.Add($_BayLocation)

                        $_PortLocation       = NewObject -UplinkSetLocationEntry
                        $_PortLocation.type  = 'Port'
                        $_PortLocation.value = [string]$_portRelativeValue.portName
                        [void]$_location.location.locationEntries.Add($_PortLocation)

                        #Create Primary Port logical location object
                        if ($PrimaryPort -match $_p -and $EthMode -eq "Failover") 
                        {

                            "[{0}] Setting Uplink Set mode to 'Failover', and Primary Port to '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PrimaryPort | Write-Verbose

                            $_liUplinkSetObject.primaryPortLocation | Add-Member -NotePropertyName locationEntries -NotePropertyValue (New-Object System.Collections.ArrayList)

                            $_liUplinkSetObject.mode = $EthMode

                            $_EnclosureLogicalLocation       = NewObject -UplinkSetLocationEntry
                            $_EnclosureLogicalLocation.type  = 'Enclosure'
                            $_EnclosureLogicalLocation.value = [int]$EnclosureID
                            [void]$_liUplinkSetObject.primaryPortLocation.locationEntries.Add($_EnclosureLogicalLocation)

                            $_BayLogicalLocation       = NewObject -UplinkSetLocationEntry
                            $_BayLogicalLocation.type  = 'Bay'
                            $_BayLogicalLocation.value = [int]$bay
                            [void]$_liUplinkSetObject.primaryPortLocation.locationEntries.Add($_BayLogicalLocation)

                            $_PortLogicalLocation       = NewOBject -UplinkSetLocationEntry
                            $_PortLogicalLocation.type  = 'Port'
                            $_PortLogicalLocation.value = [string]$_portRelativeValue.portName
                            [void]$_liUplinkSetObject.primaryPortLocation.locationEntries.Add($_PortLogicalLocation)

                        }
    
                        #Set FC Uplink Port Speed
                        if ($Type -eq "FibreChannel") 
                        { 

                            $_location.desiredSpeed = $global:SetUplinkSetPortSpeeds[$fcUplinkSpeed] 

                        }

                        else 
                        { 
                            
                            $_location.desiredSpeed = "Auto" 
                        
                        }

                        "[{0}] Adding Uplink Set to LIG: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_logicalLocation | out-string) | Write-Verbose
                            
                        [void]$_liUplinkSetObject.portConfigInfos.Add($_location)

                    }

                    #Network Objects
                    "[{0}] Getting Network Uris" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $_networkUris = GetNetworkUris -_Networks $Networks -_ApplianceConnection $ApplianceConnection

                    $_networkUris | ? { $_.StartsWith($ethNetworksUri) } | % {

                        [void]$_liUplinkSetObject.networkUris.Add($_)

                    }

                    $_networkUris | ? { $_.StartsWith($fcNetworksUri) } | % {

                        [void]$_liUplinkSetObject.networkUris.Add($_)

                    }

                    $_networkUris | ? { $_.StartsWith($fcoeNetworksUri) } | % {

                        [void]$_liUplinkSetObject.networkUris.Add($_)

                    }
                    
                    if ($NativeEthNetwork)
                    {
                        
                        "[{0}] Getting Native Ethernet Network Uri" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        $_liUplinkSetObject | Add-Member -NotePropertyName nativeNetworkUri -NotePropertyValue $null

                        $_liUplinkSetObject.nativeNetworkUri = GetNetworkUris -_Networks $NativeEthNetwork -_ApplianceConnection $ApplianceConnection

                    }

                    #Validate Uplink Network Type.
                    if ($Type -ne 'FibreChannel')
                    {

                        $_liUplinkSetObject.networkType         = $UplinkSetNetworkTypeEnum[$Type]
                        $_liUplinkSetObject.ethernetNetworkType = $UplinkSetEthNetworkTypeEnum[$Type]

                    }

                    else
                    {

                        $_liUplinkSetObject.networkType = $UplinkSetNetworkTypeEnum[$Type]

                    }
                
                    If ($Type -ne 'FibreChannel')
                    {
                
                        $_liUplinkSetObject.ethernetNetworkType = $UplinkSetEthNetworkTypeEnum[$Type]
                        
                    }  
    
                    "[{0}] {1} Uplink Set object: {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name, ($_liUplinkSetObject | convertto-json -depth 99) | Write-Verbose

                    "[{0}] Sending request..." | Write-Verbose

                    Try
                    {
                        
                        $resp = Send-HPOVRequest -uri $UplinkSetsUri -method POST -body $_liUplinkSetObject -Hostname $InputObject.ApplianceConnection.Name

                        if (-not $PSBoundParameters['Async'])
                        {

                            $resp | Wait-HPOVTaskComplete

                        }

                        else
                        {

                            $resp

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                'logical-interconnect-groups'
                {

                    #Create new instance of the LIGUplinkSet Object
                    $_ligUplinkSetObject = NewObject -ligUplinkSetObject

                    if ($Type -eq 'Imagestreamer' -and $InputObject.enclosureType -notmatch 'SY')
                    {

                        $ExceptionMessage = "The -Resource Parameter value does not contain the ApplianceConnection object property. Please validate the object was retrieved from Get-HPOVLogicalInterconnectGroup or a resource URI via Send-HPOVRequest."
                        $ErrorRecord = New-ErrorRecord ArgumentException InvalidParameter InvalidArgument 'InputObject' -TargetType 'PSObject' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    $_ligUplinkSetObject.name = $Name

                    if ($EthMode)
                    {

                        $_ligUplinkSetObject.mode = $EthMode

                        if ($EthMode -eq 'Failover' -and $PSBoundParameters['LacpTimer'])
                        {

                            $ErrorRecord = New-ErrorRecord ArgumentException InvalidParameter InvalidArgument 'LacpTimer' -Message "The -LacpTimer Parameter value is not supported when -EthMode is set to Failover."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                    if ($EthMode -eq 'Auto' -and $PSBoundParameters['LacpTimer'])
                    {

                        $_ligUplinkSetObject.lacpTimer = $LacpTimer

                    }

                    "[{0}] Provided LIG Resource Name: $($InputObject.name)" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    "[{0}] Provided LIG Resource Category: $($InputObject.category)" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    "[{0}] Provided LIG Resource URI: $($InputObject.uri)" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    #Get list of interconnects in LIG definition
                    $ligInterconnects = $InputObject.interconnectMapTemplate.interconnectMapEntryTemplates
                
                    if ($UplinkPorts) 
                    { 
                        
                        "[{0}] Uplink Ports: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [System.String]::Join(', ', $UplinkPorts) | Write-Verbose 
                    
                    }

                    else 
                    { 
                        
                        "[{0}] No uplink ports request." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
                    
                    }

                    #Loop through requested Uplink Ports
                    $port              = New-Object System.Collections.ArrayList
                    $uslogicalLocation = New-Object System.Collections.ArrayList

                    foreach ($_p in $UplinkPorts)
                    {
                        
                        #Split string to get bay and port
                        $_p = $_p.Split(':')

                        #Synergy uplink config
                        if ($_p.Count -ge 3)
                        {

                            [string]$EnclosureID = $EnclosureID = $_p[0].TrimStart('enclosureEnclosure')

                            #remove bay so we just have the ID
                            $bay = $_p[1].ToLower().TrimStart('bayBay') -replace " ",$null
                            
                            #Get faceplate portName (Need to make sure Synergy Uplink Port format which uses : instead of . for subport delimiter is replaced correctly)
                            #$uplinkPort = $_p[2].Replace('.',':')
                            $uplinkPort = $_p[2]

                            if ($_p.Count -eq 4)
                            {

                                $uplinkPort = '{0}.{1}' -f $uplinkPort, $_p[3]

                            }

                            '[{0}] Processing Frame "{1}", Bay "{2}", Port "{3}"' -f $MyInvocation.InvocationName.ToString().ToUpper(), $EnclosureID, $bay, $uplinkPort | Write-Verbose

                            "[{0}] Looking for Interconnect URI for Bay {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $bay | Write-Verbose

                            #Loop through Interconnect Map Entry Template items looking for the provided Interconnet Bay number
                            ForEach ($l in ($InputObject.interconnectmaptemplate.interconnectmapentrytemplates | ? enclosureIndex -eq $EnclosureID)) 
                            { 
                                                                
                                if ($l.logicalLocation.locationEntries | ? { $_.type -eq "Bay" -and $_.relativeValue -eq $bay }) 
                                {

                                    $permittedIcUri = $l.permittedInterconnectTypeUri

                                    "[{0}] Found permitted Interconnect Type URI {1} for Bay {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $permittedIcUri, $bay | Write-Verbose

                                }

                            } 

                        }

                        else
                        {

                            '[{0}] Port configuration is not Synergy Ethernet' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            #Set the Enclosure ID value. FC type needs to be -1
                            if ($Type -eq 'FibreChannel' -and $InputObject.enclosureType -match 'SY')
                            {

                                '[{0}] Setting EnclosureID to -1 for Synergy FibreChannel' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                [String]$EnclosureID = -1

                            }

                            else
                            {

                                [String]$EnclosureID = 1

                            }                            

                            #remove bay so we just have the ID
                            $bay = $_p[0].ToLower().TrimStart('bayBay') -replace " ",$null
                            
                            #Get faceplate portName
                            $uplinkPort = $_p[1]

                            '[{0}] Processing Bay "{1}", Port "{2}"' -f $MyInvocation.InvocationName.ToString().ToUpper(), $bay, $uplinkPort | Write-Verbose

                            "[{0}] Looking for Interconnect URI for Bay {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $bay | Write-Verbose

                            #Loop through Interconnect Map Entry Template items looking for the provided Interconnet Bay number
                            ForEach ($l in $InputObject.interconnectmaptemplate.interconnectmapentrytemplates) 
                            { 

                                if ($l.logicalLocation.locationEntries | ? { $_.type -eq "Bay" -and $_.relativeValue -eq $bay }) 
                                {
                                        
                                    $permittedIcUri = $l.permittedInterconnectTypeUri

                                    "[{0}] Found permitted Interconnect Type URI {1} for Bay {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $permittedIcUri, $bay | Write-Verbose

                                }

                            } 

                        }

                        #Get Interconnect Type object in order to get relative port ID
                        Try
                        {

                            $_interconnecttype = Send-HPOVRequest $permittedIcUri -Hostname $InputObject.ApplianceConnection.Name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }    

                        #Validate the Interconnect has capable Uplink Ports
                        if (-not ($_interconnecttype.portInfos | ? uplinkCapable))
                        {

                            $ExceptionMessage = "The Interconnect/Fabric module in 'BAY{0}' has no uplink capable ports. Please check the value and try again." -f $bay,$uplinkPort
                            $ErrorRecord = New-ErrorRecord HPOneView.UplinkSetResourceException UnsupportedInterconnectResource InvalidArgument 'UplinkPorts' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }                    

                        #Translate the port number
                        $_portRelativeValue = $_interconnecttype.portInfos | ? { $_.portName.Replace(':','.') -eq $uplinkPort } 

                        #Didn't find relative port number, so generate terminating error
                        if (-not $_portRelativeValue) 
                        {

                            $ExceptionMessage = "The provided uplink port 'BAY{0}:{1}' is an invalid port ID. Please check the value and try again." -f $bay,$uplinkPort
                            $ErrorRecord = New-ErrorRecord HPOneView.UplinkSetResourceException InvalidUplinkPortID InvalidArgument 'UplinkPorts' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        #Make sure the port found is uplinkCapable
                        if (-not $_portRelativeValue.uplinkCapable) 
                        {

                            $ExceptionMessage = "The provided uplink port 'BAY{0}:{1}' is not uplink capable. Please check the value and try again." -f $bay,$uplinkPort
                            $ErrorRecord = New-ErrorRecord HPOneView.UplinkSetResourceException UnsupportedUplinkPort InvalidArgument 'UplinkPorts' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        #Add uplink port
                        $_logicalLocation = NewObject -UplinkSetLogicalLocation

                        $_EnclosureLogicalLocation = NewObject -UplinkSetLogicalLocationEntry
                        $_EnclosureLogicalLocation.type = 'Enclosure'
                        $_EnclosureLogicalLocation.relativeValue = [int]$EnclosureID

                        [void]$_logicalLocation.logicalLocation.locationEntries.Add($_EnclosureLogicalLocation)

                        $_BayLogicalLocation = NewObject -UplinkSetLogicalLocationEntry
                        $_BayLogicalLocation.type = 'Bay'
                        $_BayLogicalLocation.relativeValue = [int]$bay

                        [void]$_logicalLocation.logicalLocation.locationEntries.Add($_BayLogicalLocation)

                        $_PortLogicalLocation = NewObject -UplinkSetLogicalLocationEntry
                        $_PortLogicalLocation.type = 'Port'
                        $_PortLogicalLocation.relativeValue = [int]$_portRelativeValue.portNumber

                        [void]$_logicalLocation.logicalLocation.locationEntries.Add($_PortLogicalLocation)

                        #Create Primary Port logical location object
                        if ($PrimaryPort -match $_p -and $EthMode -eq "Failover") 
                        {

                            "[{0}] Setting Uplink Set mode to 'Failover', and Primary Port to '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PrimaryPort | Write-Verbose 

                            $_ligUplinkSetObject.primaryPortLocation | Add-Member -NotePropertyName locationEntries -NotePropertyValue (New-Object System.Collections.ArrayList)

                            $_ligUplinkSetObject.mode = $EthMode

                            $_EnclosureLogicalLocation               = NewObject -UplinkSetLogicalLocationEntry
                            $_EnclosureLogicalLocation.type          = 'Enclosure'
                            $_EnclosureLogicalLocation.relativeValue = [int]$EnclosureID

                            [void]$_ligUplinkSetObject.primaryPortLocation.locationEntries.Add($_EnclosureLogicalLocation)

                            $_BayLogicalLocation               = NewObject -UplinkSetLogicalLocationEntry
                            $_BayLogicalLocation.type          = 'Bay'
                            $_BayLogicalLocation.relativeValue = [int]$bay

                            [void]$_ligUplinkSetObject.primaryPortLocation.locationEntries.Add($_BayLogicalLocation)

                            $_PortLogicalLocation               = NewOBject -UplinkSetLogicalLocationEntry
                            $_PortLogicalLocation.type          = 'Port'
                            $_PortLogicalLocation.relativeValue = [int]$_portRelativeValue.portNumber

                            [void]$_ligUplinkSetObject.primaryPortLocation.locationEntries.Add($_PortLogicalLocation)

                        }
    
                        #Set FC Uplink Port Speed
                        if ($Type -eq "FibreChannel") 
                        { 

                            $_logicalLocation.desiredSpeed = $global:SetUplinkSetPortSpeeds[$fcUplinkSpeed] 

                        }

                        else 
                        { 
                            
                            $_logicalLocation.desiredSpeed = "Auto" 
                        
                        }

                        "[{0}] Adding Uplink Set to LIG: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_logicalLocation | out-string) | Write-Verbose
                            
                        [void]$_ligUplinkSetObject.logicalPortConfigInfos.Add($_logicalLocation)

                    }

                    "[{0}] Getting Network Uris" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                
                    $_NetworkUris = GetNetworkUris -_Networks $Networks -_ApplianceConnection $ApplianceConnection

                    $_NetworkUris | % {
                    
                        [void]$_ligUplinkSetObject.networkUris.Add($_)

                    }            
                    
                    if ($NativeEthNetwork)
                    {
                        
                        "[{0}] Getting Native Ethernet Network Uri" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        $_ligUplinkSetObject | Add-Member -NotePropertyName nativeNetworkUri -NotePropertyValue $null

                        $_ligUplinkSetObject.nativeNetworkUri = GetNetworkUris -_Networks $NativeEthNetwork -_ApplianceConnection $ApplianceConnection

                    }

                    #Validate Uplink Network Type.
                    if ($Type -ne 'FibreChannel')
                    {

                        $_ligUplinkSetObject.networkType         = $UplinkSetNetworkTypeEnum[$Type]
                        $_ligUplinkSetObject.ethernetNetworkType = $UplinkSetEthNetworkTypeEnum[$Type]

                    }

                    else
                    {

                        $_ligUplinkSetObject.networkType = $UplinkSetNetworkTypeEnum[$Type]

                    }                    

                    "[{0}] {1} Uplink Set object: {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name, ($_ligUplinkSetObject | convertto-json -depth 99) | Write-Verbose

                    # Rebuld uplinkset collection
                    "[{0}] {1} Rebuilding UplinkSet template collection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                    '[{0}] UplinkSets to readd: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.uplinkSets.Count | Write-Verbose

                    $InputObject.uplinkSets | % {

                        "[{0}] Saving Uplink Set object to new collection: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_.name | Write-Verbose

                        [void]$_NewUplinkSetCol.Add($_)

                    }

                    [void]$_NewUplinkSetCol.Add($_ligUplinkSetObject)
                                        
                    [Array]$InputObject.uplinkSets = $_NewUplinkSetCol

                    '[{0}] UplinkSets after rebuild: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.uplinkSets.Count | Write-Verbose

                    '[{0}] Updated Resource: {1}' -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | ConvertTo-Json -Depth 99 | Out-String) | Write-Verbose

                    '[{0}] Sending request...' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    Try
                    {
                        
                        $resp = Send-HPOVRequest -uri $InputObject.uri -method PUT -body $InputObject -Hostname $InputObject.ApplianceConnection.Name

                        if ($PSBoundParameters['Async'])
                        {

                            $resp

                        }

                        else
                        {

                            $resp | Wait-HPOVTaskComplete

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                #Unsupported resource category
                default
                {

                    $ExceptionMessage = "The Resource Parameter value provided is not a Logical Interconnect Group or Logical Interconnect object. Please check the value and try again."
                    $ErrorRecord = New-ErrorRecord ArgumentException InvalidParameter InvalidArgument 'Resource' -TargetType 'PSObject' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

        }

    }

    End
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function GetNetworkUris
{

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Position = 0, Mandatory, ParameterSetName = "Default")]
        [Array]$_Networks,

        [Parameter (Position = 1, Mandatory, ParameterSetName = "Default")]
        [Object]$_ApplianceConnection

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        $_NetworkUris = New-Object System.Collections.ArrayList

    }

    Process
    {

        #Get Network URI's if values are of type String
        ForEach ($_net in $_Networks)
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] _net Type is {0}" -f $_net.GetType().FullName | Write-Verbose

            #Network is String and Name; call Get-HPOVNetwork
            if ($_net -is [String] -and (-not($_net.StartsWith('/rest/'))))
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network is type String, and Network Name"

                #Get Network Object
                Try
                {

                    $_net = Get-HPOVNetwork $_net -ApplianceConnection $_ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found Network {0} ({1})" -f $_net.name,$_net.uri | Write-Verbose 
    
                #Insert object into original arraylist
                [void]$_NetworkUris.Add($_net.uri)

            }

            elseif ($_net -is [String] -and $_net.StartsWith('/rest/'))
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network is type String, and URI of network."

                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding URI to collection: {0}" -f $_net | Write-Verbose 

                [void]$_NetworkUris.Add($_net)

            }

            # // Need to change this to HPOneView.Networking.Networks.Ethernet
            elseif ($_net -is [PSCustomObject])
            {

                if (-not('HPOneView.Networking.EthernetNetwork','HPOneView.Networking.FCoENetwork','HPOneView.Networking.Networks.FibreChannelNetwork' -contains $_net.PSObject.TypeNames[0]))
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Input object is not a valid Network type."

                }
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network '$($_net.name)' is [$($_net.GetType().Fullname)]"

                [void]$_NetworkUris.Add($_net.uri)

            }

        }

    }

    End
    {

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network URIs: {0}" -f ($_NetworkUris -join ", ") | Write-Verbose

        Return $_NetworkUris
    
    }

}

function BuildPortConfigInfos
{

    [CmdLetBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [Object]$UplinkPorts,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [String]$EnclosureID = 1

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

    }

    Process
    {



    }

    End
    {


    }

}

function BuildLogicalPortConfigInfos
{

    [CmdLetBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [Object]$UplinkPorts,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [String]$EnclosureID = 1

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

    }

    Process
    {



    }

    End
    {


    }

}

function Get-HPOVSwitchType
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Name')]
    Param
    (
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Name')]
        [ValidateNotNullorEmpty()]
        [string]$Name,

        [Parameter (Mandatory, ParameterSetName = 'PartNumber')]
        [ValidateNotNullorEmpty()]
        [string]$PartNumber,

        [Parameter (Mandatory = $false, ParameterSetName = 'Name')]
        [Parameter (Mandatory = $false, ParameterSetName = 'PartNumber')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    { 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $Collection = New-Object System.Collections.ArrayList
        $NotFound   = New-Object System.Collections.ArrayList
    
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            $uri = $SwitchTypesUri + "?sort=name:descEnding"

            if ($PSboundParameters['Name']) 
            { 
                
                $uri += "&filter=name='$name'" 
            
            }
            
            elseif ($PSboundParameters['PartNumber']) 
            {
                
                $uri += "&filter=partNumber='$partNumber'" 
            
            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

            Try
            {

                $resp = Send-HPOVRequest $uri -Appliance $_appliance

            }

            Catch
            {

              $PSCmdlet.ThrowTerminatingError($_)

            }        

            if ($resp.count -gt 0)
            {

                $resp.members | Sort-Object name | % {

                    $_switchtype = $_

                    $_switchtype | % { $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.SwitchType')}

                    [void]$Collection.Add($_switchtype)

                }

            }

            else 
            {

                [Void]$NotFound.Add($_appliance.Name)

            }

        }

    }

    End 
    {

        if ((-not($Collection) -or ($NotFound.count -gt 1)) -and $Name) 
        {

            $Collection

            $ErrorRecord = New-ErrorRecord HPOneView.SwitchTypeResourceException SwitchTypeNameResourceNotFound ObjectNotFound 'Name' -Message "No Switch Types with '$Name' name were found on appliance $($NotFound -join ", ")."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ((-not($Collection) -or ($NotFound.count -gt 0)) -and $PartNumber) 
        {

            $Collection

            $ErrorRecord = New-ErrorRecord HPOneView.SwitchTypeResourceException SwitchTypePartnumberResourceNotFound ObjectNotFound 'PartNumber' -Message "No Switch Types with '$PartNumber' partnumber were found on appliance $($NotFound -join ", ")."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        else 
        { 
        
            return $Collection

        }

    }

}

function Get-HPOVLogicalSwitchGroup
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (ValueFromPipeline, Mandatory, ParameterSetName = 'Pipeline')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Pipeline')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ("x", "export")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$exportFile

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSCmdlet.ParameterSetName -eq 'Pipeline')
        {

            $PipelineInput = $True

        }

        Else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_Collection = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        if ($PipelineInput)
        {

            #Task Resource Object
            if ($InputObject -is [PSCustomObject] -and $InputObject.category -eq 'tasks')
            {

                "[{0}] Processig task resource to get created object" -f $MyInvocation.InvocationName.ToString().ToUpper()

                if ($InputObject.taskState -eq 'Completed')
                {

                    Try
                    {

                        $_LogicalSwitchGroup = Send-HPOVRequest $InputObject.associatedResource.resourceUri -Hostname $InputObject.ApplianceConnection.Name

                        $_LogicalSwitchGroup | % { 
                
                            $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalSwitchGroup')    

                            [void]$_Collection.Add($_) 
                
                        }

                    }

                    Catch
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] API Error Caught: $($_.Exception.Message)"

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                #Generate error
                else
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.LogicalSwitchGroupResourceException TaskFailure InvalidOperation 'InputObject' -Message "The Task object provided by the pipeline did not complete successfully. Please validate the task object resource and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                }

            }

            else
            {

                $ErrorRecord = New-ErrorRecord HPOneView.LogicalSwitchGroupResourceException LogicalSwitchGroupNotFound ObjectNotFound 'InputObject' -Message "The Logical Switch Group associated with the pipeline input task object was not found on '$($InputObject.ApplianceConnection.Name)'. Please check the value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

            }

        }

        Else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                if ($PSBoundParameters['Label'])
                {

                    $_uri = '{0}?category:logical-switch-groups&query=labels:{1}' -f $IndexUri, $Label

                    Try
                    {

                        $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                        #Loop through all found members and get full SVT object
                        ForEach ($_memeber in $_IndexMembers.members)
                        {

                            Try
                            {

                                $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }                        

                            $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalSwitchGroup')    

                            [void]$_Collection.Add($_memeber) 

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                else
                {

                    $Uri = $LogicalSwitchGroupsUri + '?sort=name:asc'

                    if ($PSboundParameters['Name']) 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Switch Group name provided: '$name'"

                        $_method = 'eq'

                        if ($Name.Contains('*'))
                        {

                            $Name = $Name.Replace('*','%25')

                            $_method = 'matches'

                        }

                         $Uri += "&filter=name {0} '{1}'" -f $_method.ToLower(), $Name

                    }

                    if ($PSBoundParameters['Scope'])
                    {

                        $Uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri
                    
                    }

                    Try
                    {

                        $_LogicalSwitchGroups = Send-HPOVRequest -Uri $Uri -Hostname $_appliance.Name

                    }

                    Catch
                    {

                        "[{0}] API Error Caught {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_.Exception.Message

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
        
                    if ($_LogicalSwitchGroups.count -eq 0) 
                    { 

                        "[{0}] No Logical Switch Group resources found on {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

                    }

                    else 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($ligs.count) Logical Switch Group resource(s)."
            
                        $_LogicalSwitchGroups.members | % { 
            
                            $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalSwitchGroup')    

                            [void]$_Collection.Add($_) 

                        }

                    }

                }

            }

        }

    }

    End 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. $($_Collection.count) logical switch group(s) found."
        
        if ($_Collection.count -eq 0 -and $Name) 
        { 

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Switch Group '$Name' resource not found. Generating error"

            $ErrorRecord = New-ErrorRecord InvalidOperationException LogicalSwitchGroupNotFound ObjectNotFound 'Name' -Message "Specified Logical Switch Group '$Name' was not found on any appliance connection. Please check the name and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

        }       

        if ($exportFile)
        {
            
            $_Collection | convertto-json -Depth 99 | Set-Content -Path $exportFile -force -encoding UTF8 
        
        }
                
        else 
        {
            
            Return $_Collection | Sort name
        
        }

    }

}

function New-HPOVLogicalSwitchGroup
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateRange(1,2)]
        [int]$NumberOfSwitches = 1,

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Object]$SwitchType,

        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [switch]$Async

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $SwitchType)
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }        

    }
    
    Process
    {

        #Create new LIgObject
        $_LogicalSwitchGroup = NewObject -LogicalSwitchGroup 
        $_LogicalSwitchGroup.name = $Name

        switch ($SwitchType.GetType().Name) 
        {

            "String" 
            {            

                #Assume Name
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found VC FF in bay $($_bay.name | out-string)"

                Try
                {

                    $SwitchType = Get-HPOVSwitchType -Name $SwitchType -ApplianceConnection $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

            "PSCustomObject" 
            {

                "[{0}] Processing PSCustomObject: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($SwitchType | FL * | Out-String)

                #validate
                if ($SwitchType.category -ne 'switch-types')
                {

                    "[{0}] Invalid switchtype resource. Generating Terminating Error" -f $MyInvocation.InvocationName.ToString().ToUpper()

                    $_Message = 'The provided Switch Type {0} is not a supported object category type. Expected "switch-types", recieved "{1}".' -f $SwitchType.name, $SwitchType.category

                    $ErrorRecord = New-ErrorRecord HPOneView.SwitchTypeResourceException InvalidSwitchTypeResource InvalidArgument 'SwitchType' -TargetType 'PSObject' -Message $_Message
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }
            
            #Unsupported SwitchType object type
            default 
            {

                "[{0}] Invalid switchtype resource. Generating Terminating Error" -f $MyInvocation.InvocationName.ToString().ToUpper()

                $_Message = 'The provided Switch Type {0} is not a supported object type. Expected either [System.String] or [PSCustomObject], recieved "{1}".' -f $SwitchType.name, $SwitchType.GetType().FullName

                $ErrorRecord = New-ErrorRecord HPOneView.SwitchTypeResourceException InvalidSwitchTypeResource InvalidArgument 'SwitchType' -TargetType $SwitchType.GetType().Name -Message $_Message
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        For ($i = 1; $i -le $NumberOfSwitches; $i++)
        {

            "[{0}] Adding Location Entry {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $i | Write-Verbose

            $_SwitchLogicalLocation = NewObject -SwitchLogicalLocation
            $_SwitchLogicalLocation.permittedSwitchTypeUri = $SwitchType.uri

            $_SwitchLocationEntry = NewObject -LocationEntry
            $_SwitchLocationEntry.relativeValue = $i
            $_SwitchLocationEntry.type = "StackingMemberId"

            [void]$_SwitchLogicalLocation.logicalLocation.locationEntries.Add($_SwitchLocationEntry)
            [void]$_LogicalSwitchGroup.switchMapTemplate.switchMapEntryTemplates.Add($_SwitchLogicalLocation)

        }

        "[{0}] LS: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), (ConvertTo-Json -Depth 99 $_LogicalSwitchGroup | out-string) | Write-Verbose 

        "{0}] Sending request to create '{1}'..." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_LogicalSwitchGroup.name | Write-Verbose 
    
        Try
        {
        
            $_Task = Send-HPOVRequest -Uri $LogicalSwitchGroupsUri -Method POST -Body $_LogicalSwitchGroup -Hostname $ApplianceConnection
        
        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not $Async.IsPresent)
        {

            Try
            {

                $_Task = Wait-HPOVTaskComplete -InputObject $_Task

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_Task

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVLogicalSwitchGroup
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("ls",'LogicalSwitchGroup')]
        [Object]$InputObject,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")] 
        [switch]$Force

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        {
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_lsgcollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Object provided: $($InputObject | FL * | Out-String)"

            If ('logical-switch-groups' -eq $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "LSG:$($InputObject.Name)" -TargetType PSObject -Message "The Logical Switch Group resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_lsgcollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "Network:$($InputObject.Name)" -TargetType PSObject -Message "The Logical Switch Group resource is not an expected category type [$($InputObject.category)]. Allowed resource category type is 'logical-switch-groups'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            foreach ($_resource in $InputObject) 
            {

                if ($_resource -is [String])
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received URI: $($_resource)"

                    $ErrorRecord = New-ErrorRecord InvalidOperationException UnsupportedParameterType InvalidArgumetn 'InputObject' -Message "The provided Resource value is a String, only PSCustomObject types are supported."
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                #LIG passed is the object
                elseif ($_resource -is [PSCustomObject] -and 'logical-switch-groups' -eq $_resource.category)
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Object provided: $($_resource | FL * | out-string)"

                    [void]$_lsgcollection.Add($_resource)
                
                }

                elseif ($_resource -is [PSCustomObject] -and 'logical-switch-groups' -ne $_resource.category)
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "Invalid Logical Switch Group Parameter: $($_resource | FL * | Out-String)"
                    $PSCmdlet.WriteError($ErrorRecord)

                }

            }

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_lsgcollection.count) resources to remove."

        #Process Resources
        ForEach ($_lsg in $_lsgcollection)
        {
        
            if ($PSCmdlet.ShouldProcess($_lsg.ApplianceConnection.Name,("Remove Logical Switch Group '{0}'" -f $_lsg.name)))
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing '$($_lsg.name)' from appliance '$($_lsg.ApplianceConnection.Name)'."

                Try
                {
                    
                    if ($force.IsPresent)
                    {

                        $_lsg.uri += "?force=true"

                    }

                    Send-HPOVRequest $_lsg.Uri DELETE -Hostname $_lsg.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVLogicalSwitch
{


    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (ValueFromPipeline, Mandatory, ParameterSetName = 'Pipeline')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Pipeline')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Alias ("x", "export")]
        [ValidateScript({split-path $_ | Test-Path})]
        [String]$exportFile

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSCmdlet.ParameterSetName -eq 'Pipeline')
        {

            $PipelineInput = $True

        }

        Else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_Collection = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        if ($PipelineInput)
        {

            #Task Resource Object
            if ($InputObject -is [PSCustomObject] -and $InputObject.category -eq 'tasks')
            {

                "[{0}] Processing task resource to get created object" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                if ($InputObject.taskState -eq 'Completed')
                {

                    Try
                    {

                        $_LogicalSwitchGroup = Send-HPOVRequest $InputObject.associatedResource.resourceUri -Hostname $InputObject.ApplianceConnection.Name

                        $_LogicalSwitchGroup | % { 
                
                            $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalSwitch')    

                            [void]$_Collection.Add($_) 
                
                        }

                    }

                    Catch
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] API Error Caught: $($_.Exception.Message)"

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                #Generate error
                else
                {

                    $InputObject

                    $ErrorRecord = New-ErrorRecord HPOneView.LogicalSwitchGroupResourceException TaskFailure InvalidOperation 'InputObject' -Message "The Task object provided by the pipeline did not complete successfully. Please validate the task object resource and try again."
                    $PSCmdlet.WriteError($ErrorRecord)  

                }

            }

            else
            {

                $ExceptionMessage = "The Logical Switch associated with the pipeline input task object was not found on '{0}'. Please check the value and try again." -f $InputObject.ApplianceConnection.Name 
                $ErrorRecord = New-ErrorRecord HPOneView.LogicalSwitchResourceException LogicalSwitchNotFound ObjectNotFound 'InputObject' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)  

            }

        }

        Else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                if ($PSBoundParameters['Label'])
                {

                    $_uri = '{0}?category:storage-volume-templates&query=labels:{1}' -f $IndexUri, $Label

                    Try
                    {

                        $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                        #Loop through all found members and get full SVT object
                        ForEach ($_memeber in $_IndexMembers.members)
                        {

                            Try
                            {

                                $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }                        

                            $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalSwitch')    

                            [void]$_Collection.Add($_memeber) 

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                else
                {

                    $Uri = $LogicalSwitchesUri + '?sort=name:asc'

                    if ($PSboundParameters['Name']) 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Switch name provided: '$name'"

                        $_method = 'eq'

                        if ($Name.Contains('*'))
                        {

                            $Name = $Name.Replace('*','%25')

                            $_method = 'matches'

                        }

                        $Uri += "&filter=name {0} '{1}'" -f $_method.ToLower(), $Name

                    }

                    if ($PSBoundParameters['Scope'])
                    {

                        $Uri += "&filter=scopeUris EQ '{0}'" -f $Scope.Uri
                    
                    }

                    Try
                    {

                        $_LogicalSwitches = Send-HPOVRequest -Uri $Uri -Hostname $_appliance.Name

                    }

                    Catch
                    {

                        "[{0}] API Error Caught {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_.Exception.Message

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
        
                    if ($_LogicalSwitches.count -eq 0 -and $Name) 
                    { 

                        "[{0}] No Logical Switch resources found on {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

                        $ExceptionMessage = "The Logical Switch '{0}' was not found on '{1}' appliance connection." -f $Name, $_appliance.Name 
                        $ErrorRecord = New-ErrorRecord HPOneView.LogicalSwitchResourceException LogicalSwitchNotFound ObjectNotFound 'InputObject' -Message $ExceptionMessage
                        $PSCmdlet.WriteError($ErrorRecord)  

                    }

                    elseif ($_LogicalSwitches.count -eq 0) 
                    { 

                        "[{0}] No Logical Switch resources found on {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

                    }

                    else 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($_LogicalSwitches.count) Logical Switch resource(s)."
            
                        $_LogicalSwitches.members | % { 
            
                            $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.LogicalSwitch')    

                            [void]$_Collection.Add($_) 
            
                        }

                    }

                }
                    
            }

        }

    }

    End 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. $($_Collection.count) logical switch(es) found."

        if ($exportFile)
        {
            
            $_Collection | convertto-json -Depth 99 | Set-Content -Path $exportFile -force -encoding UTF8 
        
        }
                
        else 
        {
            
            Return $_Collection | Sort name
        
        }

    }

}

function New-HPOVLogicalSwitch
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Managed")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Managed")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateNotNullOrEmpty()]
        [Object]$LogicalSwitchGroup,

        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [Parameter (Mandatory, ParameterSetName = "ManagedSnmpV3")]
        [switch]$Managed,

        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ParameterSetName = "MonitoredSnmpV3")]
        [switch]$Monitored,

        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateNotNullOrEmpty()]
        [string]$Switch1Address,

        [Parameter (Mandatory = $false, ParameterSetName = "Managed")]
        [Parameter (Mandatory = $false, ParameterSetName = "Monitored")]
        [Parameter (Mandatory = $false, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $false, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateNotNullOrEmpty()]
        [string]$Switch2Address,

        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateNotNullOrEmpty()]
        [string]$SshUserName,

        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [Parameter (Mandatory, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateNotNullOrEmpty()]
        [Object]$SshPassword,

        [Parameter (Mandatory = $false, ParameterSetName = "Managed")]
        [Parameter (Mandatory = $false, ParameterSetName = "Monitored")]
        [Parameter (Mandatory = $false, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $false, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateNotNullOrEmpty()]
        [int]$SnmpPort = 161,

        [Parameter (Mandatory = $false, ParameterSetName = "Managed")]
        [Parameter (Mandatory = $false, ParameterSetName = "Monitored")]
        [switch]$SnmpV1,

        [Parameter (Mandatory, ParameterSetName = "Managed")]
        [Parameter (Mandatory, ParameterSetName = "Monitored")]
        [ValidateNotNullOrEmpty()]
        [string]$SnmpCommunity,

        [Parameter (Mandatory = $false, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $false, ParameterSetName = "MonitoredSnmpV3")]
        [switch]$SnmpV3,

        [Parameter (Mandatory = $false, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $false, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateNotNullOrEmpty()]
        [string]$SnmpUserName,

        [Parameter (Mandatory = $false, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $false, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateSet ("AuthOnly","AuthAndPriv")]
        [ValidateNotNullOrEmpty()]
        [string]$SnmpAuthLevel = "AuthOnly",

        [Parameter (Mandatory = $false, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $false, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateSet ("SHA","MD5")]    
        [ValidateNotNullOrEmpty()]
        [string]$SnmpAuthProtocol = 'SHA',

        [Parameter (Mandatory = $false, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $false, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateNotNullOrEmpty()]
        [Object]$SnmpAuthPassword,

        [Parameter (Mandatory = $false, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $false, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateSet ("aes128","des56")]    
        [ValidateNotNullOrEmpty()]
        [string]$SnmpPrivProtocol,

        [Parameter (Mandatory = $false, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $false, ParameterSetName = "MonitoredSnmpV3")]
        [ValidateNotNullOrEmpty()]
        [Object]$SnmpPrivPassword,

        [Parameter (Mandatory = $False, ParameterSetName = "Managed")]
        [Parameter (Mandatory = $False, ParameterSetName = "Monitored")]
        [Parameter (Mandatory = $False, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $False, ParameterSetName = "MonitoredSnmpV3")]
        [switch]$Async,
        
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "Managed")]
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "Monitored")]
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "ManagedSnmpV3")]
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "MonitoredSnmpV3")]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $LogicalSwitchGroup)
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        #Validate SNMPv3 Parameters that are required
        if ('ManagedSnmpV3','MonitoredSnmpV3' -contains $PSCmdlet.ParameterSetName)
        {

            if ($SnmpAuthLevel -eq "AuthOnly" -and 
            (-not $SnmpAuthProtocol -or 
            -not $SnmpAuthPassword)) 
            {

                #Generate Terminateing error
                $ErrorRecord = New-ErrorRecord HPOneView.LogicalSwitchResourceException MissingRequiredParameters InvalidArgument 'SnmpAuthLevel' -Message "The -SnmpAuthLevel Parameter was set to 'AuthOnly', but did not include both -SnmpAuthProtocol and -SnmpAuthPassword Parameters."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            }

            if ($SnmpAuthLevel -eq "AuthAndPriv" -and (
                -not $SnmpAuthProtocol -or 
                -not $SnmpAuthPassword -or 
                -not $SnmpPrivProtocol -or 
                -not $SnmpPrivPassword )) 
            {

                #Generate Terminateing error
                $ErrorRecord = New-ErrorRecord HPOneView.LogicalSwitchResourceException MissingRequiredParameters InvalidArgument 'SnmpAuthLevel' -Message "The -SnmpAuthLevel Parameter was set to 'AuthAndPriv', but did not include -SnmpAuthProtocol, -SnmpAuthPassword, -SnmpPrivProtocol and -SnmpPrivPassword Parameters."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

    }
    
    Process
    {

        #Create new LIgObject
        $_LogicalSwitch = NewObject -LogicalSwitch 
        $_LogicalSwitch.logicalSwitch.name = $Name
        $_LogicalSwitch.logicalSwitch.managementLevel = $LogicalSwitchManagementLevelEnum[$PSCmdlet.ParameterSetName]

        if ($SshPassword -is [SecureString])
        {

            $SshPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SshPassword))

        }

        if ($PSBoundParameters['SnmpAuthPassword'] -and $SnmpAuthPassword -is [SecureString])
        {

            $SnmpAuthPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SnmpAuthPassword))
            
        }

        if ($PSBoundParameters['SnmpPrivPassword'] -and $SnmpPrivPassword -is [SecureString])
        {

            $SnmpPrivPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SnmpPrivPassword))
            
        }

        #Validate Logic Switch
        if ($LogicalSwitchGroup -isnot [PSCustomObject])
        {

            #Generate Error
            "[{0}] Invalid LogicalSwitchGroup resource. Generating Terminating Error" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_Message = 'The provided Logical Switch Group {0} is not a supported object type. Expected [PSCustomObject], recieved "{1}".' -f $LogicalSwitchGroup.name, $SwitchType.GetType().FullName

            $ErrorRecord = New-ErrorRecord HPOneView.SwitchTypeResourceException InvalidSwitchTypeResource InvalidArgument 'LogicalSwitchGroup' -TargetType $LogicalSwitchGroup.GetType().Name -Message $_Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($LogicalSwitchGroup.category -ne 'logical-switch-groups')
        {

            #Generate error
            "[{0}] Invalid LogicalSwitchGroup resource. Generating Terminating Error" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_Message = 'The provided Logical Switch Group {0} is not a supported object category type. Expected logical-switch-groups", recieved "{1}".' -f $LogicalSwitchGroup.name, $LogicalSwitchGroup.category

            $ErrorRecord = New-ErrorRecord HPOneView.SwitchTypeResourceException InvalidSwitchTypeResource InvalidArgument 'LogicalSwitchGroup' -TargetType 'PSObject' -Message $_Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_LogicalSwitch.logicalSwitch.logicalSwitchGroupUri = $LogicalSwitchGroup.uri
        $NumberOfSwitches = $LogicalSwitchGroup.switchMapTemplate.switchMapEntryTemplates.count

        "[{0}] Processing number of switches from Switch Group: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $NumberOfSwitches | Write-Verbose

        #Add Switch Credentials to connection Object
        For ($i = 1; $i -le $NumberOfSwitches; $i++)
        {

            "[{0}] Processing switch: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $i | Write-Verbose

            #SNMP and Management Address
            $_SwitchCredentialConfig = NewObject -LogicalSwitchCredentials
            $_SwitchCredentialConfig.snmpPort = $SnmpPort

            if ($i -eq 1)
            {

                $_SwitchCredentialConfig.logicalSwitchManagementHost = $Switch1Address

            }
            
            elseif ($i -eq 2)
            {

                $_SwitchCredentialConfig.logicalSwitchManagementHost = $Switch2Address

            }

            if ($PSBoundParameters['SnmpV1'])
            {
                
                $_SwitchCredentialConfig.snmpV1Configuration.communityString = $SnmpCommunity

            }

            else
            {

                $_SwitchCredentialConfig.snmpVersion = 'SNMPv3'

            }

            [void]$_LogicalSwitch.logicalSwitch.switchCredentialConfiguration.Add($_SwitchCredentialConfig)

            #SSH
            $_LogialSwitchConnectionProperties = NewObject -LogialSwitchConnectionProperties

            #SSH User Account
            $_LogicalSwitchConnectionProperty              = NewObject -LogicalSwitchConnectionProperty
            $_LogicalSwitchConnectionProperty.propertyName = 'SshBasicAuthCredentialUser'
            $_LogicalSwitchConnectionProperty.value        = $SshUserName
            $_LogicalSwitchConnectionProperty.valueType    = 'String'

            [void]$_LogialSwitchConnectionProperties.connectionProperties.Add($_LogicalSwitchConnectionProperty)

            #SSH User Password
            $_LogicalSwitchConnectionProperty              = NewObject -LogicalSwitchConnectionProperty
            $_LogicalSwitchConnectionProperty.propertyName = 'SshBasicAuthCredentialPassword'
            $_LogicalSwitchConnectionProperty.value        = $SshPassword
            $_LogicalSwitchConnectionProperty.valueFormat  = 'SecuritySensitive'
            $_LogicalSwitchConnectionProperty.valueType    = 'String'

            [void]$_LogialSwitchConnectionProperties.connectionProperties.Add($_LogicalSwitchConnectionProperty)

            #Add
            [Void]$_LogicalSwitch.logicalSwitchCredentials.Add($_LogialSwitchConnectionProperties)            

        }
    
        #Handle Device SNMP Configuration
        if ('ManagedSnmpV3','MonitoredSnmpV3' -contains $PSCmdlet.ParameterSetName)
        {

            For ($i = 0; $i -lt $NumberOfSwitches; $i++)
            {

                "[{0}] Processing SNMPv3 Auth credentials" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                #Add SNMPv3 AuthOnly Protocol
                $_LogicalSwitch.logicalSwitch.switchCredentialConfiguration[$i].snmpV3Configuration.authorizationProtocol = $SnmpAuthProtocol.ToUpper()
                $_LogicalSwitch.logicalSwitch.switchCredentialConfiguration[$i].snmpV3Configuration.securityLevel = 'Auth'

                #Add SNMPv3 Credentials
                $_LogicalSwitchConnectionProperty              = NewObject -LogicalSwitchConnectionProperty
                $_LogicalSwitchConnectionProperty.propertyName = 'SnmpV3User'
                $_LogicalSwitchConnectionProperty.value        = $SnmpUserName
                $_LogicalSwitchConnectionProperty.valueType    = 'String'
                [void]$_LogicalSwitch.logicalSwitchCredentials[$i].connectionProperties.Add($_LogicalSwitchConnectionProperty)

                $_LogicalSwitchConnectionProperty              = NewObject -LogicalSwitchConnectionProperty
                $_LogicalSwitchConnectionProperty.propertyName = 'SnmpV3AuthorizationPassword'
                $_LogicalSwitchConnectionProperty.value        = $SnmpAuthPassword
                $_LogicalSwitchConnectionProperty.valueFormat  = 'SecuritySensitive'
                $_LogicalSwitchConnectionProperty.valueType    = 'String'
                [void]$_LogicalSwitch.logicalSwitchCredentials[$i].connectionProperties.Add($_LogicalSwitchConnectionProperty)

                #Add SNMPv3 Privacy settings if specified
                if ($SnmpAuthLevel -eq "AuthAndPriv") 
                {

                    "[{0}] Processing SNMPv3 AuthAndPrivacy credentials" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $_LogicalSwitch.logicalSwitch.switchCredentialConfiguration[$i].snmpV3Configuration.privacyProtocol = $SnmpPrivProtocol.ToUpper()
                    $_LogicalSwitch.logicalSwitch.switchCredentialConfiguration[$i].snmpV3Configuration.securityLevel   = 'AuthPrivacy'

                    $_LogicalSwitchConnectionProperty              = NewObject -LogicalSwitchConnectionProperty
                    $_LogicalSwitchConnectionProperty.propertyName = 'SnmpV3PrivacyPassword'
                    $_LogicalSwitchConnectionProperty.value        = $SnmpPrivPassword
                    $_LogicalSwitchConnectionProperty.valueFormat  = 'SecuritySensitive'
                    $_LogicalSwitchConnectionProperty.valueType    = 'String'
                    [void]$_LogicalSwitch.logicalSwitchCredentials[$i].connectionProperties.Add($_LogicalSwitchConnectionProperty)

                }

            }

        }

        "[{0}] LS: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), (ConvertTo-Json -Depth 99 $_LogicalSwitch | out-string) | Write-Verbose 

        "{0}] Sending request to create '{1}'..." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_LogicalSwitch.name | Write-Verbose 
    
        Try
        {
        
            $_Task = Send-HPOVRequest -Uri $LogicalSwitchesUri -Method POST -Body $_LogicalSwitch -Hostname $ApplianceConnection
        
        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not $Async.IsPresent)
        {

            Try
            {

                $_Task = Wait-HPOVTaskComplete -InputObject $_Task

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_Task

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVLogicalSwitch
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("ls",'LogicalSwitch')]
        [Object]$InputObject,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")] 
        [switch]$Force,

        [Parameter (Mandatory = $false, ParameterSetName = "default")] 
        [switch]$Async

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        {
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_taskcollection          = New-Object System.Collections.ArrayList
        $_logicalswitchcollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Object provided: $($InputObject | FL * | Out-String)"

            If ('logical-switches' -eq $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The Logical Switch resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_logicalswitchcollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The Logical Switch resource is not an expected category type [$($InputObject.category)]. Allowed resource category type is 'logical-switches'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            foreach ($_resource in $InputObject) 
            {

                if ($_resource -is [String])
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received URI: $($_resource)"

                    $ErrorRecord = New-ErrorRecord InvalidOperationException UnsupportedParameterType InvalidArgumetn 'InputObject' -Message "The provided Resource value is a String, only PSCustomObject types are supported."
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                #LIG passed is the object
                elseif ($_resource -is [PSCustomObject] -and 'logical-switches' -eq $_resource.category)
                {
                    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Object provided: $($_resource | FL * | out-string)"

                    [void]$_logicalswitchcollection.Add($_resource)
                
                }

                elseif ($_resource -is [PSCustomObject] -and 'logical-switches' -ne $_resource.category)
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Resource' -TargetType 'PSObject' -Message "Invalid Logical Switch Parameter: $($_lig | FL * | Out-String)"
                    $PSCmdlet.WriteError($ErrorRecord)

                }

            }

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_logicalswitchcollection.count) resources to remove."

        #Process Resources
        ForEach ($_ls in $_logicalswitchcollection)
        {
        
            if ($PSCmdlet.ShouldProcess($_ls.ApplianceConnection.Name,("Remove Logical Switch '{0}'" -f $_ls.name))) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing '$($_ls.name)' from appliance '$($_ls.ApplianceConnection.Name)'."

                Try
                {
                    
                    if ($force.IsPresent)
                    {

                        $_ls.uri += "?force=true"

                    }

                    $_reply = Send-HPOVRequest $_ls.uri DELETE -Hostname $_ls.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($PSboundParameters['Async'])
                {

                    $_reply

                }

                else
                {

                    $_reply | Wait-HPOVTaskComplete 

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Set-HPOVLogicalSwitch
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Ethernet")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [Alias ('LogialSwitch')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [string]$Prefix,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [string]$Suffix,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [ValidateNotNullOrEmpty()]
        [ValidateSet ("General", "Management", "VMMigration", "FaultTolerance")]
        [string]$Purpose,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Bool]$Smartlink, 

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Bool]$PrivateNetwork, 

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [validaterange(2,20000)]
        [int32]$TypicalBandwidth, 
        
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [validaterange(100,20000)]
        [int32]$MaximumBandwidth, 

        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateRange(1,1800)]
        [Alias ('lst')]
        [int32]$LinkStabilityTime, 

        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [Alias ('ald')]
        [Bool]$AutoLoginRedistribution,

        [Parameter (Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [Object]$ManagedSan,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false, ParameterSetName = "FibreChannel")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        Write-Warning 'IN DEV'
        BREAK

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Network resource passed via pipeline."
        
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_NetworksToUpdate = New-Object System.Collections.ArrayList
        $NetCollection     = New-Object System.Collections.ArrayList

    }

    Process 
    {

        #build collection of networks to modify
        foreach ($net in $InputObject) 
        {

            if ($PSBoundParameters['LinkStabilityTime'] -and $net.category -eq 'fcoe-networks')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'LinkStabilityTime' -TargetType 'Int' -Message "The -LinkStabilityTime Parameter is not supported with FCoE Network resources, only FibreChannel network resources. Please check your call and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if ($PSBoundParameters['AutoLoginRedistribution'] -and $net.category -eq 'fcoe-networks')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'AutoLoginRedistribution' -TargetType 'Boolean'  -Message "The -AutoLoginRedistribution Parameter is not supported with FCoE Network resources, only FibreChannel network resources. Please check your call and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Check the name Parameter value if the caller inadvertantly provided an object for name Parameter
            if ($name -and ($name -match "category=ethernet-networks" -or $name -match "category=fc-networks" -or $name -match "category=fcoe-networks"))
            { 
            
                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'Name' -Message "The -name Parameter value appears to have been passed the network resource object, which is converted to type [String] and is an invalid operation. Please verify that you provided the Network Name attribute in the -name Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

            elseif ($name -and $name.length -gt 255) 
            {

                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'Name' -Message "The -name Parameter value is greater than 255 characters. Please check the -name Parameter value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            switch ($net.Gettype().Name) 
            {

                "PSCustomObject" 
                { 
    
                    if ($net -is [PSCustomObject] -and ($net.category -eq "ethernet-networks" -or $net.category -eq "fc-networks" -or $net.category -eq "fcoe-networks")) 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Collecting $($net.type) $($net.name) resource."

                        [void]$_NetworksToUpdate.Add($net)

                    }

                    else 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "[$($net.gettype().name)] is an unspported data type. Only [System.String] or [PSCustomObject] or an [Array] of [System.String] or [PSCustomObject] network resources are allowed. Please check the -network Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }
                    
                }

                "String" 
                { 
                
                    #User provided Network 'name' and 1 or more Appliance Connections
                    if ($net -is [String] -and (-not ($net.StartsWith('/rest/'))))
                    {
                    
                        ForEach ($_appliance in $ApplianceConnection)
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting '$($net)' resource from appliance."
                            
                            Try 
                            {

                                $_tempNet = Get-HPOVNetwork $net -type $PSCmdlet.ParameterSetName -ApplianceConnection $_appliance

                            }
                            
                            Catch [HPOneView.NetworkResourceException]
                            {

                                if ($_.CategoryInfo.Category -eq 'ObjectNotFound')
                                {

                                    $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException NetworkResourceNotFound ObjectNotFound 'InputObject' -Message "'$net' Network was not found. Please check the value and try again."
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }
                                
                                else
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }

                            }
                            
                            if ($_tempNet.count -gt 1)
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException NonUniqueNetworkName InvalidResult 'InputObject' -Message "Multiple '$_tempNet' Network resource found with the same name. Please check the value and try again, or provide the Network Resource Object instead of the name."
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }
                    
                            [void]$_NetworksToUpdate.Add($_tempNet)

                        }
                        
                    }

                    elseif ($net -is [String] -and ($net.StartsWith('/rest/ethernet-networks/') -or $net.StartsWith('/rest/fc-networks/'))) 
                    {
                    
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting '$($net)' resource from appliance."

                        Try
                        {

                            $net = Send-HPOVRequest $net -Appliance $ApplianceConnection

                        }

                        Catch
                        {

                          $PSCmdlet.ThrowTerminatingError($_)

                        }
                                                
                        [void]$NetCollection.Add($net)
                    
                    }
                
                }

            }

        }

    }

    End 
    {

        ForEach ($_net in $_NetworksToUpdate)
        {

            #Set Specific Network Type settings
            switch ($_net.category) 
            {

                "ethernet-networks" 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updateing $($_net.name) Ethernet Network."

                    switch ($PSBoundParameters.keys) 
                    {

                        "purpose" 
                        { 
                        
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting network Purpose to: $purpose"
                            $_net.purpose = $purpose
                            
                        }

                        "smartlink" 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting smartlink Enabled to: $([bool]$smartlink)"
                            $_net.smartlink = [bool]$smartlink

                        }

                        "privateNetwork" 
                        { 

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting privateNetwork Enabled to: $([bool]$privateNetwork)"
                            $_net.privateNetwork = [bool]$privateNetwork
                        
                        }

                    }

                }

                "fc-networks" 
                {

                    switch ($PSBoundParameters.keys) 
                    {

                        "LinkStabilityTime" 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting LinkStabilityTime to '$LinkStabilityTime' seconds"

                            if ($_net.fabricType -eq 'DirectAttach')
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidFabricOperation InvalidOperation 'LinkStabilityTime' -TargetType $LinkStabilityTime.Gettype().Name -Message ("Cannot set LinkStabilityTime value to a DirectAttach FibreChannel resource, {0}." -f $_net.name)
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                            $_net.linkStabilityTime = [int]$linkStabilityTime

                        }

                        "AutoLoginRedistribution" 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting AutoLoginRedistribution Enabled to: $([bool]$AutoLoginRedistribution)"

                            if ($_net.fabricType -eq 'DirectAttach')
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidFabricOperation InvalidOperation 'AutoLoginRedistribution' -TargetType $AutoLoginRedistribution.Gettype().Name -Message ("Cannot set AutoLoginRedistribution value to a DirectAttach FibreChannel resource, {0}" -f $_net.name)
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }
                            
                            $_net.autoLoginRedistribution = [bool]$autoLoginRedistribution

                            if ($_net.linkStabilityTime -eq 0 -and (-not($LinkStabilityTime)) -and [Bool]$AutoLoginRedistribution)
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidLinkStabilityTimeValue InvalidOperation 'AutoLoginRedistribution' -Message ("The '{0}' FC Network resource is a Direct Attach fabric. The Managed SAN resource cannot be modified." -f $_net.name)
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                        }

                        "managedSan"
                        {

                            if ($_net.fabricType -eq 'DirectAttach')
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.NetworkResourceException InvalidFabricOperation InvalidResult 'Network' -Message ("The '{0}' FC Network resource is a Direct Attach fabric. The Managed SAN resource cannot be modified." -f $_net.name)
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                            else
                            {

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing ManagedSAN for FC Network."

                                Try
                                {

                                    $_net.managedSanUri = (VerifyManagedSan $managedSan $_net.ApplianceConnection.Name)

                                }

                                Catch
                                {

                                    $PSCmdlet.ThrowTerminatingError($_)

                                }

                            }
                            
                        }

                    }

                }

                "fcoe-networks"
                {
                    
                    switch ($PSBoundParameters.keys) 
                    {

                        "managedSan"
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing ManagedSAN for FC Network."
                    
                            $_net.managedSanUri = (VerifyManagedSan $managedSan $_net.ApplianceConnection.Name)
                            
                        }

                    }

                }

            }

            #Shared Parameters for each Network Type
            if ($PSBoundParameters["name"]) 
            {
            
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network name to '$name'."
    
                #validate name Parameter is [String]
                $_net.name = $name
                
            }
    
            if ($PSBoundParameters["prefix"]) 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network name to include '$prefix' prefix to Network Name."
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updated Network Name: $($prefix + $_net.name)"
    
                #validate name Parameter is [String]
                $_net.name = $prefix + $_net.name
                
            }
    
            if ($PSBoundParameters["suffix"]) 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network name to include '$suffix' suffix to Network Name."
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updated Network Name: $($_net.name + $suffix)"
    
                #validate name Parameter is [String]
                $_net.name += $suffix
                
            }
    
            if ($PSBoundParameters["typicalBandwidth"] -or $PSBoundParameters["maximumBandwidth"]) 
            {
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network bandwidth assignment."

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Connection Template resource."

                Try
                {

                    $ct = Send-HPOVRequest $_net.connectionTemplateUri -Appliance $_net.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                } 
                
                if ($PSBoundParameters["maximumBandwidth"]) 
                {
                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Original Maximum bandwidth assignment: $($ct.bandwidth.maximumBandwidth)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Maximum bandwidth assignment: $maximumBandwidth"

                    $ct.bandwidth.maximumBandwidth = $maximumBandwidth
    
                }

                if($PSBoundParameters["typicalBandwidth"]) 
                {
    
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Original Typical bandwidth assignment: $($ct.bandwidth.typicalBandwidth)"
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Typical bandwidth assignment: $typicalBandwidth"

                    $ct.bandwidth.typicalBandwidth = $typicalBandwidth
                    
                }
    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Connection Template: $($ct | out-string)"

                Try
                {

                    $ct = Send-HPOVRequest $ct.uri PUT $ct -Appliance $ct.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
    
            }

            $_net = $_net | select * -ExcludeProperty defaultTypicalBandwidth, defaultMaximumBandwidth, created, modified

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Network Resource object: $($_net | FL * | out-string)"
            Try
            {

                $resp = Send-HPOVRequest $_net.uri PUT $_net -Appliance $_net.ApplianceConnection.Name
            
            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            [void]$NetCollection.Add($resp)
        
        }
        
        Return $NetCollection

    }

} 

function Update-HPOVLogicalSwitch
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [Alias ('LogicalSwitch')]
        [Alias ('LS')]
        [ValidateNotNullorEmpty()]
        [object]$InputObject,
        
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [switch]$Async

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PiplineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }
            
        }        

        $_lsobjects   = New-Object System.Collections.ArrayList

    }

    Process 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($InputObject.count) LI objects."

        foreach ($_logicalswitch in $InputObject) 
        {
            
            if (($_logicalswitch -is [PSCustomObject]) -and ($_logicalswitch.category -ieq 'logical-switches')) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Logical Switch Object was provided $($_logicalswitch | out-string)"

                [void]$_lsobjects.Add($_logicalswitch)

            }

            else 
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType $_li.GetType().Name -Message "An invalid Resource object was provided. $($_li.GetType()) $($_li.category) was provided. Only type String or PSCustomObject, and 'logical-interconnects' object category are permitted."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

    }

    End 
    {

        #Loop through liobject collection to perform action
        ForEach ($_ls in $_lsobjects)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Logical Switch: $($_ls.name)"

            if ($PSCmdlet.ShouldProcess($_ls.name,"Refresh Logical Switch"))
            { 

                Try
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to refresh Logical Switch."
                
                    $uri = $_ls.uri + "/refresh"

                    $_reply = Send-HPOVRequest $uri PUT -Hostname $_ls.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($PSBoundParameters['Async'])
                {

                    $_reply

                }

                else
                {

                    $_reply | Wait-HPOVTaskComplete

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {
                
                "[{0}] User included -WhatIf." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] User cancelled." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }
        

        }

    }

}

function Get-HPOVSwitch
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Label')]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Label')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
        
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
        
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_Collection = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            if ($PSBoundParameters['Label'])
            {

                $_uri = '{0}?category:switches&query=labels:{1}' -f $IndexUri, $Label

                Try
                {

                    $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                    #Loop through all found members and get full SVT object
                    ForEach ($_memeber in $_IndexMembers.members)
                    {

                        Try
                        {

                            $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                        

                        $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.Networking.Switch')    

                        [void]$_Collection.Add($_memeber) 

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                $Uri = $SwitchesUri

                if ($PSBoundParameters['Scope'])
                {

                    "[{0}] Processing Scope: {1}, index lookup" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Scope.Name | Write-Verbose

                    $Uri = "{0}?category=switches&sort=name:asc&query=scope:'{1}'" -f $IndexUri, $Scope.Name

                }

                Try
                {

                    $_Switches = Send-HPOVRequest -Uri $Uri -Hostname $_appliance.Name

                    if ('IndexPaginatedCollection' -match $_Switches.type)
                    {

                        $_SwitchesIndex = $_Switches.PSObject.Copy()
                        $_Switches.members = New-Object System.Collections.ArrayList

                        ForEach ($_indexsw in $_SwitchesIndex.members)
                        {

                             $_switch = Send-HPOVRequest -Uri $_indexsw.uri -Hostname $_appliance.Name
                             [void]$_Switches.members.Add($_switch)

                        }

                    }

                }

                Catch
                {

                    "[{0}] API Error Caught {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_.Exception.Message | Write-Verbose

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($PSboundParameters['Name']) 
                {

                    "[{0}] Switch name provided: '{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose

                    if ($Name.Contains('*'))
                    {

                        [Array]$_Switches.members = $_Switches.members | ? name -Match $Name

                    }

                    else
                    {

                        [Array]$_Switches.members = $_Switches.members | ? name -Eq $Name

                    }

                }

                if ($_Switches.members.count -eq 0) 
                { 

                    "[{0}] No Switch resources found on {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

                }

                else 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($_Switches.count) Switch resource(s)."
        
                    $_Switches.members | % { 
        
                        $_.PSObject.TypeNames.Insert(0,'HPOneView.Networking.Switch')    

                        [void]$_Collection.Add($_) 
        
                    }

                }

            }

        }

    }

    End 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. $($_Collection.count) switch(es) found."
        
        if ($_Collection.count -eq 0 -and $Name) 
        { 

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Switch '$Name' resource not found. Generating error"

            $ErrorRecord = New-ErrorRecord InvalidOperationException SwitchNotFound ObjectNotFound 'Name' -Message "Specified Switch '$Name' was not found on any appliance connection. Please check the name and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

        }       

        if ($exportFile)
        {
            
            $_Collection | convertto-json -Depth 99 | Set-Content -Path $exportFile -force -encoding UTF8 
        
        }
                
        else 
        {
            
            Return $_Collection | Sort name
        
        }

    }

}

#######################################################
# Image Streamer
#

function Get-HPOVImageStreamerAppliance
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = ($ConnectedSessions | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(),($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not($ConnectedSessions))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Try
                {

                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException]
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try
            {

                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException]
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ImageStreamerCollection = New-Object System.Collections.ArrayList

    }

    Process
    {

        $_uri = $AvailableDeploymentServersUri

        if ($Name)
        {

            $_uri = "{0}?filter=name matches '{1}'" -f $_uri, $Name.Replace('*','%25').Replace('?','%26')

        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of $($ApplianceConnection.Count))" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            If ($_appliance.ApplianceType -ne 'Composer')
            {

                $ExceptionMessage = 'The ApplianceConnection {0} ({1}) is not a Synergy Composer. This Cmdlet only support Synergy Composer management appliances.' -f $_appliance.Name, $_appliance.ApplianceType
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                Try
                {

                    $_CollectionResults = Send-HPOVRequest -uri $_uri -Hostname $_appliance.Name            

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($Name -and -not $_CollectionResults.members)
                {

                    $ExceptionMessage = 'Image Streamer Appliance "{0}" was not found on "{1}" appliance connection.' -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ImageStreamerResourceException ResourceNotFound ObjectNotFound "Name" -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                else
                {

                    $_CollectionResults.members | % {

                        $_.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.ImageStreamerAppliance')
                    
                        $_

                    }

                }

            }
            
        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVOSDeploymentServer
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = ($ConnectedSessions | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(),($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not($ConnectedSessions))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Try
                {

                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException]
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try
            {

                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException]
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process
    {

        $_uri = $DeploymentServersUri

        if ($Name)
        {

            if ($Name.Contains('*'))
            {

                $Name = $Name.Replace("*","%25").Replace("&","%26")

            }

            $_uri = '{0}?filter=name matches "{1}"' -f $_uri, $Name

        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            If ($_appliance.ApplianceType -ne 'Composer')
            {

                $ExceptionMessage = 'The ApplianceConnection {0} ({1}) is not a Synergy Composer. This Cmdlet only support Synergy Composer management appliances.' -f $_appliance.Name, $_appliance.ApplianceType
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                if ($PSBoundParameters['Label'])
                {

                    $_uri = '{0}?category:deployment-servers&query=labels:{1}' -f $IndexUri, $Label

                    Try
                    {

                        "[{0}] Getting OS Deployment Servers from Index for Label lookup" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                        #Loop through all found members and get full SVT object
                        ForEach ($_memeber in $_IndexMembers.members)
                        {

                            Try
                            {

                                $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }                        

                            $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.OSDeploymentServer')

                            $_memeber

                        }

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                else
                {

                    "[{0}] Getting OS Deployment servers from primary URI" -f $MyInvocation.InvocationName.ToString().ToUpper()| Write-Verbose

                    Try
                    {

                        $_CollectionResults = Send-HPOVRequest -uri $_uri -Hostname $_appliance.Name            

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    if ($Name -and -not $_CollectionResults.members)
                    {

                        $ExceptionMessage = 'OS Deployment Server "{0}" was not found on "{1}" appliance connection.' -f $Name, $_appliance.Name
                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ImageStreamerResourceException ResourceNotFound ObjectNotFound "Name" -Message $ExceptionMessage
                        $PSCmdlet.WriteError($ErrorRecord)

                    }

                    else
                    {

                        ForEach ($_DeploymentServer in $_CollectionResults.members)
                        {
                            
                            $_DeploymentServer.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.OSDeploymentServer')

                            $_DeploymentServer

                        }

                    }

                }

            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function New-HPOVOSDeploymentServer
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [string]$Description,

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [Alias ('ImageStreamer','I3S')]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$ManagementNetwork,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = ($ConnectedSessions | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(),($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not($ConnectedSessions))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
                {

                    Try
                    {

                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException]
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try
                {

                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException]
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process
    {

        if ($PipelineInput)
        {

            $ApplianceConnection = $ConnectedSessions | ? Name -eq $ApplianceConnection.Name

        }

        If ($ApplianceConnection.ApplianceType -ne 'Composer')
        {

            $ExceptionMessage = 'The ApplianceConnection {0} ({1}) is not a Synergy Composer. This Cmdlet only support Synergy Composer management appliances.' -f $ApplianceConnection.Name, $ApplianceConnection.ApplianceType
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Validate the Management Network resource
        if ($ManagementNetwork -is [String])
        {

            "[{0}] ManagementNetwork Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ManagementNetwork | Write-Verbose

            Try
            {

                $ManagementNetwork = Get-HPOVNetwork -Name $ManagementNetwork -Type Ethernet -ApplianceConnection $ApplianceConnection -ErrorAction Stop

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Validation rules
        if ($ManagementNetwork.category -ne 'ethernet-networks')
        {

            "[{0}] Unsupported Network: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ManagementNetwork.name | Write-Verbose

            $ExceptionMessage = 'The ManagementNetwork {0} is not a valid "ethernet-network".' -f $ManagementNetwork.name
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ImageStreamerManagementNetworkException UnsupportedNetwork InvalidArgument 'ManagementNetwork' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
        }

        if ([System.String]::IsNullOrWhiteSpace($ManagementNetwork.subnetUri))
        {

            $ExceptionMessage = 'The ManagementNetwork {0} resource is not assigned to a valid IPv4 Address Pool.' -f $ManagementNetwork.name
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ImageStreamerManagementNetworkException UnsupportedEthernetNetwork InvalidArgument 'ManagementNetwork' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Get Subnet resource
        Try
        {

            $_ManagementNetworkSubnet = Send-HPOVRequest -Uri $ManagementNetwork.subnetUri -Hostname $ApplianceConnection
            $_ApplianceNetwork        = Send-HPOVRequest -uri $ApplianceNetworkConfigUri -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($_ManagementNetworkSubnet.subnetMask -ne $_ApplianceNetwork.applianceNetworks.ipv4Subnet)
        {

            $ExceptionMessage = 'The ManagementNetwork "{0}" resource Subnet Mask "{1}" does not match the appliance Subnet Mask "{2}".' -f $ManagementNetwork.name, $_ManagementNetworkSubnet.subnetMask, $_ApplianceNetwork.applianceNetworks.ipv4Subnet
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ImageStreamerManagementNetworkException UnsupportedEthernetNetwork InvalidArgument 'ManagementNetwork' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if (-not [HPOneView.Appliance.AddressPool]::IsInSameSubnet($_ManagementNetworkSubnet.networkId, $_ApplianceNetwork.applianceNetworks.virtIpv4Addr, $_ApplianceNetwork.applianceNetworks.ipv4Subnet))
        {

            $ExceptionMessage = "The ManagementNetwork's associated IPv4 Subnet {0} is not local to the appliance. ImageStreamer requires the IPv4 Subnet be on the same NetworkID as the appliance." -f $_ManagementNetworkSubnet.name
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ImageStreamerManagementNetworkException UnsupportedEthernetNetwork InvalidArgument 'ManagementNetwork' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Validate InputObject
        if (-not $InputObject.uri.StartsWith($AvailableDeploymentServersUri))
        {

            $ExceptionMessage = 'The InputObject is not a valid ImageStreamer resource.' -f $InputObject.name
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ImageStreamerManagementNetworkException InvalidInputObject InvalidArgument 'InputObject' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_AddI3S = NewObject -I3SAdd

        $_AddI3S.description    = $Description
        $_AddI3S.name           = $Name
        $_AddI3S.mgmtNetworkUri = $ManagementNetwork.uri
        $_AddI3S.applianceUri   = $InputObject.uri

        Try
        {

            $_Results = Send-HPOVRequest -Uri $DeploymentServersUri -Method POST -Body $_AddI3S -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not $PSBoundParameters['Async'])
        {

            $_Results | Wait-HPOVTaskComplete

        }

        else
        {

            $_Results

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVOSDeploymentServer
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Switch]$Force,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = ($ConnectedSessions | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(),($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not($ConnectedSessions))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
                {

                    Try
                    {

                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException]
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try
                {

                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException]
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process
    {

        if ($PipelineInput)
        {

            $ApplianceConnection = $ConnectedSessions | ? Name -eq $ApplianceConnection.Name

        }

        If ($ApplianceConnection.ApplianceType -ne 'Composer')
        {

            $ExceptionMessage = 'The ApplianceConnection {0} ({1}) is not a Synergy Composer. This Cmdlet only support Synergy Composer management appliances.' -f $ApplianceConnection.Name, $ApplianceConnection.ApplianceType
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Validate InputObject
        if ($InputObject.category -ne 'deployment-managers')
        {

            $ExceptionMessage = 'The InputObject is not a valid OS Deployment Server resource.' -f $InputObject.name
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ImageStreamerManagementNetworkException InvalidInputObject InvalidArgument 'InputObject' -Message $ExceptionMessage
            $PSCmdlet.WriteError($ErrorRecord)

        }

        elseif ($PSCmdlet.ShouldProcess($InputObject.ApplianceConnection.Name, ("Remove OS Deployment Server from appliance '{0}'" -f $InputObject.name))) 
        {

            "[{0}] Remove OS Deployment Server '{1}' from appliance '{2}'." -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name, $InputObject.ApplianceConnection.Name | Write-Verbose

            $Uri = $InputObject.Uri

            if ($Force)
            {

                $Uri += '?force=true'

            }

            Try
            {

                $_resp = Send-HPOVRequest -Uri $Uri -Method DELETE -Hostname $InputObject.ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if (-not $PSBoundParameters['Async'])
            {

                $_resp | Wait-HPOVTaskComplete

            }

            else
            {

                $_resp

            }

        }

        elseif ($PSBoundParameters['WhatIf'])
        {

            "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVOSDeploymentPlan
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = ($ConnectedSessions | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(),($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not($ConnectedSessions))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Try
                {

                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException]
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try
            {

                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException]
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_OSDeploymentPlanCollection = New-Object System.Collections.ArrayList

    }

    Process
    {

        $_uri = $DeploymentPlansUri

        <#if ($Name)
        {
 
            if ($Name.Contains('*'))
            {
 
                $Name = $Name.Replace("*","%25").Replace("&","%26")
 
            }
 
            $_uri = '{0}?filter=name matches "{1}"' -f $_uri, $Name
 
        }#>


        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of $($ApplianceConnection.Count))" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            If ($_appliance.ApplianceType -ne 'Composer')
            {

                $ExceptionMessage = 'The ApplianceConnection {0} ({1}) is not a Synergy Composer. This Cmdlet only support Synergy Composer management appliances.' -f $_appliance.Name, $_appliance.ApplianceType
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
                $PSCmdlet.WriteError($ErrorRecord)

            }

            else
            {

                Try
                {

                    $_CollectionResults = Send-HPOVRequest -Uri $_uri -Hostname $_appliance.Name            

                    if ($Name)
                    {

                        $_CollectionResults.members = $_CollectionResults.members | ? name -like $Name

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($Name -and -not $_CollectionResults.members)
                {

                    $ExceptionMessage = 'OS Deployment Plan "{0}" was not found on "{1}" appliance connection.' -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ImageStreamerResourceException ResourceNotFound ObjectNotFound "Name" -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                $_CollectionResults.members | % {
                    
                    $_.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.OSDeploymentPlan')

                    [void]$_OSDeploymentPlanCollection.Add($_)

                }

            }            

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        Return $_OSDeploymentPlanCollection

    }

}

function Get-HPOVOSDeploymentPlanAttribute
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = ($ConnectedSessions | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(),($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject'])
        {

            $PipelineInput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not($ConnectedSessions))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
                {

                    Try
                    {

                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException]
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try
                {

                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException]
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_PlanAttributesCol = New-Object System.Collections.ArrayList

    }

    Process
    {

        if ($PipelineInput)
        {

            $ApplianceConnection = $ConnectedSessions | ? Name -eq $ApplianceConnection.Name

        }

        If ($ApplianceConnection.ApplianceType -ne 'Composer')
        {

            $ExceptionMessage = 'The ApplianceConnection {0} ({1}) is not a Synergy Composer. This Cmdlet only support Synergy Composer management appliances.' -f $ApplianceConnection.Name, $ApplianceConnection.ApplianceType
            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_OSDeploymentSettingsCollection = New-Object 'HPOneView.ServerProfile.OSDeployment.OsDeploymentPlanParametersCollection[HPOneView.ServerProfile.OSDeployment.OSDeploymentParameter]'

        if ($InputObject.category -eq 'server-profile-templates')
        {

            # Process the osDeploymentSettings.osCustomAttributes for plan attributs to return

            ForEach ($_SptDeploymentPlanAttribute in $InputObject.osDeploymentSettings.osCustomAttributes)
            {

                '[{0}] Add {1} = {2} into OsCustomAttributesCollection' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_SptDeploymentPlanAttribute.name, $_SptDeploymentPlanAttribute.value | Write-Verbose

                $_PlanAttribute = New-Object HPOneView.ServerProfile.OSDeployment.OSDeploymentParameter ($_SptDeploymentPlanAttribute.name, $_SptDeploymentPlanAttribute.value)

                [void]$_OSDeploymentSettingsCollection.Add($_PlanAttribute)

            }

        }

        elseif ($InputObject.category -eq 'os-deployment-plans')
        {

            $ExpectedParamForNic = @{
                connectionid = $null;
                dhcp         = $False;
                ipv4disable  = $False;
                networkuri   = $null;
                constraint   = "auto"
            }

            #Build initial collection of Build Plan Parameters
            ForEach ($_PlanAttribute in $InputObject.additionalParameters)
            {

                '[{0}] Attribute name: {1}, type: {2}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_PlanAttribute.name, $_PlanAttribute.caType | Write-Verbose

                if ($_PlanAttribute.caType -eq 'nic')
                {

                    ForEach ($AdditionalNicParam in ($ExpectedParamForNic.GetEnumerator() | Sort keys ))
                    {

                        $_ParameterName = '{0}.{1}' -f $_PlanAttribute.name, $AdditionalNicParam.key

                        '[{0}] Add "{1}" NIC "{2}" = "{3}" into OsCustomAttributesCollection' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_PlanAttribute.name, $_ParameterName, $AdditionalNicParam.value | Write-Verbose                    

                        $_Attribute = New-Object HPOneView.ServerProfile.OSDeployment.OSDeploymentParameter($_ParameterName, $AdditionalNicParam.value)

                        [void]$_OSDeploymentSettingsCollection.Add($_Attribute)

                    }

                }

                if ([System.Convert]::ToBoolean($_PlanAttribute.caEditable) -and $_PlanAttribute.caType -ne 'nic')
                {

                    '[{0}] Add {1} = {2} into OsCustomAttributesCollection' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_PlanAttribute.name, $_PlanAttribute.value | Write-Verbose

                    $_PlanAttribute = New-Object HPOneView.ServerProfile.OSDeployment.OSDeploymentParameter ($_PlanAttribute.name, $_PlanAttribute.value)

                    [void]$_OSDeploymentSettingsCollection.Add($_PlanAttribute)

                }

            }
        }

        $_OSDeploymentSettingsCollection

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

#######################################################
# Server Profiles:
#

function Get-HPOVServerProfile 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "Detailed")]
        [Parameter (Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "Export")]
        [Alias ('profile')]
        [string]$Name,

        [Parameter (Mandatory, ValueFromPipeline = $false, ParameterSetName = "Detailed")]
        [switch]$Detailed,

        [Parameter (Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "Default")]
        [switch]$NonCompliant,

        [Parameter (Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "Export")]
        [switch]$Unassigned,

        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = "Export")]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "Detailed")]
        [Parameter (Mandatory = $false, ParameterSetName = "Export")]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (Mandatory = $false, ParameterSetName = "Default", ValueFromPipelinebyPropertyName)]
        [Parameter (Mandatory = $false, ParameterSetName = "Detailed", ValueFromPipelinebyPropertyName)]
        [Parameter (Mandatory = $false, ParameterSetName = "Export", ValueFromPipelinebyPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),
        
        [Parameter (Mandatory, ValueFromPipeline = $false, ParameterSetName = "Export")]
        [Alias ("x")]
        [switch]$export,

        [Parameter (Mandatory, ValueFromPipeline = $false, ParameterSetName = "Export")]
        [ValidateNotNullOrEmpty()]
        [Alias ("save")]
        [string]$location

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #Validate the path exists. If not, create it.
        if (($Export) -and (-not(Test-Path $Location)))
        { 
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Directory does not exist. Creating directory..."
            
            New-Item -path $Location -ItemType Directory
        
        }

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $ProfileCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        ForEach ($_appliance in $ApplianceConnection)
        {

            $_ServerProfileFromHardwareFlag = $false

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            if ($PSBoundParameters['Label'])
            {

                $_uri = '{0}?category:server-profiles&query=labels:{1}' -f $IndexUri, $Label

                Try
                {

                    $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                    #Loop through all found members and get full SVT object
                    ForEach ($_memeber in $_IndexMembers.members)
                    {

                        Try
                        {

                            $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                        

                        $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.ServerProfile')
                        
                        [void]$ProfileCollection.Add($_memeber)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                $uri = '{0}?sort=name:asc' -f $ServerProfilesUri

                if ($PSBoundParameters['Name']) 
                { 
                    
                    "[{0}] Received name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose

                    $uri += "&filter=name matches '{0}'" -f $Name.Replace("*","%25").Replace("&","%26")
                    
                }

                if ($PSBoundParameters['NonCompliant'])
                {

                    "[{0}] Filtering for non-compliant profiles." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $uri += "&filter=templateCompliance EQ 'NonCompliant'"

                }

                if ($PSBoundParameters['InputObject'])
                {

                    switch ($InputObject.category)
                    {

                        'server-hardware'
                        {

                            if (-not $InputObject.serverProfileUri)
                            {
                            
                                "[{0}] Filtering for Server Hardware Type from Server Hardware: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                                $uri += "&filter=serverHardwareTypeUri EQ '{0}'" -f $InputObject.serverHardwareTypeUri

                            }
                            
                            else
                            {

                                "[{0}] Returning specific Server Profile for {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                                $uri = $InputObject.serverProfileUri.Clone()

                                $_ServerProfileFromHardwareFlag = $true

                            }                            

                        }

                        'server-hardware-types'
                        {

                            "[{0}] Filtering for Server Hardware Type: {1} [{2}]"  -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name, $InputObject.model | Write-Verbose

                            $uri += "&filter=serverHardwareTypeUri EQ '{0}'" -f $InputObject.uri

                        }

                        'server-profile-templates'
                        {

                            "[{0}] Filtering for Server Profile Template: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                            $uri += "&filter=serverProfileTemplateUri EQ '{0}'" -f $InputObject.uri

                        }

                    }

                }

                "[{0}] Sending request"  -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                Try
                {

                    $profiles = Send-HPOVRequest -Uri $uri -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                # Workaround for retreive a single server profile resource that is not otherwise a collection
                if ($_ServerProfileFromHardwareFlag)
                {

                    $profiles = [PSCustomObject]@{members = $profiles.PSObject.Copy()}

                }

                if ($PSBoundParameters['Unassigned']) 
                {

                    $profiles.members = $profiles.members | ? $null -eq serverHardwareUri

                }

                if ($profiles.members.count -eq 0 -and $Name)
                {

                    "[{0}] Profile Resource Name was provided, yet no results were found. Generate Error." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $Exceptionmessage = "The specified Server Profile '{0}' was not found on '{1}' appliance connection. Please check the name again, and try again." -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerProfileResourceNotFound ObjectNotFound "Name" -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                foreach ($_profile in $profiles.members)
                {
                
                    $_profile.PSObject.TypeNames.Insert(0,'HPOneView.ServerProfile')
                        
                    [void]$ProfileCollection.Add($_profile)
                    
                }

            }

        }

    }

    End 
    {

        $ProfileCollection = $ProfileCollection | Sort-Object name

        "Done. {0} server profile resource(s) found." -f $ProfileCollection.count | write-verbose 

        if ($PSBoundParameters['Detailed']) 
        {

            #Display Pertinant Server Profile data in Table format
            $a1 = @{Expression={$_.name};Label="Name"},
                  @{Expression={$profileCache[$serverHardwareTypeUri].name};Label="Server Hardware Type"},
                  @{Expression={ if ($profileCache[$enclosureGroupUri]) {$profileCache[$enclosureGroupUri]}
                                 else { 'N/A' }
                                };Label="Enclosure Group"},
                  @{Expression={    if ($_.serverHardwareUri){ (Send-HPOVRequest $_.serverHardwareUri).name }
                                 else { "Unassigned" }
                                 };Label="Assigned"},
                  @{Expression={
                  
                         switch ($_.affinity) {
                  
                             "Bay" { "Device bay" }
                             "BayAndServer" { "Device bay + Server Hardware" }
                  
                  
                         }
                  
                  };Label="Server Affinity"},
                  @{Expression={$_.state};Label="State"},
                  @{Expression={$_.status};Label="Status"}

            $a2 = @{Expression={$_.bios.manageBios};Label="Manage BIOS";align="Left"},
                  @{Expression={$_.boot.manageBoot};Label="Manage Boot Order";align="Left"},
                  @{Expression={$_.firmware.manageFirmware};Label="Manage Firmware";align="Left"},
                  @{Expression={if ($_.serialNumberType -eq "Virtual") { $_.serialNumber + " (v)" } else { $_.serialNumber + " (p)" }};Label="Serial Number"},
                  @{Expression={if ($_.serialNumberType -eq "Virtual") { $_.uuid + " (v)" } else { $_.uuid + " (p)" }};Label="UUID"}


            #Firmware Details
            $f = @{Expression={
                if ($_.firmware.manageFirmware) {

                    $baseline = Send-HPOVRequest $_.firmware.firmwareBaselineUri
                    "$($baseline.name) version $($baseline.version)"

                }
                else { "none" }
            
            };Label="Firmware Baseline"}

            $c = @{Expression={$_.id};Label="ID";width=2},
                 @{Expression={$_.functionType};Label="Type";width=12},
                 @{Expression={
                   
                   $address = @()
                 
                   #Mac Address
                   if ($_.macType -eq "Virtual" -and $_.mac) { $address += "MAC $($_.mac) (V)" }
                   elseif ($_.macType -eq "Physical" -and $_.mac) { $address += "MAC $($_.mac) (p)" }
                   
                   #WWNN
                   if ($_.wwpnType -eq "Virtual" -and $_.wwnn) { $address += "WWNN $($_.wwnn) (v)"} 
                   elseif ($_.wwpnType -eq "Physical" -and $_.wwnn) { $address += "WWNN $($_.wwnn) (p)" }
                   
                   #WWPN
                   if ($_.wwpnType -eq "Virtual" -and $_.wwpn) { $address += "WWPN $($_.wwpn) (v)"} 
                   elseif ($_.wwpnType -eq "Physical" -and $_.wwpn) { $address += "WWPN $($_.wwpn) (p)" }

                   $addressCol = $address | Out-String | % { $_ -replace '^\s+|\s+$' }
                   $addressCol
                   
                 };Label="Address";width=32},
                 @{Expression={$profileCache[$_.networkUri]};Label="Network"},
                 @{Expression={$_.portId};Label="Port Id";width=10},
                 @{Expression={[string]$_.requestedMbps};Label="Requested BW";width=12},
                 @{Expression={[string]$_.maximumMbps};Label="Maximum BW";width=10},
                 @{Expression={
                 
                      $bootSetting = @()
                      $bootSetting += $_.boot.priority
                      if ($_.boot.targets) {
                 
                           for ($i=0; $i -eq $boot.targets.count; $i++) { $bootSetting += "WWN $($_.boot.targets[$i].arrayWwpn)`nLUN $($_.boot.targets[$i].lun)" }
                 
                      }
                      $bootSettingString = $bootSetting | Out-String | % { $_ -replace '^\s+|\s+$' }
                      $bootSettingString
                 
                   
                  };Label="Boot";width=20},
                 @{Expression={
                 
                    if ($_.functionType -eq "FibreChannel" -and -not ($_.boot.targets)) { "Yes" } 
                    elseif ($_.functionType -eq "FibreChannel" -and $_.boot.targets) { "No" }
                    else { $Null }
                 
                  };Label="Use Boot BIOS";width=13}
                               
            #Display extEnded BIOS settings
            $b = @{Expression={$_.category};Label="BIOS Category"},
                 @{Expression={$_.settingName};Label="Setting Name"},
                 @{Expression={$_.valueName};Label="Configured Value"}

            $ls = @{Expression={$_.localStorage.manageLocalStorage};Label="Manage Local Storage";align="Left"},
                  @{Expression={$_.localStorage.initialize};Label="Initialize Disk";align="Left"},
                  @{Expression={
                  
                        $logicalDriveCol = @()
                        $d=0

                        while ($d -lt $sp.localStorage.logicalDrives.count) 
                        {

                            if ($_.localStorage.logicalDrives[$d].bootable) { $logicalDriveCol += "Drive {$d} $($sp.localStorage.logicalDrives[$d].raidLevel) (Bootable)" }
                            else { $logicalDriveCol += "Drive {$d} $($sp.localStorage.logicalDrives[$d].raidLevel)" }
                            $d++
                        }

                        $logicalDriveString = $logicalDriveCol | Out-String | % { $_ -replace '^\s+|\s+$' }
                        $logicalDriveString
                    
                   };Label="Logical Disk"}

            $ss = @{Expression={$_.manageSanStorage};Label="Manage SAN Storage";align="Left"},
                  @{Expression={$_.hostOSType};Label="Host OS Type";align="Left"}

            $p = @{Expression={[int]$_.connectionId};Label="Connection ID";align="Left"},
                 @{Expression={[string]$_.network};Label="Fabric";align="Left"},
                 @{Expression={[string]$_.initiator};Label="Initiator";align="Left"},
                 @{Expression={[string]$_.target};Label="Target";align="Left"},
                 @{Expression={[bool]$_.isEnabled};Label="Enabled";align="Left"}

            #Server Profile cache
            $profileCache = @{}
            
            #loop through all Server Profile objects and display details
            ForEach ($profile in ($ProfileCollection | sort-object -property name)) 
            {

                $serverHardwareTypeUri = $profile.serverHardwareTypeUri
                $enclosureGroupUri = $profile.enclosureGroupUri

                #Cache resources during runtime to reduce API calls to appliance.
                if (-not ($profileCache[$serverHardwareTypeUri])) 
                { 
                    $profileCache.Add($serverHardwareTypeUri,(Send-HPOVRequest $serverHardwareTypeUri -appliance $profile.ApplianceConnection.name)) 
                }
                if (-not ($profileCache[$enclosureGroupUri]) -and $profile.enclosureGroupUri) 
                { 
                    $profileCache.Add($enclosureGroupUri,(Send-HPOVRequest $enclosureGroupUri -appliance $profile.ApplianceConnection.name).name) 
                }
                foreach ($connection in $profile.connections) 
                {
                
                    $connection | % { $_.psobject.typenames.Insert(0,"HPOneView.Profile.Connection") }

                    if (-not ($profileCache[$connection.networkUri])) { $profileCache.Add($connection.networkUri,(Send-HPOVRequest $connection.networkUri -appliance $profile.ApplianceConnection.name ).name) } 
                
                }

                foreach ($volume in $profile.sanStorage.volumeAttachments)
                 {

                    #insert HPOneView.Profile.SanVolume TypeName
                    $volume | % { $_.psobject.typenames.Insert(0,"HPOneView.Profile.SanVolume") }
    
                    #Cache Storage System, Storage Pool and Storage Volume Resources
                    if (-not ($profileCache[$volume.volumeStorageSystemUri])) { $profileCache.Add($volume.volumeStorageSystemUri,(Send-HPOVRequest $volume.volumeStorageSystemUri $profile.ApplianceConnection.name)) }
                    if (-not ($profileCache[$volume.volumeStoragePoolUri])) { $profileCache.Add($volume.volumeStoragePoolUri,(Send-HPOVRequest $volume.volumeStoragePoolUri $profile.ApplianceConnection.name)) }
                    if (-not ($profileCache[$volume.volumeUri])) { $profileCache.Add($volume.volumeUri,(Send-HPOVRequest $volume.volumeUri $profile.ApplianceConnection.name)) }

                }

                #$profileCache

                #Initial Server Profile information
                $profile | format-table $a1 -AutoSize -wrap
                $profile | format-table $a2 -AutoSize -wrap

                #Firmware Baseline
                $profile | format-table $f

                #Server Profile Connection details
                $profile.connections | format-table -wrap
                
                #Local Storage
                $profile | format-table $ls -wrap -auto

                #SAN Storage
                $profile.sanStorage | Format-Table $ss -auto
                #$profile.sanStorage.volumeAttachments | format-table -auto

                $profile.sanStorage.volumeAttachments | % {

                    $_ | format-table -auto

                    $pathConnectionCol = @()

                    foreach ($path in $_.storagePaths) 
                    {

                        $pathObject = [PSCustomObject]@{
                            connectionId = $Null; 
                            network      = $Null; 
                            initiator    = $Null; 
                            target       = $Null; 
                            isEnabled    = $Null
                        }

                        $pathConnection = $profile.connections | where { $path.connectionId -eq $_.id }

                        $pathObject.connectionId = $pathConnection.id
                        $pathObject.network      = $profileCache[$pathConnection.networkUri]
                        $pathObject.initiator    = $pathConnection.wwpn
                        $pathObject.target       = if ($path.storageTargets) { $path.storageTargets }
                                                   else { "PEnding" }
                        $pathObject.isEnabled    = [bool]$path.isEnabled
                        $pathConnectionCol += $pathObject

                    }

                    #
                    #Display path details with a left padded view. Format-Table doesn't have the ability to pad the display
                    $capture = ($pathConnectionCol | sort connectionId | format-table $p -AutoSize -wrap | out-string) -split "`n"
                    $capture | % { ($_).PadLeft($_.length + 5) }

                }

                #Boot Order
                $bootOrder = @()
                if ($profile.boot.manageBoot) 
                {

                    $i = 0
                    while ($i -lt $profile.boot.order.count) 
                    {
                        $bootOrder += "$($i+1) $($profile.boot.order[$i])"
                        $i++
                    }
                    write-host "Boot Order"
                    write-host "----------"
                    $bootOrder

                }
                else 
                { 
                    "No Boot Management" 
                }

                #Display configured BIOS Settings from profile
                $configedBiosSettings = @()

                foreach ($setting in $profile.bios.overriddenSettings) 
                {

                    $shtBiosSettingDetails = $profileCache[$serverHardwareTypeUri].biosSettings | ? { $setting.id -eq $_.id }

                    $biosSetting = [PSCustomObject]@{

                        Category = $shtBiosSettingDetails.category;
                        settingName = $shtBiosSettingDetails.name;
                        valueName = ($shtBiosSettingDetails.options | ? { $_.id -eq $setting.value } ).name;

                    }

                    $configedBiosSettings += $biosSetting
                
                }            
            
                $configedBiosSettings | sort category,settingName | format-list $b

                "----------------------------------------------------------------------"
            
            }

        }

        #If user wants to export the profile configuration
        elseif ($export) 
        {

            #Get the unique applianceConnection.name properties from the profile collection for grouping the output files
            $ProfileGroupings = $ProfileCollection.ApplianceConnection.name | Select -Unique

            ForEach ($pg in $ProfileGroupings)
            {
                
                $outputProfiles = New-Object System.Collections.ArrayList

                $profiles = $ProfileCollection | ? {$_.ApplianceConnection.Name -eq $pg}

                #Loop through all profiles
                foreach ($profile in $profiles) 
                {

                    #trim out appliance unique properties

                    $_profile = $profile | select-object -Property * -excludeproperty uri,etag,created,modified,status,state,inprogress,enclosureUri,enclosureBay,serverHardwareUri,taskUri,ApplianceConnection
                    $_profile.serialNumberType = "UserDefined"

                    #Loop through the connections to save the assigned address
                    $i = 0
                    foreach ($connection in $profile.connections) 
                    {

                        if ($profile.connections[$i].mac) { $_profile.connections[$i].macType = "UserDefined" }
                        if ($profile.connections[$i].wwpn) { $_profile.connections[$i].wwpnType = "UserDefined" }
                        $i++

                    }

                    [void]$outputProfiles.Add($_profile)
                    
                }

                #save profile to JSON file
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Saving $($_profile.name) to $($location)\$($_profile.name).json"

                convertto-json -InputObject $outputProfiles -depth 99 | new-item "$location\$pg`_$($_profile.name).json" -itemtype file

            }

        }

        else 
        {

            Return $ProfileCollection

        }

    }

}

function New-HPOVServerProfile 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory, ParameterSetName = "SPT")]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory, ParameterSetName = "SPT")]
        [ValidateSet ("Bay", "Server", "Unassigned")]
        [Alias ('assign')]
        [string]$AssignmentType,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [ValidateNotNullOrEmpty()]
        [object]$Enclosure,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [ValidateRange(1,16)]
        [Alias ('bay')]
        [int32]$EnclosureBay,

        [Parameter (Mandatory = $false, valuefrompipeline, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, valuefrompipeline, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, valuefrompipeline, ParameterSetName = "SPT")]
        [ValidateNotNullOrEmpty()]
        [object]$Server,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")] 
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [string]$Description,

        [Parameter (Mandatory, ParameterSetName = "SPT")]
        [Object]$ServerProfileTemplate,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [ValidateNotNullOrEmpty()]
        [array]$Connections,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [Alias ('eg')]
        [object]$EnclosureGroup,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [Alias ('sht')]
        [object]$ServerHardwareType,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [switch]$Firmware,
    
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [object]$Baseline,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [Alias ('FirmwareMode')]
        [ValidateSet ('FirmwareOnly', 'FirmwareAndSoftware', 'FirmwareOffline', 'FirmwareAndOSDrivers', 'FirmwareOnlyOfflineMode')]
        [string]$FirmwareInstallMode = 'FirmwareAndSoftware',

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [ValidateSet ('Immediate', 'Scheduled', 'NotScheduled')]
        [string]$FirmwareActivationMode = 'Immediate',

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [ValidateNotNullOrEmpty()]
        [DateTime]$FirmwareActivateDateTime,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [switch]$ForceInstallFirmware,
    
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [switch]$Bios = $false,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [array]$BiosSettings = @(),
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]        
        [ValidateSet ("UEFI","UEFIOptimized","BIOS",'Unmanaged', IgnoreCase = $False)]
        [string]$BootMode = "BIOS",

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]        
        [ValidateSet ("Auto","IPv4","IPv6","IPv4ThenIPv6","IPv6ThenIPv4", IgnoreCase = $False)]
        [string]$PxeBootPolicy = "Auto",

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [Alias ('boot')]
        [switch]$ManageBoot,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [array]$BootOrder,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [switch]$LocalStorage,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Alias ('LogicalDisk')]
        [ValidateNotNullorEmpty()]
        [Object]$StorageController,

        [Parameter (Mandatory, ParameterSetName = "SANStorageAttach")]
        [switch]$SANStorage,

        [Parameter (Mandatory, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ('CitrixXen','AIX','IBMVIO','RHEL4','RHEL3','RHEL','RHEV','VMware','Win2k3','Win2k8','Win2k12','OpenVMS','Egenera','Exanet','Solaris9','Solaris10','Solaris11','ONTAP','OEL','HPUX11iv1','HPUX11iv2','HPUX11iv3','SUSE','SUSE9','Inform', IgnoreCase=$true)]
        [Alias ('OS')]
        [string]$HostOStype,

        [Parameter (Mandatory, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullorEmpty()]
        [object]$StorageVolume,

        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Alias ('Even')]
        [switch]$EvenPathDisabled,

        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Alias ('Odd')]
        [switch]$OddPathDisabled,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ("Bay","BayAndServer", IgnoreCase = $false)]
        [string]$Affinity = "Bay",
    
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ("Virtual", "Physical", "UserDefined", IgnoreCase)]
        [string]$MacAssignment = "Virtual",

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ("Virtual", "Physical", "'UserDefined", IgnoreCase)]
        [string]$WwnAssignment = "Virtual",

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ("Virtual", "Physical", "UserDefined", IgnoreCase)]
        [string]$SnAssignment = "Virtual",

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [string]$SerialNumber,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [string]$Uuid,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [bool]$HideUnusedFlexNics = $True,

        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPTEmptyBay")]
        [ValidateNotNullOrEmpty()]
        [Array]$IscsiIPv4Address,

        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [ValidateScript ({
            
            [RegEx]::Match($_,$iQNPattern).Success
            
            })]
        [string]$ISCSIInitatorName,

        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [ValidateNotNullOrEmpty()]
        [SecureString]$ChapSecret,

        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [ValidateNotNullOrEmpty()]
        [SecureString]$MutualChapSecret,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [Object]$OSDeploymentPlan,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [Array]$OSDeploymentAttributes,

        [Parameter (Mandatory = $false, ParameterSetName = "Import")]
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Parameter (Mandatory = $false, ParameterSetName = "SPT")]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "SPT")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory, ParameterSetName = "Import")]
        [switch]$Import,
        
        [Parameter (Mandatory, ParameterSetName = "Import", ValueFromPipeline)]
        [ValidateNotNullorEmpty()]
        [Alias ("location","file")]
        [Object]$ProfileObj

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSBoundParameters['Bootable'])
        {

            Write-Warning 'The -Bootable Parameter has been deprecated. In order to configure local storage, please read Help New-HPOVServerProfile and the LocalDisk Parameter.'

        }

        if ($PSBoundParameters['RaidLevel'])
        {

            Write-Warning 'The -RaidLevel Parameter has been deprecated. In order to configure local storage, please read Help New-HPOVServerProfile and the LocalDisk Parameter.'

        }

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        if (-not($PSBoundParameters['ServerProfileTemplate']))
        {

            if ($snAssignment -eq "UserDefined" -and (-not($serialnumber)) -and (-not($uuid))) 
            {
        
                $ErrorRecord = New-ErrorRecord HPOneview.ServerProfileResourceException InvalidArgument InvalidArgument 'snAssignment' -Message "The -snAssignment paramter was set to 'UserDefined', however both -serialnumber and -uuid are Null. You must specify a value for both Parameters."
        
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
        
            }
        
            elseif ($snAssignment -eq "UserDefined" -and $serialnumber -and (-not($uuid))) 
            {
        
                $ErrorRecord = New-ErrorRecord HPOneview.ServerProfileResourceException InvalidArgument InvalidArgument 'uuid' -Message "The -snAssignment paramter was set to 'UserDefined', however -uuid is Null. You must specify a value for both Parameters."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($snAssignment -eq "UserDefined" -and (-not($serialnumber)) -and $uuid) 
            {
            
                $ErrorRecord = New-ErrorRecord HPOneview.ServerProfileResourceException InvalidArgument InvalidArgument 'serialnumber' -Message "The -snAssignment paramter was set to 'UserDefined', however -serialnumber is Null. You must specify a value for both Parameters."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
        
            }

            #Update the error information
            switch ($AssignmentType) 
            { 

                "server" 
                {

                    if (-not($server))
                    {
                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfileResourceException InvalidArgument InvalidArgument 'Server' -Message "The -AssignmentType Parameter is set to 'server', but no server Parameter was supplied."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                "bay" 
                {

                    if (-not($enclosureBay))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfileResourceException InvalidArgument InvalidArgument 'AssignmentType' -Message "The -AssignmentType Parameter is set to 'bay', but no bay Parameter was supplied."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if (-not($enclosure))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfileResourceException InvalidArgument InvalidArgument 'AssignmentType' -Message "The -AssignmentType Parameter is set to 'bay', but no Enclosure Parameter was supplied."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if (-not($ServerHardwareType))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfileResourceException InvalidArgument InvalidArgument 'AssignmentType' -Message "The -AssignmentType Parameter is set to 'bay', but no ServerHardwareType Parameter was supplied."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if ($ApplianceConnection.Count -gt 1)
                    {

                        if($enclosure -is [string] -and $enclosure.StartsWith("/rest"))
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'Enclosure' -Message "Enclosure as URI is not supported for multiple appliance connections."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                }

                "unassigned" 
                {
                
                    #If the profile is not based on a template, the SHT is required
                    if ((-not($PSBoundParameters['Template'])) -and (-not($PSBoundParameters['ServerHardwareType'])))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfileResourceException InvalidArgument InvalidArgument 'ServerHardwareType' -Message "The -AssignmentType Parameter is set to 'unassigned', but no server hardware type was supplied."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if ($PSBoundParameters['Server'])
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfileResourceException InvalidArgument InvalidArgument 'ServerHardwareType' -Message "The -AssignmentType Parameter is set to 'unassigned', and a Server object/name was provided. You cannot both assign and unassign a Server Profile."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

            }

            #Check for URI values in Parameters and validate that only one appliance connection is provided in the call
            if($ApplianceConnection.Count -gt 1)
            {
            
                #SHT
                if($serverHardwareType -is [string] -and $serverHardwareType.StartsWith($script:serverHardwareTypesUri))
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'New-HPOVPropfile' -Message "Server Hardware Type as URI is not supported for multiple appliance connections"
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
                }
            
                if($serverHardwareType -is [string] -and $serverHardwareType.StartsWith("/rest"))
                {
            
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'New-HPOVPropfile' -Message "Server Hardware Type as URI is not supported for multiple appliance connections."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
                }

                #EG
                if(($enclosureGroup -is [string] -and $enclosureGroup.StartsWith("/rest")))
                {
            
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'New-HPOVPropfile' -Message "Enclosure Group as URI is not supported for multiple appliance connections."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
                }

                #Server
                if ($server -is [string] -and $server.StartsWith("/rest")) 
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'New-HPOVPropfile' -Message "Server as URI is not supported for multiple appliance connections."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
                }

                #Baseline
                if (($baseline -is [string]) -and ($baseline.StartsWith('/rest'))) 
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'New-HPOVPropfile' -Message "Baseline as URI is not supported for multiple appliance connections."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
                }

                #import
                if($Import) 
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'New-HPOVPropfile' -Message "Import functionality is not supported for multiple appliance connections."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

        }

        if ($PSBoundParameters['IscsiIPv4Address'])
        {

            $_TmpCollection = New-Object System.Collections.ArrayList

            $IscsiIPv4Address | % { [void]$_TmpCollection.Add($_) }

            $IscsiIPv4Address = $_TmpCollection.Clone()

        }

        if ($AssignmentType -eq 'Server' -and -not $Server)
        {

            $ExcpetionMessage = 'A Server resource object or name must be provided when using the "Server" AssignmentType parameter.'
            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileTemplateResourceException NullServerNotAllowed InvalidArgument 'Server' -Message $ExcpetionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $uri = $ServerProfilesUri

        $colStatus = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        #Import Server Profile JSON to appliance
        if ($PSBoundParameters['Import']) 
        {

            "[{0}] Import server profile" -f $($MyInvocation.InvocationName.ToString().ToUpper()) | Write-Verbose

            if (($ProfileObj -is [System.String]) -and (Test-Path $ProfileObj)) 
            {

                #Recieved file location
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received JSON file as input $($ProfileObj)"
            
                $ServerProfile = (get-content $ProfileObj) -join "`n" | convertfrom-json
                
                #Remove unique values with Select-Object
                $ServerProfile = $ServerProfile | Select-Object * -Exclude uri,created,modified,eTag,ApplianceConnection

            }

            #Input object could be the JSON object, which is type [System.String]
            elseif ($ProfileObj -is [System.String]) 
            {

                "[{0}] Received JSON resource object as input {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($ProfileObj | out-string) | Write-Verbose
                
                $ServerProfile = $ProfileObj -join "`n" | convertfrom-json

            }

            #Input object is PsCustomObject of a Server Profile
            elseif ($ProfileObj -is [PsCustomObject]) 
            {

                "[{0}] Received JSON PsCustomObject as input {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($ProfileObj | out-string) | Write-Verbose

                $ServerProfile = $ProfileObj.PSObject.Copy()

            }

            #Inavlid input type for $ProfileObj and Generate Terminating Error
            else 
            { 

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidImportObject InvalidArgument 'ProfileObj' -Message "Invalid `$Import input object. Please check the object you provided for ProfileObj Parameter and try again"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

        }

        else
        {

            if ($PSBoundParameters['ServerProfileTemplate'])
            {

                #Validate ServerProfileTemplate Parameter value
                switch ($ServerProfileTemplate.GetType().Name)
                {

                    'PSCustomObject'
                    {

                        "[{0}] Recieved PSCustomObject for ServerProfileTemplate." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        "[{0}] Resource Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerProfileTemplate.name  | Write-Verbose

                        "[{0}] Resource Category: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerProfileTemplate.category | Write-Verbose

                        if ($ServerProfileTemplate.category -ne 'server-profile-templates')
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileTemplateResourceException InvalidServerProfileTemplateObject InvalidArgument 'ServerProfileTemplate' -TargetType 'PSObject' -Message "Invalid ServerProfileTemplate input object. The input object category '$($ServerProfileTemplate.category)' is not the expected value 'server-profile-templates'. Please check the value and try again."

                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                    #Validate the String data value
                    'String'
                    {

                        if ($ServerProfileTemplate.StartsWith($ServerProfileTemplatesUri))
                        {

                            "[{0}] Resource URI recieved. Getting resource object from API." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            Try
                            {

                                $ServerProfileTemplate = Send-HPOVRequest -Uri $ServerProfileTemplate -Hostname $ApplianceConnection.Name

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                        }

                        else
                        {

                            "[{0}] Resource Name recieved." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            Try
                            {

                                $ServerProfileTemplate = Get-HPOVServerProfileTemplate -Name $ServerProfileTemplate -ApplianceConnection $ApplianceConnection.Name

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                        }

                    }
                    
                }

                "[{0}] Requesting new Server Profile from API." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                Try
                {

                    $ServerProfile = Send-HPOVRequest -Uri ($ServerProfileTemplate.uri + "/new-profile") -Hostname $ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                $ServerProfile = $ServerProfile | Select * -ExcludeProperty templateCompliance,uri,serialnumber,uuid,taskUri,inProgress,state,status,modified,created,associatedServer,eTag,category

                # If there are existing connections, handle the iSCSI ones for IPAddress and CHAP password
                if ($ServerProfile.connections)
                {

                    #Rebuild Connections into an ArrayList
                    $_TmpConnections = $ServerProfile.connections.Clone()

                    $ServerProfile.connections = New-Object System.Collections.ArrayList

                    ForEach ($_con in $_TmpConnections)
                    {

                        [void]$ServerProfile.connections.Add($_con)

                    }

                    #ForEach ($_conn in $ServerProfile.connections)
                    For ([int]$c = 0; $c -lt $ServerProfile.connections.Count; $c++) 
                    {

                        #Perform Param validation
                        if ($ServerProfile.connections[$c].functionType -eq 'iSCSI')
                        {

                            #iSCSI Connection is Bootable
                            if ($ServerProfile.connections[$c].boot.priority -ne 'NotBootable')
                            {

                                #An IPv4 Address was not provided, generate error
                                if (-not($PSBoundParameters['IscsiIPv4Address']) -and $ApplianceConnection.Type -ne 'Composer')
                                {

                                    $Message     = 'Connection ID {0} is configured for {1}, but the -IscsiIPv4Address Parameter was not provided. Please specify an IPv4Address in your command.' -f $ServerProfile.connections[$c].id , $ServerProfile.connections[$c].boot.priority
                                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException IscsiIPv4AddressParamRequired InvalidArgument 'Connections' -TargetType 'PSObject' -Message $Message
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                                }

                                #This is NOT an error, do don't generate one. Set initiatorNameSource -> UserDefined, and also need to set Profile to
                                if ($PSBoundParameters['ISCSIInitatorName'])
                                {

                                    $ServerProfileTemplate.iscsiInitiatorNameType           = 'UserDefined'
                                    $ServerProfile.connections[$c].boot.initiatorName       = $ISCSIInitatorName
                                    $ServerProfile.connections[$c].boot.initiatorNameSource = 'UserDefined'

                                }

                                switch ($ServerProfile.connections[$c].boot.chapLevel)
                                {

                                    'Chap'
                                    {

                                        if (-not($PSBoundParameters['ChapSecret']))
                                        {

                                            $Message     = 'Connection ID {0} is configured for "CHAP" Authentication, but the -ChapSecret Parameter was not provided.' -f $ServerProfile.connections[$c].id 
                                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException ChapSecretParamRequired InvalidArgument 'Connections' -TargetType 'PSObject' -Message $Message
                                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                                        }

                                        $ServerProfile.connections[$c].boot.chapPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($ChapSecret))

                                    }

                                    'MutualChap'
                                    {

                                        if (-not($PSBoundParameters['ChapSecret']))
                                        {

                                            $Message     = 'Connection ID {0} is configured for "CHAP" Authentication, but the -ChapSecret Parameter was not provided.'
                                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException ChapSecretParamRequired InvalidArgument 'Connections' -TargetType 'PSObject' -Message $Message
                                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                                        }

                                        if (-not($PSBoundParameters['MutualChapSecret']))
                                        {

                                            $Message     = 'Connection ID {0} is configured for "MutualChap" Authentication, but the -MutualChapSecret Parameter was not provided.'
                                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException MutualChapSecretParamRequired InvalidArgument 'Connections' -TargetType 'PSObject' -Message $Messag
                                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                                        }

                                        $ServerProfile.connections[$c].boot.chapSecret       = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($ChapSecret))
                                        $ServerProfile.connections[$c].boot.mutualChapSecret = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($MutualChapSecret))

                                    }

                                }

                                if ($IscsiIPv4Address.count -gt 0)
                                {

                                    "[{0}] Assigning {1} IPv4Address to Connection ID {2}." -f $MyInvocation.InvocationName.ToString().ToUpper(), $IscsiIPv4Address[0], $ServerProfile.connections[$c].id | Write-Verbose

                                    $_IPv4Address = $IscsiIPv4Address[0]

                                    [void]$IscsiIPv4Address.Remove($_IPv4Address)

                                    $ServerProfile.connections[$c].boot.initiatorIp = $_IPv4Address

                                }

                                else
                                {

                                    $Message = 'Connection ID {0} is configured as a Bootable iSCSI Connection, however no additional IPv4Address is available to allocate.' -f $ServerProfile.connections[$c].id
                                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException MutualChapSecretParamRequired InvalidArgument 'Connections' -TargetType 'PSObject' -Message $Messag
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                                }

                            }

                        }

                    }

                }

                else
                {

                    $ServerProfile.connections = New-Object System.Collections.ArrayList

                }

                #Handle firmware differently
                if ($ServerProfile.firmware.manageFirmware -and $ServerProfile.firmware.firmwareActivationType -eq 'Scheduled')
                {

                    $ServerProfile.firmware.forceInstallFirmware = [bool]$ForceInstallFirmware

                    if ($PSBoundParameters['FirmwareInstallMode'])
                    {

                        "[{0}] Overriding SPT Firmware Install Type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerProfileFirmwareControlModeEnum[$FirmwareInstallMode] | Write-Verbose
                        $ServerProfile.firmware.firmwareInstallType = $ServerProfileFirmwareControlModeEnum[$FirmwareInstallMode]
                
                    }

                    if ($PSBoundParameters['FirmwareActivationMode'])
                    {

                        $ServerProfile.firmware.firmwareActivationType = $ServerProfileFirmareActivationModeEnum[$FirmwareActivationMode]

                    }

                    if ('FirmwareOffline', 'FirmwareOnlyOfflineMode' -contains $ServerProfile.firmware.firmwareActivationType -and $PSBoundParameters['FirmwareActivateDateTime'])
                    {

                        $ExceptionMessage = "The Server Profile Template is not configured to schedule firmware activation, and the use of -FirmwareActivationDateTime parameter is not supported. Please choose a different Server Profile Template with Online updates, or overrride using the -FirmwareInstallMode parameter."
                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidFirmwareInstallMode InvalidArgument 'FirmwareActivateDateTime' -TargetType 'Switch' -Message    $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                    }

                    elseif ($ServerProfile.firmware.firmwareActivationType -eq 'Scheduled' -and -not $PSBoundParameters['FirmwareActivateDateTime'])
                    {

                        $ExceptionMessage = "The Server Profile Template provided is set to schedule firmware activation, which requires the -FirmwareActivateDateTime parameter."
                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidFirmwareInstallMode InvalidArgument 'FirmwareActivateDateTime' -TargetType 'Switch' -Message    $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                    }

                    elseif ($ServerProfile.firmware.firmwareActivationType -eq 'Scheduled' -and $PSBoundParameters['FirmwareActivateDateTime'])
                    {

                        #Convert DateTime to UTC time for the appliance
                        "[{0}] Setting firmware activation schedule: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $FirmwareActivateDateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ") | Write-Verbose
                        $ServerProfile.firmware.firmwareScheduleDateTime = $FirmwareActivateDateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")

                    }    

                }

                #Get SHT from Template
                #Get the SHT of the SH that we are going to assign.
                Try
                {

                    $ServerHardwareType = Send-HPOVRequest -Uri $ServerProfile.serverHardwareTypeUri -appliance $ApplianceConnection

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($ServerProfile.enclosureGroupUri)
                {

                    Try
                    {

                        $EnclosureGroup = Send-HPOVRequest -Uri $ServerProfile.enclosureGroupUri -appliance $ApplianceConnection

                    }
                    
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                # Process OSDeploymentAttributes for SP from SPT
                # Do we need to first look at the osDeploymentSettings at all for Constraints?
                if ($PSBoundParameters['OSDeploymentAttributes'])
                {

                    If ($ApplianceConnection.ApplianceType -ne 'Composer')
                    {

                        $ExceptionMessage = 'The ApplianceConnection {0} is not a Synergy Composer. The OSDeploymentAttributes parameter is only supported with HPE Synergy and HPE ImageStreamer.' -f $ApplianceConnection.Name
                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    ForEach ($_PlanAttribute in $ServerProfile.osDeploymentSettings.osCustomAttributes)
                    {

                                    if (($ServerProfile.osDeploymentSettings.osCustomAttributes | ? { $_.Name -match ('{0}.constraint' -f $_PlanAttribute.name)}) -and 'Auto', 'DHCP' -notcontains $_PlanAttribute.value -and -not ($OSDeploymentAttributes | ? name -eq $_PlanAttribute.name))
                        {

                            $ExceptionMessage = 'The attribute {0} requires a value and is not provided in the OSDeploymentAttributes.' -f $_PlanAttribute.name
                            $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.OSDeploymentAttributeResourceException InvalidOperation InvalidArgument 'OSDeploymentAttributes' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                        }

                        '[{0}] Setting {1} attribute to {2}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_PlanAttribute.name, ($OSDeploymentAttributes | ? name -eq $_PlanAttribute.name).value | Write-Verbose

                        ($ServerProfile.osDeploymentSettings.osCustomAttributes | ? name -eq $_PlanAttribute.name).value = ($OSDeploymentAttributes | ? name -eq $_PlanAttribute.name).value

                    }

                }

            }

            else
            {

                "[{0}] Get generic Server Profile object" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                #New Server Resource Object
                $ServerProfile = NewObject -ServerProfile
                
                $ServerProfile.affinity           = $Affinity
                $ServerProfile.hideUnusedFlexNics = [bool]$HideUnusedFlexNics
                $ServerProfile.bios.manageBios    = [bool]$Bios
                $ServerProfile.boot.manageBoot    = $ManageBoot.IsPresent
                $ServerProfile.boot.order         = $BootOrder
                $ServerProfile.serialNumberType   = $SnAssignment 
                $ServerProfile.macType            = $MacAssignment
                $ServerProfile.wwnType            = $WwnAssignment
                $ServerProfile.serialNumber       = $Serialnumber
                $ServerProfile.uuid               = $Uuid

                #Process OSDeploymentPlan
                if ($PSBoundParameters['OSDeploymentPlan'])
                {

                    If ($ApplianceConnection.ApplianceType -ne 'Composer')
                    {

                        $ExceptionMessage = 'The ApplianceConnection {0} is not a Synergy Composer. The OSDeploymentPlan parameter is only supported with HPE Synergy and HPE ImageStreamer.' -f $ApplianceConnection.Name
                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if ($OSDeploymentPlan.type -ne 'Osdp')
                    {

                        $ExceptionMessage = 'The provided OSDeploymentPlan parameter value is not a valid OS Deployment Plan resource.' -f $ApplianceConnection.Name
                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.OSDeploymentPlanResourceException InvalidOperation InvalidArgument 'OSDeploymentPlan' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                        
                    }

                    $_OSDeploymentSettings = NewObject -OSDeploymentSettings
                    $_OSDeploymentSettings.osDeploymentPlanUri = $OSDeploymentPlan.uri

                    ForEach ($_PlanAttribute in $OSDeploymentAttributes)
                    {

                        if ($_PlanAttribute -isnot [HPOneView.ServerProfile.OSDeployment.OSDeploymentParameter])
                        {

                            $ExceptionMessage = 'The provided OSDeploymentAttribute parameter value is not a valid resource.' -f $ApplianceConnection.Name
                            $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.OSDeploymentAttributeResourceException InvalidOperation InvalidArgument 'OSDeploymentAttributes' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }                        

                        $_PlanAttributeSetting = NewObject -OSDeploymentPlanSetting
                        $_PlanAttributeSetting.name  = $_PlanAttribute.name
                        $_PlanAttributeSetting.value = $_PlanAttribute.value

                        '[{0}] Setting {1} attribute to {2}' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_PlanAttribute.name, $_PlanAttribute.value | Write-Verbose

                        [void]$_OSDeploymentSettings.osCustomAttributes.Add($_PlanAttributeSetting)

                    }

                    $ServerProfile | Add-Member -NotePropertyName osDeploymentSettings -NotePropertyValue $null -Force

                    $ServerProfile.osDeploymentSettings = $_OSDeploymentSettings

                }

            }

            if ('Unassigned', 'Bay' -Contains $AssignmentType) 
            {
            
                "[{0}] Profile assignmentType: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $AssignmentType | Write-Verbose 
            
                #Check to see if the serverHardwareType is null, and generate error(s) then break.
                if (-not $ServerHardwareType)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'ServerHardwareType' -Message "Server Hardware Type is missing. Please provide a Server Hardware Type using the -sht Parameter and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }
            
                #If the URI is passed as the Server Hardware Type, then set the serverHardwareTypeUri variable
                If ($ServerHardwareType -is [string])
                {

                    if ($ServerHardwareType.StartsWith($script:serverHardwareTypesUri))
                    { 
                        
                        "[{0}] SHT URI Provided: {1}"  -f $($MyInvocation.InvocationName.ToString().ToUpper()), $ServerHardwareType | Write-Verbose 

                        Try
                        {
                        
                            $ServerHardwareType = Send-HPOVRequest -Uri $ServerHardwareType -appliance $ApplianceConnection
                        
                        }
                        
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }
                
                    #Otherwise, perform a lookup ofthe SHT based on the name
                    else 
                    {

                        "[{0}] SHT Name Provided: {1}"  -f $($MyInvocation.InvocationName.ToString().ToUpper()), $ServerHardwareType | Write-Verbose 

                        Try
                        {

                            $ServerHardwareType = Get-HPOVServerHardwareType -name $ServerHardwareType -ErrorAction Stop -ApplianceConnection $ApplianceConnection

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                }

                #Else the SHT object is passed
                elseif ($ServerHardwareType)
                { 

                    $ServerHardwareType = $ServerHardwareType | ? { $_.ApplianceConnection.name -eq $ApplianceConnection.name }

                    "[{0}] ServerHardwareType object provided" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
                    "[{0}] ServerHardwareType Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerHardwareType.name | Write-Verbose 
                    "[{0}] ServerHardwareType Uri: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerHardwareType.uri | Write-Verbose 
                    
                }

                if (-not($EnclosureGroup) -and (-not($ServerHardwareType.model -match "DL")) -and $AssignmentType -eq 'unassigned')
                {
                        
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidEnclosureGroupObject InvalidArgument 'EnclosureGroup' -Message "Enclosure Group is missing. Please provide an Enclosure Group using the -EnclosureGroup Parameter and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                elseif ($EnclosureGroup -is [string])
                {

                    #If the URI is passed as the Enclosure Group, then set the enclosureGroupUri variable
                    if ($EnclosureGroup.StartsWith('/rest'))
                    { 
                        
                        Try
                        {

                            $EnclosureGroup = Send-HPOVRequest -Uri $EnclosureGroup -appliance $ApplianceConnection

                        }
                        
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
                    
                    }

                    #Otherwise, perform a lookup ofthe Enclosure Group
                    else
                    {

                        Try
                        {

                            $EnclosureGroup = Get-HPOVEnclosureGroup -name $EnclosureGroup -ErrorAction Stop -appliance $ApplianceConnection

                        }
                        
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
                        
                    }

                    "[{0}] EG URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $EnclosureGroup.uri | Write-Verbose

                }
                        
                #Else the EG object is passed
                elseif (($EnclosureGroup -is [Object]) -and ($EnclosureGroup.category -eq "enclosure-groups")) 
                { 

                    $EnclosureGroup = $EnclosureGroup | ? { $ApplianceConnection.name -eq $_.applianceConnection.name }

                    "[{0}] Enclosure Group object provided" -f $MyInvocation.InvocationName.ToString().ToUpper(), $EnclosureGroup.name | Write-Verbose
                    "[{0}] Enclosure Group Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $EnclosureGroup.name | Write-Verbose
                    "[{0}] Enclosure Group Uri: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $EnclosureGroup.uri | Write-Verbose

                }

                elseif (-not $EnclosureGroup -and ($ServerHardwareType.model -match "DL")) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server is a ProLiant DL model. Enclosure Group not required."

                }

                #EG Param not required if assignment is to a bay
                elseif (-not($EnclosureGroup) -and ($AssignmentType -eq 'bay'))
                {

                    #First check for $enclosure Param
                    if (-not($Enclosure))
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidEnclosureObject InvalidArgument 'Enclosure' -Message "Enclosure is missing. Please provide an Enclosure using the -enclosure Parameter and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }
                    
                    #Retrieve the enclosure group uri from passed in enclosure uri Param
                    elseif($Enclosure -is [string]) 
                    {
                        
                        if($Enclosure.StartsWith('/rest'))
                        { 
                                    
                            try 
                            {

                                $Enclosure = Send-HPOVRequest -Uri $Enclosure -appliance $ApplianceConnection

                            }

                            catch 
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidEnclosureGroupObject InvalidArgument 'Enclosure' -Message "Enclosure is missing. Please provide an Enclosure using the -enclosure Parameter and try again."
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                            }

                        }

                        #enclosure is a name
                        else
                        {

                            try 
                            {

                                $Enclosure = Get-HPOVEnclosure -Name $Enclosure -ErrorAction Stop -appliance $ApplianceConnection
                                
                            }

                            catch 
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidEnclosureGroupObject InvalidArgument 'Enclosure' -Message "Enclosure is missing. Please provide an Enclosure using the -enclosure Parameter and try again."
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                        }

                    }

                    elseif ($Enclosure -is [object] -and $Enclosure.category -match 'enclosures')
                    {

                        $Enclosure = $Enclosure | ? { $_.ApplianceConnection.Name -eq $ApplianceConnection.name }

                        "[{0}] Enclosure Group object provided" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                        "[{0}] Enclosure Group Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Enclosure.name | Write-Verbose
                        "[{0}] Enclosure Group Uri: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Enclosure.name | Write-Verbose

                    }

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Name: $($enclosure.uri)"

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Uri: $($enclosure.enclosureGroupUri)"

                    $serverProfile.enclosureUri      = $enclosure.uri
                    $serverProfile.enclosureGroupUri = $enclosure.enclosureGroupUri
                    $serverProfile.enclosureBay      = $EnclosureBay
                            
                } 
        
                else 
                { 

                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidEnclosureGroupObject InvalidArgument 'EnclsoureGroup' -TargetType $EnclosureGroup.GetType().Name -Message "Enclosure Group is invalid. Please specify a correct Enclosure Group name, URI or object and try again."

                    #Generate Terminating Error
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                }

            }

            # Creating an assigned profile
            else 
            {
            
                #Looking for the $server DTO to be string
                if ($Server -is [string]) 
                {
                
                    #If the server URI is passed, look up the server object
                    if ($Server.StartsWith($ServerHardwareUri)) 
                    {

                        "[{0}] Server URI passed: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Server | Write-Verbose 
                        
                        Try
                        {
                        
                            $Server = Send-HPOVRequest -Uri $Server -appliance $ApplianceConnection
                        
                        }
                        
                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }
                
                    #Else the name is passed and need to look it up.
                    else
                    {

                        Try
                        {

                            $Server = Get-HPOVServer -name $Server -appliance $ApplianceConnection

                        }
                    
                        Catch
                        {
                            
                            $PSCmdlet.ThrowTerminatingError($_)    
                            
                        }            
                    
                    }

                }
            
                "[{0}] Server object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Server | Out-String) | Write-Verbose 

                #Check to make sure the server NoProfileApplied is true
                if ($Server.serverProfileUri)
                {

                    Try
                    {

                        $ServerProfileConflict = Send-HPOVRequest -Uri $Server.serverProfileUri -Hostname $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    $ExceptionMessage = "{0} already has a profile assigned, '{1}'. Please specify a different Server Hardware object." -f $Server.name, $ServerProfileConflict.name
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerProfileAlreadyAssigned ResourceExists 'Server' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                #Get the SHT of the SH that we are going to assign.
                Try
                {

                    $ServerHardwareType = Send-HPOVRequest -Uri $Server.serverHardwareTypeUri -appliance $ApplianceConnection

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                #Set the server hardware URI value in the profile
                $ServerProfile.serverHardwareUri = $Server.uri

                if($AssignmentType -eq 'bay' -and $EnclosureBay)
                {

                    $ServerProfile | Add-Member -NotePropertyName enclosureBay -NotePropertyValue $EnclosureBay

                }

                if ($Server.serverGroupUri)
                {

                    "[{0}] Getting Enclosure Group object." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    Try
                    {
    
                        $EnclosureGroup = Send-HPOVRequest -Uri $Server.serverGroupUri
    
                    }
                    
                    Catch
                    {
    
                        $PSCmdlet.ThrowTerminatingError($_)
    
                    }

                }
            
            }

            #User provided UEFI or UEFIOptimized for a non-Gen9 platform.
            if ($BootMode -ne "BIOS" -and $ServerHardwareType.model -notmatch "Gen9")
            {

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException BootModeNotSupported InvalidArgument 'BootMode' -Message "The -bootMode Parameter was provided and the Server Hardware model '$($serverHardwareType.model)' does not support this Parameter. Please verify the Server Hardware Type is at least an HPE ProLiant Gen9."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)    

            }

            #Handle Boot Order and BootManagement
            #Perform Device Model specific functions?
            switch ($ServerHardwareType.model)
            {

                #Handle DL Server Profiles by setting BL-specific properties to NULL
                {$_ -match "DL|XL|ML"}
                {

                    "[{0}] Server Hardware Type is a DL, setting 'macType', 'wwnType', 'serialNumberType', 'affinity' and 'hideUnusedFlexNics' to supported values." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    if (-not $PSboundParameters['ServerProfileTemplate'])
                    {

                        $ServerProfile.macType            = 'Physical'
                        $ServerProfile.wwnType            = 'Physical'
                        $ServerProfile.serialNumberType   = 'Physical'
                        $ServerProfile.hideUnusedFlexNics = $true
                        $ServerProfile.affinity           = $Null

                    }                        

                }
                
                {$_ -match 'Gen7|Gen8'}
                {

                    if (-not($PSboundParameters['BootOrder']) -and $ManageBoot)
                    {

                        "[{0}] No boot order provided for Gen8 Server resource type. Defaulting to 'CD','Floppy','USB','HardDisk','PXE'" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                        [System.Collections.ArrayList]$serverProfile.boot.order = ('CD','Floppy','USB','HardDisk','PXE')

                    }

                }

                {$_ -match 'Gen9|Gen10'}
                {

                    if (-not $ServerProfileTemplate)
                    {

                        "[{0}] Gen 9/10 Server, setting BootMode to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $BootMode | Write-Verbose 

                        switch ($BootMode) 
                        {

                            'Unmanaged'
                            {

                                $serverProfile.bootMode = [PSCustomObject]@{
                                    manageMode = $false;
                                    mode       = $null;
                                }

                            }

                            "BIOS" 
                            {
                            
                                $serverProfile.bootMode = [PSCustomObject]@{
                                    manageMode = $true;
                                    mode       = $BootMode;
                                }
                            
                            }

                            { "UEFI","UEFIOptimized" -match $_ } 
                            {
                            
                                $serverProfile.bootMode = [PSCustomObject]@{
                                    manageMode    = $true;
                                    mode          = $BootMode;
                                    pxeBootPolicy = $PxeBootPolicy
                                }
                            
                            }

                        }

                    }

                    if ($BootOrder -or (-not $BootOrder -and -not $ServerProfileTemplate))
                    {

                        "[{0}] Processing Gen9/10 Server BootOrder settings." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                        if ($ManageBoot -and ($BootOrder -contains "Floppy") -and ($BootMode -match "UEFI"))
                        #if ($BootOrder -contains "Floppy" -and $BootMode -match "UEFI")
                        {
                            
                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidUEFIBootOrderParameterValue InvalidArgument 'BootOrder' -TargetType 'Array' -Message    "The -BootOrder Parameter contains 'Floppy' which is an invalid boot option for a UEFI-based system."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        elseif ((-not ($PSBoundParameters["BootOrder"])) -and $ManageBoot -and ('Unmanaged','UEFI' -notcontains $BootMode)) 
                        #elseif ((-not ($PSBoundParameters["BootOrder"])) -and ('Unmanaged','UEFI' -notcontains $BootMode))
                        {

                            "[{0}] No boot order provided for Gen9 Server resource type. Defaulting to 'CD','USB','HardDisk','PXE'" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                            [System.Collections.ArrayList]$serverProfile.boot.order = @('CD','USB','HardDisk','PXE')
                
                        }

                        elseif ((-not ($PSBoundParameters["BootOrder"])) -and $ManageBoot -and $BootMode -match 'UEFI' -and $ServerHardwareType.model -notmatch 'DL|XL|ML')
                        #elseif ((-not ($PSBoundParameters["BootOrder"])) -and $BootMode -match 'UEFI' -and $ServerHardwareType.model -notmatch 'DL')
                        {

                            "[{0}] No boot order provided for BL Gen9 Server resource type. Defaulting to 'HardDisk'." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                            [System.Collections.ArrayList]$serverProfile.boot.order = @('HardDisk')
                
                        }

                        elseif (($BootOrder.count -gt 1) -and $ManageBoot -and $BootMode -match 'UEFI')
                        #elseif (($BootOrder.count -gt 1) -and $BootMode -match 'UEFI')
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidUEFIBootOrderParameterValue InvalidArgument 'BootOrder' -TargetType 'Array' -Message    ("The -BootOrder Parameter contains more than 1 entry, and the system BootMode is set to {0}, which is invalud for a UEFI-based system. Please check the -BootOrder Parameter and make sure either 'HardDisk' or 'PXE' are the only option." -f $BootMode)
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                        }

                        elseif ($BootOrder -and $serverProfile.boot.manageBoot -and $BootMode -match 'UEFI' -and $ServerHardwareType.model -notmatch 'DL|XL|ML')
                        #elseif ($BootOrder -and $serverProfile.boot.manageBoot -and $BootMode -match 'UEFI' -and $ServerHardwareType.model -notmatch 'DL')
                        {

                            "[{0}] Adding provided BootOrder {1} to Server Profile object." -f $MyInvocation.InvocationName.ToString().ToUpper(), ($BootOrder -join ', ') | Write-Verbose 

                            [System.Collections.ArrayList]$serverProfile.boot.order = $BootOrder

                        }

                    }                    

                }

            }

            $ServerProfile.name                  = $Name
            $ServerProfile.description           = $Description
            $ServerProfile.serverHardwareTypeUri = $ServerHardwareType.uri

            if ($EnclosureGroup -and $null -eq $ServerProfile.enclsosureGroupUri)
            {

                $ServerProfile.enclosureGroupUri = $EnclosureGroup.uri 

            }

            if ($EnclosureBay -and $null -eq $ServerProfile.enclosureBay)
            {

                $ServerProfile.enclosureBay = $EnclosureBay

            }
            
            #Check to make sure Server Hardware Type supports Firmware Management (OneView supported G7 blade would not support this feature)
            if ($PSBoundParameters['Firmware']) 
            {
                
                "[{0}] Firmware Baseline: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Baseline | Write-Verbose

                if ($ServerHardwareType.capabilities -match "firmwareUpdate" ) 
                {

                    $ServerProfile.firmware.manageFirmware         = [bool]$firmware
                    $ServerProfile.firmware.forceInstallFirmware   = [bool]$forceInstallFirmware
                    $ServerProfile.firmware.firmwareInstallType    = $ServerProfileFirmwareControlModeEnum[$FirmwareInstallMode]
                    $ServerProfile.firmware.firmwareActivationType = $ServerProfileFirmareActivationModeEnum[$FirmwareActivationMode]

                    if ('FirmwareOffline', 'FirmwareOnlyOfflineMode' -contains $FirmwareInstallMode -and $PSBoundParameters['FirmwareActivateDateTime'])
                    {

                        $ExceptionMessage = "The specifying a scheduled firmware installation and performing offline method is not supported. Please choose an online method."
                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidFirmwareInstallMode InvalidArgument 'FirmwareActivateDateTime' -TargetType 'Switch' -Message    $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                    }

                    elseif ($FirmwareActivationMode -eq 'Scheduled' -and -not $PSBoundParameters['FirmwareActivateDateTime'])
                    {

                        $ExceptionMessage = "The specifying a scheduled firmware installation requires the -FirmwareActivateDateTime parameter."
                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidFirmwareInstallMode InvalidArgument 'FirmwareActivateDateTime' -TargetType 'Switch' -Message    $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                    }

                    elseif ($FirmwareActivationMode -eq 'Scheduled' -and $PSBoundParameters['FirmwareActivateDateTime'])
                    {

                        #Convert DateTime to UTC time for the appliance
                        "[{0}] Setting firmware activation schedule: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $FirmwareActivateDateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ") | Write-Verbose
                        $ServerProfile.firmware.firmwareScheduleDateTime = $FirmwareActivateDateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")

                    }                    

                    #Validating that the baseline value is a string type and that it is an SPP name.
                    if (($baseline -is [string]) -and (-not ($baseline.StartsWith('/rest'))) -and ($baseline -match ".iso")) 
                    {
                        
                        try 
                        {

                            $FirmwareBaslineName = $Baseline.Clone()

                            $Baseline = Get-HPOVBaseline -isoFileName $Baseline -ApplianceConnection $ApplianceConnection -ErrorAction SilentlyContinue

                            If (-not $_BaseLinePolicy)
                            {

                                $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $FirmwareBaslineName
                                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Baseline' -Message $ExceptionMessage
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }
                            
                            $serverProfile.firmware.firmwareBaselineUri = $baseline.uri
                        
                        }

                        catch 
                        {
                            
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Error caught when looking for Firmware Baseline."

                            $PSCmdlet.ThrowTerminatingError($_)
                        
                        }
                    
                    }

                    #Validating that the baseline value is a string type and that it is an SPP name.
                    elseif (($baseline -is [string]) -and (-not ($baseline.StartsWith('/rest')))) 
                    {

                        try 
                        {

                            $FirmwareBaslineName = $Baseline.Clone()

                            $Baseline = Get-HPOVBaseline -SppName $Baseline -ApplianceConnection $ApplianceConnection -ErrorAction SilentlyContinue

                            If (-not $_BaseLinePolicy)
                            {

                                $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $FirmwareBaslineName
                                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Baseline' -Message $ExceptionMessage
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                            $serverProfile.firmware.firmwareBaselineUri = $Baseline.uri

                        }

                        catch 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Error caught when looking for Firmware Baseline."

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }
            
                    #Validating that the baseline value is a string type and that it is the Basline URI
                    elseif (($baseline -is [string]) -and ($baseline.StartsWith('/rest'))) 
                    {
                
                        Try
                        {

                            $baselineObj = Send-HPOVRequest -Uri $baseline -appliance $ApplianceConnection

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                            

                        if ($baselineObj.category -eq "firmware-drivers") 
                        {
                        
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Valid Firmware Baseline provided: $($baselineObj.baselineShortName)"

                            $serverProfile.firmware.firmwareBaselineUri = $baselineObj.uri 
                        
                        }

                        else 
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidBaselineResource ObjectNotFound 'Basline' -Message "The provided SPP Baseline URI '$($baseline)' is not valid or the correct resource category (expected 'firmware-drivers', received '$($baselineObj.category)'. Please check the -baseline Parameter value and try again."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                    #Else we are expecting the SPP object that contains the URI.
                    elseif (($baseline) -and ($baseline -is [object])) 
                    {

                        $serverProfile.firmware.firmwareBaselineUri = $baseline.uri
                    
                    }

                    elseif (!$baseline) 
                    {
                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerHardwareMgmtFeatureNotSupported NotImplemented 'Firmware' -TargetType 'SwitchParameter' -Message "Baseline is required when manage firmware is set to true."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    }

                }

                else 
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerHardwareMgmtFeatureNotSupported NotImplemented 'Firmware' -TargetType 'SwitchParameter' -Message "`"$($serverHardwareType.name)`" Server Hardware Type does not support Firmware Management."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                }

            }

            #Exmamine the profile connections Parameter and pull only those connections for this appliance connection
            If ($PSBoundParameters['Connections'] -and $ServerHardwareType.model -notmatch "DL")
            {

                $BootableConnections = New-Object System.Collections.ArrayList

                "[{0}] Getting available Network resources based on SHT and EG." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                #Get avaialble Networks based on the EG and SHT
                $_AvailableNetworksUri = '{0}?serverHardwareTypeUri={1}&enclosureGroupUri={2}' -f $ServerProfilesAvailableNetworksUri, $ServerHardwareType.uri, $EnclosureGroup.uri

                Try
                {

                    $_AvailableNetworkResources = Send-HPOVRequest -Uri $_AvailableNetworksUri -Hostname $ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                ForEach($c in $connections)
                {

                    $Message = $null

                    #Remove connection Parameters no permitted in Template
                    $c = $c | Select-Object -property * -ExcludeProperty ApplianceConnection

                    switch (($c.networkUri.Split('\/'))[2])
                    {

                        'ethernet-networks'
                        {
                    
                            if (-not($_AvailableNetworkResources.ethernetNetworks | ? uri -eq $c.networkUri))
                            {

                                $Message = "The Ethernet network {0} specified in Connection {1} was not found to be provisioned to the provided Enclosure Group, {2}, and SHT, {3}. Please verify that the network is a member of an Uplink Set in the associated Logical Interconnect Group." -f (Send-HPOVRequest $c.networkUri -Hostname $ApplianceConnection.Name).name, $c.id, $EnclosureGroup.name, $ServerHardwareType.name

                            }

                            else
                            {

                                "[{0}] {1} is available for Connection {2} in this Server Profile request." -f $MyInvocation.InvocationName.ToString().ToUpper(), $c.networkUri, $c.id | Write-Verbose 

                                # Add check for iSCsi Initiator Name, to make sure the initiatorName property is set correctly.

                            }
                    
                        }

                        'network-sets'
                        {
                    
                            if (-not($_AvailableNetworkResources.networkSets | ? uri -eq $c.networkUri))
                            {

                                $Message = "The network set {0} specified in Connection {1} was not found to be provisioned to the provided Enclosure Group, {2}, and SHT, {3}. Please verify that the network is a member of an Uplink Set in the associated Logical Interconnect Group." -f (Send-HPOVRequest $c.networkUri -Hostname $ApplianceConnection.Name).name, $c.id, $EnclosureGroup.name, $ServerHardwareType.name

                            }
                    
                            else
                            {

                                "[$($MyInvocation.InvocationName.ToString().ToUpper())] {0} is available for Connection {1} in this Server Profile request." -f $c.networkUri, $c.id | Write-Verbose 

                            }

                        }

                        'fc-networks'
                        {
                    
                            if (-not($_AvailableNetworkResources.fcNetworks | ? uri -eq $c.networkUri))
                            {

                                $Message = "The FC network {0} specified in Connection {1} was not found to be provisioned to the provided Enclosure Group, {2}, and SHT, {3}. Please verify that the network is a member of an Uplink Set in the associated Logical Interconnect Group." -f (Send-HPOVRequest $c.networkUri -Hostname $ApplianceConnection.Name).name, $c.id, $EnclosureGroup.name, $ServerHardwareType.name

                            }
                    
                            else
                            {

                                "[$($MyInvocation.InvocationName.ToString().ToUpper())] {0} is available for Connection {1} in this Server Profile request." -f $c.networkUri, $c.id | Write-Verbose 

                            }

                        }

                        'fcoe-networks'
                        {
                    
                            if (-not($_AvailableNetworkResources.fcNetworks | ? uri -eq $c.networkUri))
                            {

                                $Message = "The FCoE network {0} specified in Connection {1} was not found to be provisioned to the provided Enclosure Group, {2}, and SHT, {3}. Please verify that the network is a member of an Uplink Set in the associated Logical Interconnect Group." -f (Send-HPOVRequest $c.networkUri -Hostname $ApplianceConnection.Name).name, $c.id, $EnclosureGroup.name, $ServerHardwareType.name

                            }
                    
                            else
                            {

                                "[$($MyInvocation.InvocationName.ToString().ToUpper())] {0} is available for Connection {1} in this Server Profile request." -f $c.networkUri, $c.id | Write-Verbose 

                            }
                    
                        }

                    }

                    if ($Message)
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException NetworkResourceNotProvisioned InvalidArgument 'Connections' -TargetType 'PSObject' -Message $Message
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                    }
                
                    [void]$ServerProfile.connections.Add($c)

                    if ($null -ne $c.boot -and $c.boot.priority -ne "NotBootable") 
                    {

                        "[{0}] Found bootable connection ID: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $c.id | Write-Verbose

                        [void]$BootableConnections.Add($c.id)

                    }
            
                }

                if (-not $PSBoundParameters['ManageBoot'] -and $BootableConnections.count -gt 0) 
                {

                    $ExceptionMessage = "Bootable Connections {0} were found, however the -ManageBoot switch Parameter was not provided. Please correct your command syntax and try again." -f [String]::Join(', ', $BootableConnections.ToArray())
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException BootableConnectionsFound InvalidArgument 'manageBoot' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                } 
        
            }

            #Check to make sure Server Hardware Type supports Bios Management (OneView supported G7 blade do not support this feature)
            if ($PSBoundParameters['BIOS']) 
            {

                if (-not ($BiosSettings | Measure-Object).count) 
                {
                    
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException BiosSettingsIsNull InvalidArgument 'biosSettings' -TargetType 'Array' -Message "BIOS Parameter was set to TRUE, but no biosSettings were provided. Either change -bios to `$False or provide valid bioSettings to set within the Server Profile."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }

                else 
                {
                
                    if ($serverHardwareType.capabilities -match "ManageBIOS" ) 
                    {
                            
                        #check for any duplicate keys
                        $biosFlag = $false
                        $hash = @{}
                        $BiosSettings.id | % { $hash[$_] = $hash[$_] + 1 }

                        foreach ($biosItem in ($hash.GetEnumerator() | ? {$_.value -gt 1} | % {$_.key} )) 
                        {
                                
                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException BiosSettingsNotUnique InvalidOperation 'BiosSettings' -TargetType 'Array' -Message "'$(($serverHardwareType.biosSettings | where { $_.id -eq $biosItem }).name)' is being set more than once. Please check your BIOS Settings are unique. This setting might be a depEndency of another BIOS setting/option. Please check your BIOS Settings are unique. This setting might be a depEndency of another BIOS setting/option."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        $serverProfile.bios.overriddenSettings = $BiosSettings

                    }

                    else 
                    { 

                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerHardwareMgmtFeatureNotSupported NotImplemented 'New-HPOVServerProfile' -Message "`"$($serverHardwareType.name)`" Server Hardware Type does not support BIOS Management."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)                
                    
                    }
                    
                }

            }

            #Set Local Storage Management and Check to make sure Server Hardware Type supports it (OneView supported G7 blade would not support this feature)
            if (($PSBoundParameters['StorageController']) -and ($ServerHardwareType.capabilities -Contains "ManageLocalStorage" )) 
            {

                #Loop through Controllers provided by user, which should have LogicalDisks attached.
                ForEach ($_Controller in $StorageController)
                {

                    #Loop through Controllers provided by user, which should have LogicalDisks attached.
                    $_Controller = $_Controller.PSObject.Copy()

                    $_NewLogicalDisksCollection = New-Object System.Collections.ArrayList

                    "[{0}] Processing {1} Controller" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_Controller.deviceSlot | Write-Verbose
                    
                    #Validate the SHT.storageCapabilities controllerModes -> mode, raidLevels -> logicalDrives.raidLevel and maximumDrives -> numPhysicalDrives
                    if ($ServerHardwareType.storageCapabilities.controllerModes -notcontains $_Controller.mode)
                    {

                        $_ExceptionMessage = "Unsupported LogicalDisk policy with Virtual Machine Appliance. The requested Controller Mode '{0}' is not supported with the expected Server Hardware Type, which only supports '{1}'" -f $_Controller.mode, ([System.String]::Join($ServerHardwareType.storageCapabilities.controllerModes,"', '")) 
                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedImportConfigurationSetting InvalidOperation "StorageController" -TargetType 'PSObject' -Message $_ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    $_l = 1

                    "[{0}] Storage Controller has {1} LogicalDrives to Process" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_Controller.logicalDrives.count | Write-Verbose

                    #Validate the SHT.storageCapabilities .raidLevels -> logicalDrives.raidLevel and .maximumDrives -> numPhysicalDrives
                    ForEach ($_ld in $_Controller.logicalDrives)
                    {

                        "[{0}] Processing {1} of {2} LogicalDisk: {3}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_l, $_Controller.logicalDrives.count, $_ld.name | Write-Verbose

                        "[{0}] {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_ld | Out-String) | Write-Verbose

                        if ($_ld.PSObject.Properties.Match('SasLogicalJBOD').Count)
                        {

                            "[{0}] Processing SasLogicalJbod {1} (ID:{2}) in Controller {3}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ld.SasLogicalJBOD.name, $_ld.SasLogicalJbodId, $_Controller.deviceSlot | Write-Verbose

                            If ($ApplianceConnection.ApplianceType -ne 'Composer')
                            {

                                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. The LogicalDisk within the StorageController contains a SasLogicalJbod configuration with is only supported with HPE Synergy.' -f $ApplianceConnection.Name)
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                            [void]$serverProfile.localStorage.sasLogicalJBODs.Add($_ld.SasLogicalJBOD)

                        }

                        if ($ServerHardwareType.storageCapabilities.raidLevels -notcontains $_ld.raidLevel)
                        {

                            $_ExceptionMessage = "Unsupported LogicalDisk RAID Level {0} policy with {1} logical disk. The Server Hardware Type only supports '{2}' RAID level(s). " -f $_ld.raidLevel, $_ld.name, [System.String]::Join("', '",$ServerHardwareType.storageCapabilities.raidLevels) 
                            $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedLogicalDriveRaidLevel InvalidOperation "StorageController" -TargetType 'PSObject' -Message $_ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        if ($_ld.numPhysicalDrives -gt $ServerHardwareType.storageCapabilities.maximumDrives)
                        {

                            $_ExceptionMessage = "Invalid number of drives requested {0}. The Server Hardware Type only supports a maximum of '{1}'." -f $_ld.numPhysicalDrives, $ServerHardwareType.storageCapabilities.maximumDrives 
                            $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedNumberofDrives InvalidOperation "StorageController" -TargetType 'PSObject' -Message $_ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        $_ld = $_ld | Select * -ExcludeProperty SasLogicalJBOD

                        [Void]$_NewLogicalDisksCollection.Add($_ld)

                        $_l++

                    }

                    $_Controller.logicalDrives = $_NewLogicalDisksCollection

                    [void]$serverProfile.localStorage.controllers.Add($_Controller)        

                }

            }
            
            #StRM Support
            if ($PSBoundParameters['SANStorage'] -and $ServerHardwareType.capabilities -Contains 'VCConnections')
            { 

                "[{0}] SAN Storage being requested" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $ServerProfile.sanStorage = [pscustomobject]@{
                    
                    hostOSType        = $ServerProfileSanManageOSType.($HostOsType);
                    manageSanStorage  = [bool]$SANStorage;
                    volumeAttachments = New-Object System.Collections.ArrayList
                
                }

                $_AllNetworkUrisCollection  = New-Object System.Collections.ArrayList

                #Build list of network URI's from connections
                ForEach ($_Connection in $ServerProfile.connections) 
                {

                    [void]$_AllNetworkUrisCollection.Add($_Connection.networkUri)

                }

                #Copy the Parameter array into a new object
                $_VolumesToAttach = New-Object System.Collections.ArrayList

                $StorageVolume | % { 

                    if ($_)
                    {
                    
                        [void]$_VolumesToAttach.Add($_)

                    }
                    
                }
                
                "[{0}] Number of Volumes to Attach: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_VolumesToAttach.Count | Write-Verbose

                $_v = 0
                
                foreach ($_Volume in $_VolumesToAttach) 
                {  

                    $_v++

                    "[{0}] Processing Volume {1} of {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_v, $_VolumesToAttach.Count | Write-Verbose

                    #Ephemeral Volume Support
                    if ($_Volume.volumeStoragePoolUri)
                    {

                        $_uri = "{0}?networks='{1}'&filter=uri='{2}'" -f $ReachableStoragePoolsUri, ([String]::Join(',', $_AllNetworkUrisCollection.ToArray())), $_Volume.volumeStoragePoolUri
                        $_VolumeName = $_Volume.volumeName
                        $_VolumeUri  = 'StoragePoolUri:{0}' -f $_Volume.volumeStoragePoolUri

                    }

                    #Provisioned Volume Support
                    else
                    {

                        $_uri = "{0}?networks='{1}'&filter=name='{2}'" -f $AttachableStorageVolumesUri, ([String]::Join(',', $_AllNetworkUrisCollection.ToArray())), $_Volume.name
                        $_VolumeUri = $_Volume.uri

                        Try
                        {

                            $_VolumeName = (Send-HPOVRequest -uri $_Volume.volumeUri).Name

                        }

                        catch
                        {

                            $PSCmdlet.ThrwoTerminatingError($_)

                        }                        

                    }

                    "[{0}] Processing Volume ID: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_Volume.id | Write-Verbose 
                    "[{0}] Looking to see if volume '{1} ({2})' is attachable" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_VolumeName, $_VolumeUri |Write-Verbose 

                    try
                    {

                        $_resp = Send-HPOVRequest -Uri $_uri -appliance $ApplianceConnection

                    }

                    catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    #members found
                    if ($_resp.count -gt 0)
                    {

                        "[{0}] '{1} ({2})' volume is attachable" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_VolumeName, $_VolumeUri | Write-Verbose

                        if (($_Volume.id -eq 0) -or (-not($_Volume.id)))
                        {

                            "[{0}] No VolumeID value provided. Getting next volume id value." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            $id = 1

                            $Found = $false

                            While (-not $Found -and $id -lt 256)
                            {

                                if (-not($_VolumesToAttach | ? id -eq $id))
                                {

                                    "[{0}] Setting Volume ID to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $id | Write-Verbose

                                    $_Volume.id = $id

                                    $Found = $true

                                }

                                $id++

                            }

                        }

                        #If the storage paths array is null, Process connections to add mapping
                        if ($_Volume.storagePaths.Count -eq 0)
                        {

                            "[{0}] Storage Paths value is Null. Building connection mapping." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            #This should only be 1 within members array
                            foreach ($_member in $_resp.members) 
                            {

                                #write-verbose "Looking for $volConnection"

                                if ($_Member.deviceSpecificAttributes.iqn -or $_Member.family -eq 'StoreVirtual')
                                {

                                    "[{0}] Looking for Ethernet connections." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                    $_StorageTypeUri = '/rest/ethernet-networks'
                                    
                                }

                                else
                                {

                                    "[{0}] Looking for FC/FCoE connections." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                    $_StorageTypeUri = '/rest/fc'

                                }

                                #Figure out which connections "should" map based on identified storage connectivity type
                                [Array]$_ProfileConnections = $ServerProfile.connections | ? { $_.networkUri.StartsWith($_StorageTypeUri) }

                                "[{0}] Number of connections that match the volume connectivity type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ProfileConnections.Count | Write-Verbose

                                if ($_ProfileConnections.Count -gt 0)
                                {

                                    "[{0}] Connections that match the volume connectivity type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [String]::Join(', ', [Array]$_ProfileConnections.id) | Write-Verbose

                                }

                                [Array]$_ReachableNetworkUris = $_Member.reachableNetworks | ? { $_.StartsWith($_StorageTypeUri) }

                                "[{0}] Number of reachable networks that match the volume connectivity type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ReachableNetworkUris.Count | Write-Verbose

                                if ($_ReachableNetworkUris.Count -gt 0)
                                {

                                    "[{0}] Reachable networks that match the volume connectivity type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [String]::Join(', ', [Array]$_ReachableNetworkUris) | Write-Verbose

                                }

                                ForEach ($_ReachableNetworkUri in $_ReachableNetworkUris)
                                {

                                    "[{0}] Processing reachable network URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ReachableNetworkUri | Write-Verbose

                                    ForEach ($_ProfileConnection in ($_ProfileConnections | ? { $_.networkUri -eq $_ReachableNetworkUri }))
                                    {

                                        "[{0}] Mapping connectionId '{1}' -> volumeId '{2}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ProfileConnection.id, $_Volume.id | Write-Verbose

                                        $_StoragePath = NewObject -StoragePath

                                        $_StoragePath.connectionId = $_ProfileConnection.id
                                        $_StoragePath.isEnabled    = $True

                                        [void]$_Volume.storagePaths.Add($_StoragePath)

                                    }

                                }

                                if ($_Volume.storagePaths.Count -eq 0)
                                {

                                    Write-Warning ('No available connections were found that could attach to {0} Storage Volume. Storage Volumes may not be attached.' -f $_VolumeName)

                                }

                                [void]$ServerProfile.sanStorage.volumeAttachments.Add($_Volume)

                            }

                        }

                        else
                        {
                        
                            [void]$ServerProfile.sanStorage.volumeAttachments.Add($_Volume)
                        
                        }

                    }

                    #no members found, generate exception
                    else
                    {

                        $ExceptionMessage = "'{0}' Volume is not available to be attached to the profile. Please check the volume or available storage pools and try again."  -f $VolumeName
                        $ErrorRecord = New-ErrorRecord InvalidOperationException StorageVolumeUnavailableForAttach ResourceUnavailable 'StorageVolume' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                #Check to see if user passed -EvenPathDisable and/or -OddPathDisable Parameter switches
                if ($EvenPathDisabled.IsPresent -or $OddPathDisabled.IsPresent) 
                {
                                        
                    "[{0}] Disable Even Path: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $EvenPathDisable.IsPresent | Write-Verbose
                    "[{0}] Disable Odd Path: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), $OddPathDisable.IsPresent | Write-Verbose

                    #Keep track of Volume Array index
                    $v = 0

                    foreach ($_vol in $ServerProfile.sanStorage.volumeAttachments) 
                    {
                        
                        #Keep track of Volume Path Array index
                        $p = 0

                        foreach ($_Path in $_vol.storagePaths) 
                        {

                            $_IsEnabled = $true

                            if ([bool]$OddPathDisabled.IsPresent -and [bool]($_Path.connectionID % 2)) 
                            { 
                                
                                $_IsEnabled = $false 
                            
                            }
                            
                            elseif ([bool]$EvenPathDisabled.IsPresent -and [bool]!($_Path.connectionID % 2)) 
                            { 
                                
                                $_IsEnabled = $false 

                            }

                            "[{0})] Setting Connection ID '{1}' path Enabled: {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_Path.connectionID, $_IsEnabled | Write-Verbose

                            $serverProfile.sanStorage.volumeAttachments[$v].storagePaths[$p].isEnabled = $_IsEnabled
                            $p++

                        }

                        $v++

                    }
                    
                }

            }

        }

        "[{0}] Profile: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($ServerProfile | out-string) | Write-Verbose

        "[{0}] Sending request" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        Try
        {
        
            $Resp = Send-HPOVRequest -Uri $ServerProfilesUri -Method POST -Body $ServerProfile -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($PSBoundParameters['Async'])
        {

            $Resp

        }

        else
        {

            Try
            {

                $Resp | Wait-HPOVTaskComplete -OutVariable Resp

                if ($Resp.taskState -eq 'Error')
                {

                    $ExceptionMessage = $resp.taskErrors.message
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidOperation InvalidOperation 'AsyncronousTask' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
    
    }    
    
}

#// TODO DEVELOP DOCUMENTATION TEST
function Set-HPOVServerProfile
{

    Throw "Not implemented."

}

function Update-HPOVServerProfile
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (
        
        [Parameter (ValueFromPipeline, Mandatory)]
        [ValidateNotNullOrEmpty()]
        [Alias ('profile','ServerProfile')]
        [object]$InputObject,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false)]
        [Switch]$Async

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {
            
            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection          = New-Object System.Collections.ArrayList
        $_ServerProfileCollection = New-OBject System.Collections.ArrayList
        
    }

    Process 
    {

        if ($PipelineInput) 
        {
        
            "[{0}] Processing Pipeline input." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            #error if the input value is not a PSObject
            if (-not($InputObject -is [PSCustomObject]))
            {

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerProfileObjectType InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided InputObject value is not a valid PSObject ($($InputObject.GetType().Name)). Please correct your input value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Validate the Input object is the allowed category
            if ($InputObject.category -ne 'server-profiles')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerProfileCategory InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided InputObject object ($($InputObject.name)) category '$($InputObject.category)' is not an allowed value. Expected category value is 'server-profiles'. Please correct your input value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if(-not($InputObject.ApplianceConnection))
            {

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerProfileObject InvalidArgument 'InputObject' -TargetType 'PSObject' -Message "The provided InputObject object ($($InputObject.name)) does not contain the required 'ApplianceConnection' object property. Please correct your input value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            "[{0}] Adding to collection to process: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

            [void]$_ServerProfileCollection.Add($InputObject)
        
        }

        #Not Pipeline input, and support Array of ServerProfile Name or PSObject
        else
        {

            "[{0}] Processing InputObject Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            "[{0}] ServerPrInputObjectofile is [$($InputObject.GetType().Name)]." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            ForEach ($_profile in $InputObject)
            {

                switch ($_profile.GetType().Name)
                {

                    #Name
                    'String' 
                    {
                    
                        "[{0}] ServerProfile value: $($_profile)." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        "[{0}] Looking for Server Profile Name on connected sessions provided" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        #Loop through all Appliance Connections
                        ForEach ($_appliance in $ApplianceConnection)
                        {

                            "[{0}] Processing '$($_appliance.Name)' Session." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                            Try
                            {

                                $_resp = Get-HPOVServerProfile $_profile -ApplianceConnection $_appliance.Name

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                            [void]$_ServerProfileCollection.Add($_resp)

                        }
                    
                    }

                    #Object
                    'PSCustomObject'
                    {

                        "[{0}] ServerProfile PSObject: $($_profile | FL * | out-string)." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        #Validate the Input object is the allowed category
                        if ($_profile.category -ne 'server-profiles')
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerProfileCategory InvalidArgument 'ServerProfile' -TargetType 'PSObject' -Message "The provided ServerProfile object ($($_profile.name)) category '$($_profile.category)' is not an allowed value. Expected category value is 'server-profiles'. Please correct your input value."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        [void]$_ServerProfileCollection.Add($_profile)

                    }

                }

            }

        }

    }

    End
    {
        
        #Perform the work
        ForEach ($_spObject in $_ServerProfileCollection) 
        {

            "[{0}] Processing Server Profile: '$($_spObject.name) [$($_spObject.uri)]'" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
            
            $_Operation = NewObject -PatchOperation
            
            $_Operation.op    = "replace"
            $_Operation.path  = "/templateCompliance"
            $_Operation.value = "Compliant" 

            "{0}] Is Server Profile 'Compliant': {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_spObject.templateCompliance | Write-Verbose

            if ($_spObject.templateCompliance -ne 'Compliant')
            {

                try
                {

                    $_spUpdateOperations = Send-HPOVRequest -Uri ($_spObject.uri + '/compliance-preview') -Hostname $_spObject.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                $ReviewObject = New-Object HPOneView.ServerProfile.CompliancePreview ($_spObject.name, $_spUpdateOperations.isOnlineUpdate, $_spUpdateOperations.ApplianceConnection)

                $_spUpdateOperations.automaticUpdates | % { [void]$ReviewObject.AutomaticUpdates.Add($_) }
                $_spUpdateOperations.manualUpdates | % { [void]$ReviewObject.ManualUpdates.Add($_) }

                if ($PSCmdlet.ShouldProcess($_spObject.name,"Update Server Profile configuration. WARNING: Depending on this action, there might be a brief outage."))
                { 

                    "[{0}] Sending request to $($PSCmdlet.ParameterSetName) configuration" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    Try
                    {

                        $_task = Send-HPOVRequest -Uri $_spObject.uri -Method PATCH -Body $_Operation -Hostname $_spObject.ApplianceConnection.Name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    if (-not($PSBoundParameters['Async']))
                    {
                    
                         $_task = Wait-HPOVTaskComplete -InputObject $_task -ApplianceConnection $_task.ApplianceConnection.Name
                
                    }

                    $_task
                    
                }

                elseif ($PSBoundParameters['WhatIf'])
                {
                
                    "[{0}] User included -WhatIf." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    #Need to return the HPOneView.ServerProfile.ComplianceReview object
                    $ReviewObject
            
                }

                else
                {

                    "[{0}] User cancelled." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                }    

            }

            else
            {

                Write-Warning ('Skipping {0} Server Profile, as it is Compliant.' -f $_spObject.name)

            }
                   
        }

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVServerProfileTemplate 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (ValueFromPipeline = $false, ParameterSetName = "Default", Mandatory = $false)]
        [Parameter (ValueFromPipeline = $false, ParameterSetName = "Detailed", Mandatory = $false)]
        [Parameter (ValueFromPipeline = $false, ParameterSetName = "Export", Mandatory = $false)]
        [Alias ('profile')]
        [ValidateNotNullorEmpty()]
        [string]$Name,
        

        [Parameter (ParameterSetName = "Default", Mandatory = $false)]
        [Parameter (ParameterSetName = "Detailed", Mandatory = $false)]
        [Parameter (ParameterSetName = "Export", Mandatory = $false)]
        [object]$ServerHardwareType,

        [Parameter (ParameterSetName = "Default", Mandatory = $false)]
        [Parameter (ParameterSetName = "Detailed", Mandatory = $false)]
        [Parameter (ParameterSetName = "Export", Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Label,

        [Parameter (ValueFromPipeline = $false, ParameterSetName = "Detailed", Mandatory)]
        [switch]$Detailed,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "Detailed")]
        [Parameter (Mandatory = $false, ParameterSetName = "Export")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),
        
        [Parameter (ValueFromPipeline = $false, ParameterSetName = "Export", Mandatory)]
        [Alias ("x")]
        [switch]$Export,

        [Parameter (ValueFromPipeline = $false, ParameterSetName = "Export", Mandatory)]
        [ValidateNotNullOrEmpty()]
        [Alias ("save")]
        [string]$Location

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #Validate the path exists. If not, create it.
        if (($Export) -and (-not(Test-Path $Location)))
        { 
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Directory does not exist. Creating directory..."
            
            New-Item -path $Location -ItemType Directory
        
        }

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $TemplateCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            if ($PSBoundParameters['Label'])
            {

                $_uri = '{0}?category:storage-volume-templates&query=labels:{1}' -f $IndexUri, $Label

                Try
                {

                    $_IndexMembers = Send-HPOVRequest -Uri $_uri -Hostname $_appliance

                    #Loop through all found members and get full SVT object
                    ForEach ($_memeber in $_IndexMembers.members)
                    {

                        Try
                        {

                            $_memeber = Send-HPOVRequest -Uri $_memeber.uri -Hostname $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }                        

                        $_memeber.PSObject.TypeNames.Insert(0,'HPOneView.ServerProfileTemplate')
                        
                        [void]$TemplateCollection.Add($_memeber)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            else
            {

                $uri = $ServerProfileTemplatesUri

                if ($Name) 
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Received name: $($name)"

                    $uri = "{0}&filter=name matches '{1}'" -f $uri, $Name.Replace("*","%25").Replace("&","%26")

                }

                if ($PSBoundParameters['ServerHardwareType'])
                {

                    switch ($ServerHardwareType.GetType().Name)
                    {

                        'String'
                        {

                            Try
                            {

                                $ServerHardwareType = Get-HPOVServerHardwareType -Name $ServerHardwareType -ApplianceConnection $ApplianceConnection -ErrorAction Stop

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                        }

                        'PSCustomObject'
                        {

                            if ($ServerHardwareType.category -ne 'server-hardware-types')
                            {

                                $ExceptionMessage = "The provided ServerHardwareType parameter value, '{0}', is not a supported resource type. Please check the value, and try again." -f $ServerHardwareType.name
                                $ErrorRecord = New-ErrorRecord HPOneView.ServerHardwareTypeResourceException ServerHardwareTypeInvalidObject InvalidParameter 'ServerHardwareType' -Message $ExceptionMessage
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                        }

                    }

                    $uri = "{0}&filter=serverHardwareTypeUri eq '{1}'" -f $uri, $ServerHardwareType.uri

                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"

                Try
                {

                    $templates = Send-HPOVRequest -Uri $uri -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                #If a search for specific profile returns 0 results, throw a terminating error
                if(-not($templates.members) -and $Name)
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Profile Template Resource Name was provided, yet no results were found. Generate Error."
                    
                    $ExceptionMessage = "The specified Server Profile Template '{0}' was not found on '{1}' appliance connection. Please check the name again, and try again." -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerProfileResourceNotFound ObjectNotFound "Name" -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)
                    
                }
            
                foreach ($_template in $templates.members)
                {
                
                    $_template.PSObject.TypeNames.Insert(0,'HPOneView.ServerProfileTemplate')
                        
                    [void]$TemplateCollection.Add($_template)
                    
                }

            }

        }

    }

    End 
    {

        "Done. {0} server profile template resource(s) found." -f $TemplateCollection.count | write-verbose 

        #If user wants to export the profile configuration
        if ($export) 
        {

            #Get the unique applianceConnection.name properties from the profile collection for grouping the output files
            $ProfileGroupings = $TemplateCollection.ApplianceConnection.name | Select -Unique

            ForEach ($pg in $ProfileGroupings)
            {
                
                $outputProfiles = New-Object System.Collections.ArrayList

                $templates = $TemplateCollection | ? { $_.ApplianceConnection.Name -eq $pg }

                #Loop through all profiles
                foreach ($_profile in $templates) 
                {

                    #trim out appliance unique properties

                    $_profile = $_profile | select-object -Property * -excludeproperty uri,etag,created,modified,status,state,inprogress,enclosureUri,enclosureBay,serverHardwareUri,taskUri,ApplianceConnection
                    $_profile.serialNumberType = "UserDefined"

                    #Loop through the connections to save the assigned address
                    $i = 0
                    foreach ($connection in $profile.connections) 
                    {

                        if ($profile.connections[$i].mac) { $_profile.connections[$i].macType = "UserDefined" }
                        if ($profile.connections[$i].wwpn) { $_profile.connections[$i].wwpnType = "UserDefined" }
                        $i++

                    }

                    [void]$outputProfiles.Add($_profile)
                    
                }

                #save profile to JSON file
                "[$($MyInvocation.InvocationName.ToString().ToUpper())] Saving Server Profile Templates to {0}" -f ($location + '\' + $pg + '_ServerProfileTemplates.json') | Write-Verbose

                convertto-json -InputObject $outputProfiles -depth 99 | new-item ($location + '\' + $pg + '_ServerProfileTemplates.json') -itemtype file

            }

        }

        else 
        {

            Return $TemplateCollection

        }

    }

}

function New-HPOVServerProfileTemplate 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")] 
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [string]$Description,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")] 
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [string]$ServerProfileDescription,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Boolean]$ManageConnections = $true,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [array]$Connections = @(),

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [Alias ('eg')]
        [object]$EnclosureGroup,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [Alias ('sht')]
        [object]$ServerHardwareType,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [switch]$Firmware,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Alias ('FirmwareMode')]
        [ValidateSet ('FirmwareOnly', 'FirmwareAndSoftware', 'FirmwareOffline', 'FirmwareAndOSDrivers', 'FirmwareOnly', 'FirmwareOnlyOfflineMode')]
        [string]$FirmwareInstallMode = 'FirmwareAndSoftware',

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ('Immediate', 'Scheduled', 'NotScheduled')]
        [string]$FirmwareActivationMode = 'Immediate',
    
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [object]$Baseline,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [switch]$ForceInstallFirmware,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Appliance.OSDeploymentPlan]$OSDeploymentPlan,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [Object]$OSDeploymentPlanAttributes,
    
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [switch]$Bios,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [array]$BiosSettings=@(),
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]        
        [ValidateSet ("UEFI", "UEFIOptimized", "BIOS", 'Unmanaged', IgnoreCase = $False)]
        [string]$BootMode = "BIOS",

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]        
        [ValidateSet ("Auto", "IPv4", "IPv6", "IPv4ThenIPv6", "IPv6ThenIPv4", IgnoreCase = $False)]
        [string]$PxeBootPolicy = "Auto",

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Alias ('boot')]
        [switch]$ManageBoot,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [array]$BootOrder,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [switch]$LocalStorage,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Alias('LogicalDisk')]
        [ValidateNotNullorEmpty()]
        [Object]$StorageController,

        [Parameter (Mandatory, ParameterSetName = "SANStorageAttach")]
        [switch]$SANStorage,

        [Parameter (Mandatory, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ('CitrixXen','AIX','IBMVIO','RHEL4','RHEL3','RHEL','RHEV','VMware','Win2k3','Win2k8','Win2k12','OpenVMS','Egenera','Exanet','Solaris9','Solaris10','Solaris11','ONTAP','OEL','HPUX11iv1','HPUX11iv2','HPUX11iv3','SUSE','SUSE9','Inform', IgnoreCase=$true)]
        [Alias ('OS')]
        [string]$HostOStype,

        [Parameter (Mandatory, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [object]$StorageVolume,

        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Alias ('Even')]
        [switch]$EvenPathDisabled,

        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Alias ('Odd')]
        [switch]$OddPathDisabled,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ("Bay","BayAndServer", IgnoreCase=$false)]
        [string]$Affinity = "Bay",
    
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ("Virtual", "Physical", "UserDefined", IgnoreCase=$true)]
        [string]$MacAssignment = "Virtual",

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ("Virtual", "Physical", "'UserDefined", IgnoreCase=$true)]
        [string]$WwnAssignment = "Virtual",

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateSet ("Virtual", "Physical", "UserDefined", IgnoreCase=$true)]
        [string]$SnAssignment = "Virtual",

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [bool]$HideUnusedFlexNics = $True,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SANStorageAttach")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
        
    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Check for URI values in Parameters and validate that only one appliance connection is provided in the call
        if($ApplianceConnection.Count -gt 1)
        {
            
            #SHT
            if($serverHardwareType -is [string] -and $serverHardwareType.StartsWith($script:serverHardwareTypesUri))
            {
                
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'New-HPOVPropfile' -Message "Server Hardware Type as URI is not supported for multiple appliance connections"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }
            
            if($serverHardwareType -is [string] -and $serverHardwareType.StartsWith("/rest"))
            {
            
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'New-HPOVPropfile' -Message "Server Hardware Type as URI is not supported for multiple appliance connections."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

            #EG
            if(($enclosureGroup -is [string] -and $enclosureGroup.StartsWith("/rest")))
            {
            
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'New-HPOVPropfile' -Message "Enclosure Group as URI is not supported for multiple appliance connections."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

            #Baseline
            if (($baseline -is [string]) -and ($baseline.StartsWith('/rest'))) 
            {
                
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'New-HPOVPropfile' -Message "Baseline as URI is not supported for multiple appliance connections."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

        }

        ForEach ($_key in $PSBoundParameters.keys.GetEnumerator())
        {

            if ('ImportLogicalDisk','Initialize','ControllerMode','Bootable','RaidLevel' -contains $_key)
            {

                Write-Warning ("The -{0} parameter is deprecated. To configure local storage, please use the New-HPOVServerProfileLogicalDisk and New-HPOVServerProfileLogicalDiskController Cmdlets." -f $_key)

            }

        }

        $uri = $ServerProfileTemplatesUri

        $colStatus = New-Object System.Collections.ArrayList

    }
    
    Process 
    {
        
        #New Server Resource Object
        $_spt = NewObject -ServerProfileTemplate
            
        $_spt.name                          = $Name
        $_spt.description                   = $Description
        $_spt.serverProfileDescription      = $ServerProfileDescription        
        $_spt.affinity                      = $Affinity
                            
        #Check to see if the serverHardwareType or enclosureGroup is null, and generate error(s) then break.
        if (-not($ServerHardwareType))
        {

            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerHardwareTypeObject InvalidArgument 'ServerHardwareType' -Message "Server Hardware Type is missing. Please provide a Server Hardware Type using the -sht Parameter and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }
        
        #If the URI is passed as the Server Hardware Type, then set the serverHardwareTypeUri variable
        If ($ServerHardwareType -is [string])
        {

            if ($ServerHardwareType.StartsWith($script:ServerHardwareTypesUri))
            { 
                        
                "[{0}] SHT URI Provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerHardwareType | Write-Verbose

                $_spt.serverHardwareTypeUri = $ServerHardwareType

                Try
                {
                        
                    $ServerHardwareType = Send-HPOVRequest -Uri $ServerHardwareType -Hostname $ApplianceConnection
                        
                }
                        
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }
                
            #Otherwise, perform a lookup ofthe SHT based on the name
            else 
            {

                "[{0}] SHT Name Provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerHardwareType | Write-Verbose

                Try
                {

                    $ServerHardwareType = Get-HPOVServerHardwareType -Name $ServerHardwareType -Appliance $ApplianceConnection -ErrorAction Stop

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                "[{0}] SHT URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerHardwareType.uri | Write-Verbose
                
                $_spt.serverHardwareTypeUri = $ServerHardwareType.uri

            }

        }
        
        #Else the SHT object is passed
        else 
        { 

            "[{0}] ServerHardwareType object provided" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
            "[{0}] ServerHardwareType Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerHardwareType.name | Write-Verbose
            "[{0}] ServerHardwareType Uri: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerHardwareType.uri | Write-Verbose

            $_spt.serverHardwareTypeUri = $serverHardwareType.uri
                    
        }

        if ($ServerHardwareType.model -notmatch "DL")
        {

            $_spt.hideUnusedFlexNics = $PSBoundParameters['HideUnusedFlexNics']
            $_spt.serialNumberType   = $SnAssignment 
            $_spt.macType            = $MacAssignment
            $_spt.wwnType            = $WwnAssignment

            if (-not($EnclosureGroup))
            {
                
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidEnclosureGroupObject InvalidArgument 'EnclosureGroup' -Message "Enclosure Group is missing. Please provide an Enclosure Group using the -eg Parameter and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($EnclosureGroup -is [string])
            {

                #If the URI is passed as the Enclosure Group, then set the enclosureGroupUri variable
                if ($EnclosureGroup.StartsWith('/rest'))
                { 
                
                    $_spt.enclosureGroupUri = $EnclosureGroup
            
                }

                #Otherwise, perform a lookup ofthe Enclosure Group
                else
                {

                    Try
                    {

                        $EnclosureGroup = Get-HPOVEnclosureGroup -name $EnclosureGroup -appliance $ApplianceConnection

                    }
                
                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] EG URI: $enclosureGroupUri"                        
                
                    $_spt.enclosureGroupUri = $EnclosureGroup.uri
                
                }

            }
                
            #Else the EG object is passed
            elseif (($EnclosureGroup -is [PSObject]) -and ($EnclosureGroup.category -eq "enclosure-groups")) 
            { 

                #Retrieve only EG from this appliance connection
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group object provided"
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Name: $($EnclosureGroup.name)"
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Uri: $($EnclosureGroup.uri)"

                #Retrieve only EG from this appliance connection
                $_spt.enclosureGroupUri = $EnclosureGroup.uri

            }

            else 
            { 

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidEnclosureGroupObject InvalidArgument 'EnclsoureGroup' -TargetType $EnclosureGroup.GetType().Name -Message "Enclosure Group is invalid. Please specify a correct Enclosure Group name, URI or object and try again."

                #Generate Terminating Error
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

        }            

        #Handle DL Server Profiles by setting BL-specific properties to NULL
        else
        {

            "[{0}]] Server Hardware Type is a DL, setting 'macType', 'wwnType', 'serialNumberType', 'affinity' and 'hideUnusedFlexNics' to supported values." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_spt.macType            = 'Physical'
            $_spt.wwnType            = 'Physical'
            $_spt.serialNumberType   = 'Physical'
            $_spt.hideUnusedFlexNics = $true
            $_spt.affinity           = $Null

        }

        #Handle Boot Order and BootManagement
        switch ($ServerHardwareType.model)
        {
                
            {$_ -match 'Gen7|Gen8'}
            {

                #User provided UEFI or UEFIOptimized for a non-Gen9 platform.
                if ('Unmanaged','BIOS' -notcontains $BootMode)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException BootModeNotSupported InvalidArgument 'BootMode' -Message "The -BootMode Parameter was provided and the Server Hardware model '$($serverHardwareType.model)' does not support this Parameter. Please verify the Server Hardware Type is at least an HPE ProLiant Gen9."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)    

                }

                if (-not($PSboundParameters['BootOrder']) -and $ManageBoot)
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No boot order provided for Gen8 Server resource type. Defaulting to 'CD','Floppy','USB','HardDisk','PXE'"

                    [System.Collections.ArrayList]$_spt.boot.order = ('CD','Floppy','USB','HardDisk','PXE')

                }

            }

            {$_ -match 'Gen9|Gen10'}
            {

                "[{0}] Gen 9 Server, setting BootMode to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $BootMode | Write-Verbose 

                switch ($BootMode) 
                {

                    'Unmanaged'
                    {

                        $_spt.bootMode = [PSCustomObject]@{
                            manageMode = $false;
                            mode       = $null;
                        }

                    }

                    "BIOS" 
                    {
                        
                        $_spt.bootMode = [PSCustomObject]@{
                            manageMode = $true;
                            mode       = $BootMode;
                        }
                        
                    }

                    { "UEFI","UEFIOptimized" -match $_ } 
                    {
                        
                        $_spt.bootMode = [PSCustomObject]@{
                            manageMode    = $true;
                            mode          = $BootMode;
                            pxeBootPolicy = $PxeBootPolicy
                        }

                        if ($ServerHardwareType.model -match 'DL|XL|ML')
                        {

                            $_spt.boot.manageBoot = $false

                        }
                        
                    }

                }

                "[{0}] Processing Gen 9 Server BootOrder settings." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                if ($_spt.boot.manageBoot -and ($BootOrder -contains "Floppy") -and ($BootMode -match "UEFI"))
                {
                        
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidUEFIBootOrderParameterValue InvalidArgument 'BootOrder' -TargetType 'Array' -Message    "The -BootOrder Parameter contains 'Floppy' which is an invalid boot option for a UEFI-based system."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                elseif ((-not ($PSBoundParameters["BootOrder"])) -and $_spt.boot.manageBoot -and ('Unmanaged','UEFI' -notcontains $BootMode)) 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No boot order provided for Gen9 Server resource type. Defaulting to 'CD','USB','HardDisk','PXE'"

                    [System.Collections.ArrayList]$_spt.boot.order = @('CD','USB','HardDisk','PXE')
            
                }

                elseif ((-not ($PSBoundParameters["BootOrder"])) -and $_spt.boot.manageBoot -and $BootMode -match 'UEFI' -and $ServerHardwareType.model -notmatch 'DL')
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No boot order provided for BL Gen9 Server resource type. Defaulting to 'HardDisk'."

                    [System.Collections.ArrayList]$_spt.boot.order = @('HardDisk')
            
                }

                elseif (($BootOrder.count -gt 1) -and $_spt.boot.manageBoot -and $BootMode -match 'UEFI')
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidUEFIBootOrderParameterValue InvalidArgument 'BootOrder' -TargetType 'Array' -Message    ("The -BootOrder Parameter contains more than 1 entry, and the system BootMode is set to {0}, which is invalud for a UEFI-based system. Please check the -BootOrder Parameter and make sure either 'HardDisk' or 'PXE' are the only option." -f $BootMode)
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
                }

                elseif ($BootOrder -and $_spt.boot.manageBoot -and $BootMode -match 'UEFI' -and $ServerHardwareType.model -notmatch 'DL')
                {

                    "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding provided BootOrder {0} to Server Profile object." -f ($BootOrder -join ', ') | Write-Verbose 

                    [System.Collections.ArrayList]$_spt.boot.order = $BootOrder

                }

            }

        }

        if ($PSBoundParameters.Keys -match 'ManageConnections' -and $ServerHardwareType.model -notmatch "DL|XL|ML")
        {

            "[{0}] Setting SPT to not track Connections with derived Server Profiles: {1}." -f $MyInvocation.InvocationName.ToString().ToUpper(), $ManageConnections.IsPresent | Write-Verbose

            $_spt.connectionSettings.manageConnections = $ManageConnections

        }

        if ($PSBoundParameters['OSDeploymentPlan'])
        {

            If ($ApplianceConnection.ApplianceType -ne 'Composer')
            {

                $ExceptionMessage = 'The ApplianceConnection {0} is not a Synergy Composer. OS Deployment Plans are only supported with HPE Synergy.' -f $ApplianceConnection.Name
                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            "[{0}] Setting OS Deployment Plan." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_spt | Add-Member -NotePropertyName osDeploymentSettings -NotePropertyValue (NewObject -SPTOSDeploymentSettings)
            
            "[{0}] Setting OS Deployment Plan URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $OSDeploymentPlan.uri | Write-Verbose
            $_spt.osDeploymentSettings.osDeploymentPlanUri = $OSDeploymentPlan.uri

            "[{0}] Number of OS Deployment Plan Custom Attributes to set: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $OSDeploymentPlanAttributes.Count | Write-Verbose
            "[{0}] Setting OS Deployment Plan Custom Attributes: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($OSDeploymentPlanAttributes | Out-String) | Write-Verbose
            $_spt.osDeploymentSettings.osCustomAttributes  = $OSDeploymentPlanAttributes

        }

        #Exmamine the profile connections Parameter and pull only those connections for this appliance connection
        If ($PSBoundParameters['Connections'] -and $ManageConnections -and $ServerHardwareType.model -notmatch "DL|XL|ML")
        {

            "[{0}] Getting available Network resources based on SHT and EG." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            #Get avaialble Networks based on the EG and SHT
            $_AvailableNetworksUri = $ServerProfilesAvailableNetworksUri + '?serverHardwareTypeUri={0}&enclosureGroupUri={1}' -f $ServerHardwareType.uri,$EnclosureGroup.uri

            Try
            {

                $_AvailableNetworkResources = Send-HPOVRequest -Uri $_AvailableNetworksUri -Hostname $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_c = 0

            $BootableConnections = New-Object System.Collections.ArrayList

            ForEach ($c in $Connections)
            {

                $Message = $null

                #Remove connection Parameters not permitted in Template
                $c = $c | Select-Object -property * -ExcludeProperty macType, wwnType, wwpnType, mac, wwnn, wwpn, ApplianceConnection
                $c.boot = $c.boot | Select-Object -property * -ExcludeProperty bootTargetName, bootTargetLun, initiatorName, initiatorIp, chapName, mutualChapName, chapSecret, mutualChapSecret

                switch (($c.networkUri.Split('\/'))[2])
                {

                    'ethernet-networks'
                    {
                    
                        if (-not($_AvailableNetworkResources.ethernetNetworks | ? uri -eq $c.networkUri))
                        {

                            $Message = "The Ethernet network {0} specified in Connection {1} was not found to be provisioned to the provided Enclosure Group, {2}, and SHT, {3}. Please verify that the network is a member of an Uplink Set in the associated Logical Interconnect Group." -f (Send-HPOVRequest $c.networkUri -Hostname $ApplianceConnection).name, $c.id, $EnclosureGroup.name, $ServerHardwareType.name

                        }

                        else
                        {

                            "[{0}] {1} is available for Connection {2} in this SPT." -f $MyInvocation.InvocationName.ToString().ToUpper(), $c.networkUri, $c.id | Write-Verbose 

                        }
                    
                    }

                    'network-sets'
                    {
                    
                        if (-not($_AvailableNetworkResources.networkSets | ? uri -eq $c.networkUri))
                        {

                            $Message = "The network set {0} specified in Connection {1} was not found to be provisioned to the provided Enclosure Group, {2}, and SHT, {3}. Please verify that the network is a member of an Uplink Set in the associated Logical Interconnect Group." -f (Send-HPOVRequest $c.networkUri -Hostname $ApplianceConnection).name, $c.id, $EnclosureGroup.name, $ServerHardwareType.name

                        }
                    
                        else
                        {

                            "[{0}] {1} is available for Connection {2} in this SPT." -f $MyInvocation.InvocationName.ToString().ToUpper(), $c.networkUri, $c.id | Write-Verbose 

                        }

                    }

                    {'fc-networks','fcoe-networks' -contains $_}
                    {
                    
                        if (-not($_AvailableNetworkResources.fcNetworks | ? uri -eq $c.networkUri))
                        {

                            $Message = "The FC/FCoE network {0} specified in Connection {1} was not found to be provisioned to the provided Enclosure Group, {2}, and SHT, {3}. Please verify that the network is a member of an Uplink Set in the associated Logical Interconnect Group." -f (Send-HPOVRequest $c.networkUri -Hostname $ApplianceConnection).name, $c.id, $EnclosureGroup.name, $ServerHardwareType.name

                        }
                    
                        else
                        {

                            "[$($MyInvocation.InvocationName.ToString().ToUpper())] {0} is available for Connection {1} in this SPT." -f $c.networkUri, $c.id | Write-Verbose 

                        }

                    }

                }

                if ($Message)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException NetworkResourceNotProvisioned InvalidArgument 'Connections' -TargetType 'PSObject' -Message $Message
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                }

                if ($c.boot.priority -ne "NotBootable") 
                {

                    "[{0}] Found bootable connection ID: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $c.id | Write-Verbose

                    [void]$BootableConnections.Add($c.id)

                }
                
                [void]$_spt.connectionSettings.connections.Add($c)

                $_c++
            
            }
        
            "[{0}] Server Profile Template Connections to add: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_spt.connectionSettings.connections | FL * -force | Out-String) | Write-Verbose 

            if (-not $PSBoundParameters['ManageBoot'] -and $BootableConnections.count -gt 0) 
            {

                $ExceptionMessage = "Bootable Connections {0} were found, however the -ManageBoot switch Parameter was not provided. Please correct your command syntax and try again." -f [String]::Join(', ', $BootableConnections.ToArray())
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException BootableConnectionsFound InvalidArgument 'manageBoot' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

            } 

        }

        #Check to make sure Server Hardware Type supports Firmware Management (OneView supported G7 blade would not support this feature)
        if ($PSBoundParameters['Firmware'])
        {

            "[{0}] Firmware Baseline: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Baseline | Write-Verbose

            if ($serverHardwareType.capabilities -contains "FirmwareUpdate" ) 
            {

                "[{0}] SHT is capable of firmware management" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                
                $_spt.firmware.manageFirmware         = [bool]$firmware
                $_spt.firmware.forceInstallFirmware   = [bool]$forceInstallFirmware
                $_spt.firmware.firmwareInstallType    = $ServerProfileFirmwareControlModeEnum[$FirmwareInstallMode]
                $_spt.firmware.firmwareActivationType = $ServerProfileFirmareActivationModeEnum[$FirmwareActivationMode]

                if ('FirmwareOffline', 'FirmwareOnlyOfflineMode' -contains $_spt.firmware.firmwareInstallType -and $FirmwareActivationMode -eq 'Scheduled')
                {

                    $ExceptionMessage = "The specifying a scheduled firmware installation and performing offline method is not supported. Please choose an online method."
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileTemplateResourceException InvalidFirmwareInstallMode InvalidArgument 'FirmwareActivateDateTime' -TargetType 'Switch' -Message    $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }

                #Validating that the baseline value is a string type and that it is an SPP name.
                if (($baseline -is [string]) -and (-not ($baseline.StartsWith('/rest'))) -and ($baseline -match ".iso")) 
                {
                    
                    try 
                    {
                        
                        $FirmwareBaslineName = $Baseline.Clone()

                        $Baseline = Get-HPOVBaseline -FileName $Baseline -ApplianceConnection $ApplianceConnection -ErrorAction SilentlyContinue

                        If (-not $_BaseLinePolicy)
                        {

                            $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $FirmwareBaslineName
                            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Baseline' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }
                        
                        $_spt.firmware.firmwareBaselineUri = $Baseline.uri
                    
                    }

                    catch 
                    {
                        
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Error caught when looking for Firmware Baseline."

                        $PSCmdlet.ThrowTerminatingError($_)
                    
                    }
                
                }

                #Validating that the baseline value is a string type and that it is an SPP name.
                elseif (($baseline -is [string]) -and (-not ($baseline.StartsWith('/rest')))) 
                {

                    try 
                    {

                        $FirmwareBaslineName = $Baseline.Clone()

                        $Baseline = Get-HPOVBaseline -SppName $Baseline -ApplianceConnection $ApplianceConnection -ErrorAction SilentlyContinue

                        If (-not $_BaseLinePolicy)
                        {

                            $ExceptionMessage = "The provided Baseline '{0}' was not found." -f $FirmwareBaslineName
                            $ErrorRecord = New-ErrorRecord HPOneView.Appliance.BaselineResourceException BaselineResourceNotFound ObjectNotFound 'Baseline' -Message $ExceptionMessage
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        $_spt.firmware.firmwareBaselineUri = $baseline.uri

                    }

                    catch 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Error caught when looking for Firmware Baseline."

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }
        
                #Validating that the baseline value is a string type and that it is the Basline URI
                elseif (($Baseline -is [string]) -and ($Baseline.StartsWith('/rest'))) 
                {
            
                    Try
                    {

                        $baselineObj = Send-HPOVRequest -Uri $Baseline -Hostname $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }                        

                    if ($baselineObj.category -eq "firmware-drivers") 
                    {
                    
                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Valid Firmware Baseline provided: $($baselineObj.baselineShortName)"
                        $_spt.firmware.firmwareBaselineUri = $baselineObj.uri 
                    
                    }

                    else 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidBaselineResource ObjectNotFound 'Baseline' -Message "The provided SPP Baseline URI '$($baseline)' is not valid or the correct resource category (expected 'firmware-drivers', received '$($baselineObj.category)'. Please check the -baseline Parameter value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

                #Else we are expecting the SPP object that contains the URI.
                elseif (($Baseline) -and ($Baseline -is [object])) 
                {

                    $_spt.firmware.firmwareBaselineUri = $Baseline.uri
                
                }

                elseif (!$baseline)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerHardwareMgmtFeatureNotSupported NotImplemented 'New-HPOVServerProfileTemplate' -Message "Baseline is required if manage firmware is set to true."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }
                
            }

            else 
            {

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerHardwareMgmtFeatureNotSupported NotImplemented 'Firmware' -Message "`"$($serverHardwareType.name)`" Server Hardware Type does not support Firmware Management."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
            }

        }
        
        #Check to make sure Server Hardware Type supports Bios Management (OneView supported G7 blade do not support this feature)
        if ($PSBoundParameters['Bios']) 
        {

            if (-not($BiosSettings | Measure-Object).count) 
            {
                
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException BiosSettingsIsNull InvalidArgument 'biosSettings' -TargetType 'Array' -Message "BIOS Parameter was set to TRUE, but no biosSettings were provided. Either change -bios to `$False or provide valid bioSettings to set within the Server Profile."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

            else 
            {
            
                if ($serverHardwareType.capabilities -match "ManageBIOS" ) 
                {
                        

                    #check for any duplicate keys
                    $biosFlag = $false
                    $hash = @{}
                    $BiosSettings.id | % { $hash[$_] = $hash[$_] + 1 }

                    foreach ($biosItem in ($hash.GetEnumerator() | ? {$_.value -gt 1} | % {$_.key} )) 
                    {
                            
                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException BiosSettingsNotUnique InvalidOperation 'BiosSettings' -TargetType 'Array' -Message "'$(($serverHardwareType.biosSettings | where { $_.id -eq $biosItem }).name)' is being set more than once. Please check your BIOS Settings are unique. This setting might be a depEndency of another BIOS setting/option."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    $_spt.bios.manageBios = $True
                    $_spt.bios.overriddenSettings = $BiosSettings

                }

                else 
                { 

                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerHardwareMgmtFeatureNotSupported NotImplemented 'New-HPOVServerProfile' -Message "`"$($serverHardwareType.name)`" Server Hardware Type does not support BIOS Management."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)                
                
                }
                
            }

        }

        #Set Local Storage Management and Check to make sure Server Hardware Type supports it (OneView supported G7 blade would not support this feature)
        if (($PSBoundParameters['StorageController']) -and ($ServerHardwareType.capabilities -match "ManageLocalStorage" )) 
        {

            #Loop through Controllers provided by user, which should have LogicalDisks attached.
            ForEach ($_Controller in $StorageController)
            {

                #Copy the object so PowerShell doesn't modify the original object from the caller
                $_Controller = $_Controller.PSObject.Copy()

                "[{0}] Processing {1} Controller" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_Controller.slotNumber | Write-Verbose
                
                #Check if controll has imporrtConfiguration set to True, which is unsupported with SPT
                if ($_Controller.importConfiguration)
                {

                    $Message = "The StorageController configuration contains the -ImportExistingConfiguration option set, which is not supported with Server Profile Templates."
                    $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedImportConfigurationSetting InvalidOperation "StorageController" -TargetType 'PSObject' -Message $Message
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)                        

                }

                #Validate the SHT.storageCapabilities controllerModes -> mode, raidLevels -> logicalDrives.raidLevel and maximumDrives -> numPhysicalDrives
                if ($ServerHardwareType.storageCapabilities.controllerModes -notcontains $_Controller.mode)
                {

                    $_ExceptionMessage = "Unsupported LogicalDisk policy with Virtual Machine Appliance. The requested Controller Mode '{0}' is not supported with the expected Server Hardware Type, which only supports '{1}'" -f $_Controller.mode, ([System.String]::Join($ServerHardwareType.storageCapabilities.controllerModes,"', '")) 
                    $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedImportConfigurationSetting InvalidOperation "StorageController" -TargetType 'PSObject' -Message $_ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $_l = 1

                "[{0}] Storage Controller has {1} LogicalDrives to Process" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_Controller.logicalDrives.count | Write-Verbose

                "[{0}] Server Hardware supports '{1}' drives." -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerHardwareType.storageCapabilities.maximumDrives | Write-Verbose

                $_NewLogicalDisksCollection = New-Object System.Collections.ArrayList

                #Validate the SHT.storageCapabilities .raidLevels -> logicalDrives.raidLevel and .maximumDrives -> numPhysicalDrives
                ForEach ($_ld in $_Controller.logicalDrives)
                {

                    "[{0}] Processing {1} of {2} LogicalDisk: {3}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_l, $_Controller.logicalDrives.count, $_ld.name | Write-Verbose

                    "[{0}] {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_ld | Out-String) | Write-Verbose

                    if ($_ld.PSObject.Properties.Match('SasLogicalJBOD').Count)
                    {

                        "[{0}] Processing SasLogicalJbod {1} (ID:{2}) in Controller {3}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ld.SasLogicalJBOD.name, $_ld.SasLogicalJbodId, $_Controller.deviceSlot | Write-Verbose

                        If ($ApplianceConnection.ApplianceType -ne 'Composer')
                        {

                            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. The LogicalDisk within the StorageController contains a SasLogicalJbod configuration with is only supported with HPE Synergy.' -f $ApplianceConnection.Name)
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        [void]$_spt.localStorage.sasLogicalJBODs.Add($_ld.SasLogicalJBOD)

                    }

                    if ($ServerHardwareType.storageCapabilities.raidLevels -notcontains $_ld.raidLevel)
                    {

                        $_ExceptionMessage = "Unsupported LogicalDisk RAID Level '{0}' policy with '{1}' logical disk. The Server Hardware Type only supports '{2}' RAID level(s). " -f $_ld.raidLevel, $_ld.name, [System.String]::Join("', '",$ServerHardwareType.storageCapabilities.raidLevels) 
                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedLogicalDriveRaidLevel InvalidOperation "StorageController" -TargetType 'PSObject' -Message $_ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if ($_ld.numPhysicalDrives -gt $ServerHardwareType.storageCapabilities.maximumDrives)
                    {

                        $_ExceptionMessage = "Invalid number of drives requested '{0}'. The Server Hardware Type only supports a maximum of '{1}'." -f $_ld.numPhysicalDrives, $ServerHardwareType.storageCapabilities.maximumDrives 
                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedNumberofDrives InvalidOperation "StorageController" -TargetType 'PSObject' -Message $_ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    $_ld = $_ld | Select * -ExcludeProperty SasLogicalJBOD

                    [Void]$_NewLogicalDisksCollection.Add($_ld)

                    $_l++

                }

                $_Controller.logicalDrives = $_NewLogicalDisksCollection

                $_Controller = $_Controller | Select * -Exclude importConfiguration

                [void]$_spt.localStorage.controllers.Add($_Controller)    
            
            }
                                                        
        }

        #StRM Support
        if ($PSBoundParameters['SANStorage'] -and $ServerHardwareType.capabilities -Contains 'VCConnections')
        { 

            "[{0}] SAN Storage being requested" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_spt.sanStorage = [pscustomobject]@{
                
                hostOSType        = $ServerProfileSanManageOSType.($HostOsType);
                manageSanStorage  = [bool]$SANStorage;
                volumeAttachments = New-Object System.Collections.ArrayList
            
            }

            $_AllNetworkUrisCollection  = New-Object System.Collections.ArrayList

            #Build list of network URI's from connections
            ForEach ($_Connection in $_spt.connectionSettings.connections) 
            {

                [void]$_AllNetworkUrisCollection.Add($_Connection.networkUri)

            }

            #Copy the Parameter array into a new object
            $_VolumesToAttach = New-Object System.Collections.ArrayList

            $StorageVolume | % { 

                if ($_)
                {
                
                    [void]$_VolumesToAttach.Add($_)

                }
                
            }
            
            "[{0}] Number of Volumes to Attach: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_VolumesToAttach.Count | Write-Verbose

            $_v = 0
            
            foreach ($_Volume in $_VolumesToAttach) 
            {  

                $_v++

                "[{0}] Processing Volume {1} of {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_v, $_VolumesToAttach.Count | Write-Verbose

                #Ephemeral Volume Support
                if ($_Volume.volumeStoragePoolUri)
                {

                    $_uri = "{0}?networks='{1}'&filter=uri='{2}'" -f $ReachableStoragePoolsUri, ([String]::Join(',', $_AllNetworkUrisCollection.ToArray())), $_Volume.volumeStoragePoolUri
                    $_VolumeName = $_Volume.volumeName
                    $_VolumeUri  = 'StoragePoolUri:{0}' -f $_Volume.volumeStoragePoolUri

                }

                #Provisioned Volume Support
                else
                {

                    $_uri = "{0}?networks='{1}'&filter=name='{2}'" -f $AttachableStorageVolumesUri, ([String]::Join(',', $_AllNetworkUrisCollection.ToArray())), $_Volume.name
                    $_VolumeUri = $_Volume.uri

                    Try
                    {

                        $_VolumeName = (Send-HPOVRequest -uri $_Volume.volumeUri).Name

                    }

                    catch
                    {

                        $PSCmdlet.ThrwoTerminatingError($_)

                    }                        

                }

                "[{0}] Processing Volume ID: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_Volume.id | Write-Verbose 
                "[{0}] Looking to see if volume '{1} ({2})' is attachable" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_VolumeName, $_VolumeUri |Write-Verbose 

                try
                {

                    $_resp = Send-HPOVRequest -Uri $_uri -appliance $ApplianceConnection

                }

                catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                #members found
                if ($_resp.count -gt 0)
                {

                    "[{0}] '{1} ({2})' volume is attachable" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_VolumeName, $_VolumeUri | Write-Verbose

                    if (($_Volume.id -eq 0) -or (-not($_Volume.id)))
                    {

                        "[{0}] No VolumeID value provided. Getting next volume id value." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        $id = 1

                        $Found = $false

                        While (-not $Found -and $id -lt 256)
                        {

                            if (-not($_VolumesToAttach | ? id -eq $id))
                            {

                                "[{0}] Setting Volume ID to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $id | Write-Verbose

                                $_Volume.id = $id

                                $Found = $true

                            }

                            $id++

                        }

                    }

                    #If the storage paths array is null, Process connections to add mapping
                    if ($_Volume.storagePaths.Count -eq 0)
                    {

                        "[{0}] Storage Paths value is Null. Building connection mapping." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        #This should only be 1 within members array
                        foreach ($_member in $_resp.members) 
                        {

                            #write-verbose "Looking for $volConnection"

                            if ($_Member.deviceSpecificAttributes.iqn -or $_Member.family -eq 'StoreVirtual')
                            {

                                "[{0}] Looking for Ethernet connections." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                $_StorageTypeUri = '/rest/ethernet-networks'
                                
                            }

                            else
                            {

                                "[{0}] Looking for FC/FCoE connections." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                $_StorageTypeUri = '/rest/fc'

                            }

                            #Figure out which connections "should" map based on identified storage connectivity type
                            [Array]$_ProfileConnections = $_spt.connectionSettings.connections | ? { $_.networkUri.StartsWith($_StorageTypeUri) }

                            "[{0}] Number of connections that match the volume connectivity type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ProfileConnections.Count | Write-Verbose

                            if ($_ProfileConnections.Count -gt 0)
                            {

                                "[{0}] Connections that match the volume connectivity type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [String]::Join(', ', [Array]$_ProfileConnections.id) | Write-Verbose

                            }

                            [Array]$_ReachableNetworkUris = $_Member.reachableNetworks | ? { $_.StartsWith($_StorageTypeUri) }

                            "[{0}] Number of reachable networks that match the volume connectivity type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ReachableNetworkUris.Count | Write-Verbose

                            if ($_ReachableNetworkUris.Count -gt 0)
                            {

                                "[{0}] Reachable networks that match the volume connectivity type: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), [String]::Join(', ', [Array]$_ReachableNetworkUris) | Write-Verbose

                            }

                            ForEach ($_ReachableNetworkUri in $_ReachableNetworkUris)
                            {

                                "[{0}] Processing reachable network URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ReachableNetworkUri | Write-Verbose

                                ForEach ($_ProfileConnection in ($_ProfileConnections | ? { $_.networkUri -eq $_ReachableNetworkUri }))
                                {

                                    "[{0}] Mapping connectionId '{1}' -> volumeId '{2}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ProfileConnection.id, $_Volume.id | Write-Verbose

                                    $_StoragePath = NewObject -StoragePath

                                    $_StoragePath.connectionId = $_ProfileConnection.id
                                    $_StoragePath.isEnabled    = $True

                                    [void]$_Volume.storagePaths.Add($_StoragePath)

                                }

                            }

                            if ($_Volume.storagePaths.Count -eq 0)
                            {

                                Write-Warning ('No available connections were found that could attach to {0} Storage Volume. Storage Volumes may not be attached.' -f $_VolumeName)

                            }

                            [void]$_spt.sanStorage.volumeAttachments.Add($_Volume)

                        }

                    }

                    else
                    {
                    
                        [void]$_spt.sanStorage.volumeAttachments.Add($_Volume)
                    
                    }

                }

                #no members found, generate exception
                else
                {

                    $ExceptionMessage = "'{0}' Volume is not available to be attached to the profile. Please check the volume or available storage pools and try again."  -f $VolumeName
                    $ErrorRecord = New-ErrorRecord InvalidOperationException StorageVolumeUnavailableForAttach ResourceUnavailable 'StorageVolume' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

        }

        "[{0}] Profile JSON Object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_spt | ConvertTo-Json -depth 99) | Write-Verbose

        Try
        {

            $resp = Send-HPOVRequest -uri $ServerProfileTemplatesUri -Method POST -Body $_spt -appliance $ApplianceConnection

        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($PSBoundParameters['Async'])
        {

            $Resp

        }

        else
        {

            Try
            {

                $Resp | Wait-HPOVTaskComplete -OutVariable Resp

                if ($Resp.taskState -eq 'Error')
                {

                    $ExceptionMessage = $resp.taskErrors.message
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileTemplateResourceException InvalidOperation InvalidOperation 'AsyncronousTask' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
    
    }    

}

#// TODO DEVELOP DOCUMENTATION TEST
function Set-HPOVServerProfileTemplate
{

    Throw "Not implemented."

}

function Join-HPOVServerProfileToTemplate 
{
        
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ("t")]
        [object]$Template,

        [Parameter (Mandatory)]
        [Alias ("p", 'Profile')] 
        [object]$ServerProfile,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = $Global:ConnectedSessions

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
        #If multiple appliance connections check for URI values in the Parameters
        If($ApplianceConnection.count -gt 1)
        {
            
            If ($template -is [string] -and $template.startswith('/rest/'))
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $template"

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidTemplateParameter InvalidArgument 'Template' -Message "Template Parameter as URI is not supported with multiple appliance connections."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            If ($profile -is [string] -and $profile.startswith('/rest/'))
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $profile"

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidProfileParameter InvalidArgument 'Profile' -Message "Profile Parameter as URI is not supported with multiple appliance connections."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        $uri = $ServerProfilesUri

        $colStatus = New-Object System.Collections.ArrayList

    }
    
    Process 
    {
        
        ForEach($_Connection in $ApplianceConnection)
        {
        
            #Process the template Parameter
            #Template passed as string
            if ($template -is [string])
            {
                
                #If the URI is passed as set the Template Uri variable. Should not Process if multiple connections identified
                if ($template.StartsWith('/rest'))
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Template URI: $template"
                    $templateUri = $template
            
                }

                #Otherwise, perform a lookup of the Enclosure Group
                else
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Template Name: $template"                        
                
                    Try 
                    {

                        $templateUri = (Get-HPOVServerProfileTemplate -Name $template -appliance $ApplianceConnection -ErrorAction Stop).Uri

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                
                }

            }
                                    
            #Else the template object or template object collection is passed
            elseif (($template -is [Object]) -and ($template.category -eq "server-profile-templates")) 
            { 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Template object provided"

                $thisTemplate = $template | ? { $_.ApplianceConnection.name -eq $_Connection.name }

                $templateUri = $thisTemplate.uri

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Name: $($thisTemplate.name)"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Uri: $($thisTemplate.uri)"

            }

            #Process the profile Parameter
            #profile passed as string
            if ($ServerProfile -is [string])
            {
                
                #If the URI is passed as set the Template Uri variable. Should not Process if multiple connections identified
                if ($ServerProfile.StartsWith('/rest'))
                { 

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Template URI: $ServerProfile"

                    Try
                    {

                        $thisProfile = Send-HPOVRequest $ServerProfile -appliance $_Connection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                
                }

                #Otherwise, perform a lookup of the Enclosure Group
                else
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Template Name: $ServerProfile"                        
                
                    Try
                    {

                        $thisProfile = Get-HPOVServerProfile -Name $ServerProfile -appliance $_Connection -ErrorAction Stop

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }
                                    
            #Else the template object or template object collection is passed
            elseif (($ServerProfile -is [Object]) -and ($ServerProfile.category -eq "server-profiles")) 
            { 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Profile object provided"

                $thisProfile = $ServerProfile | ? { $_.ApplianceConnection.name -eq $_Connection.name }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Name: $($thisProfile.name)"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Enclosure Group Uri: $($thisProfile.uri)"

            }

            if ($thisProfile.ApplianceConnection.name -eq $_Connection.name)
            {
                
                $thisProfile.serverProfileTemplateUri = $templateUri

                Try
                {

                    $task = Set-HPOVResource $thisProfile -appliance $_Connection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                [void]$colStatus.Add($task)

            }

        }

    } #End Process Block

    End 
    {

        return $colStatus

    }

}

function ConvertTo-HPOVServerProfileTemplate
{
    
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (
    
        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ("source",'ServerProfile')]
        [Object]$InputObject,

        [Parameter (Mandatory = $False)] 
        [String]$Name,

        [Parameter (Mandatory = $False)] 
        [String]$Description,

        [Parameter (Mandatory = $False)] 
        [Switch]$Async,

        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($PSBoundParameters['InputObject']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $_connection -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process
    {

        #Process Pipeline Input here
        if ($InputObject -is [PSCustomObject])
        {

            "[{0}] Received Server Profile object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

            $_ProfileToConvert = $InputObject.PSObject.Copy()
            $_SourceName       = $InputObject.name.Clone()

        }

        #Process everything else
        else
        {

            "[{0}] Received Server Profile name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

            Try
            {

                $_ProfileToConvert = Get-HPOVServerProfile -Name $InputObject -ErrorAction Stop
                $_SourceName       = $InputObject.Clone()

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
        }

        #Generate SPT from API
        try
        {

            $_uri = '{0}/new-profile-template' -f $_ProfileToConvert.uri

            $_ConvertedSPT = Send-HPOVRequest -Uri $_uri -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($PSBoundParameters['Name'])
        {

            $_ConvertedSPT.name = $Name

        }

        else
        {

            $_ConvertedSPT.name = "Temporary Name - {0}" -f $_SourceName
        
        }

        if ($PSBoundParameters['Description'])
        {

            $_ConvertedSPT.description = $Description

        }

        else
        {

            $_ConvertedSPT.description = "Created from '{0}' source Server Profile." -f $_SourceName

        }

        try
        {

            $_uri = '{0}/new-profile-template' -f $_ProfileToConvert.uri

            $_result = Send-HPOVRequest -Uri $ServerProfileTemplatesUri -Method POST -Body $_ConvertedSPT -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not $PSBoundParameters['Async'])
        {

            $_result | Wait-HPOVTaskComplete

        }

        else
        {

            $_result

        }                

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function New-HPOVServerProfileAssign 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, valuefrompipeline, ParameterSetName = "Unassigned")]
        [Parameter (Mandatory, valuefrompipeline, ParameterSetName = "Default"   )]
        [ValidateNotNullOrEmpty()]
        [Alias ('Profile')]
        [Object]$ServerProfile,
        
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Object]$Server,
        
        [Parameter (Mandatory = $false, ParameterSetName = "Unassigned")]
        [switch]$Unassigned,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Unassigned")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['ServerProfile']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose


            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }     

        $_taskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        #Look at Profile and Server if they are objects, and make sure ApplianceConnection.Name match
        if ($ServerProfile -is [PSCustomObject] -and $Server -is [PSCustomObject])
        {

            if ($ServerProfile.ApplianceConnection.Name -ne $Server.ApplianceConnection.Name)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Profile ($($ServerProfile.ApplianceConnection.Name)) and Server Hardware ($($Server.ApplianceConnection.Name)) ApplianceConnection noteproperties do not match."

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ProfileAndServerApplianceConnectionMismatch InvalidArgument 'Profile' -TargetType 'PSObject' -Message "The Server Profile ($($ServerProfile.ApplianceConnection.Name)) and Server Hardware ($($Server.ApplianceConnection.Name)) ApplianceConnection NoteProperty do not match. Please correct the value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        #Looking for the $server DTO to be string
        if ($ServerProfile -is [string]) 
        {

            try 
            { 
                
                $ServerProfile = Get-HPOVServerProfile -name $ServerProfile -ApplianceConnection $ApplianceConnection -ErrorAction Stop
            
            }
            
            catch
            {

                $PSCmdlet.ThrowTerminatingError($_)
                
            }

        }

        elseif ($ServerProfile -is [PSCustomObject] -and $ServerProfile.category -ne 'server-profiles')
        {

            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ProfileObjectInvalidCategory InvalidArgument 'Profile' -TargetType 'PSObject' -Message "The Server Profile ($($ServerProfile.name)) is an unsupported resource category type, '$($ServerProfile.category)'. Only 'server-profiles' are supported. Please correct the value and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Profile Object: $($ServerProfile | out-string)"
        
        #Check to make sure the server hardware the profile is assigned to is powered off
        if ($ServerProfile.serverHardwareUri) 
        {

            Try
            {

                $_ServerResource = Send-HPOVRequest $ServerProfile.serverHardwareUri -Hostname $ServerProfile.ApplianceConnection.Name

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($_ServerResource.powerState -ne "Off") 
            {

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException InvalidServerPowerState InvalidResult 'Profile' -Message "The Server '$($_ServerResource.name)' is currently powered On. Please power off the server and then perform the operation again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        #Looking for the $server DTO to be string
        if ($Server -is [string]) 
        {

            try 
            { 

                $Server = Get-HPOVServer -name $Server -ApplianceConnection $ApplianceConnection

            }

            catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        elseif ($Server -is [PSCustomObject] -and $Server.category -ne 'server-hardware')
        {

            $ErrorRecord = New-ErrorRecord HPOneView.ServerHardwareResourceException ServerObjectInvalidCategory InvalidArgument 'Server' -TargetType 'PSObject' -Message "The Server ($($Server.name)) is an unsupported resource category type, '$($Server.category)'. Only 'server-hardware' are supported. Please correct the value and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Object: $($Server | out-string)"
        
        if ($PSBoundParameters['Unassigned'])
        {

            $ServerProfile.serverHardwareUri = $Null
            
            if ($ServerProfile.enclosureUri) 
            {

                $ServerProfile.enclosureUri      = $Null
                $ServerProfile.enclosureBay      = $Null    

            }

        }

        else 
        {

            if ($Server.serverHardwareTypeUri -ne $ServerProfile.serverHardwareTypeUri) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server Profile assigned serverHardwareTypeUri does not match the destination Server resource. Updating Server Profile with new serverHardwareTypeUri value."

                $ServerProfile.serverHardwareTypeUri = $Server.serverHardwareTypeUri
            
            }

            $ServerProfile.serverHardwareUri = $server.uri

            if ($server.locationUri) 
            {

                $ServerProfile.enclosureUri = $server.locationUri
                $ServerProfile.enclosureBay = $server.position    

            }            

        }

        try 
        { 

            $_resp = Send-HPOVRequest $ServerProfile.uri PUT $ServerProfile -Hostname $ApplianceConnection.Name

        }

        catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        [void]$_taskCollection.Add($_resp)
        

    }

    End 
    {

        return $_taskCollection

    }

}

function Copy-HPOVServerProfile 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding ()]
    Param
    (
    
        [Parameter (Mandatory, ValueFromPipeline)]
        [Alias ('sname','src','SourceName')]
        [ValidateNotNullOrEmpty()]
        [object]$InputObject,
        
        [Parameter (Mandatory = $false)]
        [Alias ('dname','dst')]
        [string]$DestinationName,
        
        [Parameter (Mandatory = $false)]
        [object]$assign = "unassigned",

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
        if($ApplianceConnection.count -gt 1)
        {
        
            # Check for appliance specific URI Parameters and error if more than one appliance connection supplied
            if (($InputObject -is [string]) -and ($InputObject.StartsWith($ServerProfilesUri))) 
            {
                    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] InputObject is a Server Profile URI: $($InputObject)"
                $ErrorRecord = New-ErrorRecord ArgumentNullException ParametersNotSpecified InvalidArgument 'InputObject' -Message "The input Parameter 'InputObject' is a URI. For multiple appliance connections this is not supported."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
            }

            if (($assign -is [string]) -and ($assign.StartsWith($ServerHardwareUri))) 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Assign is a Server Profile URI: $($SourceName)"
                $ErrorRecord = New-ErrorRecord ArgumentNullException ParametersNotSpecified InvalidArgument 'Assign' -Message "The input Parameter 'Assign' is a URI. For multiple appliance connections this is not supported."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

        }

        $taskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        if (!$InputObject) 
        { 
        
            $ErrorRecord = New-ErrorRecord ArgumentNullException ParametersNotSpecified InvalidArgument 'InputObject' -Message "The input Parameter 'InputObject' was Null. Please provide a value and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
        }

        if (($InputObject -is [string]) -and (!$InputObject.StartsWith($ServerProfilesUri))) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] InputObject is a Server Profile Name: $($InputObject)"
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting Server Profile URI"

            Try
            {

                $_Profile = Get-HPOVServerProfile -Name $InputObject -appliance $ApplianceConnection -ErrorAction Stop
                
                $profileSourceSHT = $_Profile.serverHardwareTypeUri

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Checking if the input is System.String and IS a URI - Should not Process on multi-appliance connections
        elseif (($InputObject -is [string]) -and ($InputObject.StartsWith($ServerProfilesUri))) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] InputObject is a Server Profile URI: $($InputObject)"

            Try
            {

                $_Profile = Send-HPOVRequest -uri $InputObject -appliance $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
            $profileSourceSHT = $_Profile.serverHardwareTypeUri
        
        }

        #Checking if source is object or object collection
        elseif (($InputObject -is [PSCustomObject]) -and ($InputObject.category -ieq "server-profiles")) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] InputObject is a Server Profile object: $($InputObject.name)"
            #For multi-appliance connections retrieve the source object only for this connection
            $_Profile = $InputObject.PSObject.Copy()

            $profileSourceSHT = $InputObject.serverHardwareTypeUri
        
        }

        else 
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message "The Parameter -InputObject value is invalid. Please validate the InputObject Parameter value you passed and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($assign -ine 'unassigned') 
        {
            
            #Target Server is the server device name. Could be any empty bay assignment
            if (($assign -is [string]) -and (-not ($assign.StartsWith($ServerHardwareUri)))) 
            {
                
                # Get-HPOVServer needs to be in a try/catch since it may be an empty bay
                Try
                {
                
                    $serverDevice = Get-HPOVServer -Name $assign -appliance $ApplianceConnection
                    
                }
                
                Catch 
                {
                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($assign) server resource does not exist."
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Check for empty bay assignment."

                    Try
                    {

                        if(!$serverDevice -and ($assign -match "bay"))
                        {
                            

                            $assign = $assign.split(',').trim()

                            try
                            {

                                $thisEnc = Get-HPOVEnclosure -Name $assign[0] -appliance $ApplianceConnection -ErrorAction Stop

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }
                            
                            [int]$thisBay = (($assign[1]) -replace "bay", "").trim()

                            $presence = $thisEnc.deviceBays[($thisBay - 1)].devicePresence
                            
                            #if presence is null, invalid device bay
                            if(!$presence) 
                            {
                            
                                $ErrorRecord = New-ErrorRecord ArgumentNullException ParametersNotSpecified InvalidArgument 'Copy-HPOVProfile' -Message "The bay number $thisBay is not valid or not present."

                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                            }
                            
                            else 
                            {
                            
                                $_Profile.enclosureGroupUri = $thisEnc.uri
                                $_Profile.enclosureBay = $thisBay
                                $profileDestSHT = $profileSourceSHT
                            
                            } 
                        
                        }

                        else 
                        {
                        
                            $profileDestSHT = $serverDevice.serverHardwareTypeUri
                            
                        }
                        
                    }

                    Catch 
                    {
                    
                        $PSCmdlet.ThrowTerminatingError($_)
                        
                    }
                        
                }                    
                
            }

            #Checking if the input is System.String and IS a URI
            elseif (($assign -is [string]) -and ($assign.StartsWith($ServerHardwareUri))) 
            {
            
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Assign to the Server hardware URI: $($assign)"

                Try
                {

                    $serverDevice = Send-HPOVRequest $assign -appliance $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                                    
                $profileDestSHT = $serverDevice.serverHardwareTypeUri
        
            }

            #Checking if the input is PSCustomObject, and the category type is server-profiles, which would be passed via pipeline input
            elseif (($assign -is [PSCustomObject]) -and ($assign.category -ieq "server-hardware")) 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Assign to the Server object: $($assign.name)"

                $serverDevice = $assign | ? { $_.applianceConnection.name -eq $_Connection.name }
                $profileDestSHT = $serverDevice.serverHardwareTypeUri
        
            }

            else 
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Copy-HPOVProfile' -Message "The Parameter -Assign value is invalid. Please validate the Assign Parameter value you passed and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Checking if the input is PSCustomObject, and the category type is server-hardware, which would be passed via pipeline input
            if ($serverDevice.serverProfileUri) 
            {

                $ExceptionMessage = "A server profile is already assigned to {0} ({1}). Please try specify another server." -f $serverDevice.name, (Send-HPOVRequest $serverDevice.serverProfileUri -appliance $ApplianceConnection).name
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerPropfileResourceAlreadyExists ResourceExists 'ServerProfile' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)                
        
            }

        }

        elseif ($assign -ieq "unassigned") 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Server will be unassigned"

        }

        #Check to see if the SHT is different from the Profile and Target Assign Server
        if (($profileDestSHT -ine $profileSourceSHT) -and ($assign -ine "unassigned") -and (!$_Profile.enclosureBay))
        {
        
            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException ServerHardwareTypeMismatch InvalidOperation 'Copy-HPOVProfile' -Message "The Target Server Hardware Type does not match the source Profile Server Hardware Type. Please specify a different Server Hardware Device to assign."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)          
                
        }

        #Remove Profile Specifics:
        $_Profile = $_Profile | select-object -Property * -excludeproperty uri,etag,created,modified,uuid,status,state,inprogress,serialNumber,enclosureUri,enclosureBay,serverHardwareUri,taskUri #,sanStorage

        $newConnections = New-Object System.Collections.ArrayList
        #Create new connections with excluded properties and add to the newConnections array

        '[{0}] Rebuilding fabric connections' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        $_Profile.connections | select-object -property * -excludeproperty mac,wwnn,wwpn,deploymentstatus,interconnectUri, applianceConnection | % {
        
            #Assign the newConnections array to $_Profile.connections
            [void]$newConnections.Add($_)
        
        }

        $_Profile.connections = $newConnections

        #Process SAN Volume Attachments
        if ($_Profile.sanStorage -and $_Profile.sanStorage.volumeAttachments) 
        { 

            $newVolumeAttachments = @()
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing SAN Volume Attachments"

            ForEach ($attachVolume in $_Profile.sanStorage.volumeAttachments ) 
            {

                $tempVolume = [PSCustomObject]@{}
        
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found attached volume ID $($attachVolume.id). Getting Volume properties."

                Try
                {

                    $volume = Send-HPOVRequest $attachVolume.volumeUri -appliance $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                #Process shared volume
                if ($volume.shareable) 
                {
        
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding Shareable Volume."

                    $tempVolume = $attachVolume | Select-Object id,volumeUri,lunType,lun,storagePaths
                    $tempVolume.lun = $Null
                    $tempVolume.storagePaths = ($attachVolume.storagePaths | % { $_ | select-object * -exclude status } )

                }

                #Process private volume
                else 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding Private Volume."

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Checking for unique volume name."

                    #Get list of existing volumes from Index
                    
                    Try
                    {
                        
                        $indexVolumes = Send-HPOVRequest ($indexUri + "?category=storage-volumes&count=-1&start=0&sort=name:asc") -appliance $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    $regex = " \((([0-9]|[1-9][0-9]|[1-9][0-9][0-9])+)\)"

                    $tempVolumeName = $volume.name -replace $regex,""

                    for ($i = 1; $i -le $volume.name.length; $i++) 
                    {
                    
                        if (-not ($indexVolumes.members -contains ($tempVolumeName + " ($i)"))) 
                        {
        
                            $attachVolumeName = $tempVolumeName + " ($i)"
                            
                            #verify the name is unique by searching the index.
                            Try
                            {
                            
                                $results = Send-HPOVRequest ($indexUri + "?category=storage-volumes&filter=name='$attachVolumeName'&count=-1&start=0&sort=name:asc") -appliance $ApplianceConnection
                            
                            }
                            
                            Catch
                            {
                            
                                $PSCmdlet.ThrowTerminatingError($_)
                            
                            }

                            if ($results.count -eq 0) 
                            {    

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting Volume Name to '$attachVolumeName'."
                                break

                            }

                        }

                    }

                    $tempVolume | Add-Member -NotePropertyName id -NotePropertyValue $attachVolume.id
                    $tempVolume | Add-Member -NotePropertyName volumeName -NotePropertyValue $attachVolumeName
                    $tempVolume | Add-Member -NotePropertyName volumeUri -NotePropertyValue $Null
                    $tempVolume | Add-Member -NotePropertyName volumeStoragePoolUri -NotePropertyValue $attachVolume.volumeStoragePoolUri 
                    $tempVolume | Add-Member -NotePropertyName volumeStorageSystemUri  -NotePropertyValue $attachVolume.volumeStorageSystemUri 
                    $tempVolume | Add-Member -NotePropertyName volumeProvisionType  -NotePropertyValue $volume.provisionType
                    $tempVolume | Add-Member -NotePropertyName volumeProvisionedCapacityBytes  -NotePropertyValue $volume.provisionedCapacity
                    $tempVolume | Add-Member -NotePropertyName volumeShareable   -NotePropertyValue $False
                    $tempVolume | Add-Member -NotePropertyName lunType   -NotePropertyValue $attachVolume.lunType
                    
                    if ($attachVolume.lunType -eq "Auto") { $tempVolume | Add-Member -NotePropertyName lun  -NotePropertyValue $Null }
                    else { $tempVolume | Add-Member -NotePropertyName lun  -NotePropertyValue $attachVolume.lun }
                    
                    $tempVolume | Add-Member -NotePropertyName storagePaths  -NotePropertyValue ($attachVolume.storagePaths | % { $_ | select-object * -exclude status } )
                    $tempVolume | Add-Member -NotePropertyName permanent -NotePropertyValue $volume.isPermanent

                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Copied volume details: $($tempVolume | out-string)"

                $newVolumeAttachments += $tempVolume

            }

            $_Profile.sanStorage.volumeAttachments = $newVolumeAttachments

        }

        #Need to parse through local storage policies to null out Logical Drive ID
        if ($_Profile.localStorage.controllers.Count -gt 0)
        {

            ForEach ($_controller in $_Profile.localStorage.controllers)
            {

                For ($_ld = 0; $_ld -lt $_controller.logicalDrives.Count; $_ld++)
                {

                    '[{0}] Setting "{1}" Controller Logical Drive "{2}" drive number to null' -f $MyInvocation.InvocationName.ToString().ToUpper(), $_controller.deviceSlot, $_controller.logicalDrives[$_ld].name | Write-Verbose

                    $_controller.logicalDrives[$_ld].driveNumber = $null

                }

            }

        }

        #Set iscsiInitiatorName to null
        $_Profile.iscsiInitiatorName = $null

        #If DestinationName is provided, change to the profile name to value
        if ($DestinationName) 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Server Profile name provided $($DestinationName)"
            $_Profile.name = $destinationName
        
        }
        
        #If no DestinationName is provided, add "Copy Of " prefix.
        else 
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No new Server Profile name provided. Setting to `"Copy of $($_Profile.name)`""
            $_Profile.name = "Copy of {0}" -f $_Profile.name

        }

        #If the server hardware device is present, add the property to the object
        if ($serverDevice) 
        {

            $_Profile | Add-Member @{ serverHardwareUri = $serverDevice.Uri }
        
        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Server Profile object: $($_Profile | out-string)"
        
        #Send request to create new copied profile
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request"
        
        Try
        {
        
            $resp = Send-HPOVRequest -Uri $ServerProfilesUri -Method POST -Body $_Profile -appliance $ApplianceConnection
        
        }
        
        Catch
        {
        
            $PSCmdlet.ThrowTerminatingError($_)
        
        }
        
        [void]$taskCollection.Add($resp)

    }

    End 
    {
        
        return $taskCollection

    }

}

function Remove-HPOVServerProfile 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('uri','name','profile')]
        [Object]$ServerProfile,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Switch]$force
    
    )

   Begin 
   {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['ServerProfile']))
        {

            $PipelineINput = $true

        }
        
        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        if($ApplianceConnection.count -gt 1)
        {

            # Check for appliance specific URI Parameters and error if more than one appliance connection supplied
            if (($ServerProfile -is [string]) -and ($ServerProfile.StartsWith($ServerProfilesUri))) 
            {
                    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SourceName is a Server Profile URI: $($ServerProfile)"
                $ErrorRecord = New-ErrorRecord ArgumentNullException ParametersNotSpecified InvalidArgument 'Remove-HPOVServerProfile' -Message "The input Parameter 'profile' is a resource URI. For multiple appliance connections this is not supported."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            }

            if (($ServerProfile -is [array]) -and ($ServerProfile.getvalue(0).gettype() -is [string]) -and $ServerProfile -match '/rest/') 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Assign is a Server Profile URI: $($SourceName)"
                $ErrorRecord = New-ErrorRecord ArgumentNullException ParametersNotSpecified InvalidArgument 'Remove-HPOVServerProfile' -Message "The input Parameter 'profile' is a resource URI. For multiple appliance connections this is not supported."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

        }

        $taskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Profile input type: $($ServerProfile.gettype())"

        foreach ($_profile in $ServerProfile) 
        {

            if ($_profile -is [String] -and (-not($_profile.StartsWith.($ServerProfilesUri)))) 
            {

                Try
                {

                    $_profile = Get-HPOVServerProfile -Name $_profile -ApplianceConnection $ApplianceConnection -ErrorAction Stop

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($_profile -is [String])
            {

                Try
                {

                    $_profile = Send-HPOVRequest $_profile -Hostname $ApplianceConnection

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($_profile -is [PSCustomObject] -and $_profile.category -ine 'server-profiles') 
            {
                
                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'SeverProfile' -Message ("Invalid profile object provided: {0}. Please verify the object and try again." -f $_profile.name )
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if ($PSCmdlet.ShouldProcess($ApplianceConnection.Name,("remove Server Profile {0} from appliance?" -f $_profile.name )))
            {   
                
                $uri = $_profile.uri

                if ($PSBoundParameters['Force'])
                {

                    $uri += '?force=true'

                }

                Try
                {

                    $_resp = Send-HPOVRequest $uri DELETE -Hostname $ApplianceConnection

                    [void]$taskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['Whatif'])
            {

                "[{0}] -WhatIf provided." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] User cancelled." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

    }

    End
    {

        Return $taskCollection

    }

}

function Remove-HPOVServerProfileTemplate
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdLetBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('spt','name')]
        [Object]$ServerProfileTemplate,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Switch]$force
    
    )

   Begin 
   {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['ServerProfileTemplate']))
        {

            $PipelineINput = $true

        }
        
        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {
                
                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
                    
                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        if($ApplianceConnection.count -gt 1)
        {

            # Check for appliance specific URI Parameters and error if more than one appliance connection supplied
            if (($ServerProfileTemplate -is [string]) -and ($ServerProfileTemplate.StartsWith($ServerProfileTemplatessUri))) 
            {
                    
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SourceName is a Server Profile Template URI: $($ServerProfileTemplate)"

                $ErrorRecord = New-ErrorRecord ArgumentNullException ParametersNotSpecified InvalidArgument 'ServerProfileTemplate' -Message "The input Parameter 'ServerProfileTemplate' is a resource URI. For multiple appliance connections this is not supported."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            }

            if (($ServerProfileTemplate -is [array]) -and ($ServerProfileTemplate.getvalue(0).gettype() -is [string]) -and $ServerProfileTemplate -match '/rest/') 
            {
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Assign is a Server Profile URI: $($ServerProfileTemplate)"
                $ErrorRecord = New-ErrorRecord ArgumentNullException ParametersNotSpecified InvalidArgument 'ServerProfileTemplate' -Message "The input Parameter 'ServerProfileTemplate' is a resource URI. For multiple appliance connections this is not supported."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)
            
            }

        }

        $taskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Profile input type: $($ServerProfileTemplate.gettype())"

        foreach ($_spt in $ServerProfileTemplate) 
        {

            if ($_spt -is [String] -and (-not($_spt.StartsWith.($ServerProfileTemplatessUri)))) 
            {

                Try
                {

                    $_spt = Get-HPOVServerProfileTemplate -Name $_spt -ApplianceConnection $ApplianceConnection -ErrorAction Stop

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($_spt -is [String])
            {

                Try
                {

                    $_spt = Send-HPOVRequest -Uri $_spt -Hostname $ApplianceConnection

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($_spt -is [PSCustomObject] -and $_spt.category -ine 'server-profile-templates') 
            {
                
                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'ServerProfileTemplate' -Message ("Invalid profile template object provided: {0}. Please verify the object and try again." -f $_spt.name )
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if ($PSCmdlet.ShouldProcess($ApplianceConnection.Name,("remove Server Profile Template {0} from appliance?" -f $_spt.name )))
            {   
                
                $uri = $_spt.uri

                if ($PSBoundParameters['Force'])
                {

                    $uri += '?force=true'

                }

                Try
                {

                    $_resp = Send-HPOVRequest -uri $uri -method DELETE -Hostname $ApplianceConnection

                    [void]$taskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['Whatif'])
            {

                "[{0}] -WhatIf provided." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                "[{0}] User cancelled." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

    }

    End
    {

        Return $taskCollection

    }

}

function Get-HPOVServerProfileConnectionList 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding ()]
    Param 
    (
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $allConnections = New-Object System.Collections.ArrayList

    }

    Process 
    {
        
        ForEach($_Connection in $ApplianceConnection)
        {

            $profiles = New-Object System.Collections.ArrayList
    
            #get profiles
            if ($Name)
            {

                $uri = "{0}?filter=name='{1}'" -f $ServerProfilesUri, $Name

                Try
                {

                    $profile = (Send-HPOVRequest $uri -appliance $_Connection).members

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if (-not ($profile)) 
                { 

                    $ErrorRecord = New-ErrorRecord InvalidOperationException ProfileResourceNotFound ObjectNotFound 'Get-HPOVServerProfileConnectionList' -Message "Server Profile '$name' was not found."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }
            
                [void]$profiles.Add($profile)
    
            } 

            else 
            {

                Try
                {

                    $index = Send-HPOVRequest -Uri $ServerProfileIndexListUri -appliance $_Connection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

                if ($index.count -eq 0) 
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException ProfileResourceNotFound ObjectNotFound 'Get-HPOVServerProfileConnectionList' -Message "No Server Profile resources found. Use New-HPOVServerProfile to create one."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)            
                    
                }
    
                foreach ($entry in $index.members)
                {

                    Try
                    {

                        $profile = Send-HPOVRequest $entry.uri -appliance $_Connection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }
    
                    [void]$profiles.Add($profile)

                }     
                       
            }
    
            #get connections
            $conns = New-Object System.Collections.ArrayList

            foreach($p in $profiles)
            {
    
                foreach($c in $p.connections) 
                { 

                    Try
                    {

                        $c | add-member -membertype noteproperty -name cid -value $c.id;
                        $c | add-member -membertype noteproperty -name serverProfile -value $p.name;
                        $c | add-member -membertype NoteProperty -name Network -value (Send-HPOVRequest $c.networkUri -appliance $_Connection).Name
                        $c | Add-Member -NotePropertyName Appliance -NotePropertyValue $_Connection.name

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }                    

                    if($c.boot.targets) 
                    {

                        $c | add-member -membertype noteproperty -name arrayTarget -value $c.boot.targets[0].arrayWwpn
                        $c | add-member -membertype noteproperty -name lun -value $c.boot.targets[0].lun

                    }
    
                    if($c.portId) 
                    { 

                        $c.portId = $c.portId.Replace("Flexible", "")

                    } 

                    else 
                    {
                         
                        $name = "Dev:" + $c.deviceNumber + '-' + $c.physicalPortNumber

                        $c | add-member -membertype noteproperty -name portId -value $name

                    }
    
                   if($c.boot) { $c.boot = $c.boot.priority; }

                   if($c.boot -eq "NotBootable") { $c.boot = "-"; }      
                   
                   [void]$conns.Add($c)

                }

            }

            #output
            [void]$allConnections.Add($conns)
        
        }   

    }
    
    End 
    {

        $allConnections | Sort-Object serverProfile, cid | format-table -Property serverProfile, cid, portId, functionType, Network, mac, wwpn, boot, arrayTarget, lun, Appliance  -AutoSize

    } 

}

function New-HPOVServerProfileConnection 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdLetBinding (DefaultParameterSetName = "Common")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Common")]
        [Parameter (Mandatory, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory, ParameterSetName = "FC")]
        [Parameter (Mandatory, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [Alias ('id')]
        [int]$ConnectionID = 1,


        [Parameter (Mandatory = $false, ParameterSetName = "Common")]
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [ValidateSet ("Ethernet", "FibreChannel", "Eth", "FC", 'FCoE', 'iSCSI', IgnoreCase)]
        [Alias ('type')]
        [string]$ConnectionType = "Ethernet",

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Common")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "FC")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [object]$Network,

        [Parameter (Mandatory = $false, ParameterSetName = "Common")]
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [string]$PortId = "Auto",

        [Parameter (Mandatory = $false, ParameterSetName = "Common")]
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Common")]
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [ValidateRange(100,20000)]
        [int]$RequestedBW = 2500,
    
        [Parameter (Mandatory = $false, ParameterSetName = "Common")]
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [switch]$UserDefined,

        [Parameter (Mandatory = $false, ParameterSetName = "Common")]
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateScript({$_ -match $MacAddressPattern})]
        [string]$MAC,
    
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [ValidateScript({$_ -match $WwnAddressPattern})]
        [string]$WWNN,
        
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [ValidateScript({$_ -match $WwwnAddressPattern})]
        [string]$WWPN,

        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Int]$Virtualfunctions,
    
        [Parameter (Mandatory = $false, ParameterSetName = "Common")]
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [switch]$Bootable,

        [Parameter (Mandatory = $false, ParameterSetName = "Common")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateSet ('AdapterBIOS', 'ManagedVolume', 'UserDefined', IgnoreCase = $false)]
        [String]$BootVolumeSource = 'AdapterBIOS',
    
        [Parameter (Mandatory = $false, ParameterSetName = "Common")]
        [Parameter (Mandatory = $false, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [ValidateSet ('NotBootable', 'Primary', 'Secondary', 'IscsiPrimary', 'IscsiSecondary', IgnoreCase)]
        [string]$Priority = "NotBootable",
    
        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Alias ('ArrayWwpn')]
        [ValidateScript({$_ -match $WwnAddressPattern})]
        [string]$TargetWwpn,

        [Parameter (Mandatory = $false, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateRange(0,254)]
        [int]$LUN = 0,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateSet ('DHCP', 'UserDefined', 'SubnetPool', IgnoreCase)]
        [string]$IscsiIPv4AddressSource,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [string]$ISCSIInitatorName,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [Net.IPAddress]$IscsiIPv4Address,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [String]$IscsiIPv4SubnetMask,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [Net.IPAddress]$IscsiIPv4Gateway,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [string]$IscsiBootTargetIqn,
    
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [Net.IPAddress]$IscsiPrimaryBootTargetAddress,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateRange(1,65535)]
        [int]$IscsiPrimaryBootTargetPort = 3260,
        
        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [Net.IPAddress]$IscsiSecondaryBootTargetAddress,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateRange(1,65535)]
        [int]$IscsiSecondaryBootTargetPort = 3260,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateSet ('None','CHAP','MutualCHAP')]
        [String]$IscsiAuthenticationProtocol,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [String]$ChapName,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [SecureString]$ChapSecret,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [String]$MutualChapName,

        [Parameter (Mandatory = $false, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [SecureString]$MutualChapSecret,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Common")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Ethernet")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "FC")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "ISCSI")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        "[{0}] ParameterSet: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PSCmdlet.ParameterSetName | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Validate Boot settings
        if (('FC','FibreChannel' -contains $ConnectionType) -and $BootVolumeSource -eq 'UserDefined' -and (-not $TargetWwpn))
        {

            $Message     = 'A bootable Fibre Channel connection that is set for "UserDefined" must have the -TargetWwpn Parameter specified.'
            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException NoTargetWwpnParam InvalidArgument 'BootVolumeSource' -Message $Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }
                
        #Init object collection
        $_Connections = New-Object System.Collections.ArrayList

    }

    Process 
    {    

        # Also sets connection functionType property
        switch ($Network.Gettype().Name) 
        {

            "PSCustomObject" 
            {

                if ("fcoe-networks", "fc-networks", "ethernet-networks", "network-sets" -contains $Network.category) 
                {
                
                    "[{0}] Network resource provided via Parameter" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
                    "[{0}] Network Name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Network.name | Write-Verbose 
                    "[{0}] Network Category: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Network.category | Write-Verbose 
                    "[{0}] Creating ConnectionType: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ConnectionType | Write-Verbose 

                    switch ($Network.category)
                    {

                        {"ethernet-networks", "network-sets" -contains $_}
                        {

                            $_conn = NewObject -ServerProfileEthernetConnection

                        }

                        {"fcoe-networks", "fc-networks" -contains $_}
                        {

                            $_conn = NewObject -ServerProfileFCConnection

                        }

                    }
                        
                    $_conn.id = [Int]$connectionId;

                    if (-not $PSBoundParameters['ConnectionType'])
                    {

                        $_conn.functionType = [String]$ServerProfileConnectionTypeEnum[$Network.category];

                    }

                    else
                    {

                        $_conn.functionType = [String]$ServerProfileConnectionTypeEnum[$ConnectionType];

                    }
                    
                    $_conn.name                = [String]$name;
                    $_conn.portId              = [String]$portId; 
                    $_conn.requestedMbps       = [Int]$requestedBW; 
                    $_conn.ApplianceConnection = $Network.ApplianceConnection
                    $_conn.networkUri          = $Network.uri
                
                }

                #Generate Error due to incorrect cagtegory
                else 
                {

                    $ExceptionMessage = "The -Network value category '{0}' is not 'ethernet-networks', 'fc-networks' or 'network-sets'. Please check the value and try again." -f $Network.category
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException InvalidNetworkCategory InvalidArgument 'Network' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            default 
            {

                $ExceptionMessage = "The -Network paramter is an invalid type, {0}. Please supply a network object or object collection." -f $Network.GetType().Name
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException InvalidNetworkCategory InvalidArgument 'Network' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        #Set conneciton boot settings
        if ($PSboundParameters['Bootable']) # -and ($PSCmdlet.ParameterSetName -ne 'ISCSI' -and $ConnectionType -ne 'iSCSI'))
        {

            if ($Priority -eq 'NotBootable')
            {

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException InvalidBootPriority InvalidArgument 'Priority' -Message "The Connection is set to be bootable, however no priority value was set. Please provide either 'Primary' or 'Secondary'."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if ($_conn.functionType -eq 'FibreChannel') 
            {

                "[{0}] FibreChannel Connection. Processing boot settings." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_conn.boot = NewObject -ServerProfileFcBootableConnection
                $_conn.boot.bootVolumeSource = $BootVolumeSource

                If((-not $PSBoundParameters['TargetWwpn']) -and $BootVolumeSource -eq "UserDefined")
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException InvalidFcBootTargetParameters InvalidArgument 'TargetWwpn' -Message "FC Boot specified, and no array target WWPN is provided."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                if ($PSBoundParameters['TargetWwpn'])
                {

                    $_conn.boot.bootVolumeSource = 'UserDefined'

                    $bootTarget = NewObject -ServerProfileConnectionFcBootTarget
                    
                    $bootTarget.arrayWwpn = $TargetWwpn
                    $bootTarget.lun       = $lun.ToString()

                    [void]$_conn.boot.targets.Add($bootTarget)

                }

            }

            else
            {

                if ($PSCmdlet.ParameterSetName -eq 'ISCSI' -or $ConnectionType -eq 'iSCSI')
                {

                    #Software iSCSI only supported with Synergy
                    if ($ConnectionType -eq 'Ethernet' -and $ApplianceConnection.ApplianceType -ne 'Composer')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message ('The ApplianceConnection {0} is not a Synergy Composer. The LogicalDisk within the StorageController contains a SasLogicalJbod configuration with is only supported with HPE Synergy.' -f $ApplianceConnection.Name)
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    # HW iSCSI Connection
                    if ($ConnectionType -eq 'ISCSI')
                    {

                        "[{0}] Connection will be HW iSCSI type." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        $_conn.boot = NewObject -ServerProfileIscsiBootableConnectionWithTargets

                    }

                    # SW iSCSI Connection
                    elseif ($ConnectionType -eq 'Ethernet')
                    {

                        "[{0}] Connection will be SW iSCSI type." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        $_conn.boot                  = NewObject -ServerProfileEthBootableConnectionWithTargets
                        $_conn.boot.ethernetBootType = 'iSCSI'                        

                    }

                    $_conn.boot.iscsi = NewObject -IscsiBootEntry
                    $_conn | Add-Member -NotePropertyName ipv4 -NotePropertyValue (NewObject -IscsiIPv4Configuration)

                    if ($PSBoundParameters['BootVolumeSource'])
                    {

                        $_conn.boot.bootVolumeSource = $BootVolumeSource

                    }

                    elseif ($_conn.functionType -eq 'Ethernet')
                    {

                        $_conn.boot.bootVolumeSource = 'UserDefined'

                    }

                    else
                    {

                        $ExceptionMessage = 'The connection is bootable, but the -BootVolumeSource parameter was not provided. Please specify a BootVOlumeSource value.'
                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileConnectionException InvalidBootableConnectionParameters InvalidArgument 'Bootable' -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)                        

                    }

                    if ($PSBoundParameters['IscsiIPv4AddressSource'])
                    {

                        switch ($IscsiIPv4AddressSource)
                        {

                            'UserDefined'
                            {

                                "[{0}]Setting iSCSI connection IPv4 settings will be 'UserDefined'" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                $_conn.ipv4.ipAddressSource = 'UserDefined'

                                if ($PSBoundParameters['IscsiIPv4Address'] -or $PSBoundParameters['IscsiIPv4SubnetMask'])
                                {                    

                                    "[{0}]Setting iSCSI connection IPv4 Address: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $IscsiIPv4Address.IPAddressToString | Write-Verbose
                                    "[{0}]Setting iSCSI connection IPv4 Gateway: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $IscsiIPv4Gateway.IPAddressToString | Write-Verbose

                                    if ($PSBoundParameters['IscsiIPv4SubnetMask'].Length -le 2)
                                    {

                                        Try
                                        {

                                            "[{0}] Converting Subnet CIDR Bit value to Subnet Mask Address." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                            [Int64]$_Int64Value = ([convert]::ToInt64(('1' * $IscsiIPv4SubnetMask + '0' * (32 - $IscsiIPv4SubnetMask)), 2))

                                            [IPAddress]$IscsiIPv4SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($_Int64Value / 16777216)).ToString(),
                                                                                ([math]::Truncate(($_Int64Value % 16777216) / 65536)).ToString(),
                                                                                ([math]::Truncate(($_Int64Value % 65536)/256)).ToString(),
                                                                                ([math]::Truncate($_Int64Value % 256)).ToString()

                                        }

                                        Catch
                                        {

                                            $PSCmdlet.ThrowTerminatingError($_)

                                        }

                                    }

                                    $_conn.ipv4.ipAddress  = $IscsiIPv4Address.IPAddressToString
                                    $_conn.ipv4.subnetMask = ([IPAddress]$IscsiIPv4SubnetMask).IPAddressToString
                                    $_conn.ipv4.gateway    = $IscsiIPv4Gateway.IPAddressToString

                                }

                            }
                            
                            default
                            {

                                if ($IscsiIPv4AddressSource -eq 'SubnetPool' -and $ApplianceConnection.ApplianceType -ne 'Composer')
                                {

                                    $ExceptionMessage = 'The ApplianceConnection {0} is not a Synergy Composer. The LogicalDisk within the StorageController contains a SasLogicalJbod configuration with is only supported with HPE Synergy.' -f $ApplianceConnection.Name
                                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.ComposerNodeException InvalidOperation InvalidOperation 'ApplianceConnection' -Message $ExceptionMessage
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }

                                $_conn.ipv4.ipAddressSource = $IscsiIPv4AddressSource

                            }

                        }

                    }

                    if ($PSBoundParameters['ISCSIInitatorName'])
                    {

                        $_conn.boot.iscsi.initiatorNameSource = "UserDefined"
                        $_conn.boot.iscsi.initiatorName       = $ISCSIInitatorName

                    }

                    if ($PSBoundParameters['IscsiAuthenticationProtocol'])
                    {

                        "[{0}] Setting iSCSI auth protocol" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
                        
                        $_conn.boot.iscsi.chapLevel = $IscsiAuthenticationProtocol
                        
                        switch ($IscsiAuthenticationProtocol)
                        {

                            'Chap'
                            {

                                "[{0}] CHAP" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                                $_conn.boot.iscsi.chapName = $ChapName

                                if ($PSBoundParameters['ChapSecret'])
                                {

                                    "[{0}] Setting CHAP secret." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
                                    $_conn.boot.iscsi.chapSecret = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($ChapSecret))

                                }                        

                            }

                            'MutualChap'
                            {

                                "[{0}] MutualCHAP" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                                $_conn.boot.iscsi.chapName       = $ChapName
                                $_conn.boot.iscsi.mutualChapName = $MutualChapName

                                if ($PSBoundParameters['ChapSecret'])
                                {

                                    "[{0}] Setting CHAP secret." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                                    $_conn.boot.iscsi.chapSecret = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($ChapSecret))

                                }    

                                if ($PSBoundParameters['MutualChapSecret'])
                                {

                                    "[{0}] Setting MutualCHAP secret." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

                                    $_conn.boot.iscsi.mutualChapSecret = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($MutualChapSecret))

                                }                        

                            }

                        }

                    }
                    
                    if ($PSBoundParameters['IscsiPrimaryBootTargetAddress'])
                    {

                        "[{0}] Setting iSCSI Primary boot target: {1}:{2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $IscsiPrimaryBootTargetAddress.IPAddressToString, $IscsiPrimaryBootTargetPort | Write-Verbose 

                        $_conn.boot.bootVolumeSource          = 'UserDefined'
                        $_conn.boot.iscsi.firstBootTargetIp   = $IscsiPrimaryBootTargetAddress.IPAddressToString
                        $_conn.boot.iscsi.firstBootTargetPort = $IscsiPrimaryBootTargetPort

                    }
                    

                    if ($PSBoundParameters['IscsiSecondaryBootTargetAddress'])
                    {

                        "[{0}] Setting iSCSI Secondary boot target: {1}:{2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $IscsiSecondaryBootTargetAddress.IPAddressToString, $IscsiSecondaryBootTargetPort | Write-Verbose 

                        $_conn.boot.iscsi.secondBootTargetIp   = $IscsiSecondaryBootTargetAddress.IPAddressToString
                        $_conn.boot.iscsi.secondBootTargetPort = $IscsiSecondaryBootTargetPort

                    }

                    "[{0}] Setting iSCSI boot target name: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $IscsiBootTargetIqn | Write-Verbose 
                    "[{0}] Setting iSCSI boot target LUN: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LUN | Write-Verbose 
                    
                    $_conn.boot.iscsi.bootTargetName = $IscsiBootTargetIqn
                    $_conn.boot.iscsi.bootTargetLun  = $LUN

                }

                else
                {

                    "[{0}] Ethernet type Connection. Processing boot settings." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    
                    $_conn.boot = NewObject -ServerProfileEthBootableConnection

                }
                
            }

            "[{0}] Connection object boot priority: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerProfileConnectionBootPriorityEnum[$Priority] | Write-Verbose 

            $_conn.boot.priority = $ServerProfileConnectionBootPriorityEnum[$Priority]

            

        }        

        if ($PSboundParameters['Virtualfunctions'] -and $_conn.functionType -eq 'Ethernet' -and $PSCmdlet.ParameterSetName -ne 'ISCSI') 
        {

            $_conn.requestedVFs = $Virtualfunctions

        }

        if ($PSboundParameters['UserDefined'])
        {

            if ($_conn.functionType -eq 'Ethernet')
            {

                $_conn.macType = "UserDefined"
                $_conn.mac     = $mac

            }

            if ($_conn.functionType -eq "FibreChannel")
            {

                if($PSBoundParameters['mac'])
                {

                    $_conn.macType  = "UserDefined" 
                    $_conn.mac      = $mac 

                }

                $_conn.wwpnType = "UserDefined" 
                $_conn.wwnn     = $wwnn
                $_conn.wwpn     = $wwpn 

            }

        }

        $_conn = $_conn | Select * -Exclude requestedVFs

        "[{0}] Connection object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_conn | ConvertTo-Json) | Write-Verbose 

        $_conn
 
    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 

    }

}

#// TODO DEVELOP DOCUMENTATION TEST
function Add-HPOVServerProfileConnection
{

    <#
 
    # .ExternalHelp HPOneView.310.psm1-help.xml
     
    [CmdletBinding ()]
    Param
    (
 
        #Server Profile resource
        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,
 
        #Connections to add, from New-HPOVServerProfileConnection helper Cmdlet
        [Parameter (Mandatory )]
        [ValidateNotNullOrEmpty()]
        [Object]$Connections,
 
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Switch]$Async,
 
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
 
    )
 
    #>




    Throw "Not implemented."

}

#// TODO DEVELOP DOCUMENTATION TEST
function Set-HPOVServerProfileConnection
{

    <#
 
    # .ExternalHelp HPOneView.310.psm1-help.xml
     
    [CmdletBinding (DefaultParameterSetName = "ConnectionName")]
    Param
    (
 
        #Server Profile resource
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "ConnectionName")]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,
 
        [Parameter (Mandatory, ParameterSetName = "ConnectionName")]
        [ValidateNotNullOrEmpty()]
        [String]$ConnectionName,
 
        [Parameter (Mandatory, ParameterSetName = "ConnectionID")]
        [ValidateNotNullOrEmpty()]
        [Int]$ConnectionID
 
        # Should contain the simliar parameters from New-HPOVServerProfileConnection
 
        [Object]$Network,
 
        [Int]$TypicalBandwidth,
 
        [Int]$MaximumBandwidth,
 
        [Boolean]$Bootable,
 
        [String]$BootPriority,
 
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Switch]$Async,
 
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
 
    )
 
    #>


    Throw "Not implemented."

}

#// TODO DEVELOP DOCUMENTATION TEST
function Remove-HPOVServerProfileConnection
{

    Throw "Not implemented."

}

function New-HPOVServerProfileLogicalDisk 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "SynergyJBOD")]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false , ParameterSetName = "SynergyJBOD")]
        [ValidateSet ('RAID0', 'RAID1', 'RAID1ADM', 'RAID10', 'RAID5', 'RAID6', 'NONE')]
        [string]$RAID = 'RAID1',

        [Parameter (Mandatory = $false , ParameterSetName = "Default")]
        [Parameter (Mandatory = $false , ParameterSetName = "SynergyJBOD")]
        [ValidateNotNullOrEmpty()]
        [Int]$NumberofDrives = 2,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SynergyJBOD")]
        [ValidateSet ('SAS', 'SATA', 'SASSSD', 'SATASSD', 'NVMeSas', 'NVMeSata', 'Auto')]
        [string]$DriveType = 'Auto',

        [Parameter (Mandatory = $false, ParameterSetName = "SynergyJBOD")]
        [ValidateSet ('DriveType', 'SizeAndTechnology')]
        [String]$DriveSelectionBy = 'SizeAndTechnology',

        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = "SynergyJBOD")]
        [ValidateNotNullOrEmpty()]
        [HPOneView.Storage.AvailableDriveType]$AvailableDriveType,

        [Parameter (Mandatory = $false, ParameterSetName = "SynergyJBOD")]
        [ValidateSet ('Internal', 'External')]
        [String]$StorageLocation = "External",

        [Parameter (Mandatory = $false, ParameterSetName = "SynergyJBOD")]
        [ValidateNotNullOrEmpty()]
        [Int]$MinDriveSize,

        [Parameter (Mandatory = $False, ParameterSetName = "SynergyJBOD")]
        [ValidateNotNullOrEmpty()]
        [Int]$MaxDriveSize,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "SynergyJBOD")]
        [ValidateNotNullOrEmpty()]
        [bool]$Bootable

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Helper cmdlet does not require authentication." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                
        #Init object collection
        $_LogicalDiskCol = New-Object System.Collections.ArrayList

    }

    Process 
    {

        switch ($PSCmdlet.ParameterSetName)
        {

            'Default'
            {

                #Perform validation
                if ($RAID -eq 'RAID1' -and $NumberofDrives -ne 2)
                {

                    $ExceptionMessage = "The specified RAID Mode 'RAID1' is invalid with more or less than 2 drives. Please correct either the -RAID or -NumberofDrives parameter to the supported value."
                    $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException InvalidRaidModeForNumberofDrives InvalidArgument "NumberofDrives" -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                elseif ($RAID -eq 'RAID1ADM' -and $NumberofDrives -ne 3)
                {

                    $ExceptionMessage = "The specified RAID Mode 'RAID1ADM' is invalid with more or less than 3 drives. Please correct either the -RAID or -NumberofDrives parameter to the supported value."
                    $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException InvalidRaidModeForNumberofDrives InvalidArgument "NumberofDrives" -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $_LogicalDisk = NewObject -ServerProfileLocalStorageLogicalDrive

                $_LogicalDisk.name              = $Name
                $_LogicalDisk.bootable          = [bool]$Bootable
                $_LogicalDisk.raidLevel         = $RAID.ToUpper()
                $_LogicalDisk.numPhysicalDrives = $NumberofDrives
                $_LogicalDisk.driveTechnology   = $LogicalDiskTypeEnum[$DriveType]

            }

            'SynergyJBOD'
            {

                $_SasLogicalJBOD = NewObject -ServerProfileSasLogicalJBOD
                $_LogicalDisk    = NewObject -ServerProfileLocalStorageLogicalDrive
                
                $_SasLogicalJBOD.id                = 1;
                $_SasLogicalJBOD.name              = $Name
                
                $_SasLogicalJBOD.numPhysicalDrives = $NumberofDrives

                if ($AvailableDriveType)
                {

                    $_SasLogicalJBOD.driveTechnology = $LogicalDiskTypeEnum[$AvailableDriveType.Type]
                    $_SasLogicalJBOD.driveMinSizeGB  = $AvailableDriveType.Capacity
                    $_SasLogicalJBOD.driveMaxSizeGB  = $AvailableDriveType.Capacity

                }

                else
                {

                    $_SasLogicalJBOD.driveMinSizeGB  = $MinDriveSize
                    $_SasLogicalJBOD.driveMaxSizeGB  = if (-not $PSBoundParameters['MaxDriveSize']) { $MinDriveSize } Else { $MaxDriveSize }
                    $_SasLogicalJBOD.driveTechnology = $LogicalDiskTypeEnum[$DriveType]

                }                

                if ($PSBoundParameters['RAID'])
                {

                    if ($DriveType -eq 'Auto' -and -not $AvailableDriveType)
                    {

                        $ExceptionMessage = "DriveType parameter must not be 'Auto' when configuring an HP Synergy D3940 LogicalDisk."
                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedControllerMode InvalidArgument "DriveType" -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if ($RAID -eq 'RAID1' -and $NumberofDrives -ne 2)
                    {

                        $ExceptionMessage = "The specified RAID Mode 'RAID1' is invalid with more or less than 2 drives. Please correct either the -RAID or -NumberofDrives parameter to the supported value."
                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException InvalidRaidModeForNumberofDrives InvalidArgument "NumberofDrives" -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    elseif ($RAID -eq 'RAID1ADM' -and $NumberofDrives -ne 3)
                    {

                        $ExceptionMessage = "The specified RAID Mode 'RAID1ADM' is invalid with more or less than 3 drives. Please correct either the -RAID or -NumberofDrives parameter to the supported value."
                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException InvalidRaidModeForNumberofDrives InvalidArgument "NumberofDrives" -Message $ExceptionMessage
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    $_LogicalDisk.raidLevel        = $RAID.ToUpper()
                    $_LogicalDisk.sasLogicalJBODId = 1
                    $_LogicalDisk.bootable         = [bool]$Bootable

                }

                else
                {

                    $_LogicalDisk.sasLogicalJBODId = 1

                }

                $_LogicalDisk | Add-Member -NotePropertyName SasLogicalJBOD -NotePropertyValue $_SasLogicalJBOD -Force
                
            }

        }       

        "[{0}] Created Logical Disk object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_LogicalDisk | fl *) | Write-Verbose

        $_LogicalDisk
        
    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function New-HPOVServerProfileLogicalDiskController
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "Import")]
        [ValidateSet ('Embedded','Mezz 1','Mezz 2','Mezz 3')]
        [Object]$ControllerID = 'Embedded',

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "Import")]
        [ValidateSet ('HBA','RAID')]
        [String]$Mode = 'RAID',

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "Import")]
        [switch]$Initialize,

        #ONLY VALID FOR SERVERPROFILES. Need to add validation in New-HPOVServerProfileTemplate to verify the controller doesn't have this value set.
        [Parameter (Mandatory = $false, ParameterSetName = "Import")]
        [switch]$ImportExistingConfiguration,

        [Parameter (Mandatory = $false, ParameterSetName = "Default", ValueFromPipeline)]
        [Object]$LogicalDisk

    )
        
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Helper cmdlet does not require authentication."
                
        #Init object collection
        $_ServerProfileController = NewObject -ServerProfileLocalStorageController
        $_ServerProfileController.deviceSlot          = $ControllerID
        $_ServerProfileController.mode                = $Mode

        if ($ControllerID -notmatch 'Mezz')
        {

            $_ServerProfileController.importConfiguration = $ImportExistingConfiguration.IsPresent
            $_ServerProfileController.initialize          = $Initialize.IsPresent

        }        

        $_id = 1

    }

    Process
    {    

        #Generate terminating error
        if ($PSBoundParameters['Mode'] -eq 'HBA' -and $PSBoundParameters['LogicalDisk'])
        {

            $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedControllerMode InvalidArgument "Mode" -Message "The provide 'HBA' mode does not support assigning of Logical Disks."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($PSBoundParameters['ImportExistingConfiguration'] -and $PSBoundParameters['LogicalDisk'])
        {

            $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException SupportedParameterUse InvalidArgument "ImportExistingConfiguration" -Message "Combining ImportExistingConfiguration and LogicalDisk Parameters is not supported."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #Is an Array
        if ($LogicalDisk -is [System.Collections.IEnumerable])
        {

            "[{0}] Processing LogicalDisks collection" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose            

            ForEach ($_ld in $LogicalDisk)
            {

                "[{0}] {1} of {2}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ld, $LogicalDisk.Count | Write-Verbose

                if ($_ld.SasLogicalJBOD)
                {

                    if ($_ServerProfileController.deviceSlot -eq 'Embedded')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedControllerMode InvalidArgument "LogicalDisks" -TargetType 'PSObject' -Message "The provided Logical Disks contains a SAS JBOD policy, which is not supported with the 'Embedded' Controller."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    $_ld.SasLogicalJBOD.deviceSlot = $_ServerProfileController.deviceSlot

                    #Figure out new SasLogicalJBODId
                    if ($_ServerProfileController.logicalDrives.sasLogicalJbod.id)
                    {

                        while ($_ServerProfileController.logicalDrives.sasLogicalJbod.id -contains $_id)
                        {

                            $_id++

                        }            

                    }

                    $_ld.SasLogicalJBOD.id         = $_id
                    $_ld.sasLogicalJBODId          = $_id    

                }

                if (($_ld.raidLevel -and $PSBoundParameters['Mode'] -eq 'HBA') -or (-not($_ld.raidLevel) -and $PSBoundParameters['Mode'] -eq 'RAID'))
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedControllerMode InvalidArgument "Mode" -Message "The Controller can only operate in a single mode: RAID or HBA. One or more of the provided LogicalDisks are defined for the opposite mode."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_ServerProfileController.logicalDrives.Add($_ld)

            }

        }

        elseif ($LogicalDisk -is [PSCustomObject])
        {

            "[{0}] Processing Logical Disk: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $LogicalDisk.name | Write-Verbose

            if ($LogicalDisk.SasLogicalJBOD)
            {

                if ($_ServerProfileController.deviceSlot -eq 'Embedded')
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedControllerMode InvalidArgument "LogicalDisks" -TargetType 'PSObject' -Message "The provided Logical Disks contains a SAS JBOD policy, which is not supported with the 'Embedded' Controller."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                $LogicalDisk.SasLogicalJBOD.deviceSlot = $_ServerProfileController.deviceSlot

                #Figure out new SasLogicalJBODId
                if ($_ServerProfileController.logicalDrives.sasLogicalJbod.id)
                {

                    while ($_ServerProfileController.logicalDrives.sasLogicalJbod.id -contains $_id)
                    {

                        $_id++

                    }

                    $LogicalDisk.SasLogicalJBOD.id = $_id
                    $LogicalDisk.sasLogicalJBODId  = $_id                        

                }

            }

            if (($LogicalDisk.raidLevel -and $PSBoundParameters['Mode'] -eq 'HBA') -or (-not($LogicalDisk.raidLevel) -and $PSBoundParameters['Mode'] -eq 'RAID'))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.ServerProfile.LogicalDiskException UnsupportedControllerMode InvalidArgument "Mode" -Message "The Controller can only operate in a single mode: RAID or HBA. One or more of the provided LogicalDisks are defined for the opposite mode."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            [void]$_ServerProfileController.logicalDrives.Add($LogicalDisk)        

        }

    }

    End
    {

        Return $_ServerProfileController

    }

}

function New-HPOVServerProfileAttachVolume 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdLetBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = "ServerProfileObject")]
        [Parameter (Mandatory, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [ValidateScript({'server-profiles','server-profile-templates' -contains $_.category})]
        [Object]$ServerProfile,
        
        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObject")]
        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $False, ParameterSetName = "ManualLunIdType")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachManual")]
        [ValidateNotNullOrEmpty()]
        [Alias ('id')]
        [int]$VolumeID = 1,

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "ServerProfileObject")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "ManualLunIdType")]
        [ValidateScript({$_ | ? { 'storage-volumes' -contains $_.category}})]
        [Array]$Volume,

        [Parameter (Mandatory, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory, ParameterSetName = "DynamicVolAttachManual")]
        [ValidateNotNullOrEmpty()]
        [object]$Name,

        [Parameter (Mandatory, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory, ParameterSetName = "DynamicVolAttachManual")]
        [ValidateNotNullOrEmpty()]
        [object]$StoragePool,

        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachManual")]
        [ValidateNotNullOrEmpty()]
        [object]$StorageSystem,

        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachManual")]
        [ValidateNotNullOrEmpty()]
        [int64]$Capacity,

        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachManual")]
        [switch]$Full,

        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachManual")]
        [switch]$Permanent,

        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachManual")]
        [ValidateSet ('NetworkRaid0None','NetworkRaid5SingleParity','NetworkRaid10Mirror2Way','NetworkRaid10Mirror3Way','NetworkRaid10Mirror4Way','NetworkRaid6DualParity')]
        [String]$DataProtectionLevel,

        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObject")]
        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [Parameter (Mandatory, ParameterSetName = "ManualLunIdType")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory, ParameterSetName = "DynamicVolAttachManual")]
        [ValidateSet ("Auto","Manual", IgnoreCase=$true)]
        [Alias ('type')]
        [string]$LunIdType = "Auto",

        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObject")]
        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory, ParameterSetName = "ManualLunIdType")]
        [Parameter (Mandatory, ParameterSetName = "DynamicVolAttachManual")]        
        [ValidateRange(0,254)]
        [int]$LunID,

        [Parameter (Mandatory = $false, ParameterSetName = "ServerProfileObject")]
        [Parameter (Mandatory = $false, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [ValidateSet ('CitrixXen','AIX','IBMVIO','RHEL4','RHEL3','RHEL','RHEV','VMware','Win2k3','Win2k8','Win2k12','OpenVMS','Egenera','Exanet','Solaris9','Solaris10','Solaris11','ONTAP','OEL','HPUX11iv1','HPUX11iv2','HPUX11iv3','SUSE','SUSE9','Inform')]
        [Alias ('OS')]
        [string]$HostOStype,

        [Parameter (Mandatory = $false, ParameterSetName = "ServerProfileObject")]
        [Parameter (Mandatory = $false, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "ManualLunIdType")]
        [Parameter (Mandatory = $false, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory = $false, ParameterSetName = "DynamicVolAttachManual")]
        [Alias ('Bootable')]
        [switch]$BootVolume,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObject")]
        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $False, ParameterSetName = "ManualLunIdType")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachManual")]
        [ValidateSet ('Auto', 'TargetPorts')]
        [String]$TargetPortAssignment = 'Auto',

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObject")]
        [Parameter (Mandatory = $False, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $False, ParameterSetName = "ManualLunIdType")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory = $False, ParameterSetName = "DynamicVolAttachManual")]
        [ValidateNotNullOrEmpty()]
        [Alias ('wwpns')]
        [Array]$TargetAddresses,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "ServerProfileObject")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "ServerProfileObjectEphmeralVol")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "ManualLunIdType")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "DynamicVolAttachAuto")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "DynamicVolAttachManual")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        If (-not($PSBoundParameters['Volume']))
        {

            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }        
        
        if ($LunIdType -eq "Manual" -and (-not($PSBoundParameters.ContainsKey("LunId"))))
        { 
        
            $ErrorRecord = New-ErrorRecord ArgumentNullException ParametersNotSpecified InvalidArgument 'New-HPOVServerProfileAttachVolume' -Message "'Manual' LunIdType was specified, but no LUN ID value was provided. Please include the -LunId Parameter or a value in the Parameters position and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($LunIdType -eq "Auto" -and $PSBoundParameters.ContainsKey("LunId")) 
        { 
        
            $ErrorRecord = New-ErrorRecord ArgumentException ParametersSpecifiedCollision InvalidArgument 'New-HPOVServerProfileAttachVolume' -Message "'Auto' LunIdType was specified and a specific LUN ID were provided. Please either specify -LunIdType 'Manual' or omit the -LunId Parameter and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        #If volume Parameter is passed as URI validate that only one appliance connection is present
        if ($PSBoundParameters['Volume']) 
        {

            if (($Volume -is [String] -and $Volume.StartsWith($StorageVolumesUri)) -or ($Volume -is [String] -and $Volume.StartsWith("/rest/"))) 
            {

                "[{0}] Volume URI was provided." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                if(-not($ApplianceConnection))
                {

                    "[{0}] No Appliance connections identified with volume URI Parameter." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                    
                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Volume' -Message "The Volume Parameter contains a URI and requires the ApplianceConnection Parameter."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

        }

        #If StoragePool Parameter is present and passed as URI validate only one appliance connection is present
        if ($PSBoundParameters['StoragePool']) 
        {
            
            if (($StoragePool -is [string] -and $StoragePool.StartsWith($StoragePoolsUri)) -or ($StoragePool -is [string] -and $StoragePool.StartsWith("/rest"))) 
            {

                "[{0}] Storage Pool URI provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StoragePool | Write-Verbose

                if($ApplianceConnection.Count -ne 1)
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Multiple appliance connections identified with storage pool URI Parameter."
                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'New-HPOVServerProfileAttachVolume' -Message "The StoragePool URI Parameter is invalid with multiple appliance connections."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                }

            }

        }

        if ($PSBoundParameters['ServerProfile'])
        {

            if ($ServerProfile -isnot [PSCustomObject])
            {

                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException UnsupportedServerHardwareResource InvalidArgument 'ServerProfile' -TargetType $ServerProfile.GetType().Name -Message ("The provided Server Profile {0} is not an Object. Please provide a Server Profile object." -f $ServerProfile)
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

            }

        }

        #Initialize collection to hold multiple volume attachments objects
        $_volumeAttachments = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PSBoundParameters['Volume']) 
        {

            ForEach ($_vol in $Volume)
            {

                $volumeAttachment = NewObject -ServerProfileStorageVolume

                "[{0}] Processing Volume: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), (ConvertTo-Json $_vol -Depth 99) | Write-Verbose

                $volumeAttachment.volumeUri              = $_vol.uri
                $volumeAttachment.volumeStoragePoolUri   = $_vol.storagePoolUri
                $volumeAttachment.volumeStorageSystemUri = $_vol.storageSystemUri

                if ($PSBoundParameters['VolumeID'])
                {

                    $volumeAttachment.id = $VolumeID

                }
                
                if ($LunIdType -ne 'Auto')
                {

                    $volumeAttachment.lunType = $LunIdType
                    $volumeAttachment.lun     = $LunID

                }

                if ($PSBoundParameters['BootVolume'])
                {

                    if ($ServerProfile -and ($ServerProfile.sanStorage.volumeAttachments | ? isBootVolume))
                    {

                        $_Message = 'The Server Profile already had a Bootable Device, {0}. Please omit the -BootVolume Parameter switch or set the isBootVolume poperty of the Volume Attachment to $False.' -f ($ServerProfile.sanStorage.volumeAttachments | ? isBootVolume).id
                        $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException MultipleBootVolumesNotSupported InvalidOperation 'BootVolume' -TargetType 'SwitchParameter' -Message $_Message
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    if (-not($_volumeAttachments | ? isBootVolume))
                    {

                        "[{0}] Setting Volume as Boot Volume: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_vol.volumeName | Write-Verbose

                        $volumeAttachment.isBootVolume = $True

                    }

                    else
                    {

                        $_ConflictVolume = $Volume | ? uri -contains ($_volumeAttachments | ? isBootVolume).volumeUri

                        $_Message = 'An existing volume is already marked as a Bootable Device, {0}. Multiple Storage Volumes via Pipeline or Parameter input along with -BootVolume Parameter is not supported.' -f $_ConflictVolume.volumeName
                        $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException MultipleBootVolumesNotSupported InvalidOperation 'BootVolume' -TargetType 'SwitchParameter' -Message $_Message
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                        
                    }

                }

                $volumeAttachment.ApplianceConnection = $_vol.ApplianceConnection

                [void]$_volumeAttachments.Add($volumeAttachment)

            }

        }

        #Ephmeral Volume Support
        elseif ($PSBoundParameters['StoragePool']) 
        {

            $volumeAttachment = NewObject -ServerProfileStorageVolume

            "[{0}] Creating dynamic volume attach object." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                
            $volumeAttachment = NewObject -EphemeralStorageVolume
            $volumeAttachment.volumeStoragePoolUri           = $sp.uri
            $volumeAttachment.volumeStorageSystemUri         = $sp.storageSystemUri
            $volumeAttachment.volumeName                     = $Name
            $volumeAttachment.volumeProvisionType            = if ($PSBoundParameters['full']) { "Thick" } else { "Thin" }
            $volumeAttachment.volumeProvisionedCapacityBytes = if ($PSBoundParameters['Capacity']) { [string]([int64]$Capacity * 1GB) } else { $volumeAttachment.volumeProvisionedCapacityBytes }

            switch ($StoragePool.GetType().Name) 
            {

                "String" 
                { 
                    
                    if ($StoragePool.StartsWith($StoragePoolsUri)) 
                    {
                        
                        "[{0}] Storage Pool URI provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(),  $StoragePool | Write-Verbose

                        Try
                        {
                                
                            $sp = Send-HPOVRequest $StoragePool -appliance $ApplianceConnection

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }
                        
                    }

                    elseif ($StoragePool.StartsWith("/rest/")) 
                    {
                         
                        "[{0}] Invalid storage pool URI provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $StoragePool | Write-Verbose

                        $ErrorRecord = New-ErrorRecord ArgumentException InvalidStoragePoolURI InvalidArgument 'StoragePool' -Message "The provided URI value for the -StoragePool Parameter '$StroagePool' is invalid. The StoragePool URI must Begin with /rest/storage-pools. Please check the value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    else 
                    {
                         
                        if ($StorageSystem) 
                        {
                                
                            #If both storagepool and storagesystem were provided, look that up first

                            Try
                            {
                                
                                $sp = Get-HPOVStoragePool -poolName $StoragePool -storageSystem $StorageSystem -appliance $ApplianceConnection -ErrorAction Stop

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }
                            
                        }

                        else 
                        {

                            Try
                            {

                                #If both storagepool and storagesystem were provided, look that up first
                                $sp = Get-HPOVStoragePool -poolName $StoragePool -appliance $ApplianceConnection -ErrorAction Stop

                            }

                            Catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }

                            if ($sp -and $sp.count -gt 1) 
                            {

                                #Generate Error that StoragePool name is not unique and must supply the StorageSystem as well.
                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] {$($sp.count)} StoragePool resource found"

                                $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException MultipleStoragePoolsFound InvalidResult 'New-HPOVServerProfileAttachVolume' -Message "Multiple StoragePool resources found with the name '$StoragePool'. Please use the -StorageSystem Parameter to specify the Storage System the Storage Pool is to be used."
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }

                        }
                        
                    }
                    
                }

                "PSCustomObject" 
                { 
                    
                    #Validate the object
                    if ($StoragePool.category -eq 'storage-pools') 
                    { 
                            
                        $sp = $StoragePool 
                        
                    }

                    else 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStoragePoolCategory InvalidArgument 'StoragePool' -Message "Invalid -StoragePool Parameter value. Expected Resource Category 'storage-pools', received '$($VolumeTemplate.category)'."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }              
                    
                }

            }

            #Get the associated storage system family
            try
            {

                $StorageSystem = Send-HPOVRequest -Uri $sp.storageSystemUri -Hostname $sp.ApplianceConnection

            }

            catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($StorageSystem.family -eq 'StoreVirtual' -and -not $PSBoundParameters['DataProtectionLevel'])
            {

                $ExceptionMessage = "The DataProtectionLevel parameter is required, as the Storage System associated with the Storage Pool {0} is a StoreVirtual system." -f $StoragePool.name
                $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidStoragePoolCategory InvalidArgument 'StoragePool' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($StorageSystem.family -eq 'StoreVirtual')
            {

                $volumeAttachment | Add-Member -NotePropertyName dataProtectionLevel -NotePropertyValue $DataProtectionLevelEnum[$DataProtectionLevel]

            }

            $volumeAttachment.volumeStoragePoolUri   = $sp.uri
            $volumeAttachment.volumeStorageSystemUri = $sp.storageSystemUri           
                
            if($shared.IsPresent -and (-not($permanent.IsPresent))) 
            {
            
                $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException InvalidVolumePermanentAndShareState InvalidArgument 'shared' -Message "Unable to create a shared epehemeral storage volume. Please either remove the -shared switch, or include the -permanent switch to properly create a volume."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            $volumeAttachment.permanent = [bool]$PSBoundParameters['permanent']

            if (-not($PSBoundParameters['VolumeID']) -and $ServerProfile)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No VolumeID value provided. Getting next volume id value."

                $id = 1

                $Found = $false

                While (-not($Found))
                {

                    if (-not($ServerProfile.sanStorage.volumeAttachments | ? id -eq $id))
                    {

                        $VolumeID = $id

                        $Found = $true

                    }

                    $id++

                }

            }

            $volumeAttachment.id = $VolumeID

            if ($LunIdType -ne 'Auto')
            {

                $volumeAttachment.lunType = $LunIdType
                $volumeAttachment.lun     = $LunID

            }

            if ($PSBoundParameters['BootVolume'])
            {

                if (-not($_volumeAttachments | ? isBootVolume))
                {

                    "[{0}] Setting Volume as Boot Volume: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $volumeAttachment.volumeName | Write-Verbose

                    $volumeAttachment.isBootVolume = $True

                }

                else
                {

                    $_Message = 'An existing volume is already marked as a Bootable Device, {0}. Multiple Storage Volumes via Pipeline or Parameter input along with -BootVolume Parameter is not supported.' -f [String]::Join(' ', ($_volumeAttachments | ? isBootVolume).volumeName)
                    $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException MultipleBootVolumesNotSupported InvalidOperation 'BootVolume' -TargetType 'SwitchParameter' -Message $_Message
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            $volumeAttachment.ApplianceConnection = $_Connection

            [void]$_volumeAttachments.Add($volumeAttachment)

        }

        "[{0}] VolumeAttachments Added to collection: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_volumeAttachments.Count | Write-Verbose

    }

    End 
    {

        if ($PSBoundParameters['ServerProfile'])
        {

            #Validate Server Profile and Server Hardware resource supports StRM operations
            Try
            {

                "[{0}] Checking SHT for SanStorage operation support" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_SHTResource = Send-HPOVRequest $ServerProfile.serverHardwareTypeUri -Hostname $ServerProfile.ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if (-not [RegEx]::Match($_SHTResource.model,'BL|WS|SY', [System.Text.RegularExpressions.RegexOptions]::IgnoreCase).Success)
            {
                    
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException UnsupportedServerHardwareResource InvalidArgument 'ServerProfile' -TargetType 'PSObject' -Message ("The provided Server Profile {0} is not assigned to a supported Server Hardware Type Resource, {1}. Only WS/BL/SY Gen 8/Gen 9 or newer are supported." -f $ServerProfile.name, $_SHTResource.model)
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

            }

            #Validate Server Profile has SanStorage already set. If not, set it and add the necessary properties.
            if (-not($ServerProfile.sanStorage.manageSanStorage))
            {

                "[{0}] Server Profile does not have manageSanStorage property set to True." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                #Generate Error that HostOSType is required
                if (-not($PSBoundParameters['HostOsType']))
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException MissingHostOSTypeParameterValue InvalidArgument 'ServerProfile' -TargetType 'PSObject' -Message "The -HostOSType parmater is required when the Server Profile is not already configured for managing SAN Storage. Please specify the HostOSType Parameter in your call."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                }

                $ServerProfile.sanStorage = [PSCustomObject]@{
                        
                    hostOSType        = $ServerProfileSanManageOSType.($HostOsType);
                    manageSanStorage  = $true;
                    volumeAttachments = New-Object System.Collections.ArrayList
                    
                }

            }

            #Rebuild VolumeAttachments property to be an ArrayList
            else
            {

                if ($ServerProfile.sanStorage.volumeAttachments.Count -gt 0)
                {

                    "[{0}] Rebuilding Server Profile Volume Attachment object" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $_ExistingVols = $ServerProfile.sanStorage.volumeAttachments.Clone()                    

                    $ServerProfile.sanStorage.volumeAttachments = New-Object System.Collections.ArrayList

                    $_ExistingVols | % {

                        if ($_.volumeUri -contains $_volumeAttachments.volumeUri)
                        {

                            [void]$_volumeAttachments.Remove($_)
                            $ExceptionMessage = 'Storage Volume {0} is already attached at ID {1}. Skipping.' -f $_.name, $_.id
                            $ErrorRecord = New-ErrorRecord HPOneView.StorageVolumeResourceException StorageVolumeAlreadyAttached ResourceExists 'Volume' -Targettype 'PSObject' -Message $ExceptionMessage
                            $PSCmdlet.WriteError($ErrorRecord)

                        }

                        [void]$ServerProfile.sanStorage.volumeAttachments.Add($_)

                    }

                }

                else
                {

                    $ServerProfile.sanStorage.volumeAttachments = New-Object System.Collections.ArrayList

                }

            }

            "[{0}] Getting list of available storage systems" -f $MyInvocation.InvocationName.ToString().ToUpper()| Write-Verbose
            
            #Get list of available storage system targets and the associated Volumes based on the EG and SHT provided
            Try
            {
            
                $uri = "{0}?enclosureGroupUri={1}&serverHardwareTypeUri={2}" -f $ServerProfileAvailStorageSystemsUri, $ServerProfile.enclosureGroupUri, $ServerProfile.serverHardwareTypeUri
                $_AvailStorageSystems = (Send-HPOVRequest -Uri $uri -Hostname $ServerProfile.ApplianceConnection.Name).members
            
            }
            
            Catch
            {
            
                $PSCmdlet.ThrowTerminatingError($_)
            
            }
            
            "[{0}] Available Storage Systems: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_AvailStorageSystems | fl) | Write-Verbose
            
            #Error on no available storage systems
            if (-not ($_AvailStorageSystems)) 
            {
            
                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException NoAvailableStorageSystems ObjectNotFound 'SANStorage' -Message ("No available storage systems found for '{0}' Server Hardware and '{1}' Enclosure Group. Please verify an available Storage System exists, and has connectivity to the destination server or Enclosure Group, or that the Server Profile has a FibreChannel Connection that matches an Expected/Actual Network to a Storage System Host Port(s)." -f $ServerProfile.name, ((Send-HPOVRequest $ServerProfile.enclosureGroupUri -Hostname $ServerProfile.ApplianceConnection.Name).name))
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)  
            
            }
                    
            "[{0}] Volumes to Process {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_volumeAttachments | fl) | Write-Verbose 
                    
            $i = 0
                    
            #Process volumes being passed
            foreach ($_volume in $_volumeAttachments) 
            {  

                "[{0}] Processing '{1}' Storage Volume (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_volume.uri, $_volumeAttachments.count | Write-Verbose

                if (-not($_volume.id))
                {

                    "[{0}] No VolumeID value provided. Getting next volume id value." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $id = 1

                    $Found = $false

                    While (-not($Found))
                    {

                        if (-not($ServerProfile.sanStorage.volumeAttachments | ? id -eq $id))
                        {

                            $_volume.id = $id

                            $Found = $true

                        }

                        $id++

                    }

                }

                # // TODO: Process TargetAddresses note property to handle descrete SAN path mapping. Will also need to add this logic to New-HPOVServerProfile and New-HPOVServerProfileTemplate
                # If the storage paths array is null, Process connections to add mapping
                if (-not($_volume.storagePaths)) 
                {

                    "[{0}] Storage Paths value is Null. Building connection mapping." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    # Static Volume, must have volumeUri attribute present to be valid
                    if ($_volume.volumeUri) 
                    {

                        "[{0}] Getting list of attachable volumes" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                        # Get list of attachable Volumes (i.e. they are not assigned private or are shareable volumes)
                        Try
                        {

                            $_AttachableVolumes = (Send-HPOVRequest -Uri $AttachableStorageVolumesUri -Count 1000 -appliance $ServerProfile.ApplianceConnection.Name).members

                            # Get storage volume name for reporting purposes
                            $_VolumeName = (Send-HPOVRequest $_volume.volumeUri -appliance $ServerProfile.ApplianceConnection.Name).name

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                        "[{0}] Processing Volume ID: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_volume.id  | Write-Verbose 
                        "[{0}] Looking to see if volume '{1} ({2})' is attachable" -f $MyInvocation.InvocationName.ToString().ToUpper(),$_volume.volumeUri, $_VolumeName | Write-Verbose 
                                               
                        # validate volume is attachable
                        $_AttachableVolFound = $_AttachableVolumes | ? uri -eq $_volume.volumeUri

                        # If it is available, continue Processing
                        if ($_AttachableVolFound) 
                        {
                    
                            "[{0}] '{1} ({2})' volume is attachable" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_AttachableVolFound.uri, $_AttachableVolFound.name  | Write-Verbose
                    
                            # validate the volume that is available, is also avialable to the server hardware type and enclosure group
                            $_VolumeToStorageSystem = $_AvailStorageSystems | ? storageSystemUri -eq $_AttachableVolFound.storageSystemUri
                    
                            # If available, Process the volume networks
                            if ($_VolumeToStorageSystem) 
                            { 

                                switch ($ServerProfile.category)
                                {

                                    'server-profiles'
                                    {

                                        $ServerProfileConnectionLocation = $ServerProfile.connections

                                    }

                                    'server-profile-templates'
                                    {

                                        $ServerProfileConnectionLocation = $ServerProfile.connectionSettings.connections

                                    }

                                }
                                
                                # Check to make sure profile connections exist.
                                if ($null -ne $ServerProfileConnectionLocation -and $ServerProfileConnectionLocation.functionType -contains "FibreChannel") 
                                {

                                    "[{0}] Profile has connections" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                                        
                                    # loop through profile connections
                                    $found = 0

                                    foreach ($_volConnection in $_AttachableVolFound.reachableNetworks) 
                                    {

                                        #write-verbose "Looking for $volConnection"
                                        # $profileConnection = $ServerProfile.connections | ? networkUri -eq $_volConnection
                                        $profileConnection = $ServerProfileConnectionLocation | ? networkUri -eq $_volConnection

                                        if ($profileConnection) 
                                        {

                                            #Keep track of the connections found for error reporting later
                                            $found++

                                            "[{0}] Mapping connection ID '{1}' -> volume ID '{2}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $profileConnection.id, $_volume.id | Write-Verbose
                                                
                                            $_StoragePath = NewObject -StoragePath

                                            $_StoragePath.connectionId = $profileConnection.id
                                            $_StoragePath.isEnabled = $True

                                            [void]$_volume.storagePaths.Add($_StoragePath)

                                        }

                                    }

                                    if (-not ($found)) 
                                    {

                                        #Generate non-terminating error and continue
                                        $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException NoProfileConnectionsMapToVolume ObjectNotFound 'New-HPOVServerProfile' -Message "Unable to find a Profile Connection that will map to '$($volumeName)'. Creating server profile resource without Volume Connection Mapping." 
 
                                        $PSCmdlet.WriteError($ErrorRecord)

                                    }
                                        
                                }

                                #Else, generate an error that at least one FC connection must exist in the profile in order to attach volumes.
                                else 
                                {

                                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException NoProfileConnections ObjectNotFound 'New-HPOVServerProfile' -Message "The profile does not contain any Network Connections. The Profile must contain at least 1 FC Connection to attach Storage Volumes. Use the New-HPOVServerProfileConnection helper cmdlet to create 1 or more connections and try again." 
                                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                                }
                    
                            }
                    
                            #If not, then error
                            elseif (-not($_VolumeToStorageSystem)) 
                            { 
                                
                                $ErrorRecord = New-ErrorRecord InvalidOperationException StorageVolumeDoesNotExistOnStorageArray ObjectNotFound 'ServerProfile' -TargetType 'PSObject' -Message ("'{0}' Volume is not available on the '{1}' storage system." -f $_VolumeName, $_VolumeToStorageSystem.storageSystemName)
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)                      
                                
                            }
                    
                        }
                    
                        elseif (-not ($_AttachableVolFound)) 
                        { 
                            
                            $ErrorRecord = New-ErrorRecord InvalidOperationException StorageVolumeUnavailableForAttach ResourceUnavailable 'ServerProfile' -TargetType 'PSObject'  -Message ("'{0}' Volume is not available to be attached to the profile. Please check the volume and try again." -f $_VolumeName)
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }

                    #Ephemeral volume support
                    elseif (-not ($_volume.volumeUri) -and $_volume.volumeStoragePoolUri -and $_volume.volumeStorageSystemUri) 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No volumeUri, ephemeral volume request."

                        #Check to make sure profile connections exist.
                        if ($ServerProfile.connections -and $ServerProfile.connections.functionType -contains "FibreChannel") 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Profile has connections"

                            #Process available storage system and available FC networks
                            $_StorageSystemVolCreate = $_AvailStorageSystems | ? storageSystemUri -eq $_volume.volumeStorageSystemUri

                            if ($_StorageSystemVolCreate) 
                            {
                                        
                                "[{0}] Available Storage System targets: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($storageSystemVolCreate.storageSystemUri -join ", ") | Write-Verbose 
                                        
                                #loop through profile connections
                                $found = 0

                                foreach ($_storageSystemNetworks in $_StorageSystemVolCreate.availableNetworks) 
                                {

                                    $_ProfileConnection = $ServerProfile.connections | ? networkUri -eq $_storageSystemNetworks.uri

                                    if ($_ProfileConnection) 
                                    {

                                        #Keep track of the connections found for error reporting later
                                        $found++

                                        "[{0}] Mapping connection ID '{1}' -> volume ID '{2}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ProfileConnection.id, $_volumeAttachments[$i].id | Write-Verbose
                                                
                                        $_StoragePath = NewObject -StoragePath

                                        $_StoragePath.connectionId = $_ProfileConnection.id
                                        $_StoragePath.isEnabled    = $True

                                        if ($PSBoundParameters['TargetAddresses'])
                                        {

                                            "[{0}] Getting FC network to get associated SAN." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                                            #$_uri = "{0}/reachable-ports?query=expectedNetworkUri EQ '{1}'" -f $_VolumeToStorageSystem.uri, $profileConnection.networkUri
                                            $_StoragePath.targetSelector = 'TargetPorts'

                                            Try
                                            {

                                                $_ServerProfileConnectionNetwork = Send-HPOVRequest -Uri $profileConnection.networkUri -Hostname $ServerProfile.ApplianceConnection

                                            }

                                            Catch
                                            {

                                                $PSCmdlet.ThrowTerminatingError($_)

                                            }

                                            $_StorageSystemExpectedMappedPorts = $_AvailStorageSystems.ports | ? expectedSanUri -eq $_ServerProfileConnectionNetwork.managedSanUri

                                            ForEach ($_PortID in $TargetAddresses)
                                            {

                                                "[{0}] Looking for {1} host port from available storage system." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_PortID | Write-Verbose

                                                if ($WwnAddressPattern.Match($_PortID))
                                                {

                                                    $_PortType = 'name'

                                                }

                                                elseif ($StoreServeTargetPortIDPattern.Match($_PortID))
                                                {

                                                    $_PortType = 'address'

                                                }

                                                ForEach ($_HostPort in ($_StorageSystemExpectedMappedPorts | ? $_PortType -match $_PortID))
                                                {

                                                    "[{0}] Adding {1} ({2}) host port to targets." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_HostPort.address, $_HostPort.name | Write-Verbose

                                                    [void]$_StoragePath.targets.Add($_HostPort.address)

                                                }

                                            }

                                        }

                                        [void]$_volume.storagePaths.Add($_StoragePath)

                                    }

                                }

                                if (-not($found))
                                {

                                    #Generate non-terminating error and continue
                                    $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException NoProfileConnectionsMapToVolume ObjectNotFound 'New-HPOVServerProfile' -Message "Unable to find a Profile Connection that will map to '$($_volume.id)'. Creating server profile resource without Volume Connection Mapping." 

                                    $PSCmdlet.WriteError($ErrorRecord)

                                    
                                }

                            }

                            else 
                            {

                                $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException StorageSystemNotFound ObjectNotFound 'Volume' -TargetType 'PSObject' -Message "The provided Storage System URI '$($_volume.volumeStorageSystemUri)' for the ephemeral volume '$($_volume.name)' was not found as an available storage system." 
                                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                            }
                                        
                        }

                        #Else, generate an error that at least one FC connection must exist in the profile in order to attach volumes.
                        else 
                        {

                            $ErrorRecord = New-ErrorRecord HPOneView.ServerProfileResourceException NoProfileConnections ObjectNotFound 'ServerProfile' -TargetType 'PSObject' -Message "The profile does not contain any Network Connections. The Profile must contain at least 1 FC Connection to attach Storage Volumes. Use the New-HPOVServerProfileConnection helper cmdlet to create 1 or more connections and try again." 
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                    }
 
                }

                "[{0}] Storage Volume Object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), (ConvertTo-Json $_volume -depth 99) | Write-Verbose

                "[{0}] Attaching '{1}' Storage Volume to volumeAttachments collection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_AttachableVolFound.name | Write-Verbose

                [void]$ServerProfile.sanStorage.volumeAttachments.Add($_volume)

                $i++

            }

            #Workaround to remove a possible NULL entry in the volumeAttachments collection
            [void]$ServerProfile.sanStorage.volumeAttachments.Remove($null)

            ConvertTo-Json $ServerProfile -dept 99 | Write-Verbose

            "[{0}] Updating Server Profile with new Storage Volume Attachments: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $ServerProfile.name | Write-Verbose 

            Try
            {

                $_Task = Send-HPOVRequest -Uri $ServerProfile.uri -Method PUT -Body $ServerProfile -Hostname $ServerProfile.ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
            Return $_Task

        }
        
        else
        {

            if ($PSBoundParameters['TargetAddresses'])
            {

                "[{0}] Adding TargetPortAssignmentType and TargetAddresses to volume attachment members." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                ForEach ($_VolAttachment in $_volumeAttachments)
                {

                    $_volumeAttachments | Add-Member -NotePropertyName TargetPortAssignmentType -NotePropertyValue $TargetPortAssignment
                    $_volumeAttachments | Add-Member -NotePropertyName TargetAddresses -NotePropertyValue $TargetAddresses

                }                

            }

            return $_volumeAttachments

        }

    }

}

#######################################################
# Index:
#

function Search-HPOVIndex  
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [string]$Search,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [string]$Category,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [int]$Count = 50,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [int]$Start = 0,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Initialize collection to hold multiple volume attachments objects
        $_IndexSearchResults = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance Connection '{0}' (of {1})" -f $_appliance.Name, $ApplianceConnection.count | Write-Verbose

            $uri = $indexuri + '?start=' + $start.ToString() + '&count=' + $count.ToString()
        
            if ($search) 
            { 
                
                $uri = $uri + "&userQuery=" + $search 
            
            }
            
            if ($category) 
            { 
                
                $uri = $uri + "&category=" + $category 
            
            }
            
            $uri = $uri.Replace(" ", "%20")

            Try
            {

                $r = Send-HPOVRequest $uri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }        
            
            if ($r.count -eq 0 -and $PSBoundParameters['Search']) 
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException NoIndexResults ObjectNotFound 'Search' -Message ("No Index results found for '{0}' on '{1}." -f $Search, $_appliance.Name)
                $PSCmdlet.WriteError($ErrorRecord)
            }

            else 
            {
                
                $r.members | % {

                    $_.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.IndexResource')

                    [void]$_IndexSearchResults.Add($_)

                }

            }

        }

    }

    End
    {

        "Done. {0} index resource(s) found." -f $_IndexSearchResults.count | write-verbose

        Return $_IndexSearchResults

    }

}

function Search-HPOVAssociations 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [string]$AssociationName,

        [Parameter (Mandatory = $false, ValueFromPipeline)]
        [ValidateNotNullorEmpty()]
        [object]$Parent,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [object]$Child,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [int]$Count = 50,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [int]$Start = 0,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )    

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSBoundParameters['Parent'])
        {

            if (-not($Parent -is [PSCustomObject]))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Parent' -Message "The provided -Parent Parameter value is not an Object. Please correct the value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            $ApplianceConnection = $Parent.ApplianceConnection

        }

        elseif ($PSBoundParameters['Child'])
        {

            if (-not($Child -is [PSCustomObject]))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Chuld' -Message "The provided -Child Parameter value is not an Object. Please correct the value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            $ApplianceConnection = $Child.ApplianceConnection

        }

        if ($PSBoundParameters['ApplianceConnection'])
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        #Initialize collection to hold multiple volume attachments objects
        $_IndexSearchResults = New-Object System.Collections.ArrayList

    }

    Process 
    {

        $uri = $associationsUri + '?start=' + $start.ToString() + '&count=' + $count.ToString()

        if ($PSBoundParameters['AssociationName']) 
        { 

            $uri = $uri + "&name=" + $associationName 
        
        }
        
        if ($Parent) 
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Parent resource: {0}" -f ($Parent | Out-String) | Write-Verbose 

            if (-not($Parent -is [PSCustomObject]))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Parent' -Message "The provided -Parent Parameter value is not an Object. Please correct the value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
                    
            $uri = $uri + "&parentUri=" + $Parent.uri
        
        }
        
        if ($PSBoundParameters['Child']) 
        {

            "[$($MyInvocation.InvocationName.ToString().ToUpper())] Child resource: {0}" -f ($Child | Out-String) | Write-Verbose 

            if (-not($Child -is [PSCustomObject]))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Child' -Message "The provided -Child Parameter value is not an Object. Please correct the value."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            $uri = $uri + "&childUri=" + $Child.uri
        
        }
        
        $uri = $uri.Replace(" ", "%20")

        Try
        {

            $r = Send-HPOVRequest $uri -Hostname $ApplianceConnection.Name

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $r.members | % {

            [void]$_IndexSearchResults.Add($_)

        }

    }
    
    End
    {

        Return $_IndexSearchResults

    }

}

#######################################################
# Tasks:
#

function Get-HPOVTask 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "ResourceCategory")]
        [ValidateNotNullorEmpty()]
        [Alias ("TaskName")]
        [string]$Name,

        [Parameter (Mandatory = $false, ValueFromPipeline, ParameterSetName = "Default")]
        [Alias('Resource')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "ResourceCategory")]
        [ValidateNotNullorEmpty()]
        [Alias ("Category")]
        [String]$ResourceCategory,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "ResourceCategory")]
        [ValidateNotNullorEmpty()]
        [ValidateSet ("Unknown","New","Running","SuspEnded","Terminated","Killed","Completed","Error","Warning")]
        [string]$State,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ParameterSetName = "ResourceCategory")]
        [ValidateScript({ if ([int]$_ -gt -1) {$true} else {Throw "The Count Parameter value '$_' is invalid."}})]
        [Int]$Count = 0,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "ResourceCategory")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            $uri = $TasksUri + '?sort=modified:desc'

            if ($PSBoundParameters['Name']) 
            { 
        
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Name Parameter value: $($Name)"

                $Uri += "&filter=name='$Name'" 
        
            }

            if ($PSBoundParameters['State']) 
            { 
        
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] State Parameter value: $($State)"

                $Uri += "&filter=taskState='$State'" 
                            
            }

            if ($PSBoundParameters['Count']) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Count Parameter value: $($Count)"
                    
                $Uri += "&count=$Count&sort=created:descEnding" 

            }


            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Parameter Set Name resolved to: $($PSCmdlet.ParameterSetName)"

            switch ($PSCmdlet.ParameterSetName) 
            {

                "Default" 
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resource value: $InputObject"
                    
                    if ($PSBoundParameters['InputObject']) 
                    {

                        #If the Resource value is a Name
                        if (($InputObject -is [string]) -and (-not($InputObject.StartsWith("/rest/"))))
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resource Parameter Name: $($InputObject)"

                            $Uri += "&filter=associatedResource.resourceName='$InputObject'" 
                            
                        }

                        #Checking if the input is System.String and IS a URI
                        elseif (($InputObject -is [string]) -and ($InputObject.StartsWith("/rest/"))) 
                        {
                
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resource Parameter URI: $($InputObject)"
    
                            $Uri += "&filter=associatedResource.resourceUri='$InputObject'" 
                            
            
                        }

                        #Checking if the input is PSCustomObject, and the category type is not null, which would be passed via pipeline input
                        elseif (($InputObject -is [PSCustomObject]) -and ($InputObject.category)) 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resource is an object: '$($InputObject.name)' of type '$($InputObject.Category)'"

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Using URI value ($($InputObject.Uri)) from input object."

                            $Uri += "&filter=associatedResource.resourceUri='$($InputObject.Uri)'" 
                            
                        }

                        else 
                        {
                             
                            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'InputObject' -Message "The Resource input Parameter was not recognized as a valid type or format."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                            
                        }
                        
                    }

                } #End Default
                
                "ResourceCategory" 
                { 
                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resource Category was specified: $($ResourceCategory)"

                    $Uri += "&filter=associatedResource.resourceCategory='$($ResourceCategory)'" 

                } #End ResourceCategory

            } #End switch

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] URI: $($Uri)"

            if ($Count -gt 0 ) 
            { 
            
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting $($Count) task objects." 
        
            }

            else 
            { 
            
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] ($($Count)) Returning all available task objects." 
        
            }

            try 
            {
        
                $_tasks = Send-HPOVRequest $Uri -Hostname $_appliance

                if ($_tasks.count -eq 0) 
                { 
                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No tasks found on Appliance '$($_appliance.Name)'."

                    if ($Name)
                    {

                        $ExceptionMessage = "Task '{0}' name was not found on '{1}' appliance connection." -f $Name, $_appliance.Name
                        $ErrorRecord = New-ErrorRecord InvalidOperationException ResourceNotFound ObjectNotFound 'Name' -Message $ExceptionMessage
                        $PSCmdlet.WriteError($ErrorRecord)

                    }
                    
                }

                else 
                { 
                
                    $_tasks.members | % { 
                            
                        $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.TaskResource") 
                        
                        [void]$_TaskCollection.Add($_)
                        
                    }
 
                }

            }

            catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)
            
            }

        }

    }    

    End
    {

        "[$($MyInvocation.InvocationName.ToString().ToUpper())] Done. {0} task resource(s) found." -f $_TaskCollection.count | write-verbose

        Return $_TaskCollection

    }

}

function Wait-HPOVTaskStart  
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [Alias ('taskuri')]
        [object]$task,

        [Parameter (Mandatory = $false)]
        [string]$resourceName,

        [Parameter (Mandatory = $false)]
        [timespan]$timeout = $script:defaultTimeout,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    ) 

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['task']) { $PipelineInput = $True }

        if ($Task -is [String] -and ($ApplianceConnection.Count -gt 1) -and (-not($PipelineInput)))
        {
        
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Task' -Message "The -Task Parameter requires an Appliance to be specified. Please provide the Appliance Connection object or name by using the -ApplianceConnection Parameter."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        else
        {


            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $TaskCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput) 
        { 
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Task resource passed via pipeline input." 
        
        }

        #Validate the task object
        if (($task -is [String]) -and ($task.StartsWith($TasksUri))) 
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Task is System.String $($task)"
        
        }

        elseif (($task -is [PSCustomObject] -or $task -is [HPOneView.Appliance.TaskResource]) -and ($task.category -ieq 'tasks')) 
        {
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Task is $($task.GetType()). Task URI: $($task.uri)"

            $ApplianceConnection = $task.ApplianceConnection

            $task = $task.uri
        
        }

        else 
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument 'Wait-HPOVTaskStart' -Message "Invalid task. Please verify the task object you are passing and try again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $sw = [diagnostics.stopwatch]::StartNew()

        Try
        {

            $taskObj = Send-HPOVRequest $task -HostName $ApplianceConnection.name

        }
        
        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }
        
        $i = 0

        if ($resourceName) 
        { 
            
            $taskname = "Waiting for '{0} {1}' task to start" -f $taskObj.name, $resourceName
        
        }

        else 
        { 
            
            $taskName = "Waiting for '{0}' task to start" -f $taskObj.name
        
        }

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $taskName"

        while ($taskObj.taskState -and ($taskObj.taskState -ieq "Adding" -or $taskObj.taskState -ieq "New" -or $taskObj.taskState -ieq "Starting")) 
        {

            Try
            {

                $taskObj = Send-HPOVRequest $task -Hostname $taskObj.ApplianceConnection.Name

            }

            Catch
            {
            
                $PSCmdlet.ThrowTerminatingError($_)
            
            }
            
            if ($sw.Elapsed -gt $timeout) 
            {
                
                $ErrorRecord = New-ErrorRecord InvalidOperationException TaskWaitExceededTimeout OperationTimeout  'Wait-HPOVTaskStart' -Message "The time-out period expired before waiting for task '$taskName' to start." #-verbos
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            #Display Progress Bar

            #Display the task status
            if ($taskObject.taskStatus)
            {

                $progressStatus = $taskObject.taskStatus

            }
                        
            elseif ($taskObject.taskState)
            {

                $progressStatus = $taskObject.taskState

            }

            else
            {

                $progressStatus = "Waiting $($taskObject.Name)"

            }

            if ($taskObj.expectedDuration) 
            {

                $percentComplete = ($i / $taskObj.expectedDuration * 100)

            }

            else
            {

                $percentComplete = $taskObj.percentComplete 

            }
            
            #Handle the call from -Verbose so Write-Progress does not get borked on display.
            if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
            { 
                
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Skipping Write-Progress display."
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Task Status: '$taskName' {$progressStatus} $($percentComplete)% Complete"

            }
             
            else 
            {

                Write-Progress -activity $taskName -status $progressStatus -percentComplete $percentComplete
                
            }

            Start-Sleep 1

            $i++

        }

        Write-Progress -activity $taskName -Completed

        [void]$TaskCollection.Add($taskObj)

    }

    End 
    {
    
        Return $TaskCollection

    }

}

function Wait-HPOVTaskComplete 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (

        [Parameter (ValueFromPipeline, Mandatory)]
        [Alias ('TaskUri','Task')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false)]
        [timespan]$timeout = $DefaultTimeout,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $PSBoundParameters['InputObject']) 
        { 
            
            $PipelineInput = $True 
        
        }
        
        #Task isn't provided by pipeline, but check for ApplianceConnection property
        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $TaskCollection          = New-Object System.Collections.ArrayList
        $FinishedTasksCollection = New-Object System.Collections.ArrayList
        $_TaskIds                = New-Object System.Collections.ArrayList

        $i = 1

    }

    Process 
    {

        if ($PipelineInput) 
        { 
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Task resource passed via pipeline input." 
        
        }

        #Validate the task object
        ForEach ($_task in $InputObject)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing task resources." 

            if (($_task -is [String]) -and ($_task.StartsWith($TasksUri))) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Task is URI $($_task)"

                #Use to track -ID in Write-Progress
                $_task = [PSCustomObject]@{id = $i; uri = $_task; taskState = $Null; ApplianceConnection = $ApplianceConnection }

            }

            elseif ($_task -is [PSCustomObject] -and $_task.category -ieq 'tasks')
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Task is $($_task.GetType()). Task URI: $($_task.uri)"
                
                #Use to track -ID in Write-Progress
                $_task | Add-Member -NotePropertyName id -NotePropertyValue $i -force
                
            }

            else 
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument $_task -Message "Invalid task object provided. Please verify the task object you are passing and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            [void]$TaskCollection.Add($_task)
            [void]$_TaskIds.Add($i)

            $i++
            
        }

    }

    End
    {

        $_taskCollection = $TaskCollection.Clone()        

        #Start Stopwatch
        $sw = [diagnostics.stopwatch]::StartNew()

        while ($_taskCollection.Count -gt 0 -and $sw.Elapsed -lt $timeout)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing taskcollection."

            if ($sw.Elapsed -gt $timeout) 
            {
                #Tear down Write-Progress
                $_taskCollection | % { Write-Progress -id $_.id -Completed }

                #Return 'finished' collection to caller then display error
                if ($_taskCollection.Count -gt 0)
                {

                    $_taskCollection

                }
                
                if ($FinishedTasksCollection.Count -gt 0)
                {

                    $FinishedTasksCollection

                }

                #UPDATE ERROR MESSAGE to state timeout waiting for tasks to complete
                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.TaskResourceException TaskWaitExceededTimeout OperationTimeout  'Wait-HPOVTaskComplete' -Message "The time-out period expired before waiting for task '$taskName' to start." #-verbos
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            $_t = 1

            ForEach ($_task in $_taskCollection)
            {

                #Get task object from API
                Try
                {

                    "[{0}] Getting task object from API." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $_taskObj = Send-HPOVRequest $_task.uri -Hostname $_task.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                $Activity = '{0} {1}' -f $_taskObj.name, $_taskObj.associatedResource.resourceName
            
                #Task is in a finished state
                if ($TaskFinishedStatesEnum -contains $_taskObj.taskState)
                {

                    "[{0}] Task is finished, removing from collection." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                      
                    "[{0}] Task Collection size: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $TaskCollection.count | Write-Verbose

                    #Remove task object from base arraylist
                    [void]$TaskCollection.Remove($_task)

                    "[{0}] Updated Task Collection size: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $TaskCollection.count | Write-Verbose

                    #Add Task Object from API to return back to caller
                    [void]$FinishedTasksCollection.Add($_taskObj)

                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    {
                        
                        "[{0}] {1} [{2}{3}] Task finished. " -f $MyInvocation.InvocationName.ToString().ToUpper(), $_taskObj.name, $_taskObj.ApplianceConnection.Name, $_taskObj.uri | Write-Verbose
                    
                    }

                    else 
                    {
                    
                        Write-Progress -id $_task.id -activity $Activity -Completed
                    
                    }

                }

                #Display Progress Bar
                else
                {

                    #Check for running associated tasks for -CurrentOperation status messages
                    Try
                    {

                        $AssociatedChildTasksInexUri = "{0}?sort=created:desc&start=0&category=tasks&query=parentTaskUri:'{1}' AND state:'Running'" -f $IndexUri, $_taskObj.uri

                        # $AssociatedChildTask = Send-HPOVRequest -Uri $AssociatedChildTasksInexUri -Hostname $_taskObj.ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    $CurrentOperation = $null

                    # if ($AssociatedChildTask.count -gt 0)
                    # {

                    # ForEach ($Operation in $AssociatedChildTask.members.attributes.stateDetails)
                    # {

                    # if ($null -ne $Operation -or (-not [System.String]::IsNullOrWhiteSpace($Operation)))
                    # {

                    # $CurrentOperation += $Operation

                    # }

                    # }

                    # $CurrentOperation = [String]::Join(', ', $CurrentOperation)
                        
                    # }

                    #Handle the call from -Verbose so Write-Progress does not get borked on display.
                    if ($PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue') 
                    { 
                        
                        "[{0}] Skipping Write-Progress display." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
                        
                        "[{0}] CMDLET Task Track ID: {1}`nTask Object Name: {2}`nAssociated Resource Name: {3}`nPrecent Complete: {4}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_task.id, $_taskObj.name,$_taskObj.associatedResource.resourceName,$_taskObj.percentComplete | Write-Verbose
                    
                        If ($_taskObj.progressUpdates[-1].statusUpdate)
                        {

                            "[{0}] Child tasks - Child task: {1} ParentId: {2} {3} ({4})" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($_task.id + 100), $_task.id, $_taskObj.progressUpdates[-1].statusUpdate, $_taskObj.taskStatus | Write-Verbose

                        }

                        if ($CurrentOperation)
                        {

                            "[{0}] Current operation: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $CurrentOperation | Write-Verbose

                        }

                    }
                    
                    else 
                    {

                        #Display the task status, and associated child tasks
                        if ($_taskObj.progressUpdates.count -gt 0) 
                        { 

                            #StatusUpdate contains an embedded JSON object as a string.
                            if ($_taskObj.progressUpdates[-1].statusUpdate -match '{')
                            {

                                $ChildTaskMessage = $_taskObj.progressUpdates[-1].statusUpdate.Substring($_taskObj.progressUpdates[-1].statusUpdate.IndexOf('{'), ($_taskObj.progressUpdates[-1].statusUpdate.IndexOf('}') - $_taskObj.progressUpdates[-1].statusUpdate.IndexOf('{') + 1)) | ConvertFrom-Json
                                $StatusMessage  = '{0}{1}' -f $_taskObj.progressUpdates[-1].statusUpdate.Substring(0, $_taskObj.progressUpdates[-1].statusUpdate.IndexOf('{')), $ChildTaskMessage.name

                            }

                            else
                            {

                                $StatusMessage  = '{0}' -f $_taskObj.progressUpdates[-1].statusUpdate

                            }    

                            if ($null -eq $StatusMessage -or [System.String]::IsNullOrWhiteSpace($StatusMessage))
                            {

                                $StatusMessage = $_taskObj.taskState

                            }    

                            #Child task is executing, display reported status
                            #Need to add child task object to trask tracker so to remove them when finished from Write-Progress nested view
                            If ($_taskObj.progressUpdates[-1].statusUpdate) 
                            {

                                if ($_TaskIds -notcontains ($_task.id + 100))
                                {

                                    [void]$_TaskIds.Add($_task.id + 100)

                                }

                                $ChildTaskStatus = '{0} {1}' -f $_taskObj.name, $_taskObj.associatedResource.resourceName

                                Write-Progress -id ($_task.id + 100) -ParentId $_task.id -activity $ChildTaskStatus -status $StatusMessage -CurrentOperation $CurrentOperation -percentComplete $_taskObj.computedPercentComplete
                            
                            }

                            #There is a child task, but it's statusUpdate value is NULL, so just display the parent task status
                            else 
                            {
                            
                                if ($_taskObj.taskStatus)
                                {

                                    $progressStatus = $_taskObj.taskStatus

                                }
                                
                                else
                                {

                                    $progressStatus = $_taskObj.taskState

                                }

                                Write-Progress -Activity $Activity -Status $StatusMessage -CurrentOperation $CurrentOperation -percentComplete $_taskObj.percentComplete
                            
                            }

                        }

                        #Just display the task status, as it has no child tasks
                        elseif ($_taskObj.taskStatus) 
                        {
                            
                            Write-Progress -activity $Activity -status $_taskObj.taskStatus -CurrentOperation $CurrentOperation -percentComplete $_taskObj.percentComplete 
                        
                        }
                        
                        else 
                        {
                            
                            Write-Progress -activity $Activity -status $_taskObj.taskState -CurrentOperation $CurrentOperation -percentComplete $_taskObj.percentComplete 
                        
                        }

                    }
                    
                }
                
                if ($_t -ge $_taskCollection.count)
                {

                    Start-Sleep -seconds 2
                    $_t = 1 #reset counter

                }

                else
                {

                    $_t++

                }

            }

            #Reclone $_taskCollection object to update array with current task ArrayList
            $_taskCollection = $TaskCollection.Clone()

        }

        #Tear down any remaining Write-Progress displays before returning back to the user
        $_TaskIds | % { Write-Progress -id $_ -Activity "Completed" -Completed }

        Return $FinishedTasksCollection

    }

}

#######################################################
# Securty and LDAP functions
#

function Get-HPOVUser 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [string]$Name,
        
        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )
    
    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }    
        
        $_UserCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            $_uri = $UsersUri + "?sort=username:asc"

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            if ($PSBoundParameters['Name'])
            {

                $_filterparam = 'EQ'

                if ($Name -contains '\*')
                {

                    $_filterparam = 'MATCHES'
                    $Name = $Name.Replace('*','%25')

                }

                $_uri += '&filter=loginName {0} "{1}"' -f $_filterparam, $Name

            }

            Try
            {

                $_users = Send-HPOVRequest $_uri -Hostname $_appliance.Name 

                if ($_users.count -eq 0 -and $Name) 
                {
                
                    $_Message    = "Username '{0}' was not found on {1} Appliance Connection. Please check the spelling, or create the user and try again." -f $Name, $_appliance.Name 
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.UserResourceException UserNotFound ObjectNotFound "Name" -Message $_Message
                    $PSCmdlet.WriteError($ErrorRecord)

                }

            }

            #User isn't authorized, so let's display their user account
            Catch [HPOneView.Appliance.AuthPrivilegeException]
            {

                Try
                {

                    $_user = Send-HPOVRequest ($UsersUri + '/' + $_appliance.Username) -Hostname $_appliance.Name 

                    $_user.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.User')

                    [void]$_UserCollection.Add($_user)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Found $($_users.count) user resources on '$($_appliance.Name)' appliance."

            if ($_users.members)
            {

                ForEach ($u in $_users.members) 
                {

                    $u.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.User')

                    [void]$_UserCollection.Add($u)

                }

            }
            
        }

    }

    End 
    {

        "Done. {0} user(s) found." -f $_UserCollection.count | write-verbose 
        
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] returning account resource objects."  
        
        Return $_UserCollection    

    }

}

function New-HPOVUser 
{
     
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$UserName, 

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Password, 

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$FullName, 

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [Array]$Roles = @(),

        [Parameter (Mandatory = $false)]
        [validatescript({$_ -as [Net.Mail.MailAddress]})]
        [string]$EmailAddress,

        [Parameter (Mandatory = $false)] 
        [ValidateNotNullOrEmpty()]
        [string]$OfficePhone,
     
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$MobilePhone,

        [Parameter (Mandatory = $false)]
        [switch]$Enabled,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {


        if ($PSBoundParameters['Enabled'])
        {

            Write-Warning 'The -Enabled Parameter is now deprecated. By default, all new user accounts will be enabled. In order to disable a user account, use the Set-HPOVUser Cmdlet.'

        }

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
        $_UserStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Validating requested role values"
            
            $_unsupportedRoles = New-Object System.Collections.ArrayList
            $_NewUserRoles     = New-Object System.Collections.ArrayList

            #Validate roles provided are allowed.
            foreach ($_role in $Roles) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing role: $_role"

                if (-not ((${Global:ConnectedSessions} | ? Name -EQ $_appliance.Name).ApplianceSecurityRoles -contains $_role)) 
                { 
                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid or unsupported"

                    [void]$_unsupportedRoles.Add($_role)
            
                }

                else
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Supported"

                    $_role = $_role.SubString(0,1).ToUpper() + $_role.SubString(1).tolower()

                    [void]$_NewUserRoles.Add($_role)

                }

            }

            if ($_unsupportedRoles.count -ge 1) 
            { 
        
                $ErrorRecord = New-ErrorRecord ArgumentException UnsupportedRolesFound InvalidArgument $($MyInvocation.InvocationName.ToString().ToUpper()) -Message "The '$($_unsupportedRoles -join ", ")' role(s) is/are not supported or the correct names. Please validate the -roles Parameter contains one or more valid roles. Allowed roles are: $((${Global:ConnectedSessions} | ? Name -EQ $_appliance.Name).ApplianceSecurityRoles -join ", ")"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)            
            
            }

            $_user = NewObject -UserAccount

            $_user.userName     = $userName
            $_user.fullName     = $fullName
            $_user.password     = $password
            $_user.emailAddress = $emailAddress
            $_user.officePhone  = $officePhone 
            $_user.mobilePhone  = $mobilePhone
            $_user.enabled      = $true
            $_user.roles        = $_NewUserRoles

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User requested to create: $($_user | out-string )"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to create $($_user.userName) user"
            
            Try
            {

                $_resp = Send-HPOVRequest $usersUri POST $_user -Hostname $_appliance.Name

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.User')

            [void]$_UserStatus.Add($_resp)

        }

    }

    End
    {
        
        Return $_UserStatus

    }

}

function Set-HPOVUser 
{
     
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'default')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Pipeline')]
        [ValidateNotNullorEmpty()]
        [Object]$UserObject,

        [Parameter (Mandatory, ParameterSetName = 'default')]
        [ValidateNotNullorEmpty()]
        [string]$UserName, 

        [Parameter (Mandatory = $false, ParameterSetName = 'default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Pipeline')]
        [ValidateNotNullorEmpty()]
        [string]$Password, 

        [Parameter (Mandatory = $false, ParameterSetName = 'default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Pipeline')]
        [ValidateNotNullorEmpty()]
        [string]$FullName, 

        [Parameter (Mandatory = $false, ParameterSetName = 'default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Pipeline')]
        [ValidateNotNullorEmpty()]
        [Array]$Roles,

        [Parameter (Mandatory = $false, ParameterSetName = 'default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Pipeline')]
        [validatescript({$_ -as [Net.Mail.MailAddress]})]
        [string]$EmailAddress,

        [Parameter (Mandatory = $false, ParameterSetName = 'default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Pipeline')] 
        [ValidateNotNullorEmpty()]
        [string]$OfficePhone,
     
        [Parameter (Mandatory = $false, ParameterSetName = 'default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Pipeline')]
        [ValidateNotNullorEmpty()]
        [string]$MobilePhone,
     
        [Parameter (Mandatory = $false, ParameterSetName = 'default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Pipeline')]
        [Alias ('enable')]
        [ValidateNotNullorEmpty()]
        [switch]$Enabled,

        [Parameter (Mandatory = $false, ParameterSetName = 'default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Pipeline')]
        [Alias ('disable')]
        [ValidateNotNullorEmpty()]
        [switch]$Disabled,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'default')]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Pipeline')]
        [Alias ('Appliance')]
        [ValidateNotNullorEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #No need to validate ApplianceConnection, as object is passed via pipeline.
        if ($PSCmdlet.ParameterSetName -eq 'Pipeline')
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Pipeline input."
            
            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }
                        
        }

        $_UsersToUpdate = New-Object System.Collections.ArrayList
        $_UserStatus    = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput)
        {

            #Validate pipeline input is user object
            if (-not($UserObject -is [PSCustomObject]) -and -not($UserObject.category -eq 'users'))
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid UserObject provided: $($UserObject | FL * | Out-String)"

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.UserResourceException InvalidUserObject InvalidArgument "UserObject" -TargetType 'PSObject' -Message "The UserObject Parameter value is not a valid User object resource. Object category provided '$($UserObject.category)', allowed object category value 'users'. Please verify the input object and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding UserObject to Process collection: $($UserObject | FL * | Out-String)"

            [void]$_UsersToUpdate.Add($UserObject)

        }

        else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                try 
                { 
                    
                    $_UserObject = Get-HPOVUser -Name $userName -ApplianceConnection $_appliance
                
                }
        
                #If not found, throw error
                catch [HPOneView.Appliance.UserResourceException]
                {
                
                    #Generate terminating error
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.UserResourceException UserNotFound ObjectNotFound 'UserName' -Message "Username `'$userName`' was not found. Please check the spelling, or create the user and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                [void]$_UsersToUpdate.Add($_UserObject)

            }

        }

    }

    End
    {

        ForEach ($_User in $_UsersToUpdate)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing User: $($_User.userName)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Original User object: $($_User | FL * | Out-String)"

            #$_User | Add-Member -NotePropertyName type -NotePropertyValue 'UserAndRoles'

            switch ($PSBoundParameters.keys) 
            {

                "Password" 
                { 

                    if ($_User.userName -eq (${Global:ConnectedSessions} | ? Name -eq $_User.ApplianceConnection.Name).UserName) 
                    {

                        write-warning "This CMDLET will not modify the password for your account. Please use the Set-HPOVUserPassword CMDLET to update your user account password. Password update will not be Processed."

                    }  
                                  
                    else 
                    { 
                        
                        $_User | Add-Member -NotePropertyName password -NotePropertyValue $Password -force
                        
                    } 
                
                }

                "fullName" 
                { 
                    
                    $_User.fullName = $FullName
                
                }

                "roles" 
                {

                    if ($_User.userName -eq (${Global:ConnectedSessions} | ? Name -eq $_User.ApplianceConnection.Name).UserName) 
                    {

                        write-warning "Unable to modify roles for your account, as you must be authenticated to the appliance with a different administrator account. Roles will not be Processed."

                    }

                    else 
                    {
                    
                        $_User | add-member -NotePropertyName replaceRoles -NotePropertyValue $True -force

                        #Validate roles provided are allowed.
                        $_unsupportedRoles = New-OBject System.Collections.ArrayList
                        $_NewUserRoles     = New-OBject System.Collections.ArrayList

                        #Validate roles provided are allowed.
                        foreach ($_role in $Roles) 
                        {

                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing role: $_role"

                            if ((${Global:ConnectedSessions} | ? Name -EQ $_User.ApplianceConnection.Name).ApplianceSecurityRoles -notcontains $_role)
                            { 
                            
                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid or unsupported"

                                [void]$_unsupportedRoles.Add($_role)
                        
                            }

                            else
                            {

                                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Supported"

                                $_role = $_role.SubString(0,1).ToUpper() + $_role.SubString(1).tolower()

                                [void]$_NewUserRoles.Add($_role)

                            }

                        }

                        if ($_unsupportedRoles.count -ge 1) 
                        { 
        
                            $ErrorRecord = New-ErrorRecord ArgumentException UnsupportedRolesFound InvalidArgument $($MyInvocation.InvocationName.ToString().ToUpper()) -Message "The '$($_unsupportedRoles -join ", ")' role(s) is/are not supported or the correct names. Please validate the -roles Parameter contains one or more valid roles. Allowed roles are: $((${Global:ConnectedSessions} | ? Name -EQ $_Connection.Name).ApplianceSecurityRoles -join ", ")"
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)            
                        
                        }

                        $_User.roles = $_NewUserRoles

                    }

                }

                "emailAddress" 
                { 
                    
                    $_User.emailAddress = $EmailAddress
                
                }

                "officePhone" 
                { 
                    
                    $_User.officePhone = $OfficePhone
                
                }

                "mobilePhone" 
                { 
                    
                    $_User.mobilePhone = $MobilePhone
                
                }

                "enabled" 
                { 
                
                    if ($_User.userName -eq (${Global:ConnectedSessions} | ? Name -eq $_User.ApplianceConnection.Name).UserName) 
                    {

                        write-warning "This CMDLET will not modify the state for your account. Please authenticate to the appliance with a different administrator account. Account state will not be Processed."

                    }

                    else 
                    { 
                        
                        $_User.enabled = $true
                    
                    }

                }

                "disabled" 
                { 

                    if ($_User.userName -eq (${Global:ConnectedSessions} | ? Name -eq $_User.ApplianceConnection.Name).UserName) 
                    {

                        write-warning "This CMDLET will not modify the state for your account. Please authenticate to the appliance with a different administrator account. Account state will not be Processed."

                    }

                    else 
                    { 
                        
                        $_User.enabled = $false

                    }

                }

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updated User object: $($_User | FL * | Out-String)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to update `'$($_User.userName)`' user at '$usersUri'"

            Try
            {

                $_resp = Send-HPOVRequest $usersUri PUT $_User -Hostname $_User.ApplianceConnection.Name

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.User')

            [void]$_UserStatus.Add($_resp)

        }
        
        Return $_UserStatus

    }

}

function Set-HPOVUserPassword 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('CurrentPassword')]
        [String]$Current,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Alias ('NewPassword')]
        [String]$New,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
        
        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Prompt user for current password if not provided
        if (-not($PSBoundParameters['Current'])) 
        { 
        
            $Current                  = Read-Host -AsSecureString "Current"
            $_decryptCurrentPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Current))

        }

        else 
        { 
            
            $_decryptCurrentPassword = $Current 
        
        }

        #Prompt user for new password if not provided
        if (-not($PSBoundParameters['New'])) 
        { 
        
            Do 
            {

                $New                 = Read-Host -AsSecureString "New"
                $_CompareNewPassword = Read-Host -AsSecureString "Re-type New"
                
                #Compare provided password matches
                $_decryptNewPassword        = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($New))
                $_decryptcompareNewPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($_CompareNewPassword))

                if (-not ($_decryptNewPassword -eq $_decryptcompareNewPassword))
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.PasswordMismatchException NewPasswordsDoNotMatch InvalidResult 'New' -Message "The new password values do not match. Please check the value and try again."
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                if (-not ($_decryptNewPassword.length -ge 8) -or -not ($_decryptcompareNewPassword -ge 8)) 
                {
                
                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.PasswordMismatchException NewPasswordLengthTooShort InvalidResult 'New' -Message "The new password value do not meet the minimum character length of 8 characters. Please try again."
                    $PSCmdlet.WriteError($ErrorRecord)

                }

            } Until ($_decryptNewPassword -eq $_decryptcompareNewPassword -and $_decryptNewPassword.length -ge 8)

        }

        else 
        {

            $_decryptNewPassword = $New

        }

        $_UserStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            if ($_appliance.AuthLoginDomain -ne 'LOCAL')
            {

                $_message     = "The user account Auth Provider, {0}, is not the local appliance. HPE OneView does not support updating an LDAP User Account password." -f $_appliance.AuthLoginDomain
                $_errorrecord = New-ErrorRecord HPOneView.Appliance.UserResourceException UserNotFound ObjectNotFound 'UserName' -Message $_message
                $PSCmdlet.WriteError($_errorrecord)

            }

            else
            {

                $_UpdatePassword                 = NewObject -UpdateUserPassword
                $_UpdatePassword.currentPassword = $_decryptCurrentPassword
                $_UpdatePassword.password        = $_decryptNewPassword
                $_UpdatePassword.userName        = $_appliance.UserName

                Try
                {

                    $_resp = Send-HPOVRequest $UsersUri PUT $_UpdatePassword -Hostname $_appliance

                    if ($_resp.category -eq 'users')
                    {

                        $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.User')

                    }

                    [void]$_UserStatus.Add($_resp)

                }
                
                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }     

    }

    End 
    {

        Return $_UserStatus

    }

}

function Remove-HPOVUser 
{
     
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("u","user",'UserName')]
        [Object]$Name,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Name'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList
        $_UserCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User Object provided: $($Name | FL * | Out-String)"

            If ('users' -contains $Name.category)
            {

                If (-not($Name.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "User:$($Name.Name)" -TargetType PSObject -Message "The User object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_UserCollection.Add($Name)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "User:$($Name.Name)" -TargetType PSObject -Message "The User object resource is not an expected category type [$($Name.category)]. The allowed resource category type is 'users'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count))"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing User Name $($Name)"

                Try
                {

                    $_User = Get-HPOVUser $Name -ApplianceConnection $_appliance

                    $_User | % {

                        [void]$_UserCollection.Add($_)

                    }

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_UserCollection.count) User object resources to remove."

        #Process User Resources
        ForEach ($_user in $_UserCollection)
        {

            if ($PSCmdlet.ShouldProcess($_user.ApplianceConnection.Name,"Remove User '$($_user.userName)' from appliance")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing User '$($_user.userName)' from appliance '$($_user.ApplianceConnection.Name)'."

                Try
                {

                    $_resp = Send-HPOVRequest $_user.Uri DELETE -Hostname $_user.ApplianceConnection.Name

                    $_resp | Add-Member -NotePropertyName userName -NotePropertyValue $_user.userName

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Show-HPOVUserSession 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param ()

    Begin 
    {
    
        Write-Warning "This CMDLET has been deprecated. Please use the $ConnectedSessions Global variable for appliance session information."
    
    }

    Process { }

    End { }

}

function Get-HPOVRole 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param()
    
    Begin 
    {

        Write-Warning "This CMDLET is now deprecated. Please use the Get-HPOVUser CMDLET to retrieve the user account and associated Roles."

    }

}

function Set-HPOVUserRole 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias ("user",'userName')]
        [Object]$Name,

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [Alias ('roleName')]
        [Array]$Roles,

        [Parameter (ValueFromPipelineByPropertyName, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose    

        if (-not($PSBoundParameters['Name']))
        { 
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Validating requested role values"
                
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        #Need to make sure role name is first letter capitalized only.
        $i = 0

        foreach ($role in $roles) 
        {

            $roles[$i] = $role.SubString(0,1).ToUpper() + $role.SubString(1).tolower()

            $i++

        }

        $_UserRoleUpdateStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Validating requested role values"
            
            $_unsupportedRoles = New-Object System.Collections.ArrayList
            $_NewUserRoles     = New-Object System.Collections.ArrayList

            #Validate roles provided are allowed.
            foreach ($_role in $Roles) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing role: $_role"

                if (-not ((${Global:ConnectedSessions} | ? Name -EQ $_appliance.Name).ApplianceSecurityRoles -contains $_role)) 
                { 
                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid or unsupported"

                    [void]$_unsupportedRoles.Add($_role)
            
                }

                else
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Supported"

                    $_roleObject = [PsCustomObject]@{
                        roleName = $_role;
                        type = "RoleNameDtoV2"
                    }

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding to role collection: $($_roleObject | fl * | out-string)"

                    [void]$_NewUserRoles.Add($_roleObject)

                }

            }

            if ($_unsupportedRoles.count -ge 1) 
            { 
        
                $ErrorRecord = New-ErrorRecord ArgumentException UnsupportedRolesFound InvalidArgument $($MyInvocation.InvocationName.ToString().ToUpper()) -Message "The '$($_unsupportedRoles -join ", ")' role(s) is/are not supported or the correct names. Please validate the -roles Parameter contains one or more valid roles. Allowed roles are: $((${Global:ConnectedSessions} | ? Name -EQ $_Connection.Name).ApplianceSecurityRoles -join ", ")"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)            
            
            }

            if ($Name -is [PSCustomObject] -and $Name.category -eq 'users')
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Name Parameter value is a User object"

                $_Name = $Name.userName

            }

            elseif ($Name -is [PSCustomObject] -and $Name.category -ne 'users')
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Name Parameter value is NOT a valid User object"

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.UserResourceException InvalidUserObject InvalidArgument "Name" -TargetType 'PSObject' -Message "The object provided via the pipeline for the Name Parameter is not a valid user object. Please check the value and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            else
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Name Parameter value is string"

                $_Name = $Name

            }

            $uri = "{0}/{1}/roles?multiResource=true" -f $UsersUri, $_Name

            Try
            {

                $_resp = Send-HPOVRequest $uri PUT $_NewUserRoles -Hostname $_appliance.Name

            }
        
    
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            [void]$_UserRoleUpdateStatus.Add($_resp)

        }

    }

    End 
    {

        Return $_UserRoleUpdateStatus

    }

}

function Set-HPOVInitialPassword  
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$OldPassword,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$NewPassword,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$Appliance

    )

    Begin 
    { 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #Check to see if a connection to the appliance exists
        if ($Appliance -is [String])
        {

            if (-not(${Global:ConnectedSessions}.Name -contains $Appliance) -and (-not(${Global:ConnectedSessions} | ? Name -eq $Appliance).SessionID))
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Appliance Session not found. Running FTS sequence?"

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Creating temporary Session object"

                [HPOneView.Appliance.Connection]$Appliance = New-Object HPOneView.Appliance.Connection(99, $Appliance)

                $Appliance.SessionID    = 'TemporaryConnection'
                $Appliance.SslChecked   = $true

                [void]${Global:ConnectedSessions}.Add($Appliance)

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $($Appliance | fl * | out-string)"
            
            }

            elseif (${Global:ConnectedSessions}.Name -contains $Appliance)
            {

                "[{0}] Appliance is a string value, lookup connection in global tracker." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                [HPOneView.Appliance.Connection]$Appliance = ${Global:ConnectedSessions} | ? Name -eq $Appliance

                "[{0}] Found connection in global tracker: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Appliance | Out-String) | Write-Verbose

            }

        }        

        elseif ($Appliance -is [HPOneView.Appliance.Connection])
        {

            "[{0}] Appliance is a Connection: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($Appliance | Out-String) | Write-Verbose

        }

        else
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException UnknownCondition InvalidOperation "Appliance" -Message "An unknown condition has ocurred."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if ($OldPassword -is [SecureString])
        {

            $OldPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($OldPassword))

        }

        if ($NewPassword -is [SecureString])
        {

            $NewPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($NewPassword))

        }
    
    }

    Process 
    {
        
        $body = [PSCustomObject]@{
            
            userName    = 'Administrator'; 
            oldPassword = $OldPassword; 
            newPassword = $NewPassword
        
        }

        $uri  = $usersUri + "/changePassword"

        Try
        {

            $resp = Send-HPOVRequest $uri POST $body -Hostname $Appliance

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        finally
        {

            #Remove Temporary appliance connection
            if ((${Global:ConnectedSessions} | ? Name -eq $Appliance.Name).SessionID -eq 'TemporaryConnection')
            {

                write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing temporary Session object"

                [void]${Global:ConnectedSessions}.Remove($Appliance)

            }

        }

    }

    End 
    {

        return $resp

    }

}

function Get-HPOVApplianceTrustedCertificate
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName='Default')]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = 'Export')]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = ($ConnectedSessions | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(),($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not($ConnectedSessions))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Try
                {

                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException]
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try
            {

                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException]
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process
    {

        $_uri = $ApplianceTrustedCertStoreUri

        #API DOES NOT SUPPORT WILDCARD
        if ($Name)
        {

            $_uri += '?filter={0}' -f $Name

        }

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {

                $_CollectionResults = Send-HPOVRequest $_uri -Hostname $_appliance.Name

                $_CollectionResults.members | % {
                    
                    $_.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.TrustedCertificate')
                    $_

                }    

            }

            Catch
            {

                if ($_.Exception.Message -match ("The requested resource '{0}' could not be found" -f $_uri.Replace('?','\?')))
                {

                    $ExceptionMessage = "The specified '{0}' trusted SSL certificate resource not found on Appliance '{1}'. Please check the name and try again." -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.TrustedCertificateResourceException TrustedCertificateResourceNotFound ObjectNotFound "Name" -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                else
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}


function Add-HPOVApplianceTrustedCertificate
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [System.IO.FileInfo]$Path,
        
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
    }
    
    Process 
    {

        #Validate cert is valid X509 object
        Try
        {

            $_CertObject = New-Object Security.Cryptography.X509Certificates.X509Certificate2($Path)
            $_CertBase64 = New-Object String[] -ArgumentList 3
            
            $_CertBase64[0] = "-----BEGIN CERTIFICATE-----"
            $_CertBase64[1] = [System.Convert]::ToBase64String($_CertObject.RawData, "InsertLineBreaks")
            $_CertBase64[2] = "-----END CERTIFICATE-----"

            $_CertBase64 = $_CertBase64 -join "`n"

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $_CertificateObject = NewObject -AddSslCertificate
        $_CertificateObject.base64SSLCertData = $_CertBase64        

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {

                $_Resp = Send-HPOVRequest -Uri $ApplianceTrustedCertStoreUri -Method POST -Body $_CertificateObject -Hostname $_appliance.Name
                $_Resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.TrustedCertificate')
                $_Resp

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }
        
    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVApplianceTrustedCertificate
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        #Throw "Not implemented."

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process 
    {

        "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        "[{0}] Object provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | FL * | Out-String) | Write-Verbose

        If ($InputObject.type -ne 'SSLCertificateV200')
        {

            $ExceptionMessage = 'The InputObject is not a valid appliance trusted certificate.'
            $ErrorRecord = New-ErrorRecord HPOneview.InputObjectResourceException InvalidResourceObject InvalidArgument "InputObject" -TargetType $InputObject.GetType().Name -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $_RemoveMessage = "remove appliance trusted certificate '{0}'" -f $InputObject.aliasName

        if ($PSCmdlet.ShouldProcess($InputObject.ApplianceConnection.Name, $_RemoveMessage)) 
        {

            "[{0}] Removing appliance trusted certificate: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.aliasName | Write-Verbose

            Try
            {
                
                Send-HPOVRequest -Uri $InputObject.Uri -Method DELETE -Hostname $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        elseif ($PSBoundParameters['WhatIf'])
        {
            
            "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }
        
    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Get-HPOVLdap 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName='Default')]
    Param 
    (

        [Parameter (Mandatory, ParameterSetName = 'Export')]
        [Alias ('x')]
        [switch]$Export,

        [Parameter (Mandatory, ParameterSetName = 'Export')]
        [Alias ('location')]
        [ValidateScript ({split-path $_ | Test-Path})]
        [string]$Save,
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Export')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_GlobalAuthDirectorySettings = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {

                $_AuthDirectoryGlobalSettings = Send-HPOVRequest $authnSettingsUri -Hostname $_appliance.Name
                
                $_AuthDirectoryGlobalSettings | % { $_.psobject.typenames.Insert(0,"HPOneView.Appliance.AuthGlobalDirectoryConfiguration") }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            [void]$_GlobalAuthDirectorySettings.Add($_AuthDirectoryGlobalSettings)

        }
        
    }

    End 
    {

        if ($PSBoundParameters['export'])
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Exporting Global Directory configuration."

            ForEach ($_Directory in $_GlobalAuthDirectorySettings)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Saving to: $($save)\$($_Directory.ApplianceConnection.Name)_globalSettings.json"

                ConvertTo-Json $_Directory > $save\$($_Directory.ApplianceConnection.Name)_globalSettings.json

            }        

        }

        else
        {
             
            Return $_GlobalAuthDirectorySettings 

        }

    }

}

function Get-HPOVLdapDirectory 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName='Default')]
        [Alias ('directory','domain')]
        [String]$Name,

        [Parameter (Mandatory, ParameterSetName = 'Export')]
        [Alias ('x')]
        [ValidateScript({split-path $_ | Test-Path})]
        [string]$Export,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Export')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_AuthDirectorySettings = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {
        
            $Found = New-Object System.Collections.ArrayList

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {

                $_AuthDirectories = Send-HPOVRequest $AuthnProvidersUri -Hostname $_appliance.Name
            
                $_AuthDirectories | % { 
                    
                    Try
                    {

                        $_AuthDirectories = Send-HPOVRequest $_.uri -Hostname $_appliance.Name

                    }
                    
                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    If ($Name) 
                    {

                        $_AuthDirectories = $_AuthDirectories | ? name -like $Name

                    }

                    $_AuthDirectories | % {

                        $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AuthDirectory") 
                    
                        [void]$Found.Add($_)

                    }

                }

                if ($Found.Count -eq 0)
                {
                    
                    $ExceptionMessage = "The specified '{0}' Authentication Directory resource not found on Appliance '{1}'. Please check the name and try again." -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryException AuthDirectoryResourceNotFound ObjectNotFound "Name" -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                $Found | % {

                    $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AuthDirectory") 
                
                    [void]$_AuthDirectorySettings.Add($_)

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    End 
    {    
    
        #Export directory settings (raw JSON) to file
        if ($PSboundParameters['export'])
        {

            #Loop through each directory and get all configured settings
            ForEach ($_directory in $_AuthDirectorySettings)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Exporting Directory $($_directory.name) configuration."

                $_SaveLocation = $Export + "\" + $_directory.ApplianceConnection.Name + "_" + $_directory.name + ".json"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Saving to: $_SaveLocation"
                
                $_directory                  | Select-Object * -ExcludeProperty credential,created,modified,eTag             
                $_directory.directoryServers | Select-Object * -ExcludeProperty directoryServerCertificateStatus,serverStatus,created,modified,eTag
                $_directory                  | convertto-json > $_SaveLocation
            
            }
        
        }
        
        else
        {
            
            Return $_AuthDirectorySettings

        }

    }

}

function New-HPOVLdapDirectory 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName='AD')]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "AD")]
        [Parameter (Mandatory, ParameterSetName = "LDAP")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter (Mandatory, ParameterSetName = "AD")]
        [Switch]$AD,

        [Parameter (Mandatory, ParameterSetName = "LDAP")]
        [Alias ('LDAP')]
        [Switch]$OpenLDAP,

        [Parameter (Mandatory, ParameterSetName = "AD")]
        [Parameter (Mandatory, ParameterSetName = "LDAP")]
        [ValidateNotNullOrEmpty()]
        [Alias ('root','rootdn')]
        [String]$BaseDN,

        [Parameter (Mandatory, ParameterSetName = "LDAP")]
        [ValidateNotNullOrEmpty()]
        [Array]$OrganizationalUnits,

        [Parameter (Mandatory, ParameterSetName = "AD")]
        [Parameter (Mandatory, ParameterSetName = "LDAP")]
        [ValidateNotNullOrEmpty()]
        [Array]$Servers,

        [Parameter (Mandatory, ParameterSetName = "AD")]
        [Parameter (Mandatory, ParameterSetName = "LDAP")]
        [ValidateNotNullOrEmpty()]
        [Alias ('u','user')]
        [String]$Username,

        [Parameter (ValueFromPipeline, Mandatory = $false, ParameterSetName = "AD")]
        [Parameter (ValueFromPipeline, Mandatory = $false, ParameterSetName = "LDAP")]
        [ValidateNotNullOrEmpty()]
        [Alias ('p','pass')]
        [Object]$Password,

        [Parameter (Mandatory = $false, ParameterSetName = 'AD')]
        [Parameter (Mandatory = $false, ParameterSetName = 'LDAP')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        if (-not($PSBoundParameters['Password']))
        {

            do 
            {
                
                $securepass   = Read-Host 'Password' -AsSecureString
                $securepass2  = Read-Host 'Confirm Password' -AsSecureString
                $_DecryptPassword  = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepass))
                $_DecryptPassword2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepass2))

                if ($_DecryptPassword -ne $_DecryptPassword2)
                {

                    Write-Host "Passwords do not match!" -BackgroundColor Red

                }

            } until ($_DecryptPassword -eq $_DecryptPassword2)
            
        }

        elseif ($Password -is [SecureString])
        {

            $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

        else 
        {

            $_DecryptPassword = $Password

        }

        $_AuthDirectorySettings = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {
        
            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            $_NewAuthDirectoryObj = NewObject -AuthDirectory
        
            $_NewAuthDirectoryObj.name                = $Name
            $_NewAuthDirectoryObj.baseDN              = $BaseDN
            $_NewAuthDirectoryObj.credential.userName = $Username
            $_NewAuthDirectoryObj.credential.password = $_DecryptPassword
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Validating Server object values"

            ForEach ($_Server in $Servers)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Type: $($_Server.GetType().Name)"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Type: $($_Server | fl * | Out-String)"

                if ($_Server -is [PSCustomObject] -and $_Server.type -eq 'LoginDomainDirectoryServerInfoDto')
                {

                    [void]$_NewAuthDirectoryObj.directoryServers.Add($_Server)

                }

                else
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryException InvalidDirectoryServer InvalidArgument 'Servers' -TargetType ($_Server.GetType().Name) -Message "The Servers Parameter contains an invalid Server object: $($_Server | fl * | Out-String). Please correct this value and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

            }

            if ($PSBoundParameters['OpenLDAP'])
            {

                $_NewAuthDirectoryObj.authProtocol = 'LDAP'

                ForEach ($_ou in $OrganizationalUnits)
                {

                    if ($_ou.type -match $OrganizationalUnitPattern)
                    {

                        [void]$_NewAuthDirectoryObj.orgUnits.Add($_ou)

                    }

                    else
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryException InvalidDirectoryServer InvalidArgument 'OrganizationalUnits' -Message "The OrganizationalUnits Parameter contains an invalid OU value: '$_ou'. Please correct this value and try again."
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Authentication Directory Object: $($_NewAuthDirectoryObj | fl * | Out-String)"

            Try
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Validating authentication directory setting is valid"

                $_validateresp = Send-HPOVRequest $authnProviderValidatorUri POST $_NewAuthDirectoryObj -Hostname $_appliance

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Submitting request to create new authentication directory"

                $_resp = Send-HPOVRequest $authnProvidersUri POST $_NewAuthDirectoryObj -Hostname $_appliance

                $_resp.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AuthDirectory")

                [void]$_AuthDirectorySettings.Add($_resp)

            }

            Catch
            {

                foreach ($NestedError in (${Global:ResponseErrorObject} | ? Name -eq $ApplianceHost.Name).ErrorResponse.nestedErrors) 
                {

                    if ($NestedError.errorCode -eq "AUTHN_LOGINDOMAIN_SERVER_AUTHENTICATION_ERROR" ) 
                    { 
                        
                        $ErrorCategory = 'AuthenticationError' 

                    }

                    elseif ($NestedError.errorCode -eq "AUTHN_LOGINDOMAIN_DUPLICATE_NAME" ) 
                    { 
                        
                        $ErrorCategory = 'ResourceExists' 

                    }

                    else 
                    { 
                        
                        $ErrorCategory = 'InvalidOperation' 
                    
                    }

                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryException $NestedError.errorCode $ErrorCategory $NestedError.errorSource -Message "$($NestedError.message) $($NestedError.details)"
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryException InvalidResult InvalidOperation 'New-HPOVLdap' -Message "$((${Global:ResponseErrorObject} | ? Name -eq $_appliance.Name).ErrorResponse.message) $((${Global:ResponseErrorObject} | ? Name -eq $_appliance.Name).ErrorResponse.details)"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

    }

    End 
    {

        Return $_AuthDirectorySettings
       
    }

}

function Remove-HPOVLdapDirectory 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ("d",'Directory')]
        [Object]$InputObject,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default),

        [Parameter (Mandatory = $False, ParameterSetName = "default")]
        [switch]$Force

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection    = New-Object System.Collections.ArrayList
        $_DirectoryCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomObject]) 
        { 

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Directory Object provided: $($InputObject | FL * | Out-String)"

            If ($InputObject.category -eq 'users')
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "Directory:$($InputObject.Name)" -TargetType PSObject -Message "The Directory resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_DirectoryCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "Directory:$($InputObject.Name)" -TargetType PSObject -Message "The Directory resource is not an expected category type [$($InputObject.category)]. Allowed resource category type is 'users'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
        
        }

        else 
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count))"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Directory Name $($InputObject)"

                Try
                {

                    $_directory = Get-HPOVLdapDirectory $InputObject -ApplianceConnection $_appliance

                    $_directory | % {

                        [void]$_DirectoryCollection.Add($_)

                    }

                }

                Catch
                {

                    if ($_.FullyQualifiedErrorId -match 'AuthDirectoryResourceNotFound')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryException AuthDirectoryResourceNotFound ObjectNotFound 'InputObject' -Message "The Directory '$InputObject' was not found on Appliance '$($_appliance.Name)'."
                        $PSCmdlet.WriteError($ErrorRecord)

                    }

                    else
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }                

            }

        }
        
    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_DirectoryCollection.count) Authentication Directory resources to remove."

        #Process Directory Resources
        ForEach ($_Directory in $_DirectoryCollection)
        {

            if ($PSCmdlet.ShouldProcess($_Directory.ApplianceConnection.Name,"remove directory '$($_Directory.name)'")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Directory '$($_Directory.name)' from appliance '$($_Directory.ApplianceConnection.Name)'."

                Try
                {
                    
                    $_resp = Send-HPOVRequest $_Directory.Uri DELETE -Hostname $_Directory.ApplianceConnection.Name

                    $_resp | Add-Member -NotePropertyName name -NotePropertyValue $_Directory.name

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Set-HPOVLdapDefaultDirectory 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [Alias('Directory')]
        [Object]$InputObject,

        [Switch]$DisableLocalLogin,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
    
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_TaskCollection      = New-Object System.Collections.ArrayList
        $_DirectoryCollection = New-Object System.Collections.ArrayList
    
    }

    #Build collection of objects to Process
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count)"

            #Create default Directory configuration object
            $_DefaultDirectoryConfig = [PSCustomObject]@{
            
                allowLocalLogin     = (-not($DisableLocalLogin.IsPresent));
                defaultLoginDomain  = $Null;
                ApplianceConnection = $_appliance

            }

            switch ($InputObject.Gettype().Name) 
            {

                "String" 
                {

                    if ($InputObject -ne "Local") 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Authentication Directory Name provided: $InputObject"

                        Try
                        {

                            $InputObject = Get-HPOVLdapDirectory -Name $InputObject -Hostname $_appliance.Name -ErrorAction Stop

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                    elseif ($InputObject -eq "Local") 
                    {

                        $InputObject = [PSCustomObject] @{

                            type                = 'LoginDomainConfigInfoDto';
                            name                = "LOCAL";
                            uri                 = "";
                            loginDomain         = "0";

                        }

                    }

                }

                "PSCustomObject" 
                {

                    if ($InputObject.type -eq 'LoginDomainConfigVersion200') 
                    {

                        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Authentication Directory Object provided: $($InputObject | out-string)"

                        $InputObject.type = 'LoginDomainConfigInfoDto'

                    }

                    else 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryException InvalidAuthDirectoryObject InvalidArgument "InputObject" -TargetType "PSObject" -Message "The authentication directory object type '$($InputObject.type)' provided is not correct. The type must be 'LoginDomainConfigVersion200'. Please correct the value and try again."

                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                }

            }

            $_DefaultDirectoryConfig.defaultLoginDomain = ($InputObject | Select-Object type,loginDomain,name,eTag,uri)

            [void]$_DirectoryCollection.Add($_DefaultDirectoryConfig)

        }

    }

    #Process objects here
    End 
    {

        ForEach ($_DirectoryToProcess in $_DirectoryCollection)
        {

            if ($PSCmdlet.ShouldProcess($_DirectoryToProcess.ApplianceConnection.Name,"Set appliance authentication directory $($_DirectoryToProcess.defaultLoginDomain.name) as default domain")) 
            {
        
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Authentication Directory Object request: $($_DirectoryToProcess | out-string)"

                Try
                {

                    $_resp = Send-HPOVRequest $authnSettingsUri POST $_DirectoryToProcess -Hostname $_DirectoryToProcess.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($IsWindows)
                {

                    "[{0}] Setting PowerShell library AuthProvider registry (HKCU:\Software\Hewlett-Packard\HPOneView) value to 'AuthProvider#{1}'" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_DirectoryToProcess.defaultLoginDomain.name | Write-Verbose

                    Set-ItemProperty -Path HKCU:\Software\Hewlett-Packard\HPOneView -Name ("AuthProvider#{0}" -f $_DirectoryToProcess.ApplianceConnection.Name) -Value $_DirectoryToProcess.defaultLoginDomain.name -Type STRING | write-verbose

                }
                
            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] WhatIf was passed."

                $_resp = $null

            }

            else
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] User likely selected 'No' to prompt."

                $_resp = $null

            }

            $_resp

        }

    }

}

function Enable-HPOVLdapLocalLogin 
{
        
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory = $False)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList
    
    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count)"

            Try
            {
                
                #Get current auth directory configuration
                $_currentDirectoryConfig = Send-HPOVRequest $authnSettingsUri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Current global authentication settings: $($_currentDirectoryConfig | fl * | Out-String)"

            if ($PSCmdlet.ShouldProcess($_appliance.Name,"enable local logins")) 
            {

                $_request = 'true'

                Try
                {

                    #Update Configuration
                    $_resp = Send-HPOVRequest $AuthnAllowLocalLoginUri POST $_request -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
                [void]$_TaskCollection.Add($_resp)

            }

            elseif ($PSBoundParameters['Whatif'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }
        
    }

    End 
    {

        Return $_TaskCollection

    }

}

function Disable-HPOVLdapLocalLogin 
{
        
    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory = $False)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_TaskCollection = New-Object System.Collections.ArrayList
    
    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count)"

            if ($_appliance.AuthLoginDomain -eq 'LOCAL')
            {

                $ExceptionMessage = 'To disable local login you must log in using another authentication service.'
                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.AuthSessionException InvalidLoginDomain InvalidOperation 'AuthLoginDomain' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Try
            {
                
                #Get current auth directory configuration
                $_currentDirectoryConfig = Send-HPOVRequest $authnSettingsUri -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($_currentDirectoryConfig.defaultLoginDomain.name -eq 'LOCAL')
            {

                $ExceptionMessage = 'The Default Login Domain must not be set to "LOCAL" before disabling Local Logins.'
                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapConfigurationException InvalidDefaultLoginDomain InvalidOperation 'DefaultLoginDomain' -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Current global authentication settings: $($_currentDirectoryConfig | fl * | Out-String)"

            if ($PSCmdlet.ShouldProcess($_appliance.Name,"disable local logins")) 
            {

                $_request = 'false'

                Try
                {

                    #Update Configuration
                    $_resp = Send-HPOVRequest $AuthnAllowLocalLoginUri POST $_request -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
                [void]$_TaskCollection.Add($_resp)

            }

            elseif ($PSBoundParameters['Whatif'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }
        
    }

    End 
    {

        Return $_TaskCollection

    }

}

function New-HPOVLdapServer 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Name')]
        [String]$Hostname,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Alias ('port')]
        [ValidateRange (1,65535)]
        [Int32]$SSLPort = 636,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Alias ('cert')]
        [Object]$Certificate

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
        
        $_AuthDirectoryServer = New-Object System.Collections.ArrayList

    }

    Process 
    {

        Try
        {

            $_LdapServer = BuildLdapServer -Hostname $Hostname -SSLPort $SSLPort -Certificate $Certificate

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        "[{0}] New Auth Directory Server Object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $($_ldapServer | fl * ) | Write-Verbose

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] New Auth Directory Server Object: $($_ldapServer | fl * | Out-String)"

        #Add the directory server to the provided Auth Directory
        if ($InputObject)
        {

            "[{0}] Processing Auth Directory value" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if ($InputObject.category -ne 'users')
            {

                $ExceptionMessage = "The Directory resource is not an expected category type [{0}]. Allowed resource category type is 'users'. Please check the object provided and try again." -f $InputObject.category
                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument $InputObject.Name -TargetType PSObject -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if (-not($PSBoundParameters['Password']))
            {

                do 
                {
                    
                    $securepass   = Read-Host 'Password' -AsSecureString
                    $securepass2  = Read-Host 'Confirm Password' -AsSecureString
                    $_DecryptPassword  = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepass))
                    $_DecryptPassword2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepass2))

                    if ($_DecryptPassword -ne $_DecryptPassword2)
                    {

                        Write-Host "Passwords do not match!" -BackgroundColor Red

                    }

                } until ($_DecryptPassword -eq $_DecryptPassword2)
                
            }

            elseif ($Password -is [SecureString])
            {

                $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

            }

            else 
            {

                $_DecryptPassword = $Password

            }

            #Add credentials to object
            $InputObject.credential = @{ userName = $Username; password = $_DecryptPassword }

            Try
            {

                $_resp = Send-HPOVRequest -Uri $InputObject.Uri -Method PUT -Body $InputObject -Hostname $InputObject.ApplianceConnection.Name

                $_resp.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AuthDirectory")

                $_resp

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }            

        }

        else
        {

            "[{0}] Return directory server object" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_ldapServer

        }        

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Add-HPOVLdapServer
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param
    (
        
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'default')]
        [ValidateNotNullorEmpty()]
        [PSCustomObject]$InputObject,

        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ("Name")]
        [String]$Hostname,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Alias ('port')]
        [ValidateRange (1,65535)]
        [Int32]$SSLPort = 636,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Alias ('cert')]
        [Object]$Certificate,

        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('u','user')]
        [String]$Username,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('p','pass')]
        [Object]$Password,

        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = 'default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $InputObject) 
        {

            $PipelineINput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        if (-not($PSBoundParameters['Password']))
        {

            do 
            {
                
                $securepass   = Read-Host 'Password' -AsSecureString
                $securepass2  = Read-Host 'Confirm Password' -AsSecureString
                $_DecryptPassword  = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepass))
                $_DecryptPassword2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepass2))

                if ($_DecryptPassword -ne $_DecryptPassword2)
                {

                    Write-Host "Passwords do not match!" -BackgroundColor Red

                }

            } until ($_DecryptPassword -eq $_DecryptPassword2)
            
        }

        elseif ($Password -is [SecureString])
        {

            $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

        else 
        {

            $_DecryptPassword = $Password

        }

    }

    Process 
    {

        Try
        {

            $_LdapServer = BuildLdapServer -Hostname $Hostname -SSLPort $SSLPort -Certificate $Certificate

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        "[{0}] New Auth Directory Server Object: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $($_ldapServer | fl * ) | Write-Verbose

        "[{0}] Processing Auth Directory value" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if ($InputObject.category -ne 'users')
        {

            $ExceptionMessage = "The Directory resource is not an expected category type [{0}]. Allowed resource category type is 'users'. Please check the object provided and try again." -f $InputObject.category
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument $InputObject.Name -TargetType PSObject -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        if (-not($PSBoundParameters['Password']))
        {

            do 
            {
                
                $securepass   = Read-Host 'Password' -AsSecureString
                $securepass2  = Read-Host 'Confirm Password' -AsSecureString
                $_DecryptPassword  = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepass))
                $_DecryptPassword2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepass2))

                if ($_DecryptPassword -ne $_DecryptPassword2)
                {

                    Write-Host "Passwords do not match!" -BackgroundColor Red

                }

            } until ($_DecryptPassword -eq $_DecryptPassword2)
            
        }

        elseif ($Password -is [SecureString])
        {

            $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

        else 
        {

            $_DecryptPassword = $Password

        }

        #Add credentials to object
        $InputObject.credential = @{ userName = $Username; password = $_DecryptPassword }

        #Rebuild directoryServers property
        $_DirectoryServers = $InputObject.directoryServers.Clone()

        $InputObject.directoryServers = New-Object System.Collections.ArrayList

        [Void]$InputObject.directoryServers.Add($_ldapServer)

        ForEach ($_Server in $_DirectoryServers)
        {

            [Void]$InputObject.directoryServers.Add($_Server)

        }

        Try
        {

            $_resp = Send-HPOVRequest -Uri $InputObject.Uri -Method PUT -Body $InputObject -Hostname $InputObject.ApplianceConnection.Name

            $_resp.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AuthDirectory")

            $_resp

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }    

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function BuildLdapServer
{

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param
    (
        
        [Parameter (Mandatory, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ("Name")]
        [String]$Hostname,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Alias ('port')]
        [ValidateRange (1,65535)]
        [Int32]$SSLPort = 636,

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [Alias ('cert')]
        [Object]$Certificate

    )

    Process
    {

        if ($Certificate)
        {

            if (Test-Path $Certificate) 
            { 

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Certificate file found."

                Try
                {

                    $readfile = [System.IO.File]::OpenText($Certificate)
                    $certificate = $readfile.ReadToEnd()
                    $readfile.Close()
                    $Base64Certificate = ($Certificate | Out-String) -join "`n"

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

            else 
            {

                $ErrorRecord = New-ErrorRecord System.IO.FileNotFoundException CertificateNotFound ObjectNotFound 'Certificate' -TargetType 'PSObject' -Message "Autehntication Directory Server SSL certiciate not found. Please check the path of the public key, and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else
        {

            "[{0}] Attempting to retrieve Directory Server Secure LDAP Certificate" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            # // Support Getting LDAP Server Certificate
            $uri = $Hostname + ":" + $Sslport

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] URI: $uri"

            try 
            {
                
                $WebRequest = [Net.WebRequest]::Create("https://$uri")

                $Response = $WebRequest.GetResponse()
            
            }
            
            catch [Net.WebException] 
            { 

                Write-Verbose 'Caught handled [System.Net.WebException] exception'

                $ErrorRecord = $_
                $EvaluateMessage = $_.Exception.Message

                $ErrorRecordSplat = @{ Exception = $null; ErrorID = $null; ErrorCategory = $null; TargetObject = $null; TargetType = $null; Message = $null }

                switch ($EvaluateMessage)
                {

                    {$_ -match "The remote name could not be resolved"}
                    {

                        $ErrorRecordSplat.Message = $ErrorRecord.Exception.Message + " Please check the spelling of the hostname or FQDN."
                        $ErrorRecordSplat.ErrorCategory = 'ObjectNotFound'
                        $ErrorRecordSplat.ErrorID = 'UnknownHost'
                        $ErrorRecordSplat.TargetObject = 'Name'
                        $ErrorRecordSplat.TargetType = 'String'
                        $ErrorRecordSplat.Exception = 'System.Net.WebException'

                    }

                    {$_ -match "Unable to connect to the remote server"}
                    {

                        $ErrorRecordSplat.Message = $ErrorRecord.Exception.Message + ". Valid Ssl Port or firewall blocking port?"
                        $ErrorRecordSplat.ErrorCategory = 'ConnectionError'
                        $ErrorRecordSplat.ErrorID = 'InvalidSslPort'
                        $ErrorRecordSplat.TargetObject = 'Name'
                        $ErrorRecordSplat.TargetType = 'String'
                        $ErrorRecordSplat.Exception = 'System.Net.WebException'

                    }

                    default
                    {

                        $ErrorRecordSplat.Message = $ErrorRecord.Exception.Message
                        $ErrorRecordSplat.ErrorCategory = 'ConnectionError'
                        $ErrorRecordSplat.ErrorID = 'UnhandledException'
                        $ErrorRecordSplat.TargetObject = 'Name'
                        $ErrorRecordSplat.TargetType = 'String'
                        $ErrorRecordSplat.Exception = 'System.Net.WebException'

                    }
                    
                }

                if (-not($WebRequest.Connection) -and ([int]$Response.StatusCode -eq 0)) 
                {

                    $ErrorRecord = New-ErrorRecord @ErrorRecordSplat

                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                } 

            }

            catch
            {

                Write-Verbose 'Caught unhandled exception'

                $PSCmdlet.ThrowTerminatingError($_)

            }

            Finally 
            {

                if ($response)
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Closing response connection"
            
                    $Response.Close()

                }

                $Response   = $null

            }

            if ($null -ne $WebRequest.ServicePoint.Certificate) 
            {
                
                #Get certificate
                $Cert = New-Object Security.Cryptography.X509Certificates.X509Certificate2($WebRequest.ServicePoint.Certificate)

                $out = New-Object String[] -ArgumentList 3
                         
                $out[0] = "-----BEGIN CERTIFICATE-----"
                $out[1] = [System.Convert]::ToBase64String($Cert.RawData, "InsertLineBreaks")
                $out[2] = "-----END CERTIFICATE-----"

                $Base64Certificate = $out -join "`n"

            }

            # Error we couldn't get the certificate
            else
            {

                $ErrorRecord = New-ErrorRecord System.IO.FileNotFoundException CertificateNotFound ObjectNotFound 'Certificate' -Message "The response did not contain an SSL Certificate. Unknown reason."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }
        
        $_LdapServer = NewObject -AuthDirectoryServer

        $_LdapServer.directoryServerIpAddress             = $Hostname
        $_LdapServer.directoryServerCertificateBase64Data = $Base64Certificate

        if ($PSBoundParameters['Sslport'])
        {

            $_LdapServer.directoryServerSSLPortNumber = $Sslport.ToString()

        }
        
        $_LdapServer.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.AuthDirectoryServer')

        return $_LdapServer

    }

}

function Remove-HPOVLdapServer
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [Alias ('Directory')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Name')]
        [String]$DirectoryServerName,

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('u','user')]
        [String]$Username,

        [Parameter (ValueFromPipeline, Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('p','pass')]
        [Object]$Password,

        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $InputObject) 
        {

            $PipelineINput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        if (-not($PSBoundParameters['Password']))
        {

            do 
            {
                
                $securepass   = Read-Host 'Password' -AsSecureString
                $securepass2  = Read-Host 'Confirm Password' -AsSecureString
                $_DecryptPassword  = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepass))
                $_DecryptPassword2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepass2))

                if ($_DecryptPassword -ne $_DecryptPassword2)
                {

                    Write-Host "Passwords do not match!" -BackgroundColor Red

                }

            } until ($_DecryptPassword -eq $_DecryptPassword2)
            
        }

        elseif ($Password -is [SecureString])
        {

            $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

        else 
        {

            $_DecryptPassword = $Password

        }
        
    }

    Process 
    {

        if ($PipelineInput -or $InputObject -is [PSCustomObject]) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

        "[{0}] LdapDirectory Object provided: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | FL *) | Write-Verbose

        If ('users' -contains $InputObject.category)
        {

            If (-not($InputObject.ApplianceConnection))
            {

                $ExceptionMessage = "The InputObject parameter value resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message $ExceptionMessage
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else
        {

            $ExceptionMessage = "The Group object resource is not an expected category type [{0}]. The allowed resource category type is 'users'. Please check the object provided and try again." -f $InputObject.category
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message $ExceptionMessage
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        $PromptMessage = "remove directory server '{0}'" -f $DirectoryServerName

        if ($PSCmdlet.ShouldProcess($InputObject.ApplianceConnection.Name,$PromptMessage)) 
        {

            "[{0}] Removing Directory Server '{1}' from LDAP Directory '{2}'." -f $MyInvocation.InvocationName.ToString().ToUpper(),$DirectoryServerName, $InputObject.name | Write-Verbose

            Try
            {

                [Array]$InputObject.directoryServers = $InputObject.directoryServers | ? directoryServerIpAddress -ne $DirectoryServerName

                #Add credentials to object
                $InputObject.credential = @{ userName = $Username; password = $_DecryptPassword }
                
                $_resp = Send-HPOVRequest -Uri $InputObject.Uri -Method PUT -Body $InputObject -Hostname $InputObject.ApplianceConnection.Name

                $_resp.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AuthDirectory")

                $_resp

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        elseif ($PSBoundParameters['WhatIf'])
        {

            "[{0}] -WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Show-HPOVLdapGroups 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ("d","domain","AuthProvider")]
        [Object]$Directory,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ("u")]
        [string]$UserName,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ("p")]
        [ValidateNotNullOrEmpty()]
        [SecureString]$Password,

        [Parameter (Mandatory = $False, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [string]$GroupName,
            
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not $Directory) 
        {

            $PipelineINput = $true

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }        

        $_DirectoryGroupsCollection = New-Object System.Collections.ArrayList
        
    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {
        
            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            if ($PSBoundParameters['Directory'])
            {

                switch ($Directory.GetType().Name)
                {

                    'String'
                    {
                
                        Try
                        {
                        
                            $Directory = Get-HPOVLdapDirectory -Name $Directory -ApplianceConnection $_appliance

                        }

                        Catch
                        {

                            $PSCmdlet.ThrowTerminatingError($_)

                        }

                    }

                    'PSCustomObject'
                    {

                        if ($Directory.type -ne 'LoginDomainConfigVersion200')
                        {

                            $Message     = 'The provided -Directory Parameter value is not a support object type, {0}. Pleas verify the object type is "LoginDomainConfigVersion200".' -f $Directory.name
                            $ErrorRecord = New-ErrorRecord ArgumentException InvalidGroupCommonName InvalidArgument 'Group' -Message $Message
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                        }

                    }

                }

                $_Search = $Directory.baseDN

            }
            
            if ($PSBoundParameters['GroupName'])
            {

                $_Search = $GroupName

            }

            Try
            { 
                
                $_Groups = BuildGroupList $_Search $Username $Password $Directory.name $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }    
 
    }

    End 
    {
    
        return $_Groups

    }

}

function BuildGroupList
{

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Position = 0, Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Search,

        [Parameter (Position = 1, Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Username,

        [Parameter (Position = 2, Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [SecureString]$Password,

        [Parameter (Position = 3, Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Directory,

        [Parameter (Position = 4, Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection

    )

    Begin
    {

        "[{0}] Processing Search: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Search | Write-Verbose

        $_Collection = New-Object System.Collections.ArrayList

        $_decryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))
        
        $_body = @{

            type             = 'Group2RoleSearchContext';
            userName         = $Username; 
            password         = $_decryptPassword; 
            directoryName    = $Directory;
            searchContext    = $Search

        }

    }

    Process
    {

        $_uri = $AuthnDirectorySearchContext

        if ($Search.ToLower().StartsWith('ou=') -or $Search.ToLower().StartsWith('cn=') -or $Search.ToLower().StartsWith('dc='))
        {

            "[{0}] Navigating tree" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_body | Add-Member -NotePropertyName start -NotePropertyValue 0 -force

        }

        else
        {

            "[{0}] Searching for group name" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            $_GroupSearch = $True

            $_uri += '/search'        

        }

        Try
        {

            $_Resp = Send-HPOVRequest $_uri POST -body $_body -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if (-not($_GroupSearch))
        {

            ForEach ($_ChildOU in ($_Resp | ? hasChildren))
            {

                "[{0}] Processing Child OU {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_ChildOU.distinguishedName | Write-Verbose

                $_Groups = BuildGroupList $_ChildOU.distinguishedName $Username $Password $Directory $ApplianceConnection

                ForEach ($_group in $_Groups)
                {
            
                    [void]$_Collection.Add($_group)
            
                }

            }

        }
        
        ForEach ($_DirGroup in ($_Resp | ? groupType))
        {

            "[{0}] Processing Group {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_DirGroup.displayName.Replace('CN=',$null) | Write-Verbose

            $_entry = New-Object HPOneView.Appliance.LdapDirectoryGroup($_DirGroup.displayName.Replace('CN=',$null),
                                                                        $_DirGroup.distinguishedName, 
                                                                        $_DirGroup.distinguishedName.Replace($_DirGroup.displayName + ',',$null), 
                                                                        $Directory)

            [void]$_Collection.Add($_entry)

        }

    }

    End
    {

        Return $_Collection
    
    }
    
}

function Get-HPOVLdapGroup 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ("group","GroupName")]
        [string]$Name,

        [Parameter (Mandatory, ParameterSetName = 'Export')]
        [Alias ('x')]
        [ValidateScript({split-path $_ | Test-Path})]
        [string]$Export,
        
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ParameterSetName = 'Export')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_DirectoryGroupsCollection = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {
        
            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            { 
                
                $_Groups = Send-HPOVRequest $AuthnEgroupRoleMappingUri -Hostname $_appliance.Name

                ForEach ($_Group in $_Groups.members)
                {

                    $_Group.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.AuthDirectoryGroupRoleMapping") 
                
                    [void]$_DirectoryGroupsCollection.Add($_Group)

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }      

    }

    End 
    {

        if ($PSBoundParameters['Name']) 
        { 
            
            $_DirectoryGroupsCollection = $_DirectoryGroupsCollection | ? egroup -eq $Name

            if ($_DirectoryGroupsCollection.Count -eq 0)
            {
                
                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryGroupException AuthDirectoryGroupResourceNotFound ObjectNotFound "Name" -Message "The specified '$name' Authentication Directory Group resource not found. Please check the name and try again."
                
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }
        
        }

        if ($PSBoundParameters['Export'])
        { 
            
            $_DirectoryGroupsCollection | convertto-json > $Export 
        
        }
 
        else 
        {

            Return $_DirectoryGroupsCollection

        }

    }

}

function New-HPOVLdapGroup 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ("d","domain","authProvider")]
        [Object]$Directory,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ("g","GroupName","name")]
        [Object]$Group,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ("r","role")]
        [Array]$Roles,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ("u")]
        [string]$Username,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ("p")]
        [ValidateNotNullOrEmpty()]
        [Object]$Password,
            
        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Directory'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
                
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }


                }

            }

            else
            {

                Try 
                {
                
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_DirectroyGroupStatus = New-Object System.Collections.ArrayList

        if (-not($PSBoundParameters['Password']))
        {

            [SecureString]$password = read-host -AsSecureString "Password"
            $_decryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))
            
        }

        elseif ($Password -is [SecureString])
        {

            $_decryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

        }

        else 
        {

            $_decryptPassword = $Password

        }

    }

    Process
    {
        
        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Validating requested role values"
            
            $_unsupportedRoles = New-Object System.Collections.ArrayList
            $_Roles            = New-Object System.Collections.ArrayList

            #Validate roles provided are allowed.
            foreach ($_role in $Roles) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing role: $_role"

                if (-not ((${Global:ConnectedSessions} | ? Name -EQ $_appliance.Name).ApplianceSecurityRoles -contains $_role)) 
                { 
                
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid or unsupported"

                    [void]$_unsupportedRoles.Add($_role)
            
                }

                else
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Supported"

                    $_TempName = $_role.split(' ')

                    $_role = $_TempName[0].SubString(0,1).ToUpper() + $_TempName[0].SubString(1,($_TempName[0].length -1)).ToLower() + " " + $_TempName[1].ToLower()

                    [void]$_Roles.Add($_role)

                }

            }

            if ($_unsupportedRoles.count -ge 1) 
            { 
        
                $ErrorRecord = New-ErrorRecord ArgumentException UnsupportedRolesFound InvalidArgument $($MyInvocation.InvocationName.ToString().ToUpper()) -Message "The '$($_unsupportedRoles -join ", ")' role(s) is/are not supported or the correct names. Please validate the -roles Parameter contains one or more valid roles. Allowed roles are: $((${Global:ConnectedSessions} | ? Name -EQ $_appliance.Name).ApplianceSecurityRoles -join ", ")"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)            
            
            }

            switch ($Group.GetType().Name)
            {

                'String'
                {

                    if ($Group -notmatch $CommonNamePattern)
                    {

                        $Message     = 'The provided -Group Parameter value {0} is not a valid Common Name (CN) value. Please verify the Group CN follows this format: CN=GroupName,DC=Domain,DC=com' -f $Group
                        $ErrorRecord = New-ErrorRecord ArgumentException InvalidGroupCommonName InvalidArgument 'Group' $Message
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                    }

                    $Group = [PSCustomObject]@{ DN = $Group }

                }

                'PSCustomObject'
                {

                    if ($Group.DN -notmatch $CommonNamePattern)
                    {

                        $Message     = 'The provided -Group Parameter value {0} does not contain a valid Common Name (CN) value. Please verify the Group CN follows this format: CN=GroupName,DC=Domain,DC=com' -f $Group.Name
                        $ErrorRecord = New-ErrorRecord ArgumentException InvalidGroupCommonName InvalidArgument 'Group' -TargetType 'PSObject' $Message
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)  

                    }

                }

            }
        
            #Get new Directory Group object
            $_NewGroup = NewObject -DirectoryGroup

            $_NewGroup.group2rolesPerGroup.loginDomain = $Directory.name
            $_NewGroup.group2rolesPerGroup.egroup      = $Group.DN
            $_NewGroup.group2rolesPerGroup.roles       = $_Roles
            $_NewGroup.credentials.userName            = $Username
            $_NewGroup.credentials.password            = $_decryptPassword
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Directory Group requested to create: $($_NewGroup | out-string )"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to create $($_NewGroup.egroup) Directory Group"
            
            Try
            {

                $_resp = Send-HPOVRequest $AuthnEgroupRoleMappingUri POST $_NewGroup -Hostname $_appliance

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.AuthDirectoryGroupRoleMapping')

            [void]$_DirectroyGroupStatus.Add($_resp)
           
        }

    }

    End
    {
        
        Return $_DirectroyGroupStatus

    }

}

function Set-HPOVLdapGroupRole 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ("d","domain","directory")]
        [string]$AuthProvider,

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ("g","name",'GroupName')]
        [Object]$Group,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ("r","role")]
        [Array]$Roles,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ("u")]
        [string]$UserName,

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [Alias ("p")]
        [ValidateNotNullOrEmpty()]
        [SecureString]$Password,
        
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        #No need to validate ApplianceConnection, as object is passed via pipeline.
        if (-not($PSboundParameters['Group']))
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Pipeline input."
            
            $PipelineInput = $True

        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }
                        
        }

        $_DirectoryGroupsToUpdate = New-Object System.Collections.ArrayList
        $_DirectoryGroupStatus    = New-Object System.Collections.ArrayList

        #Decrypt the password
        $_decryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))

    }

    Process 
    {
 
        if ($PipelineInput)
        {

            #Validate pipeline input is user object
            if (-not($Group -is [PSCustomObject]) -and -not($Group.category -eq 'users'))
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid Group provided: $($Group | FL * | Out-String)"

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryGroupException InvalidDirectoryGroupObject InvalidArgument "Group" -TargetType 'PSObject' -Message "The Group Parameter value is not a valid Directory Group object resource. Object category provided '$($Group.category)', allowed object category value 'users'. Please verify the input object and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Adding Group to Process collection: $($Group | FL * | Out-String)"

            [void]$_DirectoryGroupsToUpdate.Add($Group)

        }

        else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                try 
                { 
                    
                    $_GroupObject = Get-HPOVUser $userName -ApplianceConnection $_appliance
                
                }
        
                #If not found, throw error
                catch [HPOneView.Appliance.LdapDirectoryGroupException]
                {
                
                    #Generate terminating error
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryGroupException AuthDirectoryGroupResourceNotFound ObjectNotFound 'Group' -Message "Group `'$Group`' was not found. Please check the spelling, or create the user and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                [void]$_DirectoryGroupsToUpdate.Add($_GroupObject)

            }

        }

    }

    End
    {

        ForEach ($_Group in $_DirectoryGroupsToUpdate)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Group: $($_Group.egroup)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Original Group object: $($_Group | FL * | Out-String)"

            #Validate roles provided are allowed.
            $_unsupportedRoles = New-OBject System.Collections.ArrayList
            $_NewGroupRoles    = New-Object System.Collections.ArrayList

            #Validate roles provided are allowed.
            foreach ($_role in $Roles) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing role: $_role"

                if (-not ((${Global:ConnectedSessions} | ? Name -EQ $_Group.ApplianceConnection.Name).ApplianceSecurityRoles -contains $_role)) 
                { 
                            
                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid or unsupported"

                    [void]$_unsupportedRoles.Add($_role)
                        
                }

                else
                {

                    Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Supported"

                    $_role.SubString(0,1).ToUpper()+$_role.SubString(1).tolower()

                    [void]$_NewGroupRoles.Add($_role)

                }

            }

            if ($_unsupportedRoles.count -ge 1) 
            { 
        
                $ErrorRecord = New-ErrorRecord ArgumentException UnsupportedRolesFound InvalidArgument $($MyInvocation.InvocationName.ToString().ToUpper()) -Message "The '$($_unsupportedRoles -join ", ")' role(s) is/are not supported or the correct names. Please validate the -roles Parameter contains one or more valid roles. Allowed roles are: $((${Global:ConnectedSessions} | ? Name -EQ $_Connection.Name).ApplianceSecurityRoles -join ", ")"
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)            
                        
            }

            $_Group.roles = $_NewUserRoles

            $_UpdateDirectroyGroup = NewObject -DirectoryGroup
            $_UpdateDirectroyGroup.group2rolesPerGroup  = $_Group
            $_UpdateDirectroyGroup.credentials.userName = $UserName
            $_UpdateDirectroyGroup.credentials.password = $_decryptPassword
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updated Group object: $($_UpdateDirectroyGroup | FL * | Out-String)"

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Sending request to update `'$($_Group.egroup)`' group at '$authnEgroupRoleMappingUri'"

            Try
            {

                $_resp = Send-HPOVRequest $authnEgroupRoleMappingUri PUT $updateUser -Hostname $_User.ApplianceConnection.Name

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $_resp.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.User')

            [void]$_DirectoryGroupStatus.Add($_resp)

        }
        
        Return $_DirectoryGroupStatus

    }

}

function Remove-HPOVLdapGroup 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param 
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('g','Group','Name')]
        [Object]$InputObject,
    
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_TaskCollection  = New-Object System.Collections.ArrayList
        $_GroupCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {
 
        if ($PipelineInput -or $InputObject -is [PSCustomObject]) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Group Object provided: $($InputObject | FL * | Out-String)"

            If ('users' -contains $InputObject.category)
            {

                If (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "Group:$($InputObject.Name)" -TargetType PSObject -Message "The Group object resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_GroupCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "InputObject" -TargetType PSObject -Message "The Group object resource is not an expected category type [$($Name.category)]. The allowed resource category type is 'users'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Appliance $($_appliance.Name) (of $($ApplianceConnection.Count))"

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing Group Name $($InputObject)"

                Try
                {

                    $_Group = Get-HPOVLdapGroup -Name $InputObject -ApplianceConnection $_appliance

                    $_Group | % {

                        [void]$_GroupCollection.Add($_)

                    }

                }

                Catch
                {

                    if ($_.FullyQualifiedErrorId -match 'AuthDirectoryGroupResourceNotFound')
                    {

                        $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LdapDirectoryGroupException AuthDirectoryGroupResourceNotFound ObjectNotFound 'InputObject' -Message "The Directory Group '$InputObject' was not found on Appliance '$($_appliance.Name)'."
                        $PSCmdlet.WriteError($ErrorRecord)

                    }

                    else
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }                

            }

        }

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_GroupCollection.count) Directory Group resources to remove."

        #Process Network Resources
        ForEach ($_Group in $_GroupCollection)
        {

            if ($PSCmdlet.ShouldProcess($_Group.ApplianceConnection.Name,"remove directory group '$($_Group.egroup)'")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Directory Group '$($_Group.egroup)' from appliance '$($_Group.ApplianceConnection.Name)'."

                Try
                {
                    
                    $_resp = Send-HPOVRequest $_Group.Uri DELETE -Hostname $_Group.ApplianceConnection.Name

                    $_resp | Add-Member -NotePropertyName name -NotePropertyValue $_Group.egroup

                    [void]$_TaskCollection.Add($_resp)

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

        Return $_TaskCollection

    }

}

function Get-HPOVAuditLog 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Int]$Count = 0,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [TimeSpan]$TimeSpan,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [DateTime]$Start,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [DateTime]$End = [DateTime]::Now,

        [Parameter (Mandatory = $false, ParameterSetName = 'default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }


            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_AllAuditLogs = New-Object System.Collections.ArrayList
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            $uri = $applAuditLogsUri + "?sort:desc"

            if ($PSBoundParameters['Count'])
            {

                $uri = "{0}&count={1}" -f $uri, $Count

            }

            $Filter = New-Object System.Collections.ArrayList

            if ($TimeSpan)
            {

                [Void]$Filter.Add(("DATE<='{0}/P{1}D'" -f [DateTime]::Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"),$TimeSpan.Days))
                
            }

            elseif ($Start)
            {

                [Void]$Filter.Add(("DATE>='{0}' and DATE<='{1}'" -f $Start.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"), $End.ToUniversalTime().ToString("yyyy-MM-ddT23:59:59Z")))

            }

            if ($Query.count -gt 0)
            {

                $uri = '{0}&filter="{1}"' -f $uri, [String]::Join(' and ',$Filter.ToArray())

            }

            Try
            {
                
                #Send the request
                $_AuditLogs = Send-HPOVRequest -Uri $uri -Hostname $_appliance

                $_AuditLogs.members | % {

                    $_.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.AuditLogEntry')

                    [void]$_AllAuditLogs.Add($_)

                }

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    End
    {

        Return $_AllAuditLogs

    }

}

Function Get-HPOVAuditLogArchive
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param 
    (

        [Parameter (Mandatory = $false, ParameterSetName = "default")]
        [ValidateNotNullorEmpty()]
        [Alias ("save")]
        [string]$Location = (get-location).Path,
        
        [Parameter (Mandatory = $false, ParameterSetName = 'default')]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        #Validate the path exists. If not, create it.
        if (-not(Test-Path $Location))
        {
             
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Directory does not exist. Creating directory..."

            New-Item $Location -itemtype directory

        }
        
    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {

                #Now that the Support Dump has been requested, download the file
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Downloading audit log to $($Location)"

                Download-File $applAuditLogDownloadUri $_appliance $Location

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

}

#######################################################
# Alerts & Events:
#

function Get-HPOVAlert 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory = $False, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('resourceUri','Resource')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [ValidateSet ('OK','Critical','Disabled','Warning','Unknown')]
        [string]$Severity,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [ValidateSet ('Appliance', 'DeviceBay', 'Enclosure', 'Fan', 'Firmware', 'Host', 'Instance', 'InterconnectBay', 'LogicalSwitch', 'Logs', 'ManagementProcessor', 'Memory', 'Network', 'Operational', 'Power', 'Processor', 'RemoteSupport', 'Storage', 'Thermal', 'Unknown')]
        [string]$HealthCategory,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [String]$AssignedToUser,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Alias ('State')]
        [ValidateNotNullOrEmpty()]
        [String]$AlertState,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Int]$Count = 0,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [TimeSpan]$TimeSpan,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [DateTime]$Start,
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [DateTime]$End = [DateTime]::Now,
        
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSCmdlet.ParameterSetName -eq 'ResourcePipeline') 
        { 
            
            $Pipelineinput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_AlertResources = New-Object System.Collections.ArrayList

        if (-not $Count)
        {

            $Count = -1

        }

    }
    
    Process 
    {

        If ($Pipelineinput -or $InputObject -is [PSCustomObject])
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Resource provided via pipeline."

            #Input object is a Server Profile resource, get special alerts URI
            if ($InputObject.category -eq "server-profiles") 
            {
        
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Input object is a Server Profile. Getting special URI for alert messages."
            
                Try
                {

                    $_serverAlerts = Send-HPOVRequest ($InputObject.uri + "/messages") -Hostname $InputObject.ApplianceConnection.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
                # Where is $_Alerts coming from?

                foreach ($_alert in $_serverAlerts) 
                {

                    switch ($_alert | select * -ExcludeProperty etag,type | get-member -MemberType NoteProperty | select -expandproperty Name) {

                        "connections" 
                        { 
                            
                            if ($alert.connections.count -gt 0) 
                            { 
                                
                                $_alert.connections | % { 
                                    
                                    $_.PSObject.TypeNames.Insert(0,"HPOneView.ServerProfileAlert")

                                    [void]$_AlertResources.Add($_.messages)
                                
                                }

                            } 
                        
                        }

                        "serverHardware" 
                        { 
                            
                            if ($alert.serverHardware.count -gt 0) 
                            {

                                $_alert.serverHardware | % { 
                                    
                                    $_.PSObject.TypeNames.Insert(0,"HPOneView.ServerProfileAlert")

                                    [void]$_AlertResources.Add($_.messages)
                                
                                }
                            
                            } 
                        
                        }
                        
                        "firmwareStatus" 
                        { 
                            
                            if ($alert.firmwareStatus.count -gt 0) 
                            { 
                                
                                $_alert.firmwareStatus | % { 
                                    
                                    $_.PSObject.TypeNames.Insert(0,"HPOneView.ServerProfileAlert")

                                    [void]$_AlertResources.Add($_.messages)
                                
                                }
                            
                            } 
                        
                        }
                
                    }

                }

            }

            else 
            {

                $uri = $AlertsUri + "?sort:asc"

                if ($TimeSpan)
                {

                    $uri = '{0}&query=created:<{1}d' -f $uri, $TimeSpan.Days

                }

                elseif ($Start)
                {

                    $_DateSpan = "[{0} to {1}]" -f $Start.ToString("yyyy-MM-dd"), $End.ToString("yyyy-MM-dd")
                    $uri = '{0}&userQuery:created "{1}"' -f $uri, $_DateSpan

                }

                #Generate Error, unsupported pipeline input
                if ($InputObject -is [String]) 
                { 
                    
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }

                elseif ($InputObject -is [PsCustomObject]) 
                { 
                    
                    $uri += "&filter=`"associatedResource.resourceUri='{0}'`"" -f $InputObject.uri
                
                }
            
                if ($Severity) 
                { 
                    
                    $uri += "&filter=severity='{0}'"  -f $Severity
                
                }
            
                if ($HealthCategory) 
                {
                    
                     $uri += "&filter=healthCategory='{0}'" -f $HealthCategory
                
                }
            
                if ($AssignedToUser) 
                { 
                    
                    $uri += "&filter=assignedTOuter='{0}'"  -f $AssignedToUser
                
                }
            
                if ($AlertState) 
                { 
                    
                    $uri += "&filter=alertState='{0}'" -f ($AlertState.SubString(0,1).ToUpper() + $alertState.SubString(1).ToLower())
                
                }

                Try
                {

                    $_ResourceAlerts = Send-HPOVRequest $uri -Hostname $InputObject.ApplianceConnection.Name -Count $Count

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
        
                $_ResourceAlerts.members | % { 
                    
                    $_.PSObject.TypeNames.Insert(0,"HPOneView.Alert")

                    [void]$_AlertResources.Add($_)                
                
                }

            }
            
        }

        #Process
        Else
        {

            ForEach ($_appliance in $ApplianceConnection)
            {

                "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

                $uri = $AlertsUri + "?sort:desc"

                if ($PSBoundParameters['Count'])
                {

                    $uri = "{0}&count={1}" -f $uri, $Count

                }

                $Query = New-Object System.Collections.ArrayList

                if ($TimeSpan)
                {

                    [Void]$Query.Add(("created<='{0}/P{1}D'" -f [DateTime]::Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"),$TimeSpan.Days))
                    
                }

                elseif ($Start)
                {

                    [Void]$Query.Add(("created>='{0}' and created<='{1}'" -f $Start.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"), $End.ToUniversalTime().ToString("yyyy-MM-ddT23:59:59Z")))

                }

                if ($InputObject -is [String]) 
                { 
                    
                    [Void]$Query.Add(("resourceName='{0}'" -f $InputObject))
                
                }

                elseif ($InputObject -is [PsCustomObject]) 
                { 
                    
                    [Void]$Query.Add(("resourceUri='{0}'" -f $InputObject.uri))
                
                }
            
                if ($PSBoundParameters['Severity']) 
                { 
                    
                    [Void]$Query.Add(("severity='{0}'" -f $Severity))
                
                }
            
                if ($PSBoundParameters['HealthCategory']) 
                {
                    
                    [Void]$Query.Add(("healthCategory='{0}'" -f $HealthCategory))
                
                }
            
                if ($PSBoundParameters['AssignedToUser']) 
                { 
                    
                    [Void]$Query.Add(("assignedToUser='{0}'" -f $AssignedToUser))
                
                }
            
                if ($PSBoundParameters['AlertState']) 
                { 
                    
                    [Void]$Query.Add(("alertState='{0}'" -f ($AlertState.SubString(0,1).ToUpper() + $AlertState.SubString(1).tolower())))
                
                }

                if ($Query.count -gt 0)
                {

                    $uri = '{0}&query="{1}"' -f $uri, [String]::Join(' and ',$Query.ToArray())

                }

                Try
                {

                    $_ResourceAlerts = Send-HPOVRequest -Uri $uri -Hostname $_appliance

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
        
                $_ResourceAlerts.members | % { 
                    
                    $_.PSObject.TypeNames.Insert(0,"HPOneView.Alert")

                    [void]$_AlertResources.Add($_)
                
                }

            }

        }

    }

    End 
    {

        Return $_AlertResources

    }

}

Function Get-HPOVServerProfileMessage
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory = $False, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Object]$ServerProfile,
        
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if ($PSCmdlet.ParameterSetName -eq 'ResourcePipeline') 
        { 
            
            $Pipelineinput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }
        
        $_AlertResources = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        #Input object is a Server Profile resource, get special alerts URI
        if ($ServerProfile.category -eq "server-profiles") 
        {
        
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Input object is a Server Profile. Getting special URI for alert messages."
            
            Try
            {

                [Array]$_serverAlerts = Send-HPOVRequest ($InputObject.uri + "/messages") -Hostname $InputObject.ApplianceConnection.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
                
            "[{0}] Processing {1} Server Profile messages." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_serverAlerts.Count | Write-Verbose

            foreach ($_alert in $_serverAlerts) 
            {

                switch ($_alert.PSObject.Properties.Name) 
                {

                    "connections" 
                    { 
                            
                        if ($_alert.connections.count -gt 0) 
                        { 

                            "[{0}] Processing {1} Server Profile 'Connections' messages." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_alert.connections.count | Write-Verbose
                                
                            $_alert.connections.messages | % { 
                                    
                                $_.PSObject.TypeNames.Insert(0,"HPOneView.ServerProfileMessage")

                                Add-Member -InputObject $_ -NotePropertyName ServerProfileName -NotePropertyValue $InputObject.name

                                [void]$_AlertResources.Add($_)
                                
                            }

                        } 
                        
                    }

                    "serverHardware" 
                    { 
                            
                        if ($_alert.serverHardware.count -gt 0) 
                        {

                            "[{0}] Processing {1} Server Profile 'ServerHardware' messages." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_alert.serverHardware.count | Write-Verbose

                            $_alert.serverHardware.messages | % { 
                                    
                                $_.PSObject.TypeNames.Insert(0,"HPOneView.ServerProfileMessage")

                                Add-Member -InputObject $_ -NotePropertyName ServerProfileName -NotePropertyValue $InputObject.name

                                [void]$_AlertResources.Add($_)
                                
                            }
                            
                        } 
                        
                    }
                        
                    "firmwareStatus" 
                    { 
                            
                        if ($_alert.firmwareStatus.count -gt 0) 
                        { 

                            "[{0}] Processing {1} Server Profile 'FirmwareStatus' messages." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_alert.firmwareStatus.count | Write-Verbose
                                
                            $_alert.firmwareStatus.messages | % { 
                                    
                                $_.PSObject.TypeNames.Insert(0,"HPOneView.ServerProfileMessage")

                                Add-Member -InputObject $_ -NotePropertyName ServerProfileName -NotePropertyValue $InputObject.name

                                [void]$_AlertResources.Add($_)
                                
                            }
                            
                        } 
                        
                    }
                
                }

            }

        }

        else 
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidAlertObject InvalidArgument  "ServerProfile" -TargetType 'PSObject' -Message ("An invalid object was provided, {0}. Only Server Profile objects are supported." -f $ServerProfile.category)
            $PSCmdlet.WriteError($ErrorRecord)

        }

    }

    End 
    {

        Return $_AlertResources

    }

}

function Set-HPOVAlert
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Cleared')]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Active')]
        [ValidateNotNullOrEmpty()]
        [Alias ('alertUri','Alert')]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [string]$AssignToUser,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [String]$Notes,

        [Parameter (Mandatory, ParameterSetName = 'Cleared')]
        [switch]$Cleared,

        [Parameter (Mandatory, ParameterSetName = 'Active')]
        [switch]$Active,

        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = 'Cleared')]
        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = 'Active')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Alert Object via pipeline"

            $Pipelineinput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_AlertResources = New-Object System.Collections.ArrayList

    }

    Process 
    {

        #Validate input object is correct
        if ($InputObject.category -ne 'alerts')
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidAlertObject InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message 'The Alert Parameter value is not a PSCustomObject or contains a valid resource category. Please check the value and try again.'
            $PSCmdlet.WriteError($ErrorRecord)

        }

        else
        {

            $_AlertUpdateObject = NewObject -UpdateAlert

            if (-not $PSBoundParameters['Notes'])
            {

                $_AlertUpdateObject.notes = 'Updated alert with: {0}' -f (($PSBoundParameters.Keys | ? { 'Cleared','Active','AssignToUser' -contains $_ } | % { "{0} ({1})" -f $_,$PSBoundParameters[$_] } )-Join ", ")

            }

            switch ($PSBoundParameters.keys)
            {

                'Cleared'
                {

                    $_AlertUpdateObject.alertState = 'Cleared'

                }

                'Active'
                {

                    $_AlertUpdateObject.alertState = 'Active'

                }

                'AssignToUser'
                {

                    $_AlertUpdateObject.assignedToUser = $AssignToUser

                }

                'Notes'
                {
                
                    $_AlertUpdateObject.notes = $Notes
                
                }

            }

            if ((-not $PSboundParameters['Cleared']) -and (-not $PSboundParameters['Active']))
            {

                $_AlertUpdateObject.alertState = $InputObject.alertState

            }

            if (-not($InputObject.ApplianceConnection.Name) -and -not($ApplianceConnection))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidAlertObject InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message 'The Alert Parameter value does not contain a valid ApplianceConnection property. Please check the value and try again.'
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            if ($InputObject.alertState -eq 'Locked' -and ($PSboundParameters['Cleared'] -or $PSboundParameters['Active']))
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidAlertState InvalidOperation 'InputObject' -TargetType $InputObject.GetType().Name -Message "The Alert provided is a Locked alert and it's state cannot be modified."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Try
            {

                if ($InputObject.eTag)
                {

                    $_AlertUpdateObject.eTag = $InputObject.eTag

                }

                $_resp = Send-HPOVRequest $InputObject.uri PUT $_AlertUpdateObject -Hostname $ApplianceConnection.Name
            
                $_resp.PSObject.TypeNames.Insert(0,"HPOneView.Alert")

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }        

            [void]$_AlertResources.Add($_resp)

        }

    }

    End
    {        

        return $_AlertResources

    }

}

function Clear-HPOVAlert  
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    ()

    Write-Warning 'This CMDLET is deprecated. Please use Set-HPOVAlert.'

}

function Remove-HPOVAlert
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Switch]$Force,

        [Parameter (Mandatory = $False, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            

            $Pipelineinput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }


    }

    Process 
    {

        #Validate input object is correct
        if ($InputObject.category -ne 'alerts')
        {

            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidAlertObject InvalidArgument 'InputObject' -TargetType $InputObject.GetType().Name -Message 'The Alert Parameter value is not a PSCustomObject or contains a valid resource category. Please check the value and try again.'
            $PSCmdlet.WriteError($ErrorRecord)

        }

        else
        {

            $RemoveMessage = "remove '{0}' alert" -f $InputObject.description

            $_uri = $InputObject.uri

            if ($PSCmdlet.ShouldProcess($InputObject.ApplianceConnection.Name, $RemoveMessage))
            {

                "[{0}] Removing alert: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), ($InputObject | Out-String) | Write-Verbose
                "[{0}] URI: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.uri | Write-Verbose

                if ($Force)
                {

                    $_uri += '?force=true'
                    
                }

                try
                {

                    Send-HPOVRequest -Uri $_uri -Method DELETE -Hostname $InputObject.ApplianceConnection
                
                }

                catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['whatif']) 
            {

                "[{0}] -WhatIf was passed" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
        
            }

        }

    }

    End
    {        

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}
    
function Get-HPOVLicense 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateSet ("OneViewAdvanced", "OneView", "OneViewAdvancedNoiLO", "OneViewNoiLO","all")]
        [String]$Type,
        
        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateSet ("Unlicensed", "Permanent",$null)]
        [String]$State,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Switch]$Summary,
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Switch]$Report,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose
            
        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_LicenseResources = New-Object System.Collections.ArrayList

        [string]$filter = $null
        
        If ($PSboundParameters['Type'])
        {

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] License Type: $Type"

            switch ($Type)
            {

                #User wants the HP OneView License report
                {$_ -match "OneView","OneViewAdvanced"} 
                {

                    $filter += "?filter=`"product='HP OneView Advanced'`""

                }

                #User wants the HP OneView without iLO License Report
                {$_ -match "OneViewNoiLO","OneViewAdvancedNoiLO"} 
                {

                    $filter += "?filter=`"product='HP OneView Advanced w/o iLO'`""

                }

            }

        }

        If ($PSboundParameters['State'])
        {

            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] License $State State"

            #Check to see if the license type/product was specified, as we would have an existing filter value
            If ($filter)
            {

                $filter += "&filter=`"licenseType='$State'`""

            }
            ElseIf (-not($filter))
            {

                $filter += "?filter=`"licenseType='$State'`""

            }

        }

        ElseIf (-not($PSboundParameters['State']))
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] No license state provided ($State)"

        }
  
        If ($PSboundParameters['Report'])
        {
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Generating Full Report"
            
        }

        elseif ($PSboundParameters['Summary'])
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Generating Summary Report"
            
            #Check to see if the license type/product was specified, as we would have an existing filter value
            If ($filter)
            {

                $disSummary = "&view=summary"

            }
            ElseIf (-not($filter))
            {

                $disSummary = "?view=summary"

            }

        }

    }

    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose
        
            #Display verbose data of what will be sent to Send-HPOVRequest
            write-verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] $(($script:licensesUri + $filter + $disSummary) + " GET")"
            
            Try
            {

                #Send the request
                $ret = Send-HPOVRequest ($script:licensesUri + $filter + $disSummary) GET -Hostname $_appliance

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            $ret.members | % { 

                $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.License")
                    
                if ($_.nodes) 
                { 
                        
                    $_.nodes | % { $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.License.Node") } 
                    
                } 

                [void]$_LicenseResources.Add($_)
                
            }

        }

    }

    End
    {

        if ($PSboundParameters['Report'])
        {

            ForEach ($_LicenseObject in $_LicenseResources)
            {

                $a = @{Expression={$_.Product};Label="License Name"},
                     @{Expression={$_.AvailableCapacity};Label="Available"},
                     @{Expression={$_.TotalCapacity};Label="Total"},
                     @{Expression={$licenseGroup.nodes.count};Label="Associated Nodes"}
             
                $now = (Get-Date).ToShortDateString()

                ForEach ($licenseGroup in $_LicenseObject)
                {

                    $licenseGroup | Format-Table $a -autosize -wrap
                
                    $b = @{Expression={$_.nodeName};Label="Device"},
                         @{Expression={$licenseGroup.LicenseType};Label="License Type"},
                         @{Expression={
                        
                            if ($licenseGroup.LicenseType -eq "Unlicensed") 
                            {
                                 
                                $appliedDate = (Get-Date($_.appliedDate)).ToShortDateString()
                                
                                $daysToAdd = 60 
                                    
                            }

                            elseif ($licenseGroup.LicenseType -eq "Evaluation") 
                            {  
                                
                                $appliedDate = (Get-Date($licenseGroup.created)).ToShortDateString()
                                
                                $daysToAdd = 365 

                            }

                            $expire = (Get-Date($appliedDate)).AddDays($daysToAdd)

                            $warnDate = new-timespan -start $now -End $expire

                            if ($warnDate.Days -eq 0 -or $warnDate.Days -lt 0) 
                             {

                                $appliedDate = $appliedDate + " (EXPIRED)"

                            }
                              
                            elseif($warnDate.Days -le 30) 
                            {
                                
                                $appliedDate = $appliedDate + " (Expires in $($warnDate.days) days)"

                            }
                            
                            $appliedDate

                        };Label="Applied Date"}

                    $licenseGroup.nodes | sort-object -property nodeName | Format-Table $b -autosize -wrap | Out-String | ForEach-Object {

                        $_.Split("`n") | ForEach-Object {

                            if($_ -match "EXPIRED") { Write-Host -ForegroundColor Red $_ }
                            elseif($_ -match "Expires in"){ Write-Host -ForegroundColor Yellow $_ }
                            else{ Write-Host $_ }
                       
                        }

                    } 
 
                }

            }

        }

        else 
        {

            Return $_LicenseResources

        }

    }

}

function New-HPOVLicense 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "licenseKey")]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "licenseKey")]
        [ValidateNotNullOrEmpty()]
        [String]$LicenseKey,
        
        [Parameter (Mandatory, ParameterSetName = "InputFile")]
        [ValidateScript({Test-Path $_})]
        [String]$File,
        
        [Parameter (Mandatory = $false, ParameterSetName = "licenseKey")]
        [Parameter (Mandatory = $false, ParameterSetName = "InputFile")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_LicenseResponseCollection = New-Object System.Collections.ArrayList

        if ($file)
        {

            [Array]$LicenseKey = Get-Content $file

        }

    }

    Process 
    {

        #Loop through all keys, and add one by one.
        foreach ($_lk in ($LicenseKey | ? { -not $_.startswith("#") }))
        {

            "[{0}] Processing LicenseKey: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_lk | write-verbose 

            $_key     = NewObject -LicenseKey
            $_key.key = '{0}' -f $_lk

            Try 
            {
            
                $_ret = Send-HPOVRequest -Uri $licensesUri -Method POST -Body $_key -Hostname $ApplianceConnection

            }

            Catch 
            {

                $_Exception = $_

                Switch ($_.FullyQualifiedErrorId)
                {

                    "LICENSE_ALREADY_EXISTS"
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.LicenseKeyException LicenseKeyAlreadyExists ResourceExists 'LicenseKey' -Message "The license key provided already exists on the appliance. Please correct the value, and try again."

                    }

                    "ADD_LICENSE_FAILED"
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.LicenseKeyException InstallLicenseFailure InvalidResult 'LicenseKey' -Message $_Exception.Message                        

                    }

                    default
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.LicenseKeyException InvalidResult InvalidResult 'LicenseKey' -Message $_Exception.Exception.Message

                    }

                }

                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            $_ret.PSObject.TypeNames.Insert(0,'HPOneView.Appliance.License')

            $_ret
            
        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | write-verbose 
    
    }

}

function Remove-HPOVLicense 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('uri', 'name', 'license','Resource')]
        [System.Object]$InputObject,
    
        [Parameter (Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Resource'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {


                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                    

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_ResponseCollection = New-Object System.Collections.ArrayList
        $_LicenseCollection = New-Object System.Collections.ArrayList

    }

    Process 
    {

        if ($PipelineInput -and $InputObject -ne $null) 
        {

            "[{0}] Processing Pipeline input" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] License Object provided: $($InputObject | FL * | Out-String)"

            if ('licenses' -contains $InputObject.category)
            {

                if (-not($InputObject.ApplianceConnection))
                {

                    $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "License:$($InputObject.uri)" -TargetType PSObject -Message "The License resource provided is missing the source ApplianceConnection property. Please check the object provided and try again."
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                [void]$_LicenseCollection.Add($InputObject)

            }

            else
            {

                $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidArgumentValue InvalidArgument "License:$($InputObject.uri)" -TargetType PSObject -Message "The License resource is not an expected category type [$($License.category)]. Allowed resource category types are 'licenses'. Please check the object provided and try again."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

        }

        else 
        {

            foreach ($license in $InputObject) 
            {

                switch ($license.GetType().name) 
                {

                    "String" 
                    { 
                
                        if ([System.Uri]::IsWellFormedUriString($license,'Relative') -and $license.StartsWith($script:licensesUri)) 
                        {
                    
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] License URI provided: $license"
                            
                            try
                            {

                                $license = Send-HPOVRequest $license -ApplianceConnection $ApplianceConnection

                            }
                            
                            catch
                            {

                                $PSCmdlet.ThrowTerminatingError($_)

                            }
                    
                        }

                        elseif ($license.StartsWith("/rest/")) 
                        {
                     
                            #Invalid URI, so error
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid License URI provided: $license"

                            $ErrorRecord = New-ErrorRecord ArgumentException InvalidLicenseURI InvalidArgument 'Remove-HPOVLicense' -Message "The provided URI value for the -License Parameter '$license' is invalid. The License URI must Begin with /rest/licenses. Please check the value and try again."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }

                        else 
                        {

                            #Invalid Parameter, so error
                            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Invalid License URI provided: $license"

                            $ErrorRecord = New-ErrorRecord ArgumentException InvalidLicenseValue InvalidArgument 'Remove-HPOVLicense' -Message "The provided value for the -License Parameter '$license' is invalid. Please check the value and try again."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                    
                        }
                
                    }

                    "PSCustomObject" 
                    { 
                
                        #Validate the object
                        if (-not($license.category -eq "licenses"))
                        {

                            $ErrorRecord = New-ErrorRecord ArgumentException InvalidLicenseCategory InvalidArgument 'Remove-HPOVLicense' -Message "Invalid -License Parameter value. Expected Resource Category 'licenses', received '$($license.category)'."
                            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                        }              
                
                    }

                }

                [void]$_LicenseCollection.Add($license)
            }

        }

    }

    End 
    {
        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_LicenseCollection.count) License resources to remove."

        foreach ($license in $_LicenseCollection)
        {

            if ($PSCmdlet.ShouldProcess($license.product,"remove license $($license.product) from appliance $($license.ApplianceConnection.Name)"))
            {    

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing License '$($license.product)' [$($license.productDescription)]."
                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] URI: '$($license.uri)'"

                try
                {

                    $_resp = Send-HPOVRequest $license.uri DELETE -Hostname $license.ApplianceConnection.Name

                }

                catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['whatif']) 
            { 
                           
                write-warning "-WhatIf was passed, would have proceeded with removing '$($license.product)'."
                $_resp = $null
            
            }

            else 
            {

                #If here, user chose "No", End Processing
                write-warning "`nNot removing license, $($license.product).`n"
                    
                $_resp = $null

            }

            [void]$_ResponseCollection.Add($_resp)

        }

        return $_ResponseCollection

    }

}

function Set-HPOVSmtpConfig 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (
    

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [validatescript({if ($_ -as [Net.Mail.MailAddress]) {$true} else { Throw "The Parameter value is not an email address. Please correct the value and try again." }})]
        [System.String]$SenderEmailAddress,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Alias ('SmtpServer')]        
        [ValidateNotNullOrEmpty()]
        [System.String]$Server,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Alias ('SmtpPort')]
        [ValidateNotNull()]
        [System.Int32]$Port,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Object]$Password,

        [Parameter (Mandatory, ParameterSetName = "Disabled")]
        [Switch]$AlertEmailDisabled,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Switch]$AlertEmailEnabled,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [Parameter (Mandatory = $False, ParameterSetName = "Disabled")]
        [Switch]$Async,
    
        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [Parameter (Mandatory = $False, ParameterSetName = "Disabled")]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
        
    )
    
    Begin 
    {
    
        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        if ($PSBoundParameters['Password'])
        {

            if ($Password -is [SecureString])
            {

                $_DecryptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

            }

            else 
            {

                $_DecryptPassword = $Password

            }
        
        }

        $_ResponseCollection = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            $_SmtpConfig = NewObject -SmtpConfig
        
            $_SmtpConfig.password           = $_DecryptPassword
            $_SmtpConfig.smtpServer         = $Server
            $_SmtpConfig.alertEmailDisabled = if ($alertEmailDisabled.IsPresent) { $True }
                                                elseif ($alertEmailEnabled.IsPresent) { $False }
                                                else { $False }

            Try
            {

                #Get current SMTP Configuration
                $_CurrentSmtpConfiguation = Send-HPOVRequest -Uri $SmtpConfigUri -Hostname $_appliance

                if ($PSBoundParameters['AlertEmailEnabled'] -and -not $PSBoundParameters['SenderEmailAddress'] -and -not $_CurrentSmtpConfiguation.senderEmailAddress) 
                { 
                    
                    $ExceptionMessage = 'The -AlertEmailEnabled Parameter requires the -SenderEmailAddress Parameter to be provided when the appliance is first configured.'
                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.EmailAlertResourceException InvalidArgumentValue InvalidArgument 'AlertEmailEnabled' -TargetType 'SwitchParameter' -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                
                }

                elseif ($PSBoundParameters['AlertEmailEnabled'] -and -not $PSBoundParameters['SenderEmailAddress'] -and $_CurrentSmtpConfiguation.senderEmailAddress)
                {

                    $_SmtpConfig.senderEmailAddress = $_CurrentSmtpConfiguation.senderEmailAddress

                }
                
                elseif ($PSBoundParameters['SenderEmailAddress'])
                { 
                    
                    $_SmtpConfig.senderEmailAddress = $SenderEmailAddress 
                
                }

                elseif ($_CurrentSmtpConfiguation.senderEmailAddress)
                {

                    $_SmtpConfig.senderEmailAddress = $_CurrentSmtpConfiguation.senderEmailAddress 
                    
                }

                if (-not $_CurrentSmtpConfiguation.smtpServer -and -not $PSBoundParameters['Server'] -and $PSBoundParameters['Port'])
                {

                    $ExceptionMessage = "When specifying an SMTP Server Port value, the -Server parameter or an existing SMTP Server value must be present on the appliance."

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.EmailAlertResourceException InvalidSmtpServer InvalidArgument "Port" -Message $ExceptionMessage
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                elseif ($_CurrentSmtpConfiguation.smtpServer -and -not $PSBoundParameters['Server'] -and $PSBoundParameters['Port'])
                {

                    "[{0}] Using configured SMTP Server: {1}." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_CurrentSmtpConfiguation.smtpServer | Write-Verbose

                    $_SmtpConfig.smtpServer = $_CurrentSmtpConfiguation.smtpServer

                }

                if (-not $_CurrentSmtpConfiguation.smtpPort -and -not $PSBoundParameters['Port'] -and $PSBoundParameters['Server'])
                {

                    "[{0}] Using default SMTP TCP Port 25." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                }

                else
                {

                    $_SmtpConfig.smtpPort = $Port

                }

                #Copy existing email alert filter settings
                if ($_CurrentSmtpConfiguation.alertEmailFilters)
                {

                    [Array]$_SmtpConfig.alertEmailFilters = $_CurrentSmtpConfiguation.alertEmailFilters

                }

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SMTP Configuration: $($_SmtpConfig | fl * -force | out-string)"

                $_resp = Send-HPOVRequest -Uri $SmtpConfigUri -Method POST -Body $_SmtpConfig -Hostname $_appliance

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['Async'])
            {

                $_resp

            }

            else
            {

                $_resp | Wait-HPOVTaskComplete

            }

        }

    }    
    
    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
    
    }

}

function Test-HPOVEmailAlert
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (    

        [Parameter (Mandatory)]
        [ValidateNotNullOrEmpty()]
        [Array]$Recipients,

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Subject = 'This is a test message.',

        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]$Body = 'Test email message from HPE OneView appliance.',
    
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_SMTPConfigCollection = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        $_EmailTest = NewObject -TestSmtpConfig        
        
        #Add recipients to property
        ForEach ($_recipient in $Recipients)
        {
            
            #Validate recipient is a valid Email Address
            if (-not $_recipient -as [Net.Mail.MailAddress])
            {

                #ThrowTerminatingError

            }

            [void]$_EmailTest.toAddress.Add($_recipient)

        }

        if ([Regex]::Match($Body,$HtmlPattern).Success)
        {

            $_EmailTest.htmlMessageBody = $Body

        }

        else
        {

            $_EmailTest.textMessageBody = $Body

        }

        $_EmailTest.subject = $Subject

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {
     
                Send-HPOVRequest -Uri $TestNotificationUri -Method POST -Body $_EmailTest -Hostname $_appliance

            }

            catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    End 
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
    
    }    

}

function Get-HPOVSMTPConfig 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (    
    
        [Parameter (Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)
    
    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_SMTPConfigCollection = New-Object System.Collections.ArrayList

    }
    
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing '{1}' Appliance (of {2})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name, $ApplianceConnection.Count | Write-Verbose

            Try
            {

                $currentSmtpConfig = Send-HPOVRequest $SmtpConfigUri -Hostname $_appliance

            }
            
            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
    
            $currentSmtpConfig | % { 
                
                $_.PSObject.TypeNames.Insert(0,"HPOneView.Appliance.SmtpConfiguration") 
            
                [void]$_SMTPConfigCollection.Add($_)
            
            }    

        }

    }
    
    End 
    {

        Return $_SMTPConfigCollection
    
    }

}

function Add-HPOVSmtpAlertEmailFilter 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [System.String]$Name,
    
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Alias ('query')]
        [ValidateNotNullOrEmpty()]
        [System.String]$Filter,

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = "Default")]
        [Alias ('recipients')]
        [ValidateNotNullOrEmpty()]
        [validatescript({$_ | foreach { if ($_ -as [Net.Mail.MailAddress]) {$true} else { Throw "The Parameter value '$_' is not an email address. Please correct the value and try again." }}})]
        [System.Array]$Emails,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [System.Array]$Scope,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateSet ('AND','OR')]
        [System.String]$ScopeMatchPreference = 'OR',

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {
            
            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }
                
            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

        if (-not($PSBoundParameters['Filter']))
        {

            Write-Warning 'The Filter provided is Null or Empty. This will return all resources and severities, which will cause performance issues in a large environment.'

        }

        #This is needed as the scopeQuery property cannot be null
        if (-not $PSBoundParameters['Scope'])
        {

            [String]$Scope = ""

        }

        else
        {

            $_ScopeEntries = New-Object System.Collections.ArrayList

            ForEach ($_entry in $Scope)
            {

                if (-not $_entry.StartsWith("scope:'"))
                {

                    $_entry = "scope:'{0}'" -f $_entry
                    
                }

                [void]$_ScopeEntries.Add($_entry)                

            }

            [String]$Scope = [System.String]::Join(" $ScopeMatchPreference ",$_ScopeEntries.ToArray())

        }

    }
     
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting current SMTP Configuration from '$($_appliance.Name)'."

            Try
            {

                $_smtpFilterConfiguration = Send-HPOVRequest $SmtpConfigUri -Hostname $_appliance.Name

            }

            Catch
            {

              $PSCmdlet.ThrowTerminatingError($_)

            }
            
            $_OriginalFilterConfig = $_smtpFilterConfiguration.alertEmailFilters

            #Rebuild property as ArrayList
            $_smtpFilterConfiguration.alertEmailFilters = New-Object System.Collections.ArrayList

            $_OriginalFilterConfig | % {

                [void]$_smtpFilterConfiguration.alertEmailFilters.Add($_)

            }
        
            #Create new alert filter object
            $_alertFilter = NewObject -AlertFilter
        
            $_alertFilter.filter          = $filter
            $_alertFilter.displayFilter   = $filter
            $_alertFilter.userQueryFilter = $filter
            $_alertFilter.emails          = $Emails
            $_alertFilter.scopeQuery      = $Scope
            $_alertFilter.filterName      = $Name

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing SMTP Alert Configuration for '$($_appliance.Name)'."
            
            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] SMTP Appliance Filter Configuration: $($_alertFilter | fl * -force | out-string)"

            [void]$_smtpFilterConfiguration.alertEmailFilters.Add($_alertFilter)

            Try
            {

                $_resp = Send-HPOVRequest $SmtpConfigUri POST $_smtpFilterConfiguration -Hostname $_appliance.Name

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['Async'])
            {

                $_resp

            }

            else
            {

                $_resp | Wait-HPOVTaskComplete

            }
            
        }

    }
    
    End 
    {
    
        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose 
    
    }

}

function Get-HPOVLoginMessage
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ColStatus = New-Object System.Collections.ArrayList

    }
     
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting current Login Message Configuration from '$($_appliance.Name)'."

            Try
            {

                $_LoginDomainGlobalSettings = Send-HPOVRequest $authnSettingsUri -Hostname $_appliance.Name

                $_LoginMessageObject = New-Object HPOneView.Appliance.LoginMessage($_LoginDomainGlobalSettings.loginMessage.message, $_LoginDomainGlobalSettings.loginMessage.acknowledgment)

                #$_LoginMessageObject.Message =
                #$_LoginMessageObject.Acknowledgment =
                $_LoginMessageObject.ApplianceConnection.ConnectionId = $_LoginDomainGlobalSettings.ApplianceConnection.ConnectionId
                $_LoginMessageObject.ApplianceConnection.Name         = $_LoginDomainGlobalSettings.ApplianceConnection.Name

                [void]$_ColStatus.Add($_LoginMessageObject)

            }

            Catch
            {

                $_ColStatus

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }
    
    End 
    {
    
        Return $_ColStatus
    
    }

}

function Set-HPOVLoginMessage
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (
    
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [String]$Message,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [Bool]$Acknowledgment = $False,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command again."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {


            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ColStatus = New-Object System.Collections.ArrayList

    }
     
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Getting current Login Message Configuration from '$($_appliance.Name)'."

            Try
            {

                $_LoginDomainGlobalSettings = Send-HPOVRequest $authnSettingsUri -Hostname $_appliance.Name

                $_LoginDomainGlobalSettings.loginMessage.message        = $Message
                $_LoginDomainGlobalSettings.loginMessage.acknowledgment = [bool]$Acknowledgment

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Updating Login Message Configuration."

                $_NewLoginDomainGlobalSettings = Send-HPOVRequest $authnSettingsUri PUT $_LoginDomainGlobalSettings -Hostname $_appliance.Name

                #$_LoginMessageObject = New-Object HPOneView.Appliance.LoginMessage
                #
                #$_LoginMessageObject.Message = $_NewLoginDomainGlobalSettings.loginMessage.message
                #$_LoginMessageObject.Acknowledgment = $_NewLoginDomainGlobalSettings.loginMessage.acknowledgment

                $_LoginMessageObject = New-Object HPOneView.Appliance.LoginMessage($_NewLoginDomainGlobalSettings.loginMessage.message, $_NewLoginDomainGlobalSettings.loginMessage.acknowledgment)

                $_LoginMessageObject.ApplianceConnection.ConnectionId = $_NewLoginDomainGlobalSettings.ApplianceConnection.ConnectionId
                $_LoginMessageObject.ApplianceConnection.Name         = $_NewLoginDomainGlobalSettings.ApplianceConnection.Name

                [void]$_ColStatus.Add($_LoginMessageObject)

            }

            Catch
            {
                
                $_ColStatus

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
        }

    }
    
    End 
    {
    
        Return $_ColStatus
    
    }

}

function Get-HPOVRemoteSyslog 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (
    
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullOrEmpty()]
        [Alias ('Appliance')]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ColStatus = New-Object System.Collections.ArrayList

    }
     
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing {1} appliance connection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            Try
            {

                $_RemoteSyslogSettings = Send-HPOVRequest $RemoteSyslogUri -Hostname $_appliance.Name

                $_RemoteSyslogSettings.PSObject.TypeNames.Insert(0,'HPOneView.RemoteSyslog')

                [void]$_ColStatus.Add($_RemoteSyslogSettings)

            }

            Catch
            {
                
                $_ColStatus

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
        }

    }
    
    End 
    {
    
        Return $_ColStatus
    
    }

}

function Set-HPOVRemoteSyslog 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (
    
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Net.IPAddress]$Destination,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [ValidateRange(1,65535)]
        [Int]$Port = 514,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [switch]$SendTestMessage,

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ColStatus = New-Object System.Collections.ArrayList

    }
     
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing {1} appliance connection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            $_RemoteSyslogConfig = NewObject -RemoteSyslog
            $_RemoteSyslogConfig.enabled = $true

            switch ($PSBoundParameters.Keys)
            {

                'Destination'
                {
                
                     "[{0}] Setting RemoteSyslog destination to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PSBoundParameters['Destination'] | Write-Verbose

                    $_RemoteSyslogConfig.remoteSyslogDestination = $Destination.ToString()
                
                }

                'Port'
                {
                
                    "[{0}] Setting RemoteSyslog destination TCP Port to: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $PSBoundParameters['Port'] | Write-Verbose
                
                    $_RemoteSyslogConfig.remoteSyslogPort = $Port.ToString()

                }

                'SendTestMessage'
                {
                
                    "[{0}] Will generate a test SysLog entry." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                    $_RemoteSyslogConfig.sendTestLog = $true
                
                }

            }

            Try
            {

                "[{0}] Sending API POST request." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_results = Send-HPOVRequest $RemoteSyslogUri PUT $_RemoteSyslogConfig -Hostname $_appliance.Name
                
            }

            Catch
            {
                
                $_ColStatus

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['Async'])
            {

                $_results

            }

            else
            {

                $_results | Wait-HPOVTaskComplete

            }

        }

    }
    
    End 
    {
    
        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
    
    }

}

function Enable-HPOVRemoteSyslog
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ColStatus = New-Object System.Collections.ArrayList

    }
     
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing {1} appliance connection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            Try
            {

                "[{0}] Getting current settings from the appliance." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_RemoteSyslogSettings = Get-HPOVRemoteSyslog -ApplianceConnection $_appliance.Name

            }

            Catch
            {
                
                $_ColStatus

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($_RemoteSyslogSettings.enabled)
            {

                "[{0}] SysLog already enabled." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

            else
            {

                $_RemoteSyslogSettings.enabled = $true

                Try
                {

                    $_results = Send-HPOVRequest $RemoteSyslogUri PUT $_RemoteSyslogSettings -Hostname $_appliance.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            if ($PSBoundParameters['Async'])
            {

                $_results

            }

            else
            {

                $_results | Wait-HPOVTaskComplete

            }
            
        }

    }
    
    End 
    {
    
        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
    
    }

}

function Disable-HPOVRemoteSyslog
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory = $False, ParameterSetName = "Default")]
        [switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $_ColStatus = New-Object System.Collections.ArrayList

    }
     
    Process 
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing {1} appliance connection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            Try
            {

                "[{0}] Getting current settings from the appliance." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                $_RemoteSyslogSettings = Get-HPOVRemoteSyslog -ApplianceConnection $_appliance.Name

            }

            Catch
            {
                
                $_ColStatus

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if (-not($_RemoteSyslogSettings.enabled))
            {

                "[{0}] SysLog is already disabled." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            }

            else
            {

                $_RemoteSyslogSettings.enabled = $false

                Try
                {

                    $_results = Send-HPOVRequest $RemoteSyslogUri PUT $_RemoteSyslogSettings -Hostname $_appliance.Name

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                if ($PSBoundParameters['Async'])
                {

                    $_results

                }

                else
                {

                    $_results | Wait-HPOVTaskComplete

                }

            }
            
        }

    }
    
    End 
    {
    
        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose
    
    }

}

function Get-HPOVScope
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [SupportsWildcards()]
        [String]$Name,        

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process
    {

        $_uri = $ScopesUri

        if ($PSBoundParameters['Name'])
        {

            if ($Name.Contains('*'))
            {

                $_uri = "{0}?query=name matches '{1}'" -f $_uri, $Name.Replace('*','%25')

            }

            else
            {

                $_uri = "{0}?query=name eq '{1}'" -f $_uri, $Name

            }

        }        

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing {1} appliance connection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            #Get Scope resource
            Try
            {

                $_Scopes = Send-HPOVRequest $_uri -Hostname $_appliance                

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['Name'] -and $_Scopes.count -eq 0)
            {

                $ErrorRecord = New-ErrorRecord HPOneView.Appliance.ScopeResourceException ScopeResourceNotFound ObjectNotFound -TargetObject 'Name' -Message ('{0} was not found on {1} appliance. Check the Name Parameter value.' -f $Name, $_appliance.Name)
                $PSCmdlet.WriteError($ErrorRecord)

            }

            #Process Scopes Collection from API
            ForEach ($_scopemember in $_Scopes.members)
            {

                $_Scope = New-Object HPOneView.Appliance.ScopeCollection($_scopemember.name, $_scopemember.description, $_scopemember.uri, $_scopemember.eTag)

                Add-Member -InputObject $_Scope -NotePropertyName ApplianceConnection -NotePropertyValue ([PSCustomObject]@{ Name = $_appliance.Name; ConnectionId = $_appliance.ConnectionId }) -Force 

                #Lookup Scope resource associations, and add to [ScopeCollectionMembers] Members property
                Try
                {

                    $_IndexAssocationUri = '{0}?filter=scopeuris:{1}' -f $IndexUri, $_scopemember.uri

                    $_AssociatedResources = Send-HPOVRequest $_IndexAssocationUri -Hostname $_appliance

                }

                Catch
                {

                  $PSCmdlet.ThrowTerminatingError($_)

                }

                ForEach ($_Member in $_AssociatedResources.members)
                {

                    $_ScopeMember = New-Object HPOneView.Appliance.ScopeCollectionMemberEntry($_Member.name, $ScopeCategoryEnum[$_Member.category], $_Member.uri)

                    [void]$_Scope.Members.Add($_ScopeMember)

                }

                $_Scope

            }

        }
        
    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function New-HPOVScope
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [String]$Description,

        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing {1} appliance connection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            $_Scope = New-Object HPOneView.Appliance.Scope($Name, $Description)

            #Get Scope resource
            Try
            {

                $_Scope = Send-HPOVRequest $ScopesUri POST $_Scope -Hostname $_appliance                

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            #Return Strongly typed object
            $_Scope = New-Object HPOneView.Appliance.ScopeCollection($_Scope.name, $_Scope.description, $_Scope.uri, $_Scope.eTag)

            Add-Member -InputObject $_Scope -NotePropertyName ApplianceConnection -NotePropertyValue ([PSCustomObject]@{ Name = $_appliance.Name; ConnectionId = $_appliance.ConnectionId }) -Force

            $_Scope

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Add-HPOVResourceToScope
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "Default", ValueFromPipeline)]
        [ValidateNotNullorEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,
        
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Alias('Resource')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Switch]$Async,

        [Parameter (Mandatory = $false, ParameterSetName = "Default", ValueFromPipelineByPropertyName)]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Scope'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $_connection -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process
    {

        #$_UpdateScopeMembers = NewObject -ScopeMemberUpdate
        $_UpdateScopeMembers = NewObject -PatchOperation
        $_UpdateScopeMembers.op = 'add'
        $_UpdateScopeMembers.path = '/addedResourceUris'
        $_UpdateScopeMembers.value = New-Object System.Collections.ArrayList

        ForEach ($_resource in $InputObject)
        {

            #Validate Resource is allowed
            if ($ScopeCategoryEnum[$_resource.category])
            {

                #Generate error that Resource already contains the Scope Uri
                if ($_resource.scopeUris -contains $Scope.Uri)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.ScopeResourceException ResourceAlreadyWithinScope ResourceExists -TargetObject 'InputObject' -TargetType 'PSObject' -Message ('{0} is already a member of {1} scope.' -f $_resource.name, $Scope.Name)
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                #Add resource URI to collection
                else
                {

                    "[{0}] {1} Resource is not a member of {2} Scope, adding to collection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_resource.name, $Scope.Name | Write-Verbose

                    [void]$_UpdateScopeMembers.value.Add($_resource.uri)            

                }

            }

        }

        Try
        {

            $_Resp = Send-HPOVRequest -Uri $Scope.Uri -Method PATCH -Body $_UpdateScopeMembers -Hostname $ApplianceConnection #-OverrideContentType 'application/json-patch+json'

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($PSboundParameters['Async'])
        {

            $_Resp

        }

        else
        {

            $_resp | Wait-HPOVTaskComplete

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVResourceFromScope
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default")]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "Default", ValueFromPipeline)]
        [ValidateNotNullorEmpty()]
        [HPOneView.Appliance.ScopeCollection]$Scope,
        
        [Parameter (Mandatory, ParameterSetName = "Default")]
        [Alias('Resource')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,
        
        [Parameter (Mandatory = $false, ParameterSetName = "Default")]
        [ValidateNotNullorEmpty()]
        [Switch]$Async,    

        [Parameter (Mandatory = $false, ParameterSetName = "Default", ValueFromPipelineByPropertyName)]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Scope'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $_connection -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process
    {

        $_UpdateScopeMembers = NewObject -PatchOperation
        $_UpdateScopeMembers.op = 'replace'
        $_UpdateScopeMembers.path = '/removedResourceUris'
        $_UpdateScopeMembers.value = New-Object System.Collections.ArrayList

        ForEach ($_resource in $InputObject)
        {

            #Validate Resource is allowed
            if ($ScopeCategoryEnum[$_resource.category])
            {

                #Generate error that Resource already contains the Scope Uri
                if ($Scope.Members.Uri -notcontains $_resource.uri)
                {

                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.ScopeResourceException ResourceDoesNotExistWithinScope ObjectNotFound -TargetObject 'InputObject' -TargetType 'PSObject' -Message ('{0} is not found to be a member of {1} scope.' -f $_resource.name, $Scope.Name)
                    $PSCmdlet.WriteError($ErrorRecord)

                }

                #Add resource URI to collection
                else
                {

                    "[{0}] {1} Resource is a member of {2} Scope. Removing." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_resource.name, $Scope.Name | Write-Verbose

                    [void]$_UpdateScopeMembers.value.Add($_resource.uri)                

                }

            }

        }

        Try
        {

            $_Resp = Send-HPOVRequest -Uri $Scope.Uri -Method PATCH -Body $_UpdateScopeMembers -Hostname $ApplianceConnection

        }

        Catch
        {

            $PSCmdlet.ThrowTerminatingError($_)

        }

        if ($PSboundParameters['Async'])
        {

            $_Resp

        }

        else
        {

            $_resp | Wait-HPOVTaskComplete

        }

    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Remove-HPOVScope
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "Default", SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "Default", ValueFromPipeline)]
        [ValidateNotNullorEmpty()]
        [HPOneView.Appliance.ScopeCollection[]]$Scope,    

        [Parameter (Mandatory = $false, ParameterSetName = "Default", ValueFromPipelineByPropertyName)]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['Scope'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $_connection -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        $_ScopeCollection = New-Object System.Collections.ArrayList

    }

    Process
    {

        "[{0}] Processing Scope: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Scope.Name | Write-Verbose

        [void]$_ScopeCollection.Add($Scope)

    }

    End
    {

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Processing $($_ScopeCollection.count) Scope object resources to remove."

        #Process Storage Resources
        ForEach ($_Scope in $_ScopeCollection)
        {

            if ($PSCmdlet.ShouldProcess($_Scope.ApplianceConnection.Name,"Remove Scope '$($_Scope.Name)' from appliance")) 
            {

                Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Removing Scope '$($_Scope.name)' from appliance '$($_Scope.ApplianceConnection.Name)'."

                Try
                {

                    Send-HPOVRequest $_Scope.Uri DELETE -Hostname $_Scope.ApplianceConnection.Name -addHeader @{'If-Match' = $_Scope.eTag}

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

            elseif ($PSBoundParameters['WhatIf'])
            {

                "[{0}] WhatIf Parameter was passed." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            }

        }

    }

}

function Get-HPOVLabel
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory = $false)]
        [ValidateNotNullorEmpty()]
        [Object]$Name,

        [Parameter (Mandatory = $false)]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
        {

            For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++) 
            {

                Try 
                {
            
                    $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $ApplianceConnection[$c].Name -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            Try 
            {
            
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

    }

    Process
    {

        ForEach ($_appliance in $ApplianceConnection)
        {

            "[{0}] Processing {1} appliance connection." -f $MyInvocation.InvocationName.ToString().ToUpper(), $_appliance.Name | Write-Verbose

            #Get label resources
            Try
            {

                $_Labels = Send-HPOVRequest -Uri $LabelsUri -Hostname $_appliance                

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

            if ($PSBoundParameters['Name'])
            {

                [Array]$_Labels.members = $_Labels.members | ? name -match $Name
                
                if ($_Labels.members.count -eq 0)
                {

                    $ExceptionMessage = '{0} was not found on {1} appliance. Check the Name Parameter value.' -f $Name, $_appliance.Name
                    $ErrorRecord = New-ErrorRecord HPOneView.Appliance.LabelResourceException LabelResourceNotFound ObjectNotFound -TargetObject 'Name' -Message $ExceptionMessage
                    $PSCmdlet.WriteError($ErrorRecord)

                }

            }    

            #Process Scopes Collection from API
            ForEach ($_label in $_Labels.members)
            {

                New-Object HPOneView.Appliance.Label($_label.name, $_label.uri, $_label.ApplianceConnection)

            }

        }
        
    }

    End
    {

        "[{0}] Done." -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

function Add-HPOVResourceToLabel
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding ()]
    Param
    (

        [Parameter (Mandatory)]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory, ValueFromPipeline)]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName)]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $_connection -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process
    {

        ForEach ($_Resource in $InputObject)
        {

            "[{0}] Processing Label: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name | Write-Verbose

            Try
            {

                $ExistingLabels = Send-HPOVRequest -Uri ('{0}/{1}' -f $LabelsResourcesBaseUri, $_Resource.uri) -Hostname $ApplianceConnection

            }

            Catch
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }
            
            #Label already exists. Generate non-terminating error?
            if ($Name -contains $ExistingLabels.labels)
            {

                "[{0}] Resource {1} is already associated with {2} label ({3})" -f $MyInvocation.InvocationName.ToString().ToUpper(), $_Resource.name, $Name, [String]::Join($ExistingLabels.labels, ', ') | Write-Verbose

                Write-Warning "Resource is already associated with label."

            }

            else
            {

                if ($ExistingLabels.labels.count -gt 0)
                {

                    "[{0}] Appending {1} label to resource {2} association." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name, $_Resource.name | Write-Verbose                

                    [Array]$ExistingLabels.labels += $Name

                }

                else
                {

                    "[{0}] Associating {1} label to resource {2}." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name, $_Resource.name | Write-Verbose

                    [Array]$ExistingLabels.labels = $Name

                }

                Try
                {

                    Send-HPOVRequest -Uri $ExistingLabels.uri -Method PUT -Body $ExistingLabels -Hostname $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    End
    {

        '[{0}] Done.' | Write-Verbose

    }    

}

function Remove-HPOVResourceFromLabel
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = 'Default', SupportsShouldProcess, ConfirmImpact = 'High')]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = 'Default')]
        [ValidateNotNullorEmpty()]
        [String]$Name,

        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'Default')]
        [Parameter (Mandatory, ValueFromPipeline, ParameterSetName = 'RemoveAll')]
        [ValidateNotNullorEmpty()]
        [Object]$InputObject,

        [Parameter (Mandatory = $false, ParameterSetName = 'RemoveAll')]
        [Switch]$RemoveAllLabelsFromResource,

        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'Default')]
        [Parameter (Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = 'RemoveAll')]
        [Alias ('Appliance')]
        [ValidateNotNullOrEmpty()]
        [Object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin
    {

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        if (-not($PSBoundParameters['InputObject'])) 
        { 
            
            $PipelineInput = $True 
        
        }

        else
        {

            "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

            if (-not($ApplianceConnection) -and -not(${Global:ConnectedSessions}))
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError "ApplianceConnection" -Message "No Appliance connection session found. Please use Connect-HPOVMgmt to establish a connection, then try your command agian."
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            elseif ($ApplianceConnection -is [System.Collections.IEnumerable] -and $ApplianceConnection -isnot [System.String])
            {

                For ([int]$c = 0; $c -lt $ApplianceConnection.Count; $c++)
                {

                    Try 
                    {
            
                        $ApplianceConnection[$c] = Test-HPOVAuth $ApplianceConnection[$c]

                    }

                    Catch [HPOneview.Appliance.AuthSessionException] 
                    {

                        $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError $_connection -Message $_.Exception.Message -InnerException $_.Exception
                        $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                    }

                    Catch 
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

            }

            else
            {

                Try 
                {
            
                    $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

                }

                Catch [HPOneview.Appliance.AuthSessionException] 
                {

                    $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -Message $_.Exception.Message -InnerException $_.Exception
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)

                }

                Catch 
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

    }

    Process
    {

        if ($InputObject -isnot [HPOneView.Appliance.Label])
        {

            "[{0}] Processing Label {1} for {2} resource." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name, $InputObject.name | Write-Verbose

            if ($PSCmdlet.ParameterSetName -eq 'RemoveAll')
            {

                if ($PSCmdlet.ShouldProcess($InputObject.name, 'remove resource from all associated labels'))
                {

                    "[{0}] Removing {1} resource from all labels." -f $MyInvocation.InvocationName.ToString().ToUpper(), $InputObject.name | Write-Verbose

                    Try
                    {

                        $_Uri = '{0}{1}' -f $LabelsResourcesBaseUri, $InputObject.uri
                        Send-HPOVRequest -Uri $_Uri -Method DELETE -Hostname $ApplianceConnection

                    }

                    Catch
                    {

                        $PSCmdlet.ThrowTerminatingError($_)

                    }

                }

                elseif ($PSBoundParameters['WhatIf'])
                {

                    "[{0}] User specified -WhatIf" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

                }

            }

            else
            {

                Try
                {

                    $ExistingLabels = Send-HPOVRequest -Uri ('{0}/{1}' -f $LabelsResourcesBaseUri, $InputObject.uri) -Hostname $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

                "[{0}] Removing {1} label from resource {2} association." -f $MyInvocation.InvocationName.ToString().ToUpper(), $Name, $InputObject.name | Write-Verbose                

                [Array]$ExistingLabels.labels = $ExistingLabels.labels | ? name -ne $Name

                Try
                {

                    Send-HPOVRequest -Uri $ExistingLabels.uri -Method PUT -Body $ExistingLabels -Hostname $ApplianceConnection

                }

                Catch
                {

                    $PSCmdlet.ThrowTerminatingError($_)

                }

            }

        }

        else
        {

            $_Message = "An invalid InputObject argument value type was provided, {0}. Labels cannot be removed via the appliance API. Labels are automatically removed when the last association to a resource is removed. Please provide a resource object to remove the label association." -f $InputObject.name
            $ErrorRecord = New-ErrorRecord InvalidOperationException InvalidCInputObjectParameterValue InvalidArgument 'InputObject' -TargetType "$($InputObject.GetType().Name)" -Message $_Message
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

    }

    End
    {

        '[{0}] Done.' -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

    }

}

########################################################
# HP Support CMDLETs

function Enable-HPOVDebug 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml
    
    [CmdletBinding (DefaultParameterSetName = "default")]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "default",HelpMessage = "Provide the debug Scope.")]
        [ValidateNotNullOrEmpty()]
        [String]$Scope,

        [Parameter (Mandatory, ParameterSetName = "default",HelpMessage = "Provide the component Logger Name.")]
        [ValidateNotNullOrEmpty()]
        [String]$LoggerName,

        [Parameter (Mandatory, ParameterSetName = "default",HelpMessage = "Specify the verbose log level (ERROR, WARN, DEBUG or TRACE are allowed).")]
        [ValidateNotNullOrEmpty()]
        [ValidateSet ('ERROR','WARN','DEBUG','TRACE', IgnoreCase = $False)]
        [String]$Level,

        [Parameter (Mandatory = $false, ParameterSetName = "default", ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias ('Appliance')]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        [console]::WriteLine()
        Write-Warning "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        Write-Warning "!!! FOR HP SUPPORT USE ONLY. DO NOT USE UNLESS OTHERWISE INSTRUCTED TO BY HP SUPPORT !!!"
        Write-Warning "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        [console]::WriteLine() 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection -is [HPOneView.Appliance.Connection]) -and (-not($ApplianceConnection -is [System.String])))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException InvalidApplianceConnectionDataType InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter is not type [HPOneView.Appliance.Connection] or [System.String]. Please correct this value and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif  ($ApplianceConnection.Count -gt 1)
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value. Please correct this and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        else
        {

            Try 
            {
    
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -TargetType $ApplianceConnection.GetType().Name -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        $_debug = NewObject -ApplianceDebug

        $_debug.scope      = $Scope
        $_debug.loggerName = $LoggerName
        $_debug.level      = $Level

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting '$Level' at '$Scope`:$LoggerName'"

        Try
        {

            $resp = Send-HPOVRequest $script:applianceDebugLogSetting POST $_debug -Hostname $ApplianceConnection

        }

        Catch
        {

            "Unable to set '{0}:{1}' to '{2}' logging level. Error '{3}'" -f $Scope,$LoggerName,$Level,$_.Exception.Message

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $_Status = "'{0}:{1}' successfully set to '{2}' on Appliance {3}" -f $Scope,$LoggerName,$Level,$ApplianceConnection.Name

        [void]$colStatus.Add($_Status)

    }

    End 
    {

        $colStatus

        Write-Warning "Remember to set '$Scope`:$LoggerName' back to 'INFO' with 'Disable-HPOVDebug $Scope $LoggerName'"

    }

}

function Disable-HPOVDebug 
{

    # .ExternalHelp HPOneView.310.psm1-help.xml

    [CmdletBinding (DefaultParameterSetName = "default")]
    Param
    (

        [Parameter (Mandatory, ParameterSetName = "default",HelpMessage = "Provide the debug Scope.")]
        [ValidateNotNullOrEmpty()]
        [String]$Scope,

        [Parameter (Mandatory, ParameterSetName = "default",HelpMessage = "Provide the component Logger Name.")]
        [ValidateNotNullOrEmpty()]
        [String]$LoggerName,

        [Parameter (Mandatory = $false, ParameterSetName = "default", ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [object]$ApplianceConnection = (${Global:ConnectedSessions} | ? Default)

    )

    Begin 
    {

        [console]::WriteLine()
        Write-Warning "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        Write-Warning "!!! FOR HP SUPPORT USE ONLY. DO NOT USE UNLESS OTHERWISE INSTRUCTED TO BY HP SUPPORT !!!"
        Write-Warning "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        [console]::WriteLine() 

        "[{0}] Bound PS Parameters: {1}"  -f $MyInvocation.InvocationName.ToString().ToUpper(), ($PSBoundParameters | out-string) | Write-Verbose

        $Caller = (Get-PSCallStack)[1].Command

        "[{0}] Called from: {1}" -f $MyInvocation.InvocationName.ToString().ToUpper(), $Caller | Write-Verbose

        "[{0}] Verify auth" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose

        if (-not($ApplianceConnection -is [HPOneView.Appliance.Connection]) -and (-not($ApplianceConnection -is [System.String])))
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException InvalidApplianceConnectionDataType InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter is not type [HPOneView.Appliance.Connection] or [System.String]. Please correct this value and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        elseif  ($ApplianceConnection.Count -gt 1)
        {

            $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException MultipleApplianceConnections InvalidArgument 'ApplianceConnection' -Message 'The specified ApplianceConnection Parameter contains multiple Appliance Connections. This CMDLET only supports 1 Appliance Connection in the ApplianceConnect Parameter value. Please correct this and try again.'
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)

        }

        else
        {

            Try 
            {
    
                $ApplianceConnection = Test-HPOVAuth $ApplianceConnection

            }

            Catch [HPOneview.Appliance.AuthSessionException] 
            {

                $ErrorRecord = New-ErrorRecord HPOneview.Appliance.AuthSessionException NoApplianceConnections AuthenticationError 'ApplianceConnection' -TargetType $ApplianceConnection.GetType().Name -Message $_.Exception.Message -InnerException $_.Exception
                $PSCmdlet.ThrowTerminatingError($ErrorRecord)

            }

            Catch 
            {

                $PSCmdlet.ThrowTerminatingError($_)

            }

        }

        $colStatus = New-Object System.Collections.ArrayList

    }

    Process 
    {

        $_debug = NewObject -ApplianceDebug

        $_debug.scope      = $Scope
        $_debug.loggerName = $LoggerName
        $_debug.level      = 'INFO'

        Write-Verbose "[$($MyInvocation.InvocationName.ToString().ToUpper())] Setting '$Level' at '$Scope`:$LoggerName'"

        Try
        {

            $resp = Send-HPOVRequest $script:applianceDebugLogSetting POST $_debug -Hostname $ApplianceConnection

        }

        Catch
        {

            "Unable to set '{0}:{1}' to '{2}' logging level. Error '{3}'" -f $Scope,$LoggerName,$Level,$_.Exception.Message

            $PSCmdlet.ThrowTerminatingError($_)

        }

        $_Status = "'{0}:{1}' successfully set to '{2}' on Appliance {3}" -f $Scope,$LoggerName,$Level,$ApplianceConnection.Name

        [void]$colStatus.Add($_Status)

    }

    End 
    {

        $colStatus

        Write-Warning "Remember to set '$Scope`:$LoggerName' back to 'INFO' with 'Disable-HPOVDebug $Scope $LoggerName'"

    }

}

# // TODO:
function Enable-HPOVNessusSupport
{


}

# // TODO:
function Disable-HPOVNessusSupport
{



}

########################################################
# PowerShell Filters

filter ColorPattern( [string]$Pattern, [hashtable]$Color) 
{

    $split = $_ -split $Pattern

    $found = [regex]::Matches( $_, $Pattern, 'IgnoreCase' )

    for( $i = 0; $i -lt $split.Count; ++$i ) 
    {

        [ConsoleColor]$displayColor = $Color.keys | % { if ($_ -ieq $found[$i]) { $color[$_]} }
        Write-Host $split[$i] -NoNewline
        Write-Host $found[$i] -NoNewline -ForegroundColor $displayColor

    }

    [console]::WriteLine()

}

filter Convert-IP2Decimal
{

    ([Net.IPAddress][String]([Net.IPAddress]$_)).Address
    
}


filter Convert-Decimal2IP
{

    ([System.Net.IPAddress]$_).IPAddressToString 
    
}

#######################################################
# CMDLET Aliases
set-Alias New-HPOVEnclosure Add-HPOVEnclosure
set-Alias New-HPOVServer Add-HPOVServer 
set-Alias Wait-HPOVTaskAccepted Wait-HPOVTaskStart
set-Alias Get-HPOVServerHardwareTypes Get-HPOVServerHardwareType
set-Alias New-HPOVStorageSystem Add-HPOVStorageSystem
set-Alias New-HPOVSanManager Add-HPOVSanManager
set-Alias New-HPOVStoragePool Add-HPOVStoragePool
#set-Alias New-HPOVPowerDevice Add-HPOVPowerDevice
set-Alias Set-HPOVRole Set-HPOVUserRole
set-Alias Get-HPOVSppFile Get-HPOVBaseline
set-Alias Add-HPOVSppFile Add-HPOVBaseline
set-Alias New-HPOVLdap New-HPOVLdapDirectory
set-Alias Remove-HPOVLdap Remove-HPOVLdapDirectory
set-Alias Get-HPOVProfile Get-HPOVServerProfile
set-Alias New-HPOVAddressRange New-HPOVAddressPoolRange
set-Alias New-HPOVProfile New-HPOVServerProfile
set-Alias Get-HPOVProfileAssign New-HPOVServerProfileAssign
set-Alias Copy-HPOVProfile Copy-HPOVServerProfile
set-Alias Remove-HPOVProfile Remove-HPOVServerProfile 
set-Alias Get-HPOVProfileConnectionList Get-HPOVServerProfileConnectionList
set-Alias New-HPOVProfileConnection New-HPOVServerProfileConnection
set-Alias New-HPOVProfileAttachVolume New-HPOVServerProfileAttachVolume
set-Alias sr Send-HPOVRequest
Set-Alias Show-HPOVBaselineRepositorySize Get-HPOVBaselineRepository

#######################################################
# Export the public functions from this module
# Generic suport functions:
Export-ModuleMember -function Send-HPOVRequest -Alias sr
Export-ModuleMember -function Connect-HPOVMgmt
Export-ModuleMember -function Disconnect-HPOVMgmt
Export-ModuleMember -function Set-HPOVApplianceDefaultConnection
Export-ModuleMember -function Ping-HPOVAddress
Export-ModuleMember -function New-HPOVResource
Export-ModuleMember -function Set-HPOVResource
Export-ModuleMember -function Remove-HPOVResource
Export-ModuleMember -function Wait-HPOVApplianceStart
Export-ModuleMember -function Enable-HPOVDebug
Export-ModuleMember -function Disable-HPOVDebug
Export-ModuleMember -function Get-HPOVRemoteSyslog
Export-ModuleMember -function Set-HPOVRemoteSyslog
Export-ModuleMember -function Enable-HPOVMSDSC
Export-ModuleMember -function Disable-HPOVMSDSC
Export-ModuleMember -function Start-HPOVLibraryTrace
Export-ModuleMember -function Stop-HPOVLibraryTrace
Export-ModuleMember -function Get-HPOVCommandTrace
Export-ModuleMember -function Get-HPOVRemoteSyslog
Export-ModuleMember -function Set-HPOVRemoteSyslog
Export-ModuleMember -function Enable-HPOVRemoteSyslog
Export-ModuleMember -function Disable-HPOVRemoteSyslog
Export-ModuleMember -function Set-HPOVApplianceProxy
Export-ModuleMember -function Invoke-HPOVWebBrowser
Export-ModuleMember -function Show-HPOVActiveUser

#Remote Support:
Export-ModuleMember -function Get-HPOVRemoteSupport
Export-ModuleMember -function Set-HPOVRemoteSupport
Export-ModuleMember -function Get-HPOVRemoteSupportContact
Export-ModuleMember -function New-HPOVRemoteSupportContact
Export-ModuleMember -function Remove-HPOVRemoteSupportContact
Export-ModuleMember -function Get-HPOVRemoteSupportDefaultSite
Export-ModuleMember -function Set-HPOVRemoteSupportDefaultSite
Export-ModuleMember -function Get-HPOVRemoteSupportSetting
Export-ModuleMember -function Set-HPOVRemoteSupportSetting
Export-ModuleMember -function Start-HPOVRemoteSupportCollection
Export-ModuleMember -function Get-HPOVRemoteSupportPartner
Export-ModuleMember -function New-HPOVRemoteSupportPartner
Export-ModuleMember -function Remove-HPOVRemoteSupportPartner
Export-ModuleMember -function Set-HPOVRemoteSupportDataCollectionSchedule
Export-ModuleMember -function Get-HPOVRemoteSupportDataCollectionSchedule
Export-ModuleMember -function Get-HPOVRemoteSupportEntitlementStatus
Export-ModuleMember -function Enable-HPOVRemoteSupport
Export-ModuleMember -function Disable-HPOVRemoteSupport
Export-ModuleMember -function Update-HPOVRemoteSupportEntitlement

#Appliance Configuration:
Export-ModuleMember -function Get-HPOVApplianceCertificateStatus
Export-ModuleMember -function Get-HPOVApplianceDateTime
Export-ModuleMember -function Set-HPOVApplianceDateTime
Export-ModuleMember -function New-HPOVApplianceSelfSignedCertificate
Export-ModuleMember -function New-HPOVApplianceCsr
Export-ModuleMember -function Install-HPOVApplianceCertificate
Export-ModuleMember -function Get-HPOVApplianceTrustedCertificate
Export-ModuleMember -function Add-HPOVApplianceTrustedCertificate
Export-ModuleMember -function Remove-HPOVApplianceTrustedCertificate
Export-ModuleMember -function Get-HPOVVersion
Export-ModuleMember -function Get-HPOVHealthStatus
Export-ModuleMember -function Get-HPOVXApiVersion
Export-ModuleMember -function Get-HPOVEulaStatus
Export-ModuleMember -function Set-HPOVEulaStatus
Export-ModuleMember -function Get-HPOVApplianceNetworkConfig
Export-ModuleMember -function Set-HPOVApplianceNetworkConfig
Export-ModuleMember -function Get-HPOVSnmpReadCommunity 
Export-ModuleMember -function Set-HPOVSnmpReadCommunity 
Export-ModuleMember -function Get-HPOVApplianceGlobalSetting
Export-ModuleMember -function Set-HPOVApplianceGlobalSetting
Export-ModuleMember -function Get-HPOVBaseline -Alias Get-HPOVSppFile
Export-ModuleMember -function Add-HPOVBaseline -Alias Add-HPOVSppFile
Export-ModuleMember -function New-HPOVCustomBaseline
Export-ModuleMember -function Restore-HPOVCustomBaseline
Export-ModuleMember -function Remove-HPOVBaseline
Export-ModuleMember -function Get-HPOVBaselineRepository -Alias Show-HPOVBaselineRepositorySize
Export-ModuleMember -function New-HPOVExternalRepository
Export-ModuleMember -function Set-HPOVExternalRepository
Export-ModuleMember -function Update-HPOVExternalRepository
Export-ModuleMember -function Remove-HPOVExternalRepository
Export-ModuleMember -function New-HPOVSupportDump
Export-ModuleMember -function New-HPOVBackup
Export-ModuleMember -function Get-HPOVBackup
Export-ModuleMember -function Save-HPOVBackup
Export-ModuleMember -function New-HPOVRestore
Export-ModuleMember -function Get-HPOVAutomaticBackupConfig
Export-ModuleMember -function Set-HPOVAutomaticBackupConfig
Export-ModuleMember -function Get-HPOVScmbCertificates
Export-ModuleMember -function Remove-HPOVScmbCertificate
Export-ModuleMember -function Install-HPOVUpdate
Export-ModuleMember -function Get-HPOVPEndingUpdate
Export-ModuleMember -function Remove-HPOVPEndingUpdate
Export-ModuleMember -function Import-HPOVSSLCertificate
Export-ModuleMember -function Restart-HPOVAppliance
Export-ModuleMember -function Stop-HPOVAppliance
Export-ModuleMember -function Get-HPOVComposerNode
Export-ModuleMember -function Enable-HPOVComposerHANode
Export-ModuleMember -function Remove-HPOVStandbyComposerNode
Export-ModuleMember -function Get-HPOVLabel
Export-ModuleMember -function Add-HPOVResourceToLabel
Export-ModuleMember -function Remove-HPOVResourceFromLabel

#Server hardware and enclosures:
Export-ModuleMember -function Get-HPOVServer
Export-ModuleMember -function Add-HPOVServer -Alias New-HPOVServer
Export-ModuleMember -function Set-HPOVServerPower
Export-ModuleMember -function Start-HPOVServer
Export-ModuleMember -function Stop-HPOVServer
Export-ModuleMember -function Restart-HPOVServer
Export-ModuleMember -function Remove-HPOVServer
Export-ModuleMember -function Update-HPOVServer
Export-ModuleMember -function Get-HPOVEnclosure
Export-ModuleMember -function Set-HPOVEnclosure
Export-ModuleMember -function Update-HPOVEnclosure
Export-ModuleMember -function Add-HPOVEnclosure -Alias New-HPOVEnclosure
Export-ModuleMember -function Add-HPOVRemoteFrame
Export-ModuleMember -function New-HPOVLogicalEnclosure
Export-ModuleMember -function Get-HPOVLogicalEnclosure
Export-ModuleMember -function Set-HPOVLogicalEnclosure
Export-ModuleMember -function Update-HPOVLogicalEnclosure 
Export-ModuleMember -function Remove-HPOVLogicalEnclosure
Export-ModuleMember -function Remove-HPOVEnclosure
Export-ModuleMember -function Get-HPOVEnclosureGroup
Export-ModuleMember -function New-HPOVEnclosureGroup
Export-ModuleMember -function Remove-HPOVEnclosureGroup
Export-ModuleMember -function Get-HPOVServerHardwareType -Alias Get-HPOVServerHardwareTypes
Export-ModuleMember -function Show-HPOVFirmwareReport
Export-ModuleMember -function Invoke-HPOVVcmMigration
Export-ModuleMember -function Enable-HPOVDeviceUid
Export-ModuleMember -function Disable-HPOVDeviceUid
Export-ModuleMember -function Set-HPOVEnclosureActiveFLM
Export-ModuleMember -function Reset-HPOVEnclosureDevice
Export-ModuleMember -function Get-HPOVIloSso
Export-ModuleMember -function ConvertTo-HPOVImageStreamerConfiguration
Export-ModuleMember -function Show-HPOVUtilization

#Storage
Export-ModuleMember -function Get-HPOVStorageSystem
Export-ModuleMember -function Update-HPOVStorageSystem
Export-ModuleMember -function Add-HPOVStorageSystem -Alias New-HPOVStorageSystem
Export-ModuleMember -function Remove-HPOVStorageSystem
Export-ModuleMember -function Get-HPOVStoragePool
Export-ModuleMember -function Add-HPOVStoragePool -Alias New-HPOVStoragePool
Export-ModuleMember -function Remove-HPOVStoragePool
Export-ModuleMember -function Get-HPOVStorageVolumeTemplate
Export-ModuleMember -function New-HPOVStorageVolumeTemplate
Export-ModuleMember -function Set-HPOVStorageVolumeTemplate 
Export-ModuleMember -function Remove-HPOVStorageVolumeTemplate
Export-ModuleMember -function Get-HPOVStorageVolumeTemplatePolicy
Export-ModuleMember -function Set-HPOVStorageVolumeTemplatePolicy
Export-ModuleMember -function Get-HPOVStorageVolume
Export-ModuleMember -function New-HPOVStorageVolume
Export-ModuleMember -function Add-HPOVStorageVolume
Export-ModuleMember -function Set-HPOVStorageVolume
Export-ModuleMember -function Remove-HPOVStorageVolume
Export-ModuleMember -function Get-HPOVStorageVolumeSnapshot
Export-ModuleMember -function New-HPOVStorageVolumeSnapShot
Export-ModuleMember -function Remove-HPOVStorageVolumeSnapShot
Export-ModuleMember -function ConvertTo-HPOVStorageVolume
Export-ModuleMember -function Get-HPOVSanManager
Export-ModuleMember -function Add-HPOVSanManager -Alias New-HPOVSanManager
Export-ModuleMember -function Set-HPOVSanManager
Export-ModuleMember -function Update-HPOVSanManager
Export-ModuleMember -function Remove-HPOVSanManager
Export-ModuleMember -function Get-HPOVManagedSan
Export-ModuleMember -function Set-HPOVManagedSan
Export-ModuleMember -function Get-HPOVSanZone
Export-ModuleMember -function Show-HPOVSanEndpoint
Export-ModuleMember -function Get-HPOVDriveEnclosure
Export-ModuleMember -function Get-HPOVAvailableDriveType
Export-ModuleMember -function Get-HPOVSasInterconnectType 

#Unmanaged Devices
Export-ModuleMember -function Get-HPOVUnmanagedDevice
Export-ModuleMember -function New-HPOVUnmanagedDevice 
Export-ModuleMember -function Remove-HPOVUnmanagedDevice 

#Power Devices (iPDUs):
Export-ModuleMember -function Get-HPOVPowerDevice
Export-ModuleMember -function Add-HPOVPowerDevice 
Export-ModuleMember -function Remove-HPOVPowerDevice
Export-ModuleMember -function Get-HPOVPowerPotentialDeviceConnection
Export-ModuleMember -function Get-HPOVPowerPotentialDeviceConnection
Export-ModuleMember -function New-HPOVPowerDevice
Export-ModuleMember -function Add-HPOVPowerDeviceConnection
        
#Networking and Connections:
Export-ModuleMember -function New-HPOVNetwork
Export-ModuleMember -function Get-HPOVNetwork
Export-ModuleMember -function Set-HPOVNetwork
Export-ModuleMember -function Remove-HPOVNetwork
Export-ModuleMember -function New-HPOVNetworkSet
Export-ModuleMember -function Get-HPOVNetworkSet
Export-ModuleMember -function Set-HPOVNetworkSet
Export-ModuleMember -function Remove-HPOVNetworkSet
Export-ModuleMember -function Get-HPOVInterconnect
Export-ModuleMember -function Get-HPOVInterconnectType
Export-ModuleMember -function Get-HPOVLogicalInterconnect
Export-ModuleMember -function Get-HPOVSasLogicalInterconnect
Export-ModuleMember -function Update-HPOVLogicalInterconnect
Export-ModuleMember -function Install-HPOVLogicalInterconnectFirmware
Export-ModuleMember -function Show-HPOVLogicalInterconnectMacTable
Export-ModuleMember -function Show-HPOVPortStatistics
Export-ModuleMember -function Get-HPOVLogicalInterconnectGroup
Export-ModuleMember -function New-HPOVLogicalInterconnectGroup
Export-ModuleMember -function Remove-HPOVLogicalInterconnectGroup
Export-ModuleMember -function New-HPOVQosConfig
Export-ModuleMember -function New-HPOVQosTrafficClass
Export-ModuleMember -function Get-HPOVUplinkSet
Export-ModuleMember -function New-HPOVUplinkSet
Export-ModuleMember -function Get-HPOVAddressPool
Export-ModuleMember -function Get-HPOVAddressPoolRange
Export-ModuleMember -function New-HPOVAddressPoolRange -Alias New-HPOVAddressRange
Export-ModuleMember -function Get-HPOVAddressPoolSubnet
Export-ModuleMember -function New-HPOVAddressPoolSubnet
Export-ModuleMember -function Set-HPOVAddressPoolSubnet
Export-ModuleMember -function Remove-HPOVAddressPoolSubnet
Export-ModuleMember -function Remove-HPOVAddressPoolRange
Export-ModuleMember -function New-HPOVSnmpTrapDestination
Export-ModuleMember -function New-HPOVSnmpConfiguration
Export-ModuleMember -function Get-HPOVSwitchType
Export-ModuleMember -function Get-HPOVLogicalSwitchGroup
Export-ModuleMember -function New-HPOVLogicalSwitchGroup
Export-ModuleMember -function Remove-HPOVLogicalSwitchGroup
Export-ModuleMember -function Get-HPOVLogicalSwitch
Export-ModuleMember -function New-HPOVLogicalSwitch
Export-ModuleMember -function Remove-HPOVLogicalSwitch
Export-ModuleMember -function Update-HPOVLogicalSwitch
Export-ModuleMember -function Get-HPOVSwitch

#I3S (Image Streamer) Support
Export-ModuleMember -function Get-HPOVImageStreamerAppliance
Export-ModuleMember -function Get-HPOVOSDeploymentServer
Export-ModuleMember -function New-HPOVOSDeploymentServer
Export-ModuleMember -function Remove-HPOVOSDeploymentServer
Export-ModuleMember -function Get-HPOVOSDeploymentPlan
Export-ModuleMember -function Get-HPOVOSDeploymentPlanAttribute
        
#Server Profiles:
Export-ModuleMember -function Get-HPOVServerProfile -Alias Get-HPOVProfile
Export-ModuleMember -function New-HPOVServerProfile -Alias New-HPOVProfile
Export-ModuleMember -function Set-HPOVServerProfile
Export-ModuleMember -function New-HPOVServerProfileAssign -Alias Get-HPOVProfileAssign
Export-ModuleMember -function Copy-HPOVServerProfile -Alias Copy-HPOVProfile
Export-ModuleMember -function Remove-HPOVServerProfile -Alias Remove-HPOVProfile
Export-ModuleMember -function Update-HPOVServerProfile
Export-ModuleMember -function Get-HPOVServerProfileConnectionList -Alias Get-HPOVProfileConnectionList
Export-ModuleMember -function Get-HPOVAvailableServerConnections
Export-ModuleMember -function New-HPOVServerProfileConnection -Alias New-HPOVProfileConnection
Export-ModuleMember -function New-HPOVServerProfileAttachVolume -Alias New-HPOVProfileAttachVolume
Export-ModuleMember -function New-HPOVServerProfileTemplate 
Export-ModuleMember -function Set-HPOVServerProfileTemplate 
Export-ModuleMember -function Get-HPOVServerProfileTemplate
Export-ModuleMember -function Join-HPOVServerProfileToTemplate
Export-ModuleMember -function ConvertTo-HPOVServerProfileTemplate
Export-ModuleMember -function Remove-HPOVServerProfileTemplate
Export-ModuleMember -function New-HPOVServerProfileLogicalDisk 
Export-ModuleMember -function New-HPOVServerProfileLogicalDiskController

#Facilities
Export-ModuleMember -function Get-HPOVRack
Export-ModuleMember -function New-HPOVRack
Export-ModuleMember -function Add-HPOVResourceToRack
Export-ModuleMember -function Set-HPOVRackMemberLocation
Export-ModuleMember -function Get-HPOVRackMember
Export-ModuleMember -function Remove-HPOVRackMember
Export-ModuleMember -function Remove-HPOVRack
Export-ModuleMember -function Get-HPOVDatacenter
Export-ModuleMember -function New-HPOVDatacenter
Export-ModuleMember -function Add-HPOVRackToDataCenter
Export-ModuleMember -function Set-HPOVDataCenterRemoteSupport
Export-ModuleMember -function Set-HPOVDatacenter
Export-ModuleMember -function Remove-HPOVDatacenter
    
#Index:
Export-ModuleMember -function Search-HPOVIndex
Export-ModuleMember -function Search-HPOVAssociations

#Tasks:
Export-ModuleMember -function Get-HPOVTask
Export-ModuleMember -function Wait-HPOVTaskStart -Alias Wait-HPOVTaskAccepted
Export-ModuleMember -function Wait-HPOVTaskComplete

#Security:
Export-ModuleMember -function Get-HPOVUser
Export-ModuleMember -function New-HPOVUser
Export-ModuleMember -function Set-HPOVUser
Export-ModuleMember -function Set-HPOVUserPassword
Export-ModuleMember -function Remove-HPOVUser
Export-ModuleMember -function Show-HPOVUserSession
Export-ModuleMember -function Get-HPOVRole
Export-ModuleMember -function Set-HPOVUserRole -Alias Set-HPOVRole
Export-ModuleMember -function Set-HPOVInitialPassword
Export-ModuleMember -function Get-HPOVLdap
Export-ModuleMember -function Get-HPOVLdapDirectory
Export-ModuleMember -function New-HPOVLdapDirectory -Alias New-HPOVLdap
Export-ModuleMember -function Set-HPOVLdapDefaultDirectory 
Export-ModuleMember -function Enable-HPOVLdapLocalLogin
Export-ModuleMember -function Disable-HPOVLdapLocalLogin
Export-ModuleMember -function New-HPOVLdapServer
Export-ModuleMember -function Add-HPOVLdapServer
Export-ModuleMember -function Remove-HPOVLdapServer
Export-ModuleMember -function Set-HPOVLdapGroupRole
Export-ModuleMember -function Remove-HPOVLdapDirectory -Alias Remove-HPOVLdap
Export-ModuleMember -function Show-HPOVLdapGroups
Export-ModuleMember -function Get-HPOVLdapGroup
Export-ModuleMember -function New-HPOVLdapGroup
Export-ModuleMember -function Set-HPOVLdapGroup
Export-ModuleMember -function Remove-HPOVLdapGroup
Export-ModuleMember -function Get-HPOVAuditLog
Export-ModuleMember -function Get-HPOVAuditLogArchive
Export-ModuleMember -function Get-HPOVLoginMessage
Export-ModuleMember -function Set-HPOVLoginMessage
Export-ModuleMember -function Get-HPOVScope
Export-ModuleMember -function New-HPOVScope
Export-ModuleMember -function Remove-HPOVScope
Export-ModuleMember -function Add-HPOVResourceToScope
Export-ModuleMember -function Remove-HPOVResourceFromScope

#Alerts:
Export-ModuleMember -function Get-HPOVAlert
Export-ModuleMember -function Set-HPOVAlert
Export-ModuleMember -function Set-HPOVAlertAssignToUser
Export-ModuleMember -function Clear-HPOVAlert
Export-ModuleMember -function Remove-HPOVAlert
Export-ModuleMember -function Set-HPOVSmtpConfig
Export-ModuleMember -function Get-HPOVSmtpConfig
Export-ModuleMember -function Add-HPOVSmtpAlertEmailFilter
Export-ModuleMember -function Get-HPOVServerProfileMessage
Export-ModuleMember -function Test-HPOVEmailAlert

#Licenses
Export-ModuleMember -function Get-HPOVLicense
Export-ModuleMember -function New-HPOVLicense
Export-ModuleMember -function Remove-HPOVLicense

#######################################################
# Import-Module Processing
#
#Create HPOneView HKCU key
If (-not(Test-Path "HKCU:\Software\Hewlett-Packard\HPOneView")) 
{
     
    New-Item "HKCU:\Software\Hewlett-Packard\HPOneView" -force | Out-Null 

}

#######################################################
# Library Global Settings Init
#

#Needed to support non-Windows PowerShell environments
$private:IsWindows = if (-not (Get-Variable -Name IsWindows -ErrorAction SilentlyContinue)) { $True } else { $IsWindows }

if ($private:IsWindows)
{

    #Check to see if Global Policy is set first.
    $regkeyGlobal = "HKLM:\Software\Hewlett-Packard\HPOneView"
    $regkeyUser   = "HKCU:\Software\Hewlett-Packard\HPOneView" 
    $UserUseMSDSC = [bool](Get-ItemProperty -LiteralPath $regkeyUser -ea SilentlyContinue).'UseMSDSC'
    $PesterRun    = Get-Variable -Name PesterTest -Scope Global -ErrorAction SilentlyContinue

    Write-Verbose "$regkeyUser exists: $(Test-Path $regkeyUser)" -verbose:$script:ModuleVerbose
    Write-Verbose "UseMSDSC Enabled: $($UserUseMSDSC)" -verbose:$script:ModuleVerbose

    #Override Write-Host for MSDSC
    if ((Test-Path $regkeyUser) -and ($UserUseMSDSC)) 
    {
        
        function Write-Host 
        {
            
            [CmdletBinding ()]
            Param
            (

                [Parameter (Mandatory = $false)]
                [Object]$Object,

                [Parameter (Mandatory = $false)]
                [Object]$Object2,

                [Parameter (Mandatory = $false)]
                [Object]$Object3,

                [Switch]$NoNewLine,

                [ConsoleColor]$ForegroundColor,

                [ConsoleColor]$BackgroundColor
        
            )
        
            #Override default Write-Host...
            Write-Verbose $Object -verbose:$script:ModuleVerbose

        }

        function Get-Host 
        {

            [CmdletBinding ()]
            Param()

            Return [PSCustomObject]$Width = @{ UI = @{ RawUI = @{ MaxWindowSize = @{ width = 120 } } } }

        }

    }

}

if ($PesterRun)
{

    function Write-Host 
    {
        
        [CmdletBinding ()]
        Param
        (

            [Parameter (Mandatory = $false)]
            [Object]$Object,

            [Parameter (Mandatory = $false)]
            [Object]$Object2,

            [Parameter (Mandatory = $false)]
            [Object]$Object3,

            [Switch]$NoNewLine,

            [ConsoleColor]$ForegroundColor,

            [ConsoleColor]$BackgroundColor

        )

        #Override default Write-Host...
        Out-Null

    }

}

# Import-Module Text
$_WelcomeTitle = "Welcome to the HPE OneView POSH Library, v{0}" -f $ModuleVersion.ToString()
write-host ""
write-host (" {0}" -f $_WelcomeTitle)
write-host (" {0}" -f (New-Object System.String('-',$_WelcomeTitle.Length)))
write-host ""
write-host " To get a list of available CMDLETs in this library, type : " -NoNewline
write-host "Get-Command -module HPOneView.310" -foregroundcolor yellow
write-host " To get help for a specific command, type: " -NoNewLine
write-host "get-help " -NoNewLine -foregroundcolor yellow
Write-Host "[verb]" -NoNewLine -foregroundcolor red
Write-Host "-HPOV" -NoNewLine -foregroundcolor yellow
Write-Host "[noun]" -foregroundcolor red
write-host " To get extEnded help for a specific command, type: " -NoNewLine
write-host "get-help " -NoNewLine -foregroundcolor yellow
Write-Host "[verb]" -NoNewLine -foregroundcolor red
Write-Host "-HPOV" -NoNewLine -foregroundcolor yellow
Write-Host "[noun]" -NoNewLine -foregroundcolor red
Write-Host " -full" -foregroundcolor yellow
write-host " To update the offline help for this module, type: " -NoNewLine
write-host "Update-Help -module HPOneView.310" -foregroundcolor yellow
Write-Host ""
Write-Host " Module sample scripts are located at: " -NoNewLine
write-host "$(split-path -parent $MyInvocation.MyCommand.Path)\Samples" -ForegroundColor yellow
write-host ""
write-host " If you need further help, please consult one of the following:" -ForegroundColor Green
write-host ""
write-host " * Get-Help about_HPOneView.310"
write-host " * Get-Help about_Appliance_Connections"
Write-host " * Online documentation at https://github.com/HewlettPackard/POSH-HPOneView/wiki"
Write-host " * Online Issues Tracker at https://github.com/HewlettPackard/POSH-HPOneView/issues"
write-host ""
write-host " (C) Copyright 2013-2018 Hewlett Packard Enterprise Development LP "
if ((Get-Host).UI.RawUI.MaxWindowSize.width -lt 150) 
{
    write-host ""
    write-host " Note: Set your PowerShell console width to 150 to properly view report output. (Current Max Width: $((Get-Host).UI.RawUI.MaxWindowSize.width))" -ForegroundColor Green
}
write-host ""

#######################################################
# Remove-Module Processing
#

$ExecutionContext.SessionState.Module.OnRemove = {

    "[{0}] Cleaning up" -f $MyInvocation.InvocationName.ToString().ToUpper() | Write-Verbose -verbose:$script:ModuleVerbose

    'PesterTest','CallStack', 'ConnectedSessions','FCNetworkFabricTypeEnum','GetUplinkSetPortSpeeds','SetUplinkSetPortSpeeds','LogicalInterconnectConsistencyStatusEnum','UplinkSetNetworkTypeEnum','UplinkSetEthNetworkTypeEnum','LogicalInterconnectGroupRedundancyEnum','IgnoreCertPolicy','ResponseErrorObject' | % { Remove-Variable -Name $_ -Scope Global -ErrorAction SilentlyContinue }     

}

# SIG # Begin signature block
# MIIleAYJKoZIhvcNAQcCoIIlaTCCJWUCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCafwIU1kcM8Fzj
# xl4wcD2GFxp3BjA13dNAeC6QE+kC6aCCFhowggVMMIIDNKADAgECAhMzAAAANdjV
# WVsGcUErAAAAAAA1MA0GCSqGSIb3DQEBBQUAMH8xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAMTIE1pY3Jvc29mdCBDb2RlIFZlcmlm
# aWNhdGlvbiBSb290MB4XDTEzMDgxNTIwMjYzMFoXDTIzMDgxNTIwMzYzMFowbzEL
# MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
# cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0
# ZXJuYWwgQ0EgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3
# GjPm8gAELTngTlvtH7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrW
# lymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6s
# YapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpP
# hNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSo
# RcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNC
# bxWyuHv77+ldU9U0WicCAwEAAaOB0DCBzTATBgNVHSUEDDAKBggrBgEFBQcDAzAS
# BgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBStvZh6NLQm9/rEJlTvA73gJMtU
# GjALBgNVHQ8EBAMCAYYwHwYDVR0jBBgwFoAUYvsKIVt/Q24R2glUUGv10pZx8Z4w
# VQYDVR0fBE4wTDBKoEigRoZEaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9j
# cmwvcHJvZHVjdHMvTWljcm9zb2Z0Q29kZVZlcmlmUm9vdC5jcmwwDQYJKoZIhvcN
# AQEFBQADggIBADYrovLhMx/kk/fyaYXGZA7Jm2Mv5HA3mP2U7HvP+KFCRvntak6N
# NGk2BVV6HrutjJlClgbpJagmhL7BvxapfKpbBLf90cD0Ar4o7fV3x5v+OvbowXvT
# gqv6FE7PK8/l1bVIQLGjj4OLrSslU6umNM7yQ/dPLOndHk5atrroOxCZJAC8UP14
# 9uUjqImUk/e3QTA3Sle35kTZyd+ZBapE/HSvgmTMB8sBtgnDLuPoMqe0n0F4x6GE
# NlRi8uwVCsjq0IT48eBr9FYSX5Xg/N23dpP+KUol6QQA8bQRDsmEntsXffUepY42
# KRk6bWxGS9ercCQojQWj2dUk8vig0TyCOdSogg5pOoEJ/Abwx1kzhDaTBkGRIywi
# pacBK1C0KK7bRrBZG4azm4foSU45C20U30wDMB4fX3Su9VtZA1PsmBbg0GI1dRtI
# uH0T5XpIuHdSpAeYJTsGm3pOam9Ehk8UTyd5Jz1Qc0FMnEE+3SkMc7HH+x92DBdl
# BOvSUBCSQUns5AZ9NhVEb4m/aX35TUDBOpi2oH4x0rWuyvtT1T9Qhs1ekzttXXya
# Pz/3qSVYhN0RSQCix8ieN913jm1xi+BbgTRdVLrM9ZNHiG3n71viKOSAG0DkDyrR
# fyMVZVqsmZRDP0ZVJtbE+oiV4pGaoy0Lhd6sjOD5Z3CfcXkCMfdhoinEMIIFajCC
# BFKgAwIBAgIRAMrweR1t1bu9z9KSImtE18gwDQYJKoZIhvcNAQELBQAwfTELMAkG
# A1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMH
# U2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxIzAhBgNVBAMTGkNP
# TU9ETyBSU0EgQ29kZSBTaWduaW5nIENBMB4XDTE3MTEwOTAwMDAwMFoXDTE4MTEw
# OTIzNTk1OVowgdIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQRDAU5NDMwNDELMAkGA1UE
# CAwCQ0ExEjAQBgNVBAcMCVBhbG8gQWx0bzEcMBoGA1UECQwTMzAwMCBIYW5vdmVy
# IFN0cmVldDErMCkGA1UECgwiSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgQ29t
# cGFueTEaMBgGA1UECwwRSFAgQ3liZXIgU2VjdXJpdHkxKzApBgNVBAMMIkhld2xl
# dHQgUGFja2FyZCBFbnRlcnByaXNlIENvbXBhbnkwggEiMA0GCSqGSIb3DQEBAQUA
# A4IBDwAwggEKAoIBAQCfY9MkbYyF0XdnYSEOHfuTNDmCvkzhhNsjbeI9I9/mkvQs
# 2MoyUPKPVNdXom5/FAmY34gOZ1/NEz2Fzbmx1TYfdNyj30iIrXMK5xhSdR3BmAvu
# plWQnlaetJXsjvBJe/DwWYzWolyedV33bFV3owX9GqfkW6b1R4xpnOESfNBh5K7J
# iXKDaK8As++Cx0+f4K77FsTWHflUeao519uIsFbFRxURQjxql0ydx8GpCCzEF6pa
# KQVx/WG7g/368P5GmqxVeH86kN4i1qGudQ+dMLwxdhm3fHNpXBnEOsdGfuWtC2ls
# pBY6LuTNP6fcXBRctJTCH5rA6F+QzhmfmXndMBKzAgMBAAGjggGNMIIBiTAfBgNV
# HSMEGDAWgBQpkWD/ik366/mmarjP+eZLvUnOEjAdBgNVHQ4EFgQUTkSybbkdnXe7
# pkRTy3t6SaDOyKswDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0l
# BAwwCgYIKwYBBQUHAwMwEQYJYIZIAYb4QgEBBAQDAgQQMEYGA1UdIAQ/MD0wOwYM
# KwYBBAGyMQECAQMCMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9k
# by5uZXQvQ1BTMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2Eu
# Y29tL0NPTU9ET1JTQUNvZGVTaWduaW5nQ0EuY3JsMHQGCCsGAQUFBwEBBGgwZjA+
# BggrBgEFBQcwAoYyaHR0cDovL2NydC5jb21vZG9jYS5jb20vQ09NT0RPUlNBQ29k
# ZVNpZ25pbmdDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2Nh
# LmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAByfbvBvqLus0/hnJSNhw5PagGRRWNDwf
# sd09noRqnkpgwbtMoP8tHOCuAbEMqrhSczgkhhk6g3yq4GSno2wnJ4qbPG4SP9zt
# HHluPmHLdEQhRQIJ9bphZiItQzbGIHFbM0W4w/U7OT2CPBZbiZ7EXTknGnkOZmJm
# uwk9MUfzgVPRRFlw0gfV10QW2dRGHCQkxtyBe9yArO3Ha6o/qEKV7GAo5dut/Su4
# NRUaUEFTkz3dcOLJN5oVjiGrhGmzgKIiEos4qxpp4Aqba8RNodgLNi3MGeVwCypm
# bzObZPJGrgAxuP1r4KNBQfG9jj/IQb6XMWm0pIy4Pd8AmFwRsl+jlTCCBXQwggRc
# oAMCAQICECdm7lbrSfOOq9dwovyE3iIwDQYJKoZIhvcNAQEMBQAwbzELMAkGA1UE
# BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBF
# eHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwg
# Q0EgUm9vdDAeFw0wMDA1MzAxMDQ4MzhaFw0yMDA1MzAxMDQ4MzhaMIGFMQswCQYD
# VQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdT
# YWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDErMCkGA1UEAxMiQ09N
# T0RPIFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEB
# BQADggIPADCCAgoCggIBAJHoVJLSClaxrA0k3cXPRGd0mSs3o30jcABxvFPfxPoq
# Eo9LfxBWvZ9wcrdhf8lLDxenPeOwBGHu/xGXx/SGPgr6Plz5k+Y0etkUa+ecs4Wg
# gnp2r3GQ1+z9DfqcbPrfsIL0FH75vsSmL09/mX+1/GdDcr0MANaJ62ss0+2PmBwU
# q37l42782KjkkiTaQ2tiuFX96sG8bLaL8w6NmuSbbGmZ+HhIMEXVreENPEVg/DKW
# USe8Z8PKLrZr6kbHxyCgsR9l3kgIuqROqfKDRjeE6+jMgUhDZ05yKptcvUwbKIpc
# Inu0q5jZ7uBRg8MJRk5tPpn6lRfafDNXQTyNUe0LtlyvLGMa31fIP7zpXcSbr0WZ
# 4qNaJLS6qVY9z2+q/0lYvvCo//S4rek3+7q49As6+ehDQh6J2ITLE/HZu+GJYLiM
# KFasFB2cCudx688O3T2plqFIvTz3r7UNIkzAEYHsVjv206LiW7eyBCJSlYCTaeiO
# TGXxkQMtcHQC6otnFSlpUgK7199QalVGv6CjKGF/cNDDoqosIapHziicBkV2v4IY
# J7TVrrTLUOZr9EyGcTDppt8WhuDY/0Dd+9BCiH+jMzouXB5BEYFjzhhxayvspoq3
# MVw6akfgw3lZ1iAar/JqmKpyvFdK0kuduxD8sExB5e0dPV4onZzMv7NR2qdH5YRT
# AgMBAAGjgfQwgfEwHwYDVR0jBBgwFoAUrb2YejS0Jvf6xCZU7wO94CTLVBowHQYD
# VR0OBBYEFLuvfgI9+qbxPISOre44mOzZMjLUMA4GA1UdDwEB/wQEAwIBhjAPBgNV
# HRMBAf8EBTADAQH/MBEGA1UdIAQKMAgwBgYEVR0gADBEBgNVHR8EPTA7MDmgN6A1
# hjNodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vQWRkVHJ1c3RFeHRlcm5hbENBUm9v
# dC5jcmwwNQYIKwYBBQUHAQEEKTAnMCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC51
# c2VydHJ1c3QuY29tMA0GCSqGSIb3DQEBDAUAA4IBAQBkv4PxX5qF0M24oSlXDeha
# 99HpPvJ2BG7xUnC7Hjz/TQ10asyBgiXTw6AqXUz1uouhbcRUCXXH4ycOXYR5N0AT
# d/W0rBzQO6sXEtbvNBh+K+l506tXRQyvKPrQ2+VQlYi734VXaX2S2FLKc4G/HPPm
# uG5mEQWzHpQtf5GVklnxTM6jkXFMfEcMOwsZ9qGxbIY+XKrELoLL+QeWukhNkPKU
# yKlzousGeyOd3qLzTVWfemFFmBhox15AayP1eXrvjLVri7dvRvR78T1LBNiTgFla
# 4EEkHbKPFWBYR9vvbkb9FfXZX5qz29i45ECzzZc5roW7HY683Ieb0abv8TtvEDhv
# MIIF4DCCA8igAwIBAgIQLnyHzA6TSlL+lP0ct800rzANBgkqhkiG9w0BAQwFADCB
# hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
# A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
# BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTMwNTA5
# MDAwMDAwWhcNMjgwNTA4MjM1OTU5WjB9MQswCQYDVQQGEwJHQjEbMBkGA1UECBMS
# R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
# T01PRE8gQ0EgTGltaXRlZDEjMCEGA1UEAxMaQ09NT0RPIFJTQSBDb2RlIFNpZ25p
# bmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmmJBjd5E0f4rR
# 3elnMRHrzB79MR2zuWJXP5O8W+OfHiQyESdrvFGRp8+eniWzX4GoGA8dHiAwDvth
# e4YJs+P9omidHCydv3Lj5HWg5TUjjsmK7hoMZMfYQqF7tVIDSzqwjiNLS2PgIpQ3
# e9V5kAoUGFEs5v7BEvAcP2FhCoyi3PbDMKrNKBh1SMF5WgjNu4xVjPfUdpA6M0ZQ
# c5hc9IVKaw+A3V7Wvf2pL8Al9fl4141fEMJEVTyQPDFGy3CuB6kK46/BAW+QGiPi
# XzjbxghdR7ODQfAuADcUuRKqeZJSzYcPe9hiKaR+ML0btYxytEjy4+gh+V5MYnmL
# Agaff9ULAgMBAAGjggFRMIIBTTAfBgNVHSMEGDAWgBS7r34CPfqm8TyEjq3uOJjs
# 2TIy1DAdBgNVHQ4EFgQUKZFg/4pN+uv5pmq4z/nmS71JzhIwDgYDVR0PAQH/BAQD
# AgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEQYD
# VR0gBAowCDAGBgRVHSAAMEwGA1UdHwRFMEMwQaA/oD2GO2h0dHA6Ly9jcmwuY29t
# b2RvY2EuY29tL0NPTU9ET1JTQUNlcnRpZmljYXRpb25BdXRob3JpdHkuY3JsMHEG
# CCsGAQUFBwEBBGUwYzA7BggrBgEFBQcwAoYvaHR0cDovL2NydC5jb21vZG9jYS5j
# b20vQ09NT0RPUlNBQWRkVHJ1c3RDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v
# Y3NwLmNvbW9kb2NhLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAAj8COcPu+Mo7id4M
# bU2x8U6ST6/COCwEzMVjEasJY6+rotcCP8xvGcM91hoIlP8l2KmIpysQGuCbsQci
# GlEcOtTh6Qm/5iR0rx57FjFuI+9UUS1SAuJ1CAVM8bdR4VEAxof2bO4QRHZXavHf
# WGshqknUfDdOvf+2dVRAGDZXZxHNTwLk/vPa/HUX2+y392UJI0kfQ1eD6n4gd2HI
# TfK7ZU2o94VFB696aSdlkClAi997OlE5jKgfcHmtbUIgos8MbAOMTM1zB5TnWo46
# BLqioXwfy2M6FafUFRunUkcyqfS/ZEfRqh9TTjIwc8Jvt3iCnVz/RrtrIh2IC/gb
# qjSm/Iz13X9ljIwxVzHQNuxHoc/Li6jvHBhYxQZ3ykubUa9MCEp6j+KjUuKOjswm
# 5LLY5TjCqO3GgZw1a6lYYUoKl7RLQrZVnb6Z53BtWfhtKgx/GWBfDJqIbDCsUgmQ
# Fhv/K53b0CDKieoofjKOGd97SDMe12X4rsn4gxSTdn1k0I7OvjV9/3IxTZ+evR5s
# L6iPDAZQ+4wns3bJ9ObXwzTijIchhmH+v1V04SF3AwpobLvkyanmz1kl63zsRQ55
# ZmjoIs2475iFTZYRPAmK0H+8KCgT+2rKVI2SXM3CZZgGns5IW9S1N5NGQXwH3c/6
# Q++6Z2H/fUnguzB9XIDj5hY5S6cxgg60MIIOsAIBATCBkjB9MQswCQYDVQQGEwJH
# QjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3Jk
# MRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEjMCEGA1UEAxMaQ09NT0RPIFJT
# QSBDb2RlIFNpZ25pbmcgQ0ECEQDK8HkdbdW7vc/SkiJrRNfIMA0GCWCGSAFlAwQC
# AQUAoHwwEAYKKwYBBAGCNwIBDDECMAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcC
# AQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIE
# IKEVoTcLzW+PDWuTPLYlSlyXisY5tDMz2PUUa9k/+eUbMA0GCSqGSIb3DQEBAQUA
# BIIBAIOxbOf3HXmSW2RbFzbV/HjavEMgaPH3ZVdheBtZ3f0TPmXDnjCrSf+co9F+
# MRJFL462BuOBBd6YwoiRNTby3YGtnQU/F+zjRapUPgNfBx7S/XZ6t9itkxdUf3mc
# uzLBQVZp/uypKuYrA5mcGF+pk3059PfQcDA6zuQYVFo1IqMiKW7nzgIGKKRt0RVb
# luCa3hRKz+iEtWwwL15+PeyikvDEJca7hvx0shZXXajTapQ1ElFN5Iu98YtvA6Kv
# 9bKBoHZcp2Rl1x0fbX4hJKNeFYJUhYT50/LmNsAQuKHZB2tvg2XPmDvkRSQhnLX+
# 3Hhxa4bOM1CorDesxRpK38DMMHmhggx0MIIMcAYKKwYBBAGCNwMDATGCDGAwggxc
# BgkqhkiG9w0BBwKgggxNMIIMSQIBAzEPMA0GCWCGSAFlAwQCAQUAMIGvBgsqhkiG
# 9w0BCRABBKCBnwSBnDCBmQIBAQYJKwYBBAGgMgIDMDEwDQYJYIZIAWUDBAIBBQAE
# IDb4pEMuXlFt89Su2wwyBZ1cE8vjP89FjkkLJorBXTkKAhRAIHr1MOFTsiWduijA
# ZiUSR5x96RgPMjAxODA5MTMyMjExMjJaoC+kLTArMSkwJwYDVQQDDCBHbG9iYWxT
# aWduIFRTQSBmb3IgQWR2YW5jZWQgLSBHMqCCCNMwggS2MIIDnqADAgECAgwMp89d
# BwckrInnmjowDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCQkUxGTAXBgNVBAoT
# EEdsb2JhbFNpZ24gbnYtc2ExMTAvBgNVBAMTKEdsb2JhbFNpZ24gVGltZXN0YW1w
# aW5nIENBIC0gU0hBMjU2IC0gRzIwHhcNMTgwMjE5MDAwMDAwWhcNMjkwMzE4MTAw
# MDAwWjArMSkwJwYDVQQDDCBHbG9iYWxTaWduIFRTQSBmb3IgQWR2YW5jZWQgLSBH
# MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALfHkooo2PORy1ANXesp
# RMGCWaXKZM69g7VR5ZTMboCaF2zc/2LmNkNeAcIMZI3Kd572XXdFuV7IJOtBNxFm
# N6zIzXSbzLPvTOJ/G85zvsmWnTUefPdU92zsoBLWrpmdY8R4X1mpLiL1wyfYsltF
# YyeQ/4yxPam08w7A8SBlBomdAxyjsFJBhTTrvMvOVPYS/rMBiUqm+lTFH/vTHMDj
# v5fjP9Ab+UDHG9XrJnxDMMdw8ngRqoVOpQ4NAEo6EXejyiMBgJ7Ik1ZdRsyK2NKq
# CoSFsolb1TLOQXsYTlTKq9FSXhLTJJ5W8wyP3b2SjnnVQYnDo6DlkfzHZ52HM85x
# MnMCAwEAAaOCAagwggGkMA4GA1UdDwEB/wQEAwIHgDBMBgNVHSAERTBDMEEGCSsG
# AQQBoDIBHjA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNv
# bS9yZXBvc2l0b3J5LzAJBgNVHRMEAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMI
# MEYGA1UdHwQ/MD0wO6A5oDeGNWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vZ3Mv
# Z3N0aW1lc3RhbXBpbmdzaGEyZzIuY3JsMIGYBggrBgEFBQcBAQSBizCBiDBIBggr
# BgEFBQcwAoY8aHR0cDovL3NlY3VyZS5nbG9iYWxzaWduLmNvbS9jYWNlcnQvZ3N0
# aW1lc3RhbXBpbmdzaGEyZzIuY3J0MDwGCCsGAQUFBzABhjBodHRwOi8vb2NzcDIu
# Z2xvYmFsc2lnbi5jb20vZ3N0aW1lc3RhbXBpbmdzaGEyZzIwHQYDVR0OBBYEFC1u
# btGN5QOA7udj6afZ2gs8VyI9MB8GA1UdIwQYMBaAFJIhp0qVXWSwm7Qe5gA3R+ad
# QStMMA0GCSqGSIb3DQEBCwUAA4IBAQCN/R0fj4jTZfi1XEbpp9O2P0rLQwXCBw3D
# XgOEIzeoeoyXI/8nnIR9YetcS1c+m/RE24BY97Zl3o8SCl+nh3S32hRAh1Hsn0pH
# VfAX6Bg+cSAx5igiq072rpxrwudE+2gNIH9TP5QboYaCTjIWEFo/iVjB0LTbtpD7
# jTLpoUtGUDe2wzrpKSQSklpOK7m2Cno2jJfA74l8M94x4aGX5OdFrWFS/VqJ01R+
# ik1biXsOlnfR8jw4G9r5pWEgZQK8xa3XDGIQKCzdtuOoYQCsCCajjYXQZMk2kB6K
# UsmHjTWlXUiR/JOmpWXx7Pk63KUsngRtYjP+3vqfxc6vlfNRqPLOMIIEFTCCAv2g
# AwIBAgILBAAAAAABMYnGUAQwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
# YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNV
# BAMTCkdsb2JhbFNpZ24wHhcNMTEwODAyMTAwMDAwWhcNMjkwMzI5MTAwMDAwWjBb
# MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTExMC8GA1UE
# AxMoR2xvYmFsU2lnbiBUaW1lc3RhbXBpbmcgQ0EgLSBTSEEyNTYgLSBHMjCCASIw
# DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKqbjsOrEVElAbaWlOJP2MEI9kYj
# 2UXFlZdbqxq/0mxXyTMGH6APxjx+U0h6v52Hnq/uw4xH4ULs4+OhSmwMF8SmwbnN
# W/EeRImO/gveIVgT7k3IxWcLHLKz8TR2kaLLB203xaBHJgIVpJCRqXme1+tXnSt8
# ItgU1/EHHngiNmt3ea+v+X+OTuG1CDH96u1LcWKMI/EDOY9EebZ2A1eerS8IRtzS
# jLz0jnTOyGhpUXYRiw9dJFsZVD0mzECNgicbWSB9WfaTgI74Kjj9a6BAZR9Xdsxb
# jgRPLKjbhFATT8bci7n43WlMiOucezAm/HpYu1m8FHKSgVe3dsnYgAqAbgkCAwEA
# AaOB6DCB5TAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV
# HQ4EFgQUkiGnSpVdZLCbtB7mADdH5p1BK0wwRwYDVR0gBEAwPjA8BgRVHSAAMDQw
# MgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRv
# cnkvMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5uZXQv
# cm9vdC1yMy5jcmwwHwYDVR0jBBgwFoAUj/BLf6guRSSuTVD6Y5qL3uLdG7wwDQYJ
# KoZIhvcNAQELBQADggEBAARWgkp80M7JvzZm0b41npNsl+gGzjEYWflsQV+ALsBC
# JbgYx/zUsTfEaKDPKGoDdEtjl4V3YTvXL+P1vTOikn0RH56KbO8ssPRijTZz0RY2
# 8bxe7LSAmHj80nZ56OEhlOAfxKLhqmfbs5xz5UAizznO2+Z3lae7ssv2GYadn8jU
# mAWycW9Oda7xPWRqO15ORqYqXQiS8aPzHXS/Yg0jjFwqOJXSwNXNz4jaHyi1uoFp
# ZCq1pqLVc6/cRtsErpHXbsWYutRHxFZ0gEd4WIy+7yv97Gy/0ZT3v1Dge+CQ/SAY
# eBgiXQgujBygl/MdmX2jnZHTBkROBG56HCDjNvC2ULkxggKoMIICpAIBATBrMFsx
# CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTEwLwYDVQQD
# EyhHbG9iYWxTaWduIFRpbWVzdGFtcGluZyBDQSAtIFNIQTI1NiAtIEcyAgwMp89d
# BwckrInnmjowDQYJYIZIAWUDBAIBBQCgggEOMBoGCSqGSIb3DQEJAzENBgsqhkiG
# 9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMTgwOTEzMjIxMTIyWjAvBgkqhkiG9w0B
# CQQxIgQgvxFiudccG/JfRHUugxvpLqYYAyXhaRs5iVSg6OZVM3kwgaAGCyqGSIb3
# DQEJEAIMMYGQMIGNMIGKMIGHBBSbEgV65yqv9tY3crSfaiNvJknNqTBvMF+kXTBb
# MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTExMC8GA1UE
# AxMoR2xvYmFsU2lnbiBUaW1lc3RhbXBpbmcgQ0EgLSBTSEEyNTYgLSBHMgIMDKfP
# XQcHJKyJ55o6MA0GCSqGSIb3DQEBAQUABIIBAE3BhWTROOucd+LggsWZQXpw5gNU
# BNOuRKGOyylmQR3Oj5eA1XgKCd5FHA5cS1SJG7rvqFmQNiSlSxT9W9Tr1Y444MZd
# bNn6kq9Xt4R3ARorygzNdLvb762IMyIeAz485jsAhhk+WPHzUYXMt8G8vAOoTtYS
# N9yAOR2OV0cMmyk74AGPPokn9+D1P+ENXwrDfLZ5oWVvSI3/V1YgPh+owiUa7BGc
# aNpNFv1pDFeaGEOanObnpzGThgH3caOBeT+2rNMhK8E1rulwxiavuy7GMA3FWaaO
# Rkrur+8Vbq3kPyL2AKfLWSTk/dk96LtSOy2MhdpR1AY6WWqfwG8xjc2vTY8=
# SIG # End signature block