# # Copyright (c) 2011 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. ## @summary VserverSetup Task Module ## @author dl-nacl-dev@netapp.com ## @status shared ## @pod here =head1 NAME NACL::MTask::VserverSetup =head1 DESCRIPTION C provides a number of well-defined but potentially complex or multi-step methods related to VserverSetup in ONTAP. The Mtask Will perform following steps in order to complete the setup - 1. Create Aggregate associated with the vserver. 2. Create vserver on the node. 3. Create Vserver interfaces. 4. Create a default unix-user and unix-group (for root and nobody) 5. Create vserver name-mapping if security-style is 'mixed' 6. Create Vserver nfs 7. Create exportruleset 8. Create open-access rule. 9. Setting and unlocking password for the vsadmin account =head1 ATTRIBUTES =head2 vserver_obj Object return by the Vserver->create() task =head2 aggr_obj Object return by the Aggregate->create() task =head2 data_lif_obj Object return by the NetworkInterface->create() task =head2 nfs_obj Object return by the VserverNfs->create() task =head2 routing_grp_obj Object return by the NetworkRoutingGroupsRoute->create() task =head2 export_rule_obj Object return by the ExportPolicy->create() component =head2 export_policy_rule_obj Object return by the ExportPolicyRule->create() component =cut package NACL::MTask::VserverSetup; use base qw(NACL::MTask::MTask); use strict; use warnings; use Params::Validate qw(validate_with :types); use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); use NACL::STask::Vserver; use NACL::STask::Aggregate; use NACL::STask::VserverNfs; use NACL::STask::NetworkInterface; use NACL::STask::NetworkRoute; use NACL::STask::NetworkRoutingGroupsRoute; use NACL::C::ExportPolicy; use NACL::C::ExportPolicyRule; use NACL::C::SecurityLogin; use NACL::C::VserverServicesUnixUser; use NACL::C::VserverServicesUnixGroup; use NACL::C::VserverNameMapping; use NACL::C::RoutingGroups; use NACL::C::SystemServicesFirewall; use NATE::BaseException qw(:try); use NACL::ComponentUtils qw(Dumper _verify_invocation ); use NACL::Exceptions::SetupFailure::VserverSetupFailure qw(:try); use Class::MethodMaker [ new => [ '-hash', 'new' ], scalar => 'vserver_obj', scalar => 'aggr_obj', scalar => 'data_lif_obj', scalar => 'nfs_obj', scalar => 'routing_grp_obj', scalar => 'export_rule_obj', scalar => 'export_policy_rule_obj', scalar => [ { -type => 'NACL::C::CommandInterface::ONTAP' }, 'command_interface' ], ]; =head1 METHODS =head2 setup (Class method) This method perform the setup steps for vserver on the node and on pass it returns VserverSetup object consisting the hash of object created in each step.On setup failure, it throws NACL::Exceptions::SetupFailure exception which inturn has the NACL::MTask::Setup object in 'setup_object' attribute which has all information about the objects created so far to setup the vserver. Supports only for CMode. Returns the VserverSetup object. my $setup_obj = NACL::MTask::VserverSetup->setup( command_interface => $command_interface, vserver_params => $vserver_params, aggregate_params => $aggr_params, network_interface_params => $network_interface_params, nfs_params => $nfs_params, routing_grp_params => $routing_grp_params, export_policy_params => $export_policy_params, export_policy_rule_params => $export_policy_rule_params, %other_options ); =over =item Options =over =item vserver_params(Type -hashref) (Required)Parameters to create the vserver. See L Ignore the command_interface as it is already passed by VserverSetup task. Example: $vserver_params = { vserver => $Vserver_name, aggregate => $Aggr_name, "rootvolume" => $Root_vol, "ns-switch" => \@ns_switch, "nm-switch" => \@nm_switch, "rootvolume-security-style" => "mixed", "language" => 'C', 'snapshot-policy' => 'default', 'antivirus-on-access-policy' => 'default', job_component => \$job, %other_options }; =item aggregate_params(Type -hashref) (Optional)Parameters to create the aggregate. See L Ignore the command_interface as it is already passed by VserverSetup task. Example: $aggregate_params = { aggregate => $Aggr_name, raidtype => "raid4", diskcount => 2, job_component => \$job, %other_options }; =item network_interface_params(Type -ARRAYREF or HASHREF) (Optional)Parameters to create the one or multiple Network Interface. See L Ignore the command_interface as it is already passed by VserverSetup task. It fetches unused ip addresses if address is not passed in through network_interface_params. Example: $network_interface_params = [ { lif => $Lif, vserver => $Vserver_name, role => 'data', 'home-node' => $Node_name, 'home-port' => $home_port, address => $Address, netmask => $Netmask, %other_options }; { lif => $Lif1, vserver => $Vserver_name, role => 'data', 'home-node' => $Node_name, 'home-port' => $home_port, address => $Address1, netmask => $Netmask1, %other_options }; ]; or { lif => $Lif, vserver => $Vserver_name, role => 'data', 'home-node' => $Node_name, 'home-port' => $home_port, address => $Address, netmask => $Netmask, %other_options }; =item nfs_params(Type -hashref) (Optional)Parameters to create the Nfs. See L Ignore the command_interface as it is already passed by VserverSetup task. Example: $nfs_params = { vserver => $Vserver_name, if_exists => $action, # default 'die' %other_options }; =item routing_grp_params(Type - ARRAYREF or HASHREF) (Optional)Parameters to create the Routing groups. See L Ignore the command_interface as it is already passed by VserverSetup task. routing_grp_params can pe passed as Hashref when only one routing group needs to be create and can be paased as arrayref in case of multiple routing group creation and it also makes it compatible with network_interface_param. Mandatory parameter gateway for creating routing group must be passed in $routing_grp_params as creating network interface will not always create a routing group as well. Example: $routing_grp_params = { 'routing-group' => $Routing_Group, vserver => $Vserver_name, destination => $destination, gateway => $gateway, %other_options }; or $routing_grp_params = [ { 'routing-group' => $Routing_Group, vserver => $Vserver_name, destination => $destination, gateway => $gateway, %other_options }, { 'routing-group' => $Routing_Group1, vserver => $Vserver_name1, destination => $destination1, gateway => $gateway1, %other_options }; ] =item name_mapping_params(Type -hashref) (Optional)Parameters to create the vserver name mapping. See L Ignore the command_interface as it is already passed by VserverSetup task. Example: $name_mapping_params = { vserver => $Vserver_name, direction => $Direction, position => 101, pattern => 'SETUPTEST', replacement => 'test_new' %other_options }; =item export_policy_params(Type -hashref) (Optional)Parameters to create the Export policy. See L Ignore the command_interface as it is already passed by VserverSetup task. Example: $export_policy_params = { vserver => $Vserver_name, policyname => $TestPolicy, %other_options }; =item export_policy_rule_params(Type -hashref) (Optional)Parameters to create the Export policy Rule. See L Ignore the command_interface as it is already passed by VserverSetup task. Example: $export_policy_params = { ruleindex => $TestRule, vserver => $TestVserver, policyname => $TestPolicy, clientmatch => "test_client", rorule => ["any"], protocol => ["any"], rwrule => ["any"], %other_options }; =item security_login_params(Type -hashref) (Optional)Parameters to setting and unlocking password for the vsadmin account See L Ignore the command_interface as it is already passed by VserverSetup task. Example: $security_login_params = { vserver => $vserver, username => $username, force => $boolean, oldpwd => $password, newpwd => $password, newpwd2 => $password, %other_options }; =item firewall_params(Type -hashref) (Optional)Parameters to enable and logging firewall settings See L Ignore the command_interface as it is already passed by VserverSetup task. Example: $firewall_params = { node => $node, enabled => $trueorfalse, logging => $trueorfalse, %other_options }; =item nacltask_reuse_route_group_from_lif(Type -boolean) Optional(Default = 0) If this variable is set it will reuse the gateway and routing-group from already created network interface lif.The default gateway will be extract from routing group and will append 1 at the end as it should be in same subnet or routeing-group =item C<< command_interface >> The command interface in which the vserver setup is done =item C<< apiset_must => $ruleset >> (Optional) See L =item C<< apiset_should => $ruleset >> (Optional) See L =item C<< method-timeout => $timeout >> (Optional) As component method-timeout, controls how long the command will wait before completing. See L =back =back =cut sub setup { $Log->enter() if $may_enter; my $pkg = shift; my (%return_opts, $aggr_obj, $data_lif_obj, $vserver_obj, $nfs_obj, $export_policy_rule, $export_policy_rule_obj, $export_rule, $export_rule_obj, @network_int_params ); $pkg->_verify_invocation( style => 'static_only' ); my %opts = $pkg->_common_validate_with( params => \@_, additional_spec => { vserver_params => { type => HASHREF }, aggregate_params => { type => HASHREF, optional => 1 }, network_interface_params => { type => ARRAYREF | HASHREF, optional => 1 }, nfs_params => { type => HASHREF, optional => 1 }, routing_grp_params => { type => ARRAYREF | HASHREF, optional => 1 }, export_policy_params => { type => HASHREF, optional => 1 }, export_policy_rule_params => { type => HASHREF, optional => 1 }, security_login_params => { type => HASHREF, optional => 1 }, name_mapping_params => { type => HASHREF, optional => 1 }, firewall_params => { type => HASHREF, optional => 1 }, nacltask_reuse_route_group_from_lif => => { type => BOOLEAN, default => 0 }, }, allow_extra => 1 ); # Use 'vserver' from vserver_params, if user did not specify the # 'vserver' in other params my @params = qw(nfs_params export_policy_params export_policy_rule_params security_login_params name_mapping_params); foreach my $param (@params) { $opts{$param}->{vserver} ||= $opts{vserver_params}->{vserver} if ( defined( $opts{$param} ) ); } my $command_interface = $opts{command_interface}; my $vserver_params = delete $opts{vserver_params}; my $aggregate_params = delete $opts{aggregate_params}; my $net_int_params = delete $opts{network_interface_params}; my $nfs_params = delete $opts{nfs_params}; my $routing_grp_params = delete $opts{routing_grp_params}; my $export_policy_params = delete $opts{export_policy_params}; my $export_policy_rule_params = delete $opts{export_policy_rule_params}; my $security_login_params = delete $opts{security_login_params}; my $name_mapping_params = delete $opts{name_mapping_params}; my $firewall_params = delete $opts{firewall_params}; my $nacltask_reuse_route_group_from_lif = delete $opts{nacltask_reuse_route_group_from_lif}; my (@network_interface_params, @routing_group_params, @default_routing_group, @default_routing_destination ); if ( defined $net_int_params ) { if ( ref($net_int_params) eq 'ARRAY' ) { @network_interface_params = @$net_int_params; } else { # Is a hash-reference, so make it an array with this # one hash-reference as value @network_interface_params = ($net_int_params); } ## end else [ if ( ref($net_int_params...))] foreach my $single_param_hash (@network_interface_params) { $single_param_hash->{vserver} ||= $vserver_params->{vserver}; } } ## end if ( defined $net_int_params) if ( defined $routing_grp_params ) { if ( ref($routing_grp_params) eq 'ARRAY' ) { @routing_group_params = @$routing_grp_params; } else { # Is a hash-reference, so make it an array with this # one hash-reference as value @routing_group_params = ($routing_grp_params); } ## end else [ if ( ref($routing_grp_params...))] foreach my $single_param_hash (@routing_group_params) { $single_param_hash->{vserver} ||= $vserver_params->{vserver}; } } ## end if ( defined $routing_grp_params) my %common_params; $pkg->_copy_common_component_params( source => \%opts, target => \%common_params ); try { # Create the Aggregate associated with the vserver $aggr_obj = NACL::STask::Aggregate->create( %opts, %{$aggregate_params}, ); $return_opts{'aggr_obj'} = $aggr_obj; # Create the vserver on the node $vserver_obj = NACL::STask::Vserver->create( command_interface => $command_interface, %{$vserver_params} ); $return_opts{'vserver_obj'} = $vserver_obj; # Create the data lifs on the node that is bound to the vserver foreach my $net_int_params (@network_interface_params) { $data_lif_obj = NACL::STask::NetworkInterface->create( %opts, %{$net_int_params} ); push @{ $return_opts{'data_lif_obj'} }, $data_lif_obj; if ($nacltask_reuse_route_group_from_lif) { push( @default_routing_group, $data_lif_obj->get_one_state_attribute('routing-group') ); foreach my $routing_grps (@default_routing_group) { if ($routing_grps !~ /-/){ my $obj = NACL::C::RoutingGroups->find( command_interface => $command_interface, filter => { vserver => $vserver_params->{vserver}, 'routing-group' => $routing_grps } ); push( @default_routing_destination, $obj->get_one_state_attribute('address-family') ); } } ## end foreach my $routing_grps (@default_routing_group) } ## end if ($nacltask_reuse_route_group_from_lif) } ## end foreach my $net_int_params ... # Create a default unix-user and unix-group (for root and nobody) my %users = ( 'root' => '0', 'nobody' => '65534' ); while ( my ( $user, $id ) = each %users ) { NACL::C::VserverServicesUnixUser->find_or_create( command_interface => $command_interface, vserver => $vserver_params->{vserver}, user => $user, create_specific_options => { id => $id, 'primary-gid' => $id, }, %common_params ); $Log->trace("VserverServicesUnixUser is done for $user"); NACL::C::VserverServicesUnixGroup->find_or_create( command_interface => $command_interface, vserver => $vserver_params->{vserver}, name => $user, create_specific_options => { id => $id }, %common_params ); $Log->trace("VserverServicesUnixGroup is done for $user"); } ## end while ( my ( $user, $id )...) # Create vserver name-mapping if ( ( defined($name_mapping_params) ) && ( $vserver_params->{'rootvolume-security-style'} eq "mixed" ) ) { NACL::C::VserverNameMapping->create( command_interface => $command_interface, %{$name_mapping_params} ); } ## end if ( ( defined($name_mapping_params...))) # Create NFS on the vserver if ( defined($nfs_params) ) { $nfs_obj = NACL::STask::VserverNfs->create( %opts, %{$nfs_params} ); $return_opts{'nfs_obj'} = $nfs_obj; } # Create New network routing group for Vserver foreach my $route_obj (@routing_group_params) { unless ( defined $$route_obj{'routing-group'} ) { my $index = 0; $index++; if (defined $default_routing_group[ $index ] && $default_routing_group[ $index ] !~ /-/) { $$route_obj{'routing-group'} = $default_routing_group[ $index ]; $$route_obj{'routing-group'} =~ /((\d+\.){3})/; my $default_gateway = $1 . 1; # If user did not provide gateway, create it through route-group $$route_obj{'gateway'} = $default_gateway unless ( defined $$route_obj{'gateway'} ); $Log->debug( "routing_grp_params is\n" . Dumper($route_obj) ); } ## end (defined $default_routing_group[ $index ] ...) } ## end unless ( defined $$route_obj...) } ## end foreach my $route_obj (@routing_group_params) if (@routing_group_params) { if ( $command_interface->version_manager->has_uichange( uichange => 'ipspaces-ms4', throw_exception => 0 ) ){ foreach my $route_grp_params (@routing_group_params) { delete $$route_grp_params{'routing-group'}; my $routing_grp_obj = NACL::STask::NetworkRoute->create( %opts, %{$route_grp_params} ); push @{ $return_opts{'routing_grp_obj'} }, $routing_grp_obj; } ## end foreach my $route_grp_params... } else { foreach my $route_grp_params (@routing_group_params) { my $routing_grp_obj = NACL::STask::NetworkRoutingGroupsRoute->create( %opts, %{$route_grp_params} ); push @{ $return_opts{'routing_grp_obj'} }, $routing_grp_obj; } ## end foreach my $route_grp_params... } } ## end if (@routing_group_params) # Create exportruleset for Verver if it does not exist if ( defined($export_policy_params) ) { try { $export_rule = NACL::C::ExportPolicy->find( command_interface => $command_interface, filter => { %{$export_policy_params} } ); } ## end try catch NACL::Exceptions::NoElementsFound with { $export_rule_obj = NACL::C::ExportPolicy->create( command_interface => $command_interface, %{$export_policy_params}, %opts ); }; $return_opts{'export_rule_obj'} = $export_rule_obj; } ## end if ( defined($export_policy_params...)) # Create export rule within the ruleset if ( defined($export_policy_rule_params) ) { try { $export_policy_rule = NACL::C::ExportPolicyRule->find( command_interface => $command_interface, filter => { %{$export_policy_rule_params} } ); } ## end try catch NACL::Exceptions::NoElementsFound with { $export_policy_rule_obj = NACL::C::ExportPolicyRule->create( command_interface => $command_interface, %{$export_policy_rule_params}, %opts ); }; ## end with $return_opts{'export_policy_rule_obj'} = $export_policy_rule_obj; } ## end if ( defined($export_policy_rule_params...)) # Sets up services required to use a Vserver LIF - # Setting and unlocking password for the vsadmin account if ( defined($security_login_params) ) { NACL::C::SecurityLogin->password( command_interface => $command_interface, %{$security_login_params}, %opts ); # Unlock the account NACL::C::SecurityLogin->unlock( command_interface => $command_interface, vserver => $security_login_params->{vserver}, username => $security_login_params->{username}, %opts ); } ## end if ( defined($security_login_params...)) if ( defined($firewall_params) ) { NACL::C::SystemServicesFirewall->modify( command_interface => $command_interface, %{$firewall_params}, %opts ); } ## end if ( defined($firewall_params...)) } ## end try otherwise { my $e = shift; $Log->exit() if $may_exit; NACL::Exceptions::SetupFailure::VserverSetupFailure->throw( $e->text(), setup_object => $pkg->new(%return_opts) ); }; $Log->exit() if $may_exit; return $pkg->new(%return_opts); } ## end sub setup 1;