# # Copyright (c) 2013 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary LV ComponentState Module ## @author praveent@netapp.com, dl-nacl-dev@netapp.com ## @status shared ## @pod here ################################################################################ =head1 NAME NACL::CS::Client::LV =head1 DESCRIPTION C is a derived class of L. It represents the state of LV element. A related class is L, which represents access to a LV element. =head1 ATTRIBUTES The individual pieces of data that are part of the state of the LV element are the individual attributes of the LV ComponentState =over =item C<< "cow_table_le" >> Filled in for Linux CLI. =item C<< "lv_size" >> Filled in for Linux CLI. =item C<< "vg_name" >> Filled in for Linux CLI. =item C<< "segments" >> Filled in for Linux CLI. =item C<< "read_ahead_sectors" >> Filled in for Linux CLI. =item C<< "currently_set_to" >> Filled in for Linux CLI. =item C<< "snapshot_chunk_size" >> Filled in for Linux CLI. =item C<< "lv_name" >> Filled in for Linux CLI. =item C<< "lv_snapshot_status" >> Filled in for Linux CLI. =item C<< "lv_uuid" >> Filled in for Linux CLI. =item C<< "allocation" >> Filled in for Linux CLI. =item C<< "lv_write_access" >> Filled in for Linux CLI. =item C<< "lv_status" >> Filled in for Linux CLI. =item C<< "allocated_to_snapshot" >> Filled in for Linux CLI. =item C<< "open_count_of_lv" >> Filled in for Linux CLI. =item C<< "block_device" >> Filled in for Linux CLI. =item C<< "current_le" >> Filled in for Linux CLI. =item C<< "cow_table_size" >> Filled in for Linux CLI. =item C<< "time" >> Filled in for Linux CLI. =item C<< "lv_creation_host" >> Filled in for Linux CLI. =item C<< "lv_path" >> Filled in for Linux CLI. =item C<< "lvsize_in_sectors" >> Filled in for Linux CLI. =item C<< "minor_dev_num_of_lv" >> Filled in for Linux CLI. =item C<< "allocated_le_of_lv" >> Filled in for Linux CLI. =item C<< "current_le_associated_to_lv" >> Filled in for Linux CLI. =item C<< "lv_acess" >> Filled in for Linux CLI. =item C<< "internal_lv_number" >> Filled in for Linux CLI. =item C<< "alloc_policy_of_lv" >> Filled in for Linux CLI. =item C<< "major_dev_num_of_lv" >> Filled in for Linux CLI. =item C<< "physical_volume" >> Filled in for Linux CLI. =item C<< "physical_extents" >> Filled in for Linux CLI. =item C<< "stripes" >> Filled in for Linux CLI. =item C<< "stripe_size" >> Filled in for Linux CLI. =item C<< "type" >> Filled in for Linux CLI. =item C<< "convert" >> Filled in for Linux CLI. =item C<< "move" >> Filled in for Linux CLI. =item C<< "origin" >> Filled in for Linux CLI. =item C<< "data" >> Filled in for Linux CLI. =item C<< "attr" >> Filled in for Linux CLI. =item C<< "copy" >> Filled in for Linux CLI. =item C<< "pool" >> Filled in for Linux CLI. =item C<< "log" >> Filled in for Linux CLI. =item C<< "snap" >> Filled in for Linux CLI. =item C<< "logical_volumes" >> (Array) Note that for array fields, the accessor method can be invoked in either scalar or list context. my $logical_volumes = $obj->logical_volumes(); $logical_volumes contains a reference to the array of values my @logical_volumes = $obj->logical_volumes(); @logical_volumes contains the array of values Filled in for Linux CLI. =item C<< "stripes_info" >> (Array) Note that for array fields, the accessor method can be invoked in either scalar or list context. my $stripes_info = $obj->stripes_info(); $stripes_info contains a reference to the array of values my @stripes_info = $obj->stripes_info(); @stripes_info contains the array of values Filled in for Linux CLI. =back =cut ################### # Package package NACL::CS::Client::LV; ################### # Everytime use strict; use warnings; ################### # Module includes use Params::Validate qw (validate validate_with HASHREF ARRAYREF OBJECT); use NACL::ComponentUtils qw (_optional_scalars Dumper); use NACL::APISet::Exceptions::UnexpectedOutputException qw(:try); use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); use base 'NACL::CS::ComponentState::Client'; use Class::MethodMaker [ scalar => "cow_table_le", scalar => "lv_size", scalar => "vg_name", scalar => "segments", scalar => "read_ahead_sectors", scalar => "currently_set_to", scalar => "snapshot_chunk_size", scalar => "lv_name", scalar => "lv_snapshot_status", scalar => "lv_uuid", scalar => "allocation", scalar => "lv_write_access", scalar => "lv_status", scalar => "allocated_to_snapshot", scalar => "open_count_of_lv", scalar => "block_device", scalar => "current_le", scalar => "cow_table_size", scalar => "time", scalar => "lv_creation_host", scalar => "lv_path", scalar => "lvsize_in_sectors", scalar => "minor_dev_num_of_lv", scalar => "allocated_le_of_lv", scalar => "current_le_associated_to_lv", scalar => "lv_acess", scalar => "internal_lv_number", scalar => "alloc_policy_of_lv", scalar => "major_dev_num_of_lv", scalar => "physical_volume", scalar => "physical_extents", scalar => "stripes", scalar => "stripe_size", scalar => "type", scalar => "convert", scalar => "move", scalar => "origin", scalar => "data", scalar => "attr", scalar => "copy", scalar => "pool", scalar => "log", scalar => "snap", array => "logical_volumes", array => "stripes_info", ]; =head1 METHODS =head2 fetch my $logical_volumes = NACL::CS::Client::LV->fetch(command_interface=>$ci,...); my @logical_volumes = NACL::CS::Client::LV->fetch(command_interface=>$ci,...); see L Supports Linux CLI. Invokes "lvdisplay" command for Linux CLI. =cut sub fetch { $Log->enter(); my ($pkg, @opts) = @_; my @state_objs = $pkg->SUPER::fetch( @opts, choices => [ { method => "_fetch_linux_cli", interface => "CLI", set => 'Linux' }, ], exception_text => 'No logical volume found' ); $Log->exit(); return wantarray ? @state_objs : $state_objs[0]; } ## end sub fetch sub _fetch_linux_cli { $Log->enter(); my ( $pkg, @opts ) = @_; my %opts = validate @opts, $pkg->_fetch_backend_validate_spec(); my $apiset = $opts{apiset}; my $requested_fields = $opts{requested_fields}; my $filter = $opts{filter}; my ( @lvdisplay_args, @state_objs, @final_object ); # Provide a large timeout so that the command will not timeout if there is # a lot of output to display my $timeout = $opts{'timeout'} || 1200; push @lvdisplay_args, ( 'connectrec-timeout' => $timeout ); my @orig_requested_fields = @{ $opts{requested_fields} }; my %orig_filter = %{ $opts{filter} }; $pkg->_remove_relational_regex_filters( filter => \%orig_filter, requested_fields => \@orig_requested_fields ); $requested_fields = \@orig_requested_fields; $filter = \%orig_filter; my ( $response, $caught_exception, $obj, $lvpath ); my %temp_hash; $lvpath = $pkg->_construct_lvpath( filter => $filter); push @lvdisplay_args, ( "lv-path" => $lvpath ); try { $response = $apiset->lvdisplay(@lvdisplay_args); } catch NACL::APISet::Exceptions::UnexpectedOutputException with { # A caught exception indicates that the device 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(); return; } my $output = $response->get_parsed_output(); foreach my $row (@$output) { my $state_base_field_settings = $pkg->_hash_copy( source => $row, copy => [qw( cow_table_le lv_size vg_name segments read_ahead_sectors currently_set_to snapshot_chunk_size lv_name lv_snapshot_status lv_uuid allocation lv_write_access lv_status allocated_to_snapshot open_count_of_lv block_device current_le cow_table_size time lv_creation_host )], ); $obj = $pkg->new(command_interface => $opts{command_interface}); $obj->_set_fields(row => $state_base_field_settings); push @state_objs, $obj; } ## end foreach my $row (@$output) my %commands = $pkg->_handle_commands_returning_common_fields( common_fields => [qw( cow_table_le lv_size vg_name segments segments currently_set_to snapshot_chunk_size lv_name lv_snapshot_status lv_uuid allocation lv_write_access lv_status allocated_to_snapshot open_count_of_lv block_device current_le cow_table_size time lv_creation_host lv_path )], commands => { 'lvdisplay_colon' => [ qw( lvsize_in_sectors minor_dev_num_of_lv allocated_le_of_lv current_le_associated_to_lv lv_acess internal_lv_number alloc_policy_of_lv major_dev_num_of_lv ) ], 'lvdisplay_Columns' => [ qw( convert move origin data attr copy pool log snap ) ], 'lvdisplay_maps' => [ qw( physical_volume physical_extents stripes stripe_size type stripes_info ) ], 'lvdisplay_verbose' => [ qw( logical_volumes ) ], }, preferred_command => 'lvdisplay', requested_fields => $requested_fields, filter => $filter ); if ( exists $commands{'lvdisplay_colon'} ) { my @show_args; push @show_args, ('colon' => 1); $lvpath = $pkg->_construct_lvpath( filter => $filter); push @show_args, ( "lv-path" => $lvpath ); my $lvdisplay_response = $apiset->lvdisplay(@show_args); my $lvdisplay_show_output = $lvdisplay_response->get_parsed_output(); foreach my $show_info (@{$lvdisplay_show_output}) { my $device_info = $pkg->_hash_copy( source => $show_info, copy => [qw( lvsize_in_sectors minor_dev_num_of_lv allocated_le_of_lv current_le_associated_to_lv lv_acess internal_lv_number alloc_policy_of_lv major_dev_num_of_lv )], ); $obj->_set_fields(row => $device_info); push @state_objs, $obj; } } if ( exists $commands{'lvdisplay_Columns'} ) { my @show_args; push @show_args, ('columns' => 1); $lvpath = $pkg->_construct_lvpath( filter => $filter); push @show_args, ( "lv-path" => $lvpath ); my $lvdisplay_response = $apiset->lvdisplay(@show_args); my $lvdisplay_show_output = $lvdisplay_response->get_parsed_output(); foreach my $show_info (@{$lvdisplay_show_output}) { my $device_info = $pkg->_hash_copy( source => $show_info, copy => [qw( convert move origin data attr copy pool log snap )], ); $obj->_set_fields(row => $device_info); push @state_objs, $obj; } } if ( exists $commands{'lvdisplay_maps'} ) { my @show_args; push @show_args, ('maps' => 1); $lvpath = $pkg->_construct_lvpath( filter => $filter); push @show_args, ( "lv-path" => $lvpath ); my $lvdisplay_response = $apiset->lvdisplay(@show_args); my $lvdisplay_show_output = $lvdisplay_response->get_parsed_output(); foreach my $show_info (@{$lvdisplay_show_output}) { my $device_info = $pkg->_hash_copy( source => $show_info, copy => [qw( physical_volume physical_extents stripes stripe_size type stripes_info )], ); $obj->_set_fields(row => $device_info); push @state_objs, $obj; } } if ( exists $commands{'lvdisplay_verbose'} ) { my @show_args; push @show_args, ('verbose' => 1); $lvpath = $pkg->_construct_lvpath( filter => $filter); push @show_args, ( "lv-path" => $lvpath ); my $lvdisplay_response = $apiset->lvdisplay(@show_args); my $lvdisplay_show_output = $lvdisplay_response->get_parsed_output(); foreach my $show_info (@{$lvdisplay_show_output}) { my $device_info = $pkg->_hash_copy( source => $show_info, copy => [qw( logical_volumes )], ); $obj->_set_fields(row => $device_info); push @state_objs, $obj; } } $Log->exit(); return @state_objs; } sub _construct_lvpath { $Log->enter(); my ($pkg, %hash) = @_; my $filter = $hash{'filter'}; my $lvpath; if ($filter->{lv_name} =~ /^\/dev\/.+?\/.+?$/) { $lvpath = $filter->{lv_name}; } elsif ( defined ($filter->{lv_name} && $filter->{vg_name}) ) { $lvpath = "/dev/$filter->{vg_name}/$filter->{lv_name}"; } $Log->exit(); return $lvpath; } 1;