# Copyright (c) 2011-2013 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary StorageAggregate ComponentState Module ## @author dl-nacl-dev@netapp.com ## @status shared ## @pod here =head1 NAME NACL::CS::StorageAggregate =head1 DESCRIPTION C is a derived class of L. It represents the state of an ONTAP StorageAggregate. A related class is L, which represents access to an ONTAP StorageAggregate. =head1 ATTRIBUTES The individual pieces of data that are part of the state of the StorageAggregate element are the attributes of the StorageAggregate ComponentState. =over =item C<< aggregate >> The name of the aggregate element whose state is being represented. This is the Primary Key for an aggregate, and is filled in for all modes and interfaces. =item C<< uuid >> Filled in for at least C-mode CLI, C-mode ZAPI, C-mode SNMP, and 7-mode SNMP =item C<< size >> Filled in for at least C-mode CLI, C-mode ZAPI, 7-mode CLI, and 7-mode ZAPI =item C<< usedsize >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode CLI =item C<< percent_used >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< availsize >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode CLI =item C<< state >> Filled in for at least C-mode CLI, C-mode ZAPI, 7-mode CLI, 7-mode ZAPI, C-mode SNMP, and 7-mode SNMP =item C<< capacity >> Filled in for at least 7-mode CLI =item C<< nodes >> (Array) Filled in for at least C-mode CLI, C-mode ZAPI, 7-mode CLI, 7-mode ZAPI, C-mode SNMP, and 7-mode SNMP. (The 7-mode value is faked by getting the hostname of the node being talked to) Maps to: CM ZAPI: $value =item C<< diskcount >> Filled in for at least C-mode CLI, C-mode ZAPI, 7-mode CLI, and 7-mode ZAPI =item C<< disklist >> (Array) Filled in for at least 7-mode CLI =item C<< volcount >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< plexes >> (Array) Filled in for at least C-mode CLI, C-mode ZAPI, 7-mode CLI, and 7-mode ZAPI. Note that for C-mode the value is an array of plex names, while for 7-mode the value has a deep hierarchy of plex, raidgroup, and disk information (see plexes in aggr-list-info in ZAPI). To deal with this inconsistency, we created plexes_cm and plexes_7m, below. =item C<< plexes_cm >> (Array) Filled in for at least C-mode CLI, C-mode ZAPI, 7-mode CLI and 7-mode ZAPI. As "plexes", but will always have the C-mode interpretation (an array containing names of plexes). =item C<< plexes_7m >> (Array) Filled in for 7-mode CLI and 7-mode ZAPI, undef in C-mode. As "plexes", but will always have the 7-mode interpretation or else not be set. =item C<< raidgroups >> (Array) Filled in for at least C-mode CLI and C-mode ZAPI =item C<< raidtype >> Filled in for at least 7-mode CLI, C-mode SNMP, and 7-mode SNMP =item C<< maxraidsize >> Filled in for at least C-mode CLI, C-mode ZAPI, 7-mode CLI, and 7-mode ZAPI (7-mode CLI labels this "raidsize"; ZAPI labels this "raid-size") =item C<< raidstatus >> Filled in for at least C-mode CLI, C-mode ZAPI, 7-mode CLI, 7-mode ZAPI, C-mode SNMP, and 7-mode SNMP. (Note that even though this appears to be a comma-separated string, it really is a comma-separated B. Unlike real array values, it is not coming from an SMF "list" value and not coming from a ZAPI "array") =item C<< chksumenabled >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< chksumstyle >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< chksumstatus >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< inconsistent >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< ignore_inconsistent >> Filled in for at least 7-mode CLI =item C<< raid_block_checksum >> =item C<< raid_zoned_checksum >> =item C<< snapshot_autodelete >> Filled in for at least 7-mode CLI =item C<< thorough_scrub >> Filled in for at least 7-mode CLI =item C<< volume_style >> This field was removed from ONTAP in FS.0. Any scripts invoking this accessor method in FS should be modified to remove the call to this method. Also, "volume-style" should not be passed through requested_fields/filter. Support for this field will be removed from the library soon. Filled in for CMode-CLI/CMode-ZAPI. =item C<< voltype >> This field was removed from ONTAP in FS.0. Any scripts invoking this accessor method in FS should be modified to remove the call to this method. Also, "voltype" should not be passed through requested_fields/filter. Support for this field will be removed from the library soon. Filled in for CMode-CLI/CMode-ZAPI. =item C<< has_mroot >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< has_partner_mroot >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< type >> Filled in for C-mode SNMP and 7-mode SNMP =item C<< volcount_quiesced >> Filled in for at least C-mode ZAPI =item C<< volcount_not_online >> Filled in for at least C-mode ZAPI =item C<< mirror_count_ls_destinations >> =item C<< mirror_count_dp_destinations >> =item C<< mirror_count_move_destinations >> =item C<< mirror_count_dp_qtree_destinations >> =item C<< ha_policy >> Filled in for at least C-mode CLI, C-mode ZAPI, 7-mode CLI, C-mode SNMP, and 7-mode SNMP =item C<< block_type >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode CLI =item C<< volumes >> (Array) Filled in for 7-mode CLI, 7-mode ZAPI, and 7-mode SNMP. This is a 7-mode only, array field which is the list of volumes present in that aggregate. =item C<< raid_status >> =item C<< lost_write_protect >> Filled in for at least 7-mode CLI =item C<< fs_size_fixed >> Filled in for at least 7-mode CLI =item C<< resyncsnaptime >> Filled in for at least 7-mode CLI =item C<< nosnap >> Filled in for at least 7-mode CLI =item C<< snapmirrored >> Filled in for at least 7-mode CLI =item C<< root >> Filled in for at least 7-mode CLI =item C<< diskroot >> Filled in for at least 7-mode CLI =item C<< plex_count >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode CLI =item C<< size_used >> =item C<< upgrade_64bit_added_space >> Filled in for C-mode ZAPI and 7-mode ZAPI. =item C<< upgrade_64bit_cookie >> Filled in for C-mode ZAPI and 7-mode ZAPI. =item C<< upgrade_64bit_check_last_errno >> Filled in for C-mode ZAPI and 7-mode ZAPI. =item C<< upgrade_64bit_is_space_estimate_complete >> Filled in for C-mode ZAPI and 7-mode ZAPI. =item C<< snap_maxfiles_possible >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< percent_snapshot_space >> Filled in for C-mode CLI. =item C<< home_name >> Filled in for C-mode CLI. =item C<< fs_maxfiles_used >> Filled in for at least C-mode CLI and 7-mode ZAPI =item C<< home_id >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< free_space_realloc >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode CLI =item C<< auto_snapshots >> Filled in for C-mode CLI. =item C<< snap_maxfiles_used >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< snap_maxfiles_available >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< diskrpm >> Filled in for C-mode CLI. =item C<< files_total >> Filled in for at least C-mode CLI =item C<< files >> Filled in for at least 7-mode ZAPI and C-mode ZAPI =item C<< files_used >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< snap_mirrored >> Filled in for C-mode CLI. =item C<< snap_size_total >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< upgrade_64bit_is_in_progress >> Filled in for C-mode CLI. =item C<< disksize_in_blks >> Filled in for C-mode CLI. =item C<< filesys_size_fixed >> Filled in for C-mode CLI. =item C<< upgrade_64bit_is_estimate_complete >> Filled in for C-mode CLI. =item C<< isphantom >> Filled in for C-mode CLI. =item C<< owner_name >> Filled in for C-mode CLI and 7-mode SNMP =item C<< disktype >> Filled in for C-mode CLI. =item C<< unmount_volumes >> Filled in for C-mode CLI. =item C<< is_snaplock >> Is Snaplock possible value(s) are, true,false Filled in for CMode CLI/ZAPI iter and 7Mode ZAPI. =item C<< snaplock_type >> Snaplock Type Filled in for CMode CLI/ZAPI iter and 7Mode CLI. =item C<< fsid >> Filled in for at least C-mode CLI, C-mode ZAPI, C-mode SNMP, and 7-mode SNMP =item C<< selected_disks >> Filled in for C-mode CLI. =item C<< fs_inodefile_private_capacity >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< hybrid >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode CLI =item C<< snap_percent_inode_used_capacity >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< raid_lost_write_state >> Filled in for at least C-mode CLI and 7-mode CLI =item C<< keep_same_uuid >> Filled in for C-mode CLI. =item C<< snap_size_available >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< mirror_status >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< allow_mixed >> Filled in for C-mode CLI. =item C<< upgrade_64bit_min_space_for_upgrade >> Filled in for C-mode CLI. =item C<< simulate >> Filled in for C-mode CLI. =item C<< force_spare_pool >> Filled in for C-mode CLI. =item C<< snap_files_used >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< disksize >> Filled in for C-mode CLI. =item C<< resync_snap_time >> Filled in for C-mode CLI. =item C<< raid_lost_write >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< striped_volcount >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< hybrid_cache_size_total >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< member_count >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< snap_files_total >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< fs_total_reserved_space >> Filled in for at least C-mode ZAPI and 7-mode ZAPI Filled in for C-mode CLI. =item C<< group_selection_mode >> Filled in for C-mode CLI. =item C<< fs_inodefile_public_capacity >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< disksize_with_unit >> Filled in for C-mode CLI. =item C<< upgrade_64bit_start_last_errno >> Filled in for C-mode CLI. =item C<< owner_id >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< bad_disks >> Filled in for C-mode CLI. =item C<< snap_size_used >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< hybrid_enabled >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode CLI =item C<< sis_metadata_space_used >> Filled in for C-mode CLI, and 7-mode CLI (from aggr_show_space field "a_sis") =item C<< snap_percent_used_capacity >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< mount_state >> Filled in for C-mode CLI. =item C<< fs_percent_inode_used_capacity >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< force_zcs >> Filled in for C-mode CLI. =item C<< fs_files_private_used >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< fs_maxfiles_possible >> Filled in for at least C-mode CLI, C-mode ZAPI, and 7-mode ZAPI =item C<< rawvolcount >> Filled in for C-mode CLI. =item C<< fs_maxfiles_available >> Filled in for at least C-mode CLI and 7-mode ZAPI =item C<< collective_volcount >> Filled in for at least C-mode CLI and C-mode ZAPI =item C<< allow_mixed_rpms >> Filled in for C-mode CLI. =item C<< mirror >> Filled in for C-mode CLI/ZAPI. Maps to CM ZAPI: $value =item C<< storage_type >> Filled in for C-mode CLI/ZAPI. Maps to CM ZAPI: $value =item C<< dr_home_id >> Filled in for C-mode CLI. =item C<< force_online >> Filled in for C-mode CLI. =item C<< dr_home_name >> Filled in for C-mode CLI. =item C<< plex >> Filled in for C-mode CLI. =item C<< mirror_disklist >> Filled in for C-mode CLI. (Array) Note that for array fields, the accessor method can be invoked in either scalar or list context. my $mirror_disklist = $obj->mirror_disklist(); # $mirror_disklist contains a reference to the array of values my @mirror_disklist = $obj->mirror_disklist(); # @mirror_disklist contains the array of values Filled in for C-mode CLI. =item C<< ignore_pool >> Filled in for C-mode CLI. =item C<< total_space >> Filled in for 7-mode CLI. =item C<< max_write_alloc_blocks >> Filled in for C-mode CLI. =item C<< force_hybrid_enabled >> Filled in for C-mode CLI. =item C<< allow_same_carrier >> Filled in for C-mode CLI. =item C<< allow_mixed_rpm >> Filled in for C-mode CLI. =item C<< is_home >> Filled in for C-mode CLI. =item C<< ignore_pool_checks >> Filled in for C-mode CLI. =item C<< snapshot_reserve >> Filled in for C-mode CLI. =item C<< id >> Filled in for C-mode SNMP and 7-mode SNMP =item C<< volume_footprints_percent >> Volume Data and Metadata Footprint Percent Filled in for C-mode CLI. =item C<< volume_footprints >> Volume Data and Metadata Footprint, possible value(s) are [KB,MB,GB,TB,PB] Filled in for C-mode CLI. =item C<< aggregate_metadata_percent >> Aggregate Metadata Percent Filled in for C-mode CLI. =item C<< aggregate_metadata >> Aggregate Metadata, possible value(s) are [KB,MB,GB,TB,PB] Filled in for C-mode CLI. =item C<< used_including_snapshot_reserve >> Used Including Snapshot Reserve, possible value(s) are [KB,MB,GB,TB,PB] Filled in for C-mode CLI. =item C<< used_including_snapshot_reserve_percent >> Used Percent Including Snapshot Reserve Filled in for C-mode CLI. Filled in for C-mode/7-mode SNMP =item C<< options >> Filled in for C-mode SNMP and 7-mode SNMP =item C<< rowinfo >> Filled in for C-mode SNMP =item C<< wafl_reserve >> Filled in for 7-mode CLI =item C<< smtape >> Filled in for 7-mode CLI =item C<< smtape >> Filled in for 7-mode CLI =item C<< bsr_nvlog >> Filled in for 7-mode CLI =item C<< pre_check_results >> Filled in for CMode CLI. =item C<< pre_check >> Filled in for CMode CLI. =item C<< cache_raid_group_size >> Hybrid Aggregate SSD Tier Maximum RAID Group Size Filled in for CMode CLI, 7Mode-CLI. =item C<< plex_path >> Plex path Filled in for CMode CLI. =item C<< is_online >> Is Online possible value(s) are, true,false Filled in for CMode CLI. =item C<< pool >> Pool ranges from 0 to 1 Filled in for CMode CLI. =item C<< status >> Status Filled in for CMode CLI. =item C<< in_progress >> Resync is in Progress possible value(s) are, true,false Filled in for CMode CLI. =item C<< resync_level >> Resync Level ranges from 0 to 1 Filled in for CMode CLI. =item C<< resyncing_percent >> Resyncing Percentage Filled in for CMode CLI. =item C<< cluster_banner >> Cluster Banner Filled in for CMode CLI. =item C<< selected_mirror_disks >> List of mirrored disks that would be used for Aggregate creation (Array) Note that for array fields, the accessor method can be invoked in either scalar or list context. my $selected_mirror_disks = $obj->selected_mirror_disks(); # $selected_mirror_disks contains a reference to the array of values my @selected_mirror_disks = $obj->selected_mirror_disks(); # @selected_mirror_disks contains the array of values If this field needs to be passed to the filter hash, the value for this field should be passed in as an arrayref # filter => { selected_mirror_disks = [ value1, value2...] } Filled in for CMode CLI. =item C<< cluster_id >> Home Cluster ID Filled in for CMode CLI. =item C<< cluster_state >> Cluster State Filled in for CMode CLI. =item C<< is_MCC >> Is Aggregate Part of MetroCluster Configuration possible value(s) are, true,false Filled in for CMode CLI. =item C<< cluster >> Cluster Filled in for CMode CLI. =item C<< node >> Node possible value(s) are, ,local (Array) Note that for array fields, the accessor method can be invoked in either scalar or list context. my $node = $obj->node(); # $node contains a reference to the array of values my @node = $obj->node(); # @node contains the array of values If this field needs to be passed to the filter hash, the value for this field should be passed in as an arrayref # filter => { node = [ value1, value2...] } Filled in for CMode CLI/ZAPI Maps to: CM ZAPI: $value =item C<< uses_shared_disks >> Uses Shared Disks possible value(s) are, true,false Filled in for CMode CLI. =item C<< is_flash_pool_caching_enabled >> Is Flash Pool Caching possible value(s) are, true,false Filled in for CMode CLI. =item C<< selected_disks_for_shared_pool >> List of disks that would be added to a shared pool during Aggregate creation/addition (Array) Note that for array fields, the accessor method can be invoked in either scalar or list context. my $selected_disks_for_shared_pool = $obj->selected_disks_for_shared_pool(); # $selected_disks_for_shared_pool contains a reference to the array of values my @selected_disks_for_shared_pool = $obj->selected_disks_for_shared_pool(); # @selected_disks_for_shared_pool contains the array of values If this field needs to be passed to the filter hash, the value for this field should be passed in as an arrayref # filter => { selected_disks_for_shared_pool = [ value1, value2...] } Filled in for CMode CLI. =item C<< partitionlist >> Partitions for First Plex (Array) Note that for array fields, the accessor method can be invoked in either scalar or list context. my $partitionlist = $obj->partitionlist(); # $partitionlist contains a reference to the array of values my @partitionlist = $obj->partitionlist(); # @partitionlist contains the array of values If this field needs to be passed to the filter hash, the value for this field should be passed in as an arrayref # filter => { partitionlist = [ value1, value2...] } Filled in for CMode CLI. =item C<< mirror_partitionlist >> partitions for Mirrored Plex (Array) Note that for array fields, the accessor method can be invoked in either scalar or list context. my $mirror_partitionlist = $obj->mirror_partitionlist(); # $mirror_partitionlist contains a reference to the array of values my @mirror_partitionlist = $obj->mirror_partitionlist(); # @mirror_partitionlist contains the array of values If this field needs to be passed to the filter hash, the value for this field should be passed in as an arrayref # filter => { mirror_partitionlist = [ value1, value2...] } Filled in for CMode CLI. =item C<< balancer_state >> Balancer state of aggregate possible value(s) are, disabled , excluded , balanced , unbalanced Filled in for CMode CLI. =item C<< excluded_from_balancer >> Is the Capacity Balancer Excluded possible value(s) are, true,false Filled in for CMode CLI. =item C<< orig_owner >> Original Owner Name Filled in for CMode CLI. =item C<< aggregate_uuid >> UUID Filled in for CMode CLI. =item C<< force_offline >> Force offline Filled in for CMode CLI. =item C<< is_balance_eligible >> Is Eligible for the Balancer possible value(s) are, true,false Filled in for CMode CLI. =item C<< space_full_threshold_percent >> Aggregate Full Threshold Percent Filled in for CMode CLI. =item C<< space_nearly_full_threshold_percent >> Aggregate Nearly Full Threshold Percent Filled in for CMode CLI. =back =cut # Most of the structure is present, but the only data represented # about an aggregate so far is its name. package NACL::CS::StorageAggregate; use strict; use warnings; use Params::Validate qw(validate validate_with SCALAR HASHREF); use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); use NATE::ParamSet qw( param_global); use NACL::ComponentUtils qw(Dumper); use NACL::APISet::Exceptions::InvalidParamValueException qw(:try); use NACL::APISet::Exceptions::ResponseException (); use NACL::C::Exceptions::StorageAggregate::ZsmConnectionError (); use base 'NACL::CS::ComponentState::ONTAP'; use NACL::CS::ComponentState::ZapiSkip qw(make_zapi_skip); use NACL::CS::ComponentState::ZapiArray qw(make_zapi_array); use NACL::C::_Mixins::StorageAggregate qw(:all); use NACL::C::_Mixins::AggregateVolume qw(:all); use NACL::Exceptions::InvalidChoice; use Class::MethodMaker [ scalar => "aggregate", scalar => "uuid", scalar => "size", scalar => "usedsize", scalar => "percent_used", scalar => "availsize", scalar => "state", array => "nodes", scalar => "diskcount", array => "disklist", scalar => "volcount", array => "plexes", array => "raidgroups", scalar => "raidtype", scalar => "maxraidsize", scalar => "raidstatus", scalar => "capacity", scalar => "chksumenabled", scalar => "chksumstatus", scalar => "chksumstyle", scalar => "inconsistent", scalar => "ignore_inconsistent", scalar => "raid_block_checksum", scalar => "raid_zoned_checksum", scalar => "snapshot_autodelete", scalar => "thorough_scrub", scalar => "has_mroot", scalar => "has_partner_mroot", scalar => "iron_status", scalar => "iron_scan_percentage", scalar => "iron_last_start_errno", scalar => "iron_last_start_error_info", scalar => "type", scalar => "volcount_quiesced", scalar => "volcount_not_online", scalar => "mirror_count_ls_destinations", scalar => "mirror_count_dp_destinations", scalar => "mirror_count_move_destinations", scalar => "mirror_count_dp_qtree_destinations", scalar => "ha_policy", scalar => "block_type", scalar => "size_used", # specific to 7Mode array => "volumes", scalar => "lost_write_protect", scalar => "fs_size_fixed", scalar => "resyncsnaptime", scalar => "nosnap", scalar => "snapmirrored", scalar => "root", scalar => "diskroot", scalar => "plex_count", scalar => "is_snaplock", scalar => "files", scalar => "files_used", scalar => 'striping', array => "plexes_7m", array => "plexes_cm", # CMode/7Mode specific scalar => 'upgrade_64bit_added_space', scalar => 'upgrade_64bit_check_last_errno', scalar => 'upgrade_64bit_cookie', scalar => 'upgrade_64bit_is_space_estimate_complete', scalar => 'snap_maxfiles_possible', scalar => 'percent_snapshot_space', scalar => 'home_name', scalar => 'fs_maxfiles_used', scalar => 'home_id', scalar => 'free_space_realloc', scalar => 'auto_snapshots', scalar => 'snap_maxfiles_used', scalar => 'snap_maxfiles_available', scalar => 'diskrpm', scalar => 'files_total', scalar => 'snap_mirrored', scalar => 'snap_size_total', scalar => 'upgrade_64bit_is_in_progress', scalar => 'disksize_in_blks', scalar => 'filesys_size_fixed', scalar => 'upgrade_64bit_is_estimate_complete', scalar => 'isphantom', scalar => 'owner_name', scalar => 'disktype', scalar => 'unmount_volumes', scalar => 'snaplock_type', scalar => 'fsid', scalar => 'selected_disks', scalar => 'fs_inodefile_private_capacity', scalar => 'hybrid', scalar => 'snap_percent_inode_used_capacity', scalar => 'raid_lost_write_state', scalar => 'keep_same_uuid', scalar => 'snap_size_available', scalar => 'mirror_status', scalar => 'allow_mixed', scalar => 'upgrade_64bit_min_space_for_upgrade', scalar => 'simulate', scalar => 'force_spare_pool', scalar => 'snap_files_used', scalar => 'disksize', scalar => 'resync_snap_time', scalar => 'raid_lost_write', scalar => 'striped_volcount', scalar => 'hybrid_cache_size_total', scalar => 'member_count', scalar => 'snap_files_total', scalar => 'fs_total_reserved_space', scalar => 'group_selection_mode', scalar => 'fs_inodefile_public_capacity', scalar => 'disksize_with_unit', scalar => 'upgrade_64bit_start_last_errno', scalar => 'owner_id', scalar => 'bad_disks', scalar => 'snap_size_used', scalar => 'hybrid_enabled', scalar => 'sis_metadata_space_used', scalar => 'snap_percent_used_capacity', scalar => 'mount_state', scalar => 'fs_percent_inode_used_capacity', scalar => 'force_zcs', scalar => 'fs_files_private_used', scalar => 'fs_maxfiles_possible', scalar => 'rawvolcount', scalar => 'fs_maxfiles_available', scalar => 'collective_volcount', scalar => 'allow_mixed_rpms', scalar => 'mirror', scalar => 'dr_home_id', scalar => 'force_online', scalar => 'dr_home_name', scalar => 'plex', array => 'mirror_disklist', scalar => 'ignore_pool', scalar => 'wafl_reserve', scalar => 'smtape', scalar => 'bsr_nvlog', scalar => 'total_space', scalar => 'a_sis', scalar => 'max_write_alloc_blocks', scalar => 'iron_summary_scan_percentage', scalar => 'force_hybrid_enabled', scalar => 'allow_same_carrier', scalar => 'allow_mixed_rpm', scalar => 'is_home', scalar => 'ignore_pool_checks', scalar => 'snapshot_reserve', scalar => 'volume_footprints_percent', scalar => 'volume_footprints', scalar => 'aggregate_metadata_percent', scalar => 'aggregate_metadata', scalar => 'used_including_snapshot_reserve', scalar => 'used_including_snapshot_reserve_percent', # CMode/7Mode SNMP only fields scalar => 'id', scalar => 'options', scalar => 'rowinfo', # CMode ZAPI only fields scalar => 'no_delete_log', scalar => 'i2p_enabled', scalar => 'dlog_hole_reserve', scalar => 'pre_check_results', scalar => 'pre_check', scalar => 'cache_raid_group_size', scalar => 'plex_path', scalar => 'is_online', scalar => 'pool', scalar => 'status', scalar => 'in_progress', scalar => 'resync_level', scalar => 'resyncing_percent', scalar => 'cluster_banner', array => 'selected_mirror_disks', scalar => 'cluster_id', scalar => 'cluster_state', scalar => 'is_MCC', scalar => 'cluster', array => 'node', scalar => 'uses_shared_disks', scalar => 'is_flash_pool_caching_enabled', array => 'selected_disks_for_shared_pool', array => 'partitionlist', array => 'mirror_partitionlist', scalar => 'balancer_state', scalar => 'excluded_from_balancer', scalar => 'orig_owner', scalar => 'aggregate_uuid', scalar => 'force_offline', scalar => 'is_balance_eligible', scalar => 'space_full_threshold_percent', scalar => 'space_nearly_full_threshold_percent', scalar => 'storage_type', ]; # Turn Params::Validate failures into NATE::Exceptions::Argument BEGIN { Params::Validate::validation_options( on_fail => sub { NATE::Exceptions::Argument->throw(shift); } ); } # Unfortunately we can't use -read_cb for MethodMaker because that ends # up getting invoked while storing the value as well (so would result # in one warning per row containing this field). Hence, we need to create # new methods that mimic MethodMaker. # For every scalar field 'foo' defined in MethodMaker, the following methods # get installed: "foo" (in get/set context); "foo_isset"; "foo_reset"; "foo_clear" no strict 'refs'; foreach my $removed_field (qw(volume_style voltype)) { *{$removed_field} = sub { my ($self, $value) = @_; # Method is invoked with a package name to determine the data-type. # Simply returned if invoked without an object instance. return unless ref $self; if ($value) { $self->{$removed_field} = $value; return $value; } else { # Guaranteed to be flex, so default to this value if undef $self->{$removed_field} //= 'flex'; $self->_warn_for_removed_field_accessor($removed_field); return $self->{$removed_field}; } }; *{"${removed_field}_isset"} = sub { exists $_[0]->{$removed_field} }; *{"${removed_field}_reset"} = sub { delete $_[0]->{$removed_field} }; *{"${removed_field}_clear"} = sub { $_[0]->{$removed_field} = undef }; } use strict 'refs'; sub isa { $Log->enter() if $may_enter; my ($pkg_or_obj, $kind) = @_; my $isa = $pkg_or_obj->_build_isa( kind => $kind, alias => 'NACL::CS::Aggregate' ); $Log->exit() if $may_exit; return $isa; } =head1 METHODS =head2 fetch my $aggregate_state = NACL::CS::StorageAggregate->fetch(command_interface=>$ci,...); my @aggregate_states = NACL::CS::StorageAggregate->fetch(command_interface=>$ci,...); see L Uses a CMode CLI or 7Mode CLI or Nodescope CLI or 7Mode ZAPI or CMode ZAPI APISet or CMode SNMP or 7Mode SNMP APISet. The following table provides mapping for the fields of SNMP aggrTable to the corresponding attributes of ComponentState StorageAggregate instance ________________________________________________________________________________ SNMP Field Name - Attribute of StorageAggregate Object _________________________________________________________________________________ aggrIndex - id aggrName - aggregate aggrFSID - fsid aggrOwningHost - owner_name aggrState - state aggrStatus - raidstatus aggrUUID - uuid aggrType - type aggrRaidType - raidtype aggrHAType - ha_policy aggrOwners - nodes aggrOptions - options aggrRowInfo - rowinfo aggrFlexvollist - volumes ________________________________________________________________________________ ComponentState SNMP Attributes ________________________________________________________________________________ Following are the ComponentState StorageAggregate Attributes which are filled in for CMode as well as 7Mode SNMP interfaces =over =item C<< id >> =item C<< aggregate >> =item C<< fsid >> =item C<< state >> =item C<< raidstatus >> =item C<< options >> =item C<< uuid >> =item C<< type >> =item C<< raidtype >> =item C<< "ha_policy" >> =item C<< nodes >> The following fields are filled in for CMode SNMP only =item C<< rowinfo >> The following fields are filled in for 7Mode SNMP only =item C<< owner_name >> =item C<< volumes >> =back =over =item Exceptions =over =item C When there are no elements matching the query specified or elements of that type doesn't exist, then this exception will be thrown. =back =back =cut sub fetch { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my %opts = validate(@args, $pkg->_fetch_validate_spec()); # volume-style, voltype were removed in FS.0 (since striped aggregates # were removed in SN). If these are passed through filter/requested_fields, # log a warning and remove them. # We need to delete the options here because when _apply_filter is called, # it will end up invoking the read accessor method for these fields and # will end up logging warnings for each object. if ( exists $opts{filter}->{'volume-style'} || exists $opts{filter}->{voltype}) { my %filter = %{$opts{filter}}; foreach my $removed_field (qw(volume-style voltype)) { if (exists $opts{filter}->{$removed_field}) { delete $filter{$removed_field}; _warn_for_removed_req_filter_field( type => 'filter', field => $removed_field ); } } $opts{filter} = \%filter; } my %req_field_hash = map { $_ => 1 } @{$opts{requested_fields}}; if ( exists $req_field_hash{'volume-style'} || exists $req_field_hash{voltype}) { foreach my $removed_field (qw(volume-style voltype)) { if (exists $req_field_hash{$removed_field}) { delete $req_field_hash{$removed_field}; _warn_for_removed_req_filter_field( type => 'requested_fields', field => $removed_field ); } } my @requested_fields = keys %req_field_hash; $opts{requested_fields} = \@requested_fields; } my $global_block_type = param_global->get('NACL_SET_AGGREGATE_BLOCK_TYPE'); if($global_block_type) { $Log->comment("Setting block-type filter to '$global_block_type' " . "because parameter 'NACL_SET_AGGREGATE_BLOCK_TYPE' was provided"); $opts{filter}{'block-type'} = $global_block_type; } my @state_objs = $pkg->SUPER::fetch( %opts, choices => [ { method => '_fetch_cmode_cli', interface => 'CLI', set => 'CMode', }, { method => '_fetch_7mode_cli', interface => 'CLI', set => '7Mode|Nodescope', }, { method => '_fetch_7mode_zapi', interface => 'ZAPI', set => '7Mode', }, { method => '_fetch_cmode_zapi', interface => 'ZAPI', set => 'CMode', check => "_check_cmode_zapi", }, { method => '_fetch_cmode_snmp', interface => 'SNMP', set => 'CMode', }, { method => '_fetch_7mode_snmp', interface => 'SNMP', set => '7Mode', }, ], show_cmd => 'storage aggregate show', exception_text => 'No matching storage aggregate(s) found' ); $Log->exit() if $may_exit; return wantarray ? @state_objs : $state_objs[0]; } ## end sub fetch sub _fetch_cmode_cli { my $pkg = shift; my %opts = @_; my @states; try { @states = $pkg->SUPER::_fetch_cmode_cli(%opts, api => 'storage_aggregate_show'); foreach my $state (@states) { $state->plexes_cm($state->plexes()); } } catch NACL::APISet::Exceptions::ResponseException with { my $exception = $_[0]; $Log->exit() if $may_exit; NACL::C::Exceptions::StorageAggregate::ZsmConnectionError ->detect_convert_and_throw(exception => $exception); $exception->throw(); }; return @states; } ## end sub _fetch_cmode_cli sub _fetch_7mode_cli { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my %opts = validate @args, $pkg->_fetch_backend_validate_spec(); my $apiset = $opts{apiset}; my %aggrstatus_args; my %copy_filter = %{$opts{filter}}; my @copy_requested_fields = @{$opts{requested_fields}}; my $deleted_filter = $pkg->_remove_relational_regex_filters( filter => \%copy_filter, requested_fields => \@copy_requested_fields ); my $filter = \%copy_filter; my $requested_fields = \@copy_requested_fields; my $req_field_filter; $req_field_filter->{'requested_fields'} = $requested_fields; $req_field_filter->{'filter'} = \%copy_filter; # The set of options at the end are those which will either eventually # need to be added to copy/map, or are present for backwards # compatibility. my $fields_only_in_verbose = [ qw(raid-lost-write ignore-inconsistent ha-policy free-space-realloc raid-cv lost-write-protect resyncsnaptime fs-size-fixed raidtype snapshot-autodelete thorough-scrub hybrid-enabled nosnap snapmirrored raidsize percent-snapshot-space diskroot free-space-realloc hybrid raid-block-checksum maxraidsize volumes) ]; if ($pkg->_want_any_field_of( %{$req_field_filter}, fields_filled_by_api => $fields_only_in_verbose ) ) { $aggrstatus_args{verbose} = 1; } ## end if ( $pkg->_want_any_field_of... # The only server-side filtering possible in 7-mode is if the # caller limits to one aggregate name, then we can get info on just # that aggregate. Otherwise, we get info on all aggregates and # filter out undesired entries somewhere below. my %aggr_filter; if (defined($filter->{aggregate})) { $aggrstatus_args{aggregate} = $filter->{aggregate}; $aggr_filter{aggregate} = $filter->{aggregate}; } my ($response, $caught_exception); try { $response = $apiset->aggr_status(%aggrstatus_args); } catch NACL::APISet::Exceptions::InvalidParamValueException with { # A caught exception indicates that the aggregate being looked for # does not exist. We catch the exception and return immediately. The # 'fetch' frontend decides whether to throw a NoElementsFound # exception based on the value of 'allow_empty' $caught_exception = 1; }; if ($caught_exception) { $Log->exit() if $may_exit; return; } my $output = $response->get_parsed_output(); my @state_objs; foreach my $row (@$output) { # In the mapping below, the mappings of status and options # to internal fields is to indicate that these are not # copied directly into the state object. They need to be # flattened and remapped my $state_base_field_settings = $pkg->_hash_copy( source => $row, copy => [qw(aggregate volumes state)], map => { 'options' => '_options', 'status' => '_status', }, ); # Fix up _(raid_)status to be an array of states. # XXX I'm making the assumption that 7mode vol status "status" # maps up with ZAPI "raid-status" and my $_raid_status = delete $state_base_field_settings->{_status}; if (defined($_raid_status)) { $state_base_field_settings->{raidstatus} = $_raid_status; # blocktype is extracted from 'raidstatus' => 'raid_dp, aggr, 64-bit' # or from 'raidstatus' => 'raid_dp, aggr, parity uninit'd!, 64-bit' my @raid_status = split(/,/, $_raid_status); my @block_type_arr = grep(/(32-bit)|(64-bit)/, @raid_status); my $block_type = $block_type_arr[0]; if (defined $block_type) { # block-type might not be present in the output if it's a # failed aggregate, so first check if it's defined $block_type =~ s/^\s*//; $block_type =~ s/\s*$//; $state_base_field_settings->{block_type} = $block_type; } # Also determine whether the aggregate is hybrid or not from # the raidstatus if ($_raid_status =~ /\bhybrid\b/) { # If it's hybrid, then it must be hybrid-enabled as well $state_base_field_settings->{hybrid} = 'true'; $state_base_field_settings->{'hybrid-enabled'} = 'true'; } } ## end if ( defined($_raid_status... my $contains_no_volumes = sub { $state_base_field_settings->{volumes} = []; $state_base_field_settings->{volcount} = 0; }; if (defined $state_base_field_settings->{volumes}) { my $_volumes = delete $state_base_field_settings->{volumes}; # If there are no volumes in the aggregate, the field will # be returned with the value ''. If the aggregate is # actually a tradvol then it cannot have volumes within it and # this field will be returned as '' if ( ($_volumes !~ /^\s*\s*$/) && ($_volumes !~ /^\s*\s*$/)) { $state_base_field_settings->{volumes} = [split(/,\s*/, $_volumes)]; $state_base_field_settings->{volcount} = @{$state_base_field_settings->{volumes}}; } else { $contains_no_volumes->(); } } else { $contains_no_volumes->(); } # Flatten and remap "options" hash into regular state fields my $state_option_field_settings = {}; if (defined $state_base_field_settings->{_options}) { my $_options = delete $state_base_field_settings->{_options}; my $options = $_options->[0]; $state_option_field_settings = $pkg->_hash_copy( source => $options, map => {reverse %{_aggr_options_map()}}, copy => _aggr_options_copy(), ); $pkg->_handle_snaplock_type( options => $options, final_hashref => $state_option_field_settings, ); # Add in fields currently not handled by _aggr_options_(map|copy) # These will need to be added at some point $pkg->_hash_copy( source => $options, target => $state_option_field_settings, copy => [qw(fs_size_fixed resyncsnaptime raidtype diskroot)], ); } if (defined $state_option_field_settings->{root}) { $state_option_field_settings->{root} = 'true'; } else { $state_option_field_settings->{root} = 'false'; } if (!defined $state_option_field_settings->{'snaplock-type'}) { $state_option_field_settings->{'snaplock-type'} = 'non-snaplock'; $state_option_field_settings->{'is-snaplock'} = 'false'; } # 7Mode returns the field hybrid_enabled as on/off. In CMode it is # true/false my $hybrid_enabled = $state_option_field_settings->{hybrid_enabled}; if (defined $hybrid_enabled) { if ($hybrid_enabled eq 'on') { $state_option_field_settings->{hybrid_enabled} = 'true'; } else { $state_option_field_settings->{hybrid_enabled} = 'false'; } } ## end if ( defined $hybrid_enabled) my %final_attributes = (%$state_base_field_settings, %$state_option_field_settings); my $obj = $pkg->new(command_interface => $opts{command_interface}); $obj->_set_fields(row => \%final_attributes); push @state_objs, $obj; } ## end foreach my $row (@$output) # Create a hash which has the state objects keyed by aggregate name # so we can quickly determine which state object is to be updated # (speeds up the comparison from O(n^2) to O(n)) my %state_objs_keyed_by_aggr; foreach my $state_obj (@state_objs) { $state_objs_keyed_by_aggr{$state_obj->aggregate()} = $state_obj; } # Certain commands (such as df and aggr show-space) should be run only # on online aggregates. Here, we determine whether to run those commands. # If an aggregate was provided in the filter, then we check if it's online. # If no aggregate was provided in the filter, then we run the commands to # list all aggregates. my $need_to_run_other_cmds = 1; if (exists $aggr_filter{aggregate}) { my $aggr_obj = $state_objs_keyed_by_aggr{$aggr_filter{aggregate}}; if ($aggr_obj->state() ne 'online') { $need_to_run_other_cmds = 0; } } # Fill node info. 7M CLI doesn't give the node name in 'aggr status' # with any of its option. Further CM CLI/ZAPI doesn't clarify whether # 'nodes' field represent the home-node or owner-node (as opposed to # 7M ZAPI). So for now, we will fill in this field for 7M CLI by # finding the hostname of the host which displayed the aggregate on running # 'aggr status' if ($pkg->_want_any_field_of( %{$req_field_filter}, fields_filled_by_api => ['nodes'] ) ) { my $host_response = $apiset->hostname(); my $nodename = $host_response->get_parsed_output()->[0]->{hostname}; foreach my $obj (@state_objs) { $obj->nodes($nodename); } } ## end if ( $pkg->_want_any_field_of... if ($need_to_run_other_cmds) { my $size_fields = [qw(availsize usedsize size capacity)]; if ($pkg->_want_any_field_of( %{$req_field_filter}, fields_filled_by_api => $size_fields ) ) { my %df_args; if (exists $aggr_filter{aggregate}) { $df_args{name} = $aggr_filter{aggregate}; } my $df_status = $apiset->df(aggregate => 1, %df_args); my $df_output = $df_status->get_parsed_output(); foreach my $df_hash_ouput (@$df_output) { my $aggr_name = $df_hash_ouput->{aggregate}; # Skip over snapshot lines next unless (exists $state_objs_keyed_by_aggr{$aggr_name}); my $obj = $state_objs_keyed_by_aggr{$aggr_name}; $obj->availsize($df_hash_ouput->{avail} * 1024); $obj->usedsize($df_hash_ouput->{used} * 1024); $obj->size($df_hash_ouput->{kbytes} * 1024); $obj->capacity($df_hash_ouput->{capacity}); } } if ($pkg->_want_any_field_of( %$req_field_filter, fields_filled_by_api => [qw(wafl_reserve smtape bsr_nvlog total_space a_sis)] ) ) { my $response = $apiset->aggr_show_space(%aggr_filter); my $output = $response->get_parsed_output(); foreach my $row (@$output) { # Extract the object to be updated from the hash next unless ( exists $state_objs_keyed_by_aggr{$row->{aggregate}}); my $obj = $state_objs_keyed_by_aggr{$row->{aggregate}}; my $aggr_show_fields = $pkg->_hash_copy( source => $row->{info}[0], copy => [qw(wafl_reserve smtape total_space)], map => {a_sis => 'sis-metadata-space-used'} ); $obj->_set_fields(row => $aggr_show_fields); } } } # If any of the plexes related information is required, then invoke # "aggr status -r" my $plexes_fields = [qw(plex-count plexes disklist plexes_cm plexes_7m diskcount)]; if ($pkg->_want_any_field_of( %{$req_field_filter}, fields_filled_by_api => $plexes_fields ) ) { my $aggr_status_response = $apiset->aggr_status( 'raid-disk' => 1, %aggr_filter, ); my $aggr_status_output = $aggr_status_response->get_parsed_output(); foreach my $aggr (@{$aggr_status_output->[0]{aggregate}}) { my $aggr_name = $aggr->{aggregate}; if (exists $state_objs_keyed_by_aggr{$aggr_name}) { my $obj = $state_objs_keyed_by_aggr{$aggr_name}; $obj->plex_count(scalar(@{$aggr->{plex}})); # The value of "plexes" attribute is made to look similar to the # value of "plexes" field which is got when the Zapi command # "aggr-list-info" is executed. my @plex_arr; my @plex_arr_cm; my @raid_arr_cm; my @disklist; foreach my $plex_info (@{$aggr->{plex}}) { my $plex; #update plexes_cm my $status_cm = (split /,/, $plex_info->{status})[0]; # Cmode standard for plex "/aggr0/plex0(online)" my $plex_cm = $plex_info->{plex_name} . "(" . $status_cm . ")"; push @plex_arr_cm, $plex_cm; #update plexes and plexes_7m my $status = $plex_info->{status}; $plex->{'is-online'} = ($status =~ /online/) ? 'true' : 'false'; $plex->{status} = $plex_info->{status}; $plex->{name} = $plex_info->{plex_name}; my @raid_arr; foreach my $plex_raid (@{$plex_info->{raid_group}}) { my @disks; my $raid_group_cm = $plex_raid->{raid_group_name}; # update raidgroups # Cmode standard for raidgroups "/aggr0/plex0/rg0 (block)" # 7Mode ouput 'status' => 'normal, block checksums', $plex_raid->{status} =~ /,\s*(\w+)\s*checksums/; $raid_group_cm .= " (" . $1 . ")"; push @raid_arr_cm, $raid_group_cm; foreach my $plex_disk (@{$plex_raid->{disks}}) { my $disk_name; $disk_name->{name} = $plex_disk->{device}; push(@disks, $disk_name); push(@disklist, $plex_disk->{device}); } ## end foreach my $plex_disk ( @{ ... # Getting disklist info $obj->disklist(@disklist); my $obj_diskcount = scalar @disklist; $obj->diskcount($obj_diskcount); my $raid_group; $raid_group->{disks}->[0]->{'disk-info'} = \@disks; $raid_group->{name} = $plex_raid->{raid_group_name}; $raid_group->{status} = $plex_raid->{status}; push(@raid_arr, $raid_group); } ## end foreach my $plex_raid ( @{ ... $plex->{'raid-groups'}->[0]{'raid-group-info'} = \@raid_arr; push(@plex_arr, $plex); } ## end foreach my $plex_info ( @{ ... my $_plex_info; $_plex_info->[0]->{'plex-info'} = \@plex_arr; $obj->plexes(@$_plex_info); $obj->plexes_7m(@$_plex_info); $obj->plexes_cm(@plex_arr_cm); $obj->raidgroups(@raid_arr_cm); } ## end if ( exists $state_objs_keyed_by_aggr... } ## end foreach my $aggr ( @{ $aggr_status_output... # end foreach my $aggr ( @{ $aggr_status_output...}) } ## end if ( $pkg->_want_any_field_of... $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_7mode_cli sub _fetch_7mode_zapi { my $pkg = shift; my %opts = validate @_, $pkg->_fetch_backend_validate_spec(); my $apiset = $opts{apiset}; my %copy_filter = %{$opts{filter}}; my @copy_requested_fields = @{$opts{requested_fields}}; $pkg->_remove_relational_regex_filters( filter => \%copy_filter, requested_fields => \@copy_requested_fields ); my $filter = \%copy_filter; my $requested_fields = \@copy_requested_fields; my %aggr_list_info_args; # The only extra details shown in verbose mode are the plexes # related information. Set 'aggr-list-info' to run in verbose if # any of these fields are required if ($pkg->_want_any_field_of( requested_fields => $requested_fields, filter => $filter, fields_filled_by_api => [ qw(plexes plex-count disklist plexes_7m plexes_cm raidgroups) ] ) ) { $aggr_list_info_args{verbose} = 'true'; } ## end if ( $pkg->_want_any_field_of... # The only server-side filtering possible in ZAPI is if the # caller limits to one aggregate name, then we can get info on just # that aggregate. Otherwise, we get info on all aggregates and # filter out undesired entries somewhere below. if (defined $filter->{aggregate}) { $aggr_list_info_args{aggregate} = $filter->{aggregate}; } my ($aggr_response, $caught_exception); # find all the aggregates present. try { $aggr_response = $apiset->aggr_list_info(%aggr_list_info_args); } catch NACL::APISet::Exceptions::ResponseException with { # A caught exception indicates that the aggregate being looked for # does not exist. We catch the exception and return immediately. The # 'fetch' frontend decides whether to throw a NoElementsFound # exception based on the value of 'allow_empty' $caught_exception = 1; }; return if ($caught_exception); my $aggr_output = $aggr_response->get_parsed_output(); my @state_objs; foreach my $row (@{$aggr_output->[0]{aggregates}[0]{'aggr-info'}}) { my $state_fields = $pkg->_zapi_hash_copy( source => $row, source_has_extra_arrays => 1, copy => [ qw(uuid state striping ha-policy is-snaplock files-used block-type plex-count size-used) ], map => [ "plexes" => "plexes_7m", "checksum-style" => "chksumstyle", "size-percentage-used" => "percent_used", "disk-count" => "diskcount", "name" => "aggregate", 'size-available' => 'availsize', "files-total" => "files", "raid-size" => "maxraidsize", "volume-count" => "volcount", "size-total" => "size", "is-inconsistent" => "inconsistent", "is-checksum-enabled" => "chksumenabled", "raid-status" => "raidstatus", [ "aggregate-space-details", "aggregate-space-info", "aggregate-space", "fs-space-info", "fs-inodefile-public-capacity" ] => "fs_inodefile_public_capacity", [ "aggregate-space-details", "aggregate-space-info", "aggregate-space", "fs-space-info", "fs-total-reserved-space" ] => "fs_total_reserved_space", [ "aggregate-space-details", "aggregate-space-info", "aggregate-space", "fs-space-info", "fs-maxfiles-used" ] => "fs_maxfiles_used", [ "aggregate-space-details", "aggregate-space-info", "aggregate-space", "fs-space-info", "fs-inodefile-private-capacity" ] => "fs_inodefile_private_capacity", [ "aggregate-space-details", "aggregate-space-info", "aggregate-space", "fs-space-info", "fs-percent-inode-used-capacity" ] => "fs_percent_inode_used_capacity", [ "aggregate-space-details", "aggregate-space-info", "aggregate-space", "fs-space-info", "fs-files-private-used" ] => "fs_files_private_used", [ "aggregate-space-details", "aggregate-space-info", "aggregate-space", "fs-space-info", "fs-maxfiles-possible" ] => "fs_maxfiles_possible", [ "aggregate-space-details", "aggregate-space-info", "aggregate-space", "fs-space-info", "fs-maxfiles-available" ] => "fs_maxfiles_available", [ "aggregate-space-details", "aggregate-space-info", "snapshot-space", "snapshot-space-info", "snapshot-maxfiles-possible" ] => "snap_maxfiles_possible", [ "aggregate-space-details", "aggregate-space-info", "snapshot-space", "snapshot-space-info", "snapshot-maxfiles-used" ] => "snap_maxfiles_used", [ "aggregate-space-details", "aggregate-space-info", "snapshot-space", "snapshot-space-info", "snapshot-maxfiles-available" ] => "snap_maxfiles_available", [ "aggregate-space-details", "aggregate-space-info", "snapshot-space", "snapshot-space-info", "snapshot-size-total" ] => "snap_size_total", [ "aggregate-space-details", "aggregate-space-info", "snapshot-space", "snapshot-space-info", "snapshot-percent-inode-used-capacity" ] => "snap_percent_inode_used_capacity", [ "aggregate-space-details", "aggregate-space-info", "snapshot-space", "snapshot-space-info", "snapshot-size-available" ] => "snap_size_available", [ "aggregate-space-details", "aggregate-space-info", "snapshot-space", "snapshot-space-info", "snapshot-files-used" ] => "snap_files_used", [ "aggregate-space-details", "aggregate-space-info", "snapshot-space", "snapshot-space-info", "snapshot-files-total" ] => "snap_files_total", [ "aggregate-space-details", "aggregate-space-info", "snapshot-space", "snapshot-space-info", "snapshot-size-used" ] => "snap_size_used", [ "aggregate-space-details", "aggregate-space-info", "snapshot-space", "snapshot-space-info", "snapshot-percent-used-capacity" ] => "snap_percent_used_capacity", # For 7M CLI, we are filling in the 'nodes' field by finding # the hostname of the host. On takeover, SFO aggregates of the # partner node will be listed by this node as though they # belong to it. Considering this fact, I guess it would be # more appropriate to match 'owner-name' field in the output of # 'aggr-list-info' which is currently owning the disks of this # aggregate rather than 'home-name'. "owner-name" => "nodes", [ "aggr-64bit-upgrade", "aggr-64bit-upgrade-info", "aggr-64bit-upgrade-check-info", "added-space" ] => "upgrade_64bit_added_space", [ "aggr-64bit-upgrade", "aggr-64bit-upgrade-info", "aggr-64bit-upgrade-check-info", "cookie" ] => "upgrade_64bit_cookie", [ "aggr-64bit-upgrade", "aggr-64bit-upgrade-info", "aggr-64bit-upgrade-check-info", "last-errno" ] => "upgrade_64bit_check_last_errno", [ "aggr-64bit-upgrade", "aggr-64bit-upgrade-info", "aggr-64bit-upgrade-check-info", "last-errno" ] => "upgrade_64bit_is_space_estimate_complete", ["wafliron", "aggr-wafliron-info", "last-start-errno"] => "iron_last_start_errno", ["wafliron", "aggr-wafliron-info", "last-start-error-info"] => "iron_last_start_error_info", ["wafliron", "aggr-wafliron-info", "scan-percentage"] => "iron_scan_percentage", ["wafliron", "aggr-wafliron-info", "state"] => "iron_status", ], ); # Fill in the contained volumes if (exists $row->{volumes}) { my $volumes = $row->{volumes}; my @volume_list; if (exists $volumes->[0]{'contained-volume-info'}) { my $contained_vol_info = $volumes->[0]{'contained-volume-info'}; foreach my $contained_volume (@$contained_vol_info) { push @volume_list, $contained_volume->{name}; } } ## end if ( exists $volumes->... $state_fields->{volumes} = \@volume_list; } ## end if ( exists $row->{volumes... if (exists $row->{plexes}[0]{'plex-info'}[0]{'raid-groups'}) { my @disklist; my $_raid_groups = $row->{plexes}[0]{'plex-info'}[0]{'raid-groups'}; foreach my $disk ( @{ $_raid_groups->[0]{'raid-group-info'}[0]{disks}[0] {'disk-info'} } ) { push(@disklist, $disk->{name}); } ## end foreach my $disk ( @{ $_raid_groups... my @plexes_cm; foreach my $plex_cm (@{$state_fields->{'plexes_7m'}[0]{'plex-info'}}) { my $plex_val; if ($plex_cm->{'is-online'} eq 'true') { $plex_val = $plex_cm->{'name'} . '(online)'; } else { $plex_val = $plex_cm->{'name'}; } push @plexes_cm, $plex_val; $state_fields->{plexes_cm} = \@plexes_cm; $state_fields->{plexes} = $state_fields->{plexes_cm}; } ## end foreach my $plex_cm ( @{ $state_fields... $state_fields->{disklist} = \@disklist; my @raid_groups; foreach my $raid_group_cm (@{$_raid_groups->[0]{'raid-group-info'}}) { push @raid_groups, $raid_group_cm->{'name'} . ' (' . $raid_group_cm->{'checksum-style'} . ')'; $state_fields->{raidgroups} = \@raid_groups; } ## end foreach my $raid_group_cm (... } ## end if ( exists $row->{plexes... my $obj = $pkg->new(command_interface => $opts{command_interface}); $obj->_set_fields(row => $state_fields); $obj->_handle_block_type_zapi(); push @state_objs, $obj; } ## end foreach my $row ( @{ $aggr_output... # end foreach my $row ( @{ $aggr_output...}) return @state_objs; } ## end sub _fetch_7mode_zapi sub _fetch_cmode_zapi { $Log->enter() if $may_enter; my ($pkg, @args) = @_; my %opts = validate @args, $pkg->_fetch_backend_validate_spec(); my $apiset = $opts{apiset}; my $filter = $opts{filter}; my $requested_fields = $opts{requested_fields}; if (defined($opts{filter}->{node}) || defined($opts{filter}->{nodes})){ my $attribute; $attribute = 'node' if($opts{filter}->{node}); $attribute = 'nodes' if($opts{filter}->{nodes}); if (!ref($opts{filter}->{$attribute})) { my %filter = %{$opts{filter}}; $filter{$attribute} = [$opts{filter}->{$attribute}]; $opts{filter} = \%filter; } } #<<< begin perltidy format skipping my $map = { # Ordered by ZAPI elements ( in # lib/NACL/APISet/Node/ZAPI/CMode/main/aggr.xml) "upgrade-64bit-added-space" => [ 'aggr-64bit-upgrade-attributes', 'aggr-check-attributes', 'added-space' ], "upgrade-64bit-check-last-errno" => [ 'aggr-64bit-upgrade-attributes', 'aggr-check-attributes', 'check-last-errno' ], "upgrade-64bit-cookie" => [ 'aggr-64bit-upgrade-attributes', 'aggr-check-attributes', 'cookie' ], "upgrade-64bit-is-space-estimate-complete" => [ 'aggr-64bit-upgrade-attributes', 'aggr-check-attributes', 'is-space-estimate-complete' ], "upgrade-64bit-min-space-for-upgrade" => [ 'aggr-64bit-upgrade-attributes', 'aggr-start-attributes', 'min-space-for-upgrade', ], "upgrade-64bit-start-last-errno" => [ 'aggr-64bit-upgrade-attributes', 'aggr-start-attributes', 'start-last-errno' ], "upgrade-64bit-is-in-progress" => [ 'aggr-64bit-upgrade-attributes', 'aggr-status-attributes', 'is-64-bit-upgrade-in-progress' ], "block-type" => [ 'aggr-fs-attributes', 'block-type' ], "fsid" => [ 'aggr-fs-attributes', 'fsid' ], "type" => [ 'aggr-fs-attributes', 'type' ], "fs-files-private-used" => [ 'aggr-inode-attributes', 'fs-files-private-used' ], "files-total" => [ 'aggr-inode-attributes', 'files' ], "files-used" => [ 'aggr-inode-attributes', 'files-used' ], "fs-inodefile-private-capacity" => [ 'aggr-inode-attributes', 'inodefile-private-capacity' ], "fs-inodefile-public-capacity" => [ 'aggr-inode-attributes', 'inodefile-public-capacity' ], "fs-maxfiles-available" => [ 'aggr-inode-attributes', 'maxfiles-available' ], "fs-maxfiles-possible" => [ 'aggr-inode-attributes', 'maxfiles-possible' ], "fs-maxfiles-used" => [ 'aggr-inode-attributes', 'maxfiles-used' ], "fs-percent-inode-used-capacity" => [ 'aggr-inode-attributes', 'percent-inode-used-capacity' ], "home-id" => [ 'aggr-ownership-attributes', 'home-id' ], "home-name" => [ 'aggr-ownership-attributes', 'home-name' ], "owner-id" => [ 'aggr-ownership-attributes', 'owner-id' ], "owner-name" => [ 'aggr-ownership-attributes', 'owner-name' ], "dr-home-id" => [ 'aggr-ownership-attributes', 'dr-home-id' ], "dr-home-name" => [ 'aggr-ownership-attributes', 'dr-home-name' ], "free-space-realloc" => [ 'aggr-performance-attributes', 'free-space-realloc' ], "max-write-alloc-blocks" => [ 'aggr-performance-attributes', 'max-write-alloc-blocks' ], "chksumstatus" => [ 'aggr-raid-attributes', 'checksum-status' ], "chksumstyle" => [ 'aggr-raid-attributes', 'checksum-style' ], "diskcount" => [ 'aggr-raid-attributes', 'disk-count' ], "ha-policy" => [ 'aggr-raid-attributes', 'ha-policy' ], "has-mroot" => [ 'aggr-raid-attributes', 'has-local-root' ], "has-partner-mroot" => [ 'aggr-raid-attributes', 'has-partner-root' ], 'root' => ['aggr-raid-attributes', 'is-root-aggregate'], "chksumenabled" => [ 'aggr-raid-attributes', 'is-checksum-enabled' ], "hybrid" => [ 'aggr-raid-attributes', 'is-hybrid' ], "hybrid-enabled" => [ 'aggr-raid-attributes', 'is-hybrid-enabled' ], "inconsistent" => [ 'aggr-raid-attributes', 'is-inconsistent' ], "mirror-status" => [ 'aggr-raid-attributes', 'mirror-status' ], "mount-state" => [ 'aggr-raid-attributes', 'mount-state' ], "plex-count" => [ 'aggr-raid-attributes', 'plex-count' ], "plexes" => [ 'aggr-raid-attributes', make_zapi_array('plexes'), make_zapi_skip('plex-attributes'), 'plex-name', ], "raidgroups" => [ 'aggr-raid-attributes', make_zapi_array('plexes'), make_zapi_skip('plex-attributes'), make_zapi_array('raidgroups'), make_zapi_skip('raidgroup-attributes'), 'raidgroup-name' ], "raid-lost-write" => [ 'aggr-raid-attributes', 'raid-lost-write-state' ], "raid-lost-write-state" => [ 'aggr-raid-attributes', 'raid-lost-write-state' ], "maxraidsize" => [ 'aggr-raid-attributes', 'raid-size' ], "raidstatus" => [ 'aggr-raid-attributes', 'raid-status' ], "state" => [ 'aggr-raid-attributes', 'state' ], "mirror" => [ 'aggr-raid-attributes', 'is-mirrored' ], "is-snaplock" => [ 'aggr-snaplock-attributes', 'is-snaplock' ], "snaplock-type" => [ 'aggr-snaplock-attributes', 'snaplock-type', ], "snap-files-total" => [ 'aggr-snapshot-attributes', 'files-total' ], "snap-files-used" => [ 'aggr-snapshot-attributes', 'files-used' ], "snap-maxfiles-available" => [ 'aggr-snapshot-attributes', 'maxfiles-available' ], "snap-maxfiles-possible" => [ 'aggr-snapshot-attributes', 'maxfiles-possible' ], "snap-maxfiles-used" => [ 'aggr-snapshot-attributes', 'maxfiles-used' ], "snap-percent-inode-used-capacity" => [ 'aggr-snapshot-attributes', 'percent-inode-used-capacity' ], "snap-percent-used-capacity" => [ 'aggr-snapshot-attributes', 'percent-used-capacity' ], "snap-size-available" => [ 'aggr-snapshot-attributes', 'size-available' ], "snap-size-total" => [ 'aggr-snapshot-attributes', 'size-total' ], "snap-size-used" => [ 'aggr-snapshot-attributes', 'size-used' ], "hybrid-cache-size-total" => [ 'aggr-space-attributes', 'hybrid-cache-size-total' ], "percent-used" => [ 'aggr-space-attributes', 'percent-used-capacity' ], "availsize" => [ 'aggr-space-attributes', 'size-available' ], "size" => [ 'aggr-space-attributes', 'size-total' ], "usedsize" => [ 'aggr-space-attributes', 'size-used' ], "fs-total-reserved-space" => [ 'aggr-space-attributes', 'total-reserved-space' ], "volume-footprints" => [ 'aggr-space-attributes', 'volume-footprints' ], "raid-zoned-checksum" => [ 'aggr-raid-attributes', 'raid-zoned-checksum' ], # I don't know why aggr-striping-attributes isn't listed as a # typedef in the cdef, but let's assume it actually is. "member-count" => [ 'aggr-striping-attributes', 'member-count' ], "volcount" => [ 'aggr-volume-count-attributes', 'flexvol-count' ], "collective-volcount" => [ 'aggr-volume-count-attributes', 'flexvol-count-collective' ], "volcount-not-online" => [ 'aggr-volume-count-attributes', 'flexvol-count-not-online' ], "volcount-quiesced" => [ 'aggr-volume-count-attributes', 'flexvol-count-quiesced' ], "striped-volcount" => [ 'aggr-volume-count-attributes', 'flexvol-count-striped' ], "iron-last-start-errno" => [ 'aggr-wafliron-attributes', 'last-start-errno' ], "iron-last-start-error-info" => [ 'aggr-wafliron-attributes', 'last-start-error-info' ], "iron-scan-percentage" => [ 'aggr-wafliron-attributes', 'scan-percentage' ], "iron-status" => [ 'aggr-wafliron-attributes', 'state' ], "iron-summary-scan-percentage" => [ 'aggr-wafliron-attributes', 'summary-scan-percentage' ], "aggregate" => 'aggregate-name', "uuid" => 'aggregate-uuid', "nodes" => [ make_zapi_array('nodes'), make_zapi_skip('node-name') ], "node" => [ make_zapi_array('nodes'), make_zapi_skip('node-name') ], "raidtype" => [ 'aggr-raid-attributes', 'raid-type' ], "auto-snapshots" => [ 'aggr-snapshot-attributes', 'is-snapshot-auto-create-enabled' ], "storage-type" => [ 'aggr-raid-attributes', 'aggregate-type' ], "striping" => 'striping-type', }; #>>> end perltidy format skipping if (@$requested_fields && (exists $filter->{'is-home'} || grep {$_ eq 'is-home'} @{$opts{requested_fields}})) { my @deep_copy = @{$opts{requested_fields}}; push @deep_copy, ('home-id', 'owner-id'); $opts{requested_fields} = \@deep_copy; } my @states; try { @states = $pkg->SUPER::_fetch_cmode_zapi( %opts, api => 'aggr-get-iter', map => $map, fix_response => sub { my %fix_opts = @_; my $cli = $fix_opts{cli}; my $home_id = $cli->{'home-id'}; my $owner_id = $cli->{'owner-id'}; if (defined $home_id && defined $owner_id) { $cli->{'is-home'} = ($home_id == $owner_id)? "true" : "false"; } }, # is-home does not have a direct mapping, but is constructed # by looking at other fields (home-id, owner-id). Specify to # not look-up the help_xml for this field. inapplicable_for_help_xml => [qw(is-home)], ); } catch NACL::APISet::Exceptions::ResponseException with { my $exception = shift; my $response_obj = $exception->get_response_object(); # The fix for burt 569514 made aggr-get-iter fail when searching # for a non-existant aggregate. In this case it fails with # # We catch this and suppress it (the front-end should decide whether # to turn this into a NoElementsFound or not) if ($response_obj->get_error_number() ne '13040') { $Log->exit() if $may_exit; $exception->throw(); } }; unless (@states) { $Log->exit() if $may_exit; return; } if (exists $filter->{'is-home'}) { # Filter only for is-home (since the ZAPI would not have filtered # it for us). $pkg->_apply_filter( state_objs => \@states, filter => {'is-home' => $filter->{'is-home'}} ); } foreach my $state (@states) { ##ZAPI does not fetch percent_used with '%' sign,hence corrected below if ($state->percent_used_isset()) { my $val = $state->percent_used(); $val = $val.'%'; $state->percent_used($val); } $state->plexes_cm($state->plexes()); } # ZAPI does not return volume-style/voltype; we fill that in by # looking at the value of the "striping" field. For this reason, # a filter for volume-style/voltype will not be done by the ZAPI, # so we do so here. if (exists $filter->{'volume-style'} || exists $filter->{voltype}) { my %vol_style_type_filter; $pkg->_hash_copy( source => $filter, target => \%vol_style_type_filter, copy => [qw(volume-style voltype)], ); $pkg->_apply_filter( state_objs => \@states, filter => \%vol_style_type_filter, ); } my $fields_filled_by_api = [ qw( snapshot-autodelete dlog-hole-reserve filesys-size-fixed ignore-inconsistent lost-write-protect no-delete-log i2p-enabled resyncsnaptime snapmirrored thorough-scrub raid-block-checksum percent-snapshot-space) ]; if ($pkg->_want_any_field_of( requested_fields => $requested_fields, filter => $filter, fields_filled_by_api => $fields_filled_by_api, ) ) { foreach my $state (@states) { try { my $aggr_options_response = $apiset->aggr_options_list_info( aggregate => $state->aggregate() ); my $test_aggr_parsed_op = $aggr_options_response->get_parsed_output(); my %source_hash; foreach my $temp ( @{ $test_aggr_parsed_op->[0]{'options'}[0]{'aggr-option-info'} } ) { my $key = $temp->{'name'}; $key =~ tr/_/-/; $source_hash{$key} = $temp->{'value'}; $source_hash{$key} = $source_hash{$key}.'%' if($key eq 'percent-snapshot-space'); } ## end foreach my $temp ( @{ $test_aggr_parsed_op...}) my %target_hash; $pkg->_hash_copy( source => \%source_hash, copy => $fields_filled_by_api, map => { 'raid-cv' => 'raid-block-checksum', 'no-i2p' => 'i2p-enabled', 'fs-size-fixed' => 'filesys-size-fixed', }, target => \%target_hash, ); #Mapping no-i2p attribute output to the i2p-enabled attribute my @map_options = ('i2p-enabled'); foreach my $option (@map_options) { if ( $target_hash{$option} =~ /off/ ) { $target_hash{$option} = 'on'; } elsif ( $target_hash{$option} =~ /on/ ) { $target_hash{$option} = 'off'; } else { $Log->warn( "Invalid value returned by the aggr_options_list_info ZAPI API for the attribute $option" ); } } ## end foreach my $option (@map_options) $state->_set_fields( row => \%target_hash ); } otherwise{}; } # Filter on the aggr-options-list-info fields my %aggr_info_filter; $pkg->_hash_copy( source => $filter, target => \%aggr_info_filter, copy => $fields_filled_by_api, ); $pkg->_apply_filter( state_objs => \@states, filter => \%aggr_info_filter, ); } $Log->exit() if $may_exit; return @states; } ## end sub _fetch_cmode_zapi sub _update_state_objs_cmode_zapi { $Log->enter() if $may_enter; my ($pkg, @args) = @_; $pkg->SUPER::_update_state_objs_cmode_zapi( @args, zapi_field_translations => { hyphenate_value => [qw(block-type snaplock-type)], }, ); $Log->exit() if $may_exit; } sub _handle_block_type_zapi { $Log->enter() if $may_enter; my $state = $_[0]; if ($state->block_type_isset()) { # ZAPI returns the value as 32_bit, 64_bit, while CLI returns it # as 32-bit, 64-bit. Normalize this. my $val = $state->block_type(); $val =~ s/_/-/g; $state->block_type($val); } $Log->exit() if $may_exit; } sub _fetch_cmode_snmp { $Log->enter() if $may_enter; my $pkg = shift; my %opts = @_; $Log->debug( sub { "This is the args passed _fetch_cmode_snmp" . Dumper(\%opts) }); my $map = { "aggregate" => 'aggrName', "fsid" => 'aggrFSID', "state" => 'aggrState', "raidstatus" => 'aggrStatus', "uuid" => 'aggrUUID', "type" => 'aggrType', "raidtype" => 'aggrRaidType', "ha_policy" => 'aggrHAType', "nodes" => 'aggrOwners', "id" => 'aggrIndex', "options" => 'aggrOptions', "rowinfo" => 'aggrRowInfo' }; my @state_objs = $pkg->SUPER::_fetch_snmp( %opts, map => $map, baseoid => "aggrTable" ); $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_cmode_snmp sub _fetch_7mode_snmp { $Log->enter() if $may_enter; my $pkg = shift; my %opts = @_; $Log->debug( sub { "This is the args passed _fetch_7mode_snmp" . Dumper(\%opts) }); my $map = { "aggregate" => 'aggrName', "fsid" => 'aggrFSID', "owner_name" => 'aggrOwningHost', "state" => 'aggrState', "raidstatus" => 'aggrStatus', "uuid" => 'aggrUUID', "volumes" => 'aggrFlexvollist', "type" => 'aggrType', "raidtype" => 'aggrRaidType', "ha_policy" => 'aggrHAType', "nodes" => 'aggrOwners', "id" => 'aggrIndex', "options" => 'aggrOptions' }; my @state_objs = $pkg->SUPER::_fetch_snmp( %opts, map => $map, baseoid => "aggrTable" ); $Log->exit() if $may_exit; return @state_objs; } ## end sub _fetch_7mode_snmp sub _warn_for_removed_field_accessor { my ($self, $field) = @_; $Log->warn("The option '$field' was removed in FS, but the accessor " . 'method was invoked. Update the script to remove the call ' . 'to this method. Support for this method will be removed from ' . 'the library soon.'); } sub _warn_for_removed_req_filter_field { my %opts = validate_with( params => \@_, spec => { type => {type => SCALAR}, field => {type => SCALAR}, } ); $Log->warn("The field '$opts{field}' was removed in FS, but it was " . "passed through '$opts{type}' in the call to Aggregate->fetch. " . 'Please remove this option from the call because support for ' . 'this option will be removed from the library soon.'); } sub _check_data_type_of_filter { $Log->enter() if $may_enter; my ( $pkg, @args ) = @_; my %opts = validate_with( params => \@args, spec => { filter => {type => HASHREF}, }, allow_extra => 1 ); my %filter = %{ $opts{filter} }; delete $filter{node}; delete $filter{nodes}; $pkg->SUPER::_check_data_type_of_filter( %opts, filter => \%filter ); $Log->exit() if $may_exit; } sub _check_cmode_zapi { $Log->enter() if $may_enter; my ( $pkg, %opts ) = @_; my $filter = $opts{filter}; my @requested = @{$opts{requested_fields}}; if ('disklist' ~~ @requested || defined $filter->{'disklist'}) { $Log->exit() if $may_exit; NACL::Exceptions::InvalidChoice->throw("'disklist' is not supported " . "by 'aggr-get-iter' ZAPI in NACL::CS::StorageAggregate, hence ZAPI cannot be used. "); } $Log->exit() if $may_exit; } =head1 CANNED FILTERS See http://wikid.netapp.com/w/QA/projects/Libraries_Initiative/Project/Common_Infrastructure/Users_Guide/Component_Layer_Users_Guide#Canned_filters for a description of canned filters. =head2 online Returns aggregates which are online. =cut sub _canned_filter_online { return {state => 'online'}; } =head2 root Returns the root aggregate. =cut sub _canned_filter_root { return {root => 'true'}; } =head2 not_root Returns all the non-root aggregates. =cut sub _canned_filter_not_root { return {root => 'false'}; } =head2 online_not_root Returns all the online, non-root aggregates. =cut sub _canned_filter_online_not_root { return {state => 'online', root => 'false'}; } =head2 online_not_root_64_bit Returns all the online, non-root, 64 bit aggregates. =cut sub _canned_filter_online_not_root_64_bit { return {state => 'online', root => 'false', 'block-type' => '64-bit'}; } =head2 online_not_root_32_bit Returns all the online, non-root, 32 bit aggregates. =cut sub _canned_filter_online_not_root_32_bit { return {state => 'online', root => 'false', 'block-type' => '32-bit'}; } =head2 64_bit Returns all 64-bit aggregates. =cut sub _canned_filter_64_bit { return {'block-type' => '64-bit'}; } =head2 32_bit Returns all 32-bit aggregates. =cut sub _canned_filter_32_bit { return {'block-type' => '32-bit'}; } 1;