# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# bos720 src/bos/usr/lpp/bosinst/samples/NIM/LPAR.pm 1.1 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2008,2009 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 

# @(#)58        1.1  src/bos/usr/lpp/bosinst/samples/NIM/LPAR.pm, bosinst, bos720 3/29/09 15:20:53

package NIM::LPAR;

=head1 NAME

NIM::LPAR

=over 2

=item

NIM::LPAR base class.

=back

=head1 VARIABLES

=head2 %Settings

=over 2

=item * project

=back

=head2 %Defaults

=over 2

=item * type

=item * nim_type

=item * platform

=item * netboot_kernel

=item * cable_type

=item * connect

=item * network_type

=item * subnet_mask

=item * net_settings

=back

=head1 FUNCTIONS

=cut

BEGIN
{
  # print "NIM::LPAR BEGIN\n";

  use Hash::Util;
  use NIM::Util;
  use Sys::Hostname;

  %Settings = ('project'		=> 'sysp');

  # may need to default some of these values from those of the nim master's
  %Defaults = ('type'			=> 'aix',
	       'nim_type'		=> 'standalone',
	       'platform'		=> 'chrp',
	       'netboot_kernel'		=> 'mp',
	       'cable_type'		=> 'N/A',
	       'connect'		=> 'shell',
	       'network_type'		=> 'ent',
	       'subnet_mask'		=> '255.255.255.0',
	       'net_settings'		=> 'auto auto',
	       'hmc'			=> '',
	       'hmc_user'		=> '');
}

#-------------------------------------------------------------------------------

=head2 new

=over 2

=item

C<new NIM::LPAR(%args)>

=back

=head3 DESCRIPTION

=over 2

=item

Instantiates a NIM::LPAR object.

=back

=head3 PARAMETERS

=over 2

=item * %args

=over 2

=item * type

=item * name

=item * profile

=item * cec

=item * hmc

=item * hmc_user

=item * host_name

=item * nim_machine_name

=item * nim_type

=item * type

=item * platform

=item * netboot_kernel

=item * cable_type

=item * connect

=item * net_settings

=item * mac_addr

=item * if

=item * ip_addr

=item * gateway

=item * network_type

=item * subnet_mask

=item * domain

=item * nameservers

=back

=back

=head3 RETURNS

=over 2

=item * Reference to the newly created hash object.

=back

=head3 EXCEPTIONS

=cut

#-------------------------------------------------------------------------------
sub new
{
  my $type = shift;
  my %args = @_;

  log_print("NIM::LPAR::new(@_)\n");

  my $this = {};
  bless $this, $type;

  my $nim_info = ((defined $NIM::Config{'info'}) ? $NIM::Config{'info'} : new NIM::Info());
  $this->{'info'} = $nim_info;

  ###
  
  $this->{'type'}	= (defined $args{'type'}	? $args{'type'}		: $Defaults{'type'});
  $this->{'name'}	= (defined $args{'name'}	? $args{'name'}		: '');
  $this->{'profile'}	= (defined $args{'profile'}	? $args{'profile'}	: '');
  $this->{'cec'}	= (defined $args{'cec'}		? $args{'cec'}		: '');

  ###
  
  $this->{'hmc'}	= (defined $args{'hmc'}		? $args{'hmc'}		: $Defaults{'hmc'});
  $this->{'hmc_user'}	= (defined $args{'hmc_user'}	? $args{'hmc_user'}	: $Defaults{'hmc_user'});
  
  ###
  
  $this->{'hostname'}		= (defined $args{'hostname'}		? $args{'hostname'}		: '');
  $this->{'nim_machine_name'}	= (defined $args{'nim_machine_name'}	? $args{'nim_machine_name'}	: '');
  $this->{'nim_type'}		= (defined $args{'nim_type'}		? $args{'nim_type'}		: $Defaults{'nim_type'});

  $this->{'platform'}		= (defined $args{'platform'}		? $args{'platform'}		: $Defaults{'platform'});
  $this->{'netboot_kernel'}	= (defined $args{'netboot_kernel'}	? $args{'netboot_kernel'}	: $Defaults{'netboot_kernel'});
  $this->{'cable_type'}		= (defined $args{'cable_type'}		? $args{'cable_type'}		: $Defaults{'cable_type'});
  $this->{'connect'}		= (defined $args{'connect'}		? $args{'connect'}		: $Defaults{'connect'});
  $this->{'net_settings'}	= (defined $args{'net_settings'}	? $args{'net_settings'}		: $Defaults{'net_settings'});
  $this->{'mac_addr'}		= (defined $args{'mac_addr'}		? $args{'mac_addr'}		: '0');
  $this->{'if'}			= (defined $args{'if'}			? $args{'if'}			: '');

  ###

  $this->{'ip_addr'}		= (defined $args{'ip_addr'}		? $args{'ip_addr'}	: '');
  $this->{'gateway'}		= (defined $args{'gateway'}		? $args{'gateway'}	: '');
  $this->{'network_type'}	= (defined $args{'network_type'}	? $args{'network_type'}	: $Defaults{'network_type'});
  $this->{'subnet_mask'}	= (defined $args{'subnet_mask'}		? $args{'subnet_mask'}	: $Defaults{'subnet_mask'});

  $this->{'domain'}		= (defined $args{'domain'}		? $args{'domain'}	: '');
  $this->{'nameservers'}	= (defined $args{'nameservers'}		? $args{'nameservers'}	: '');

  ###

  $this->{'disk_size'}		= (defined $args{'disk_size'}		? $args{'disk_size'}		: '');
  $this->{'paging_space_size'}	= (defined $args{'paging_space_size'}	? $args{'paging_space_size'}	: '');

  ###

  if ($this->{'domain'} && ($this->{'hostname'} =~ m/^[^\.]+$/))
  {
    $this->{'hostname'} = "$this->{'hostname'}.$this->{'domain'}";
  }

  if ($this->{'hostname'} && (! $this->{'nim_machine_name'}))
  {
    $this->{'nim_machine_name'} = $this->{'hostname'};
    $this->{'nim_machine_name'} =~ s/^([^\.]+).*$/$1/;
  }

  if ((! $this->{'ip_addr'}) && $this->{'hostname'})
  {
    my ($name, $aliases, $addrtype, $length, @addr) = gethostbyname $this->{'hostname'};
    my ($a, $b, $c, $d) = unpack('C4', $addr[0]);

    # print "$a.$b.$c.$d\n";
    $this->{'ip_addr'} = "$a.$b.$c.$d";
  }
  
  if ($this->{'ip_addr'} && (! $this->{'gateway'}))
  {
    $this->{'gateway'} = $this->{'ip_addr'};
    $this->{'gateway'} =~ s/^([^\.]+)\.([^\.]+)\.([^\.]+)\.([^\.]+)$/$1\.$2\.$3\.1/;
  }

  if ((! $this->{'domain'}) && ($this->{'hostname'} =~ m/^[^\.]+\.(.+)$/))
  {
    $this->{'domain'} = $1;
  }

  if (! $this->{'if'})
  {
    $this->{'if'} = 'find_net ' . $this->{'hostname'} . ' ' . $this->{'mac_addr'};
  }

  $this->{'update_nim'}	= (defined $args{'update_nim'}	? $args{'update_nim'}	: '1');
  if ($this->{'update_nim'} && ($this->{'update_nim'} != 0))
  {
    # the following is all that's needed to define a machine if a pre-existing network is found
    #	invoke("$Cmds{'nim'} -o define -t $this->{'nim_type'} -a if1=\"$this->{'if'}\" $this->{'nim_machine_name'}");
    #
    # net_definition values only used if a network isn't found
    
    my $nim_attrs = "-a if1=\"$this->{'if'}\" " .
      "-a cable_type1=$this->{'cable_type'} -a netboot_kernel=$this->{'netboot_kernel'} " .
      "-a net_definition=\"$this->{'network_type'} $this->{'subnet_mask'}\" " .
      "-a connect=$this->{'connect'} -a net_settings1=\"$this->{'net_settings'}\"";
    
    my $machines = $nim_info->locate_machine_by_name($this->{'nim_machine_name'});
    if ($machines->empty())
    {
      # create NIM machine definition
      invoke("$Cmds{'nim'} -o define -t $this->{'nim_type'} $nim_attrs $this->{'nim_machine_name'}");
    }
    else
    {
      # the cpuid needs to be reset if we allow for the same nim object
      # to be reused for a different lpar

      $nim_attrs = $nim_attrs . " -a cpuid=";
      invoke("$Cmds{'nim'} -o change $nim_attrs $this->{'nim_machine_name'}");
    }
  }
  return $this;
}

#-------------------------------------------------------------------------------
sub delete
{
  my $this = shift;

  log_print("NIM::LPAR::delete()\n");
  invoke("$Cmds{'nim'} -o remove $this->{'nim_machine_name'}");

  my $res_group_name = $this->delete_resources();
  if ($res_group_name)
  {
    invoke("$Cmds{'nim'} -o remove $res_group_name");
  }
}

#-------------------------------------------------------------------------------
sub delete_by_name
{
  my ($nim_machine_name) = @_;
  log_print("NIM::LPAR::delete_by_name(\'$nim_machine_name\')\n");

  my $this = new NIM::LPAR('nim_machine_name'	=> $lpar_name,
			   'update_nim'		=> 0);
  $this->delete();
}

#-------------------------------------------------------------------------------
sub get_nameservers
{
  my $this = shift;
  my @rc = ();

  my $nameservers = $this->{'nameservers'};
  
  @rc = split(/[ \t]+/, $nameservers);
  return @rc;
}

#-------------------------------------------------------------------------------
sub update_from_image_attributes
{
  #
  # 'machine' can have
  #	platform		= chrp
  #	netboot_kernel		= 64
  #
  # 'master' is a subclass of 'machine' and can also have
  #	if_defined		= chrp.64.ent
  #	if_defined		= chrp.mp.ent
  #
  # 'spot' can have
  #	platform_defined	= chrp
  #	arch			= power
  #	if_supported		= chrp.64 ent
  #	if_supported		= chrp.mp ent
  #

  my $this = shift;
  log_print "NIM::LPAR::update_from_image_attributes()\n";

  $nim_info = $this->{'info'};
}

#-------------------------------------------------------------------------------

=head2 netboot

=over 2

=item

C<$lpar-E<gt>netboot()>

=back

=head3 DESCRIPTION

=over 2

=item

Network boot the LPAR via its HMC.

=back

=head3 PARAMETERS

=head3 RETURNS

=head3 EXCEPTIONS

=cut

#-------------------------------------------------------------------------------
sub netboot
{
  my $this = shift;
  
  log_print "NIM::LPAR::netboot($this->{'hostname'})\n";

  my $host = hostname;
  my $nim_master_ip_addr = '';
  if ($host)
  {
    my ($name, $aliases, $addrtype, $length, @addr) = gethostbyname $host;
    my ($a, $b, $c, $d) = unpack('C4', $addr[0]);
    $nim_master_ip_addr = "$a.$b.$c.$d";
  }
  
  if ($this->{'hmc_user'} && $this->{'hmc'} && $this->{'network_type'} &&
      $nim_master_ip_addr && $this->{'gateway'} && $this->{'ip_addr'} &&
      $this->{'name'} && $this->{'profile'} && $this->{'cec'})
  {
    # run restricted shell /usr/hmcrbin hmc commands
    # in restricted mode, some hmc's require that commands not be fully qualified path names - i.e. no '/'s

    # change boot mode to normal
    invoke_ssh("$this->{'hmc_user'}\@$this->{'hmc'}", "chsyscfg -r prof -m $this->{'cec'} -i \"name=$this->{'profile'},lpar_name=$this->{'name'},boot_mode=norm\"");

    # older versions of the HMC does not support the -K option - pre-hmcV7.3.2.0
    my $snm = '';
    if (0)
    {
      my $result = invoke_ssh("$this->{'hmc_user'}\@$this->{'hmc'}", "lshmc -V -F base_version");
      my $hmc_version = $result->[0];
      
      if ($hmc_version =~ m/\"V([1-9][0-9]*)\.([1-9][0-9]*)\.([1-9][0-9]*)\n\"\n$/)
      {
	if (($1 > 7) || ($1 == 7) && ($2 > 320) || ($1 == 7) && ($2 == 320) && ($3 > 0))
	{
	  $snm = "-K $this->{'subnet_mask'}";
	}
      }
    }
    else
    {
      my $result = invoke_ssh("$this->{'hmc_user'}\@$this->{'hmc'}", "lpar_netboot --help | grep 'Subnetmask IP address' | grep -- -K");
      if ($#$result >= 0)
      {
	# print "result => $result->[0]\n";
	$snm = "-K $this->{'subnet_mask'}";
      }
    }

    my ($speed, $duplex) = split(/[ \t]+/, $this->{'net_settings'});
    if (! $speed)
    {
      $speed = "auto";
    }
    if (! $duplex)
    {
      $duplex = "auto";
    }

    # same as lpar_netboot -f option - not needed for the SystemU1 (550) system
    # invoke_ssh("$this->{'hmc_user'}\@$this->{'hmc'}", "rmvterm -m $this->{'cec'} -p $this->{'name'}");

    # add -D option to perform ping test
    # The -f and -D options seems to be needed for the pcloud (550) system but not for SystemU1 (570)

    # -x -v options are for debug

    invoke_ssh("$this->{'hmc_user'}\@$this->{'hmc'}", "lpar_netboot -x -v -i -f -D -t $this->{'network_type'} -s $speed -d $duplex -S $nim_master_ip_addr -G $this->{'gateway'} -C $this->{'ip_addr'} $snm \"$this->{'name'}\" \"$this->{'profile'}\" \"$this->{'cec'}\"");
  }
  else
  {
    log_print "\tUnable to netboot the LPAR\n";

    log_print "\t- Unspecified hmc user\n" if (! $this->{'hmc_user'});
    log_print "\t- Unspecified hmc\n" if (! $this->{'hmc'});
    log_print "\t- Unspecified network type\n" if (! $this->{'network_type'});
    log_print "\t- Unspecified nim master\n" if (! $nim_master_ip_addr);
    log_print "\t- Unspecified gateway\n" if (! $this->{'gateway'});
    log_print "\t- Unspecified ip address\n" if (! $this->{'ip_addr'});
    log_print "\t- Unspecified partition name\n" if (! $this->{'name'});
    log_print "\t- Unspecified partition profile name\n" if (! $this->{'profile'});
    log_print "\t- Unspecified cec name\n" if (! $this->{'cec'});
  }
}

#-------------------------------------------------------------------------------

=head2 print_deploy_status

=over 2

=item

C<$lpar-E<gt>print_deploy_status()>

=back

=head3 DESCRIPTION

=over 2

=item

Prints the deployment status obtained via NIM machine state information.  Also
serializes/waits for deployment operation to complete or fail.

=back

=head3 PARAMETERS

=head3 RETURNS

=head3 EXCEPTIONS

=cut

#-------------------------------------------------------------------------------
sub print_deploy_status
{
  my $this = shift;

  log_print("NIM::LPAR::print_deploy_status()\n");

  my $rc = 0;
  my $nim_info = $this->{'info'};
  my $nim_machine_name = $this->{'nim_machine_name'};

  my $keep_printing = 0;
  my ($prev_Cstate, $prev_Cstate_result, $prev_Mstate, $prev_info, $prev_err_info) = ('', '', '', '', '');
  my $i = 0;
  my $repeat_count = 0;

  do
  {
    $nim_info->refresh("$Lang $Cmds{'lsnim'} -lF $nim_machine_name 2>/dev/null");
    my $machines = $nim_info->locate_machine_by_name($nim_machine_name);

    if (! $machines->empty())
    {
      my ($name, $attr_hash) = $machines->get_first_object();
      
      select(STDOUT); $| = 1;	# flush stdout on next output

      if ($i &&
	  ($prev_Cstate eq $attr_hash->{'Cstate'}->[0]) &&
	  ($prev_Mstate eq $attr_hash->{'Mstate'}->[0]) &&
	  ((! defined $attr_hash->{'err_info'}) && (! $prev_err_info) ||
	   (defined $attr_hash->{'err_info'}) && ($attr_hash->{'err_info'} eq $prev_err_info)) &&
	  $prev_info &&
	  (defined $attr_hash->{'info'}) &&
	  ($attr_hash->{'info'}->[0] =~ m/^BOS install [0-9]+% complete/))
      {
	my $info = $attr_hash->{'info'}->[0];
	print "\rinfo = $info";

	if ($prev_info)
	{
	  for (my $diff = length($prev_info) - length($info); $diff > 0; $diff--)
	  {
	    print ' ';
	  }
	}
      }
      else
      {
	if ((defined $attr_hash->{'Cstate'}) && ($prev_Cstate ne $attr_hash->{'Cstate'}->[0]) ||
	    (defined $attr_hash->{'Mstate'}) && ($prev_Mstate ne $attr_hash->{'Mstate'}->[0]) ||
	    (defined $attr_hash->{'Cstate_result'}) && ($prev_Cstate_result ne $attr_hash->{'Cstate_result'}->[0]) ||
	    (defined $attr_hash->{'info'}) && ($prev_info ne $attr_hash->{'info'}->[0]) ||
	    (defined $attr_hash->{'err_info'}) && ($prev_err_info ne $attr_hash->{'err_info'}->[0]))
	{
	  if ($i)
	  {
	    print "\n";
	  }
	  print "===";
	  
	  my @attr_keys = ('Cstate', 'Cstate_result', 'Mstate', 'info', 'err_info');
	  foreach my $attr_key (@attr_keys)
	  {
	    if (defined $attr_hash->{$attr_key})
	    {
	      print "\n$attr_key = ";
	      my $values = $attr_hash->{$attr_key};
	      foreach my $value (@$values)
	      {
		print "$value";
	      }
	    }
	  }
	}
      }
   
      if (($i < 3) ||		# keep printing for a minimum of 90 seconds
	  ($attr_hash->{'Cstate'}->[0] eq 'BOS installation has been enabled') ||
	  
	  (($attr_hash->{'Cstate'}->[0] eq 'Base Operating System installation is being performed') ||
	   ($attr_hash->{'Cstate'}->[0] eq 'post install processing is being performed') ||
	   ($attr_hash->{'Cstate'}->[0] eq 'BOS installation has been enabled') ||
	   ($attr_hash->{'Cstate'}->[0] eq 'customization is being performed')) &&
	  ($attr_hash->{'Mstate'}->[0] eq 'in the process of booting') &&
	  ((! defined $attr_hash->{'info'}) || ($attr_hash->{'info'}->[0] ne 'prompting_for_data_at_console')) ||
	  
	  # during reboot
	  ($attr_hash->{'Cstate'}->[0] eq 'ready for a NIM operation') &&
	  ($attr_hash->{'Cstate_result'}->[0] ne 'failure') &&
	  (($prev_Mstate eq 'in the process of booting') || ($prev_Mstate eq 'not running')) &&
	  ($attr_hash->{'Mstate'}->[0] eq 'in the process of booting') || ($attr_hash->{'Mstate'}->[0] eq 'not running'))
      {
	$keep_printing = 1;

	my $new_Cstate_result = (defined $attr_hash->{'Cstate_result'}) ? $attr_hash->{'Cstate_result'}->[0] : '';
	my $new_info = (defined $attr_hash->{'info'}) ? $attr_hash->{'info'}->[0] : '';
	my $new_err_info = (defined $attr_hash->{'err_info'}) ? $attr_hash->{'err_info'}->[0] : '';
	
	if (($prev_Cstate ne $attr_hash->{'Cstate'}->[0]) ||
	    ($prev_Mstate ne $attr_hash->{'Mstate'}->[0]) ||
	    ($prev_Cstate_result ne $new_Cstate_result) ||
	    ($prev_info ne $new_info) ||
	    ($prev_err_info ne $new_err_info))
	{
	  $repeat_count = 0;

	  $prev_Cstate = $attr_hash->{'Cstate'}->[0];
	  $prev_Mstate = $attr_hash->{'Mstate'}->[0];

	  $prev_Cstate_result = $new_Cstate_result;
	  $prev_info = $new_info;
	  $prev_err_info = $new_err_info;
	}
	elsif ($repeat_count++ > 20)
	{
	  $keep_printing = 0;
	}

	if ($keep_printing)
	{
	  $i++;
	  sleep 30;
	}
      }
      else
      {
	$keep_printing = 0;
	print "\n";

	if (($attr_hash->{'Cstate'}->[0] eq 'ready for a NIM operation') &&
	    (($prev_Mstate eq 'in the process of booting') || ($prev_Mstate eq 'not running')) &&
	    ($attr_hash->{'Mstate'}->[0] eq 'currently running'))
	{
	  print "===\n";
	  print "Installation complete!\n";

	  $rc = 1;
	}
	else
	{
	  print "===\n";
	  print "Cstate = $attr_hash->{'Cstate'}->[0]\n";
	  print "Mstate = $attr_hash->{'Mstate'}->[0]\n";
	  print "prev_Mstate = $prev_Mstate\n";
	}
      }
    }
  } while ($keep_printing);

  # refresh with complete nim info
  $nim_info->refresh();

  return $rc;
}

#-------------------------------------------------------------------------------
sub get_nim_name
{
  my $this = shift;
  my ($type) = @_;
  
  if ($type ne 'res_group')
  {
    $type = '';
  }
  return ($type ? sprintf("%s\-%s\-%s", $Settings{'project'}, $this->{'nim_machine_name'}, $type) : '');
}

#-------------------------------------------------------------------------------
sub add_to_res_group
{
  my $this = shift;
  my ($resource_name, $resource_type) = @_;

  log_print("NIM::LPAR::add_to_res_group(\'$resource_name\', \'$resource_type\')\n");

  if ($resource_name && $resource_type)
  {
    my $res_group_name = $this->get_nim_name('res_group');
    my $res_groups = $this->{'info'}->locate_resource_group_by_name($res_group_name);
    
    if ($res_groups->empty())
    {
      log_print "\tDefining res_group: $res_group_name\n";
      invoke("$Cmds{'nim'} -o define -t res_group -a $resource_type=$resource_name $res_group_name");
    }
    else
    {
      my ($res_group, $attr_hash) = $res_groups->get_first_object();
      my $index = 0;
      
      for (my $i = 1; $index == 0; $i++)
      {
	if (! $attr_hash->{"member${i}"})
	{
	  $index = $i;
	}
      }
      log_print "\tRedefining res_group: $res_group_name\n";
      invoke("$Cmds{'nim'} -o change -a member${index}=$resource_name $res_group_name");
    }
    $this->{'info'}->update("$Lang $Cmds{'lsnim'} -lF $res_group_name 2>/dev/null");
  }
}

#-------------------------------------------------------------------------------
sub reset_by_name
{
  my ($nim_machine_name) = @_;

  log_print("NIM::LPAR::reset_by_name(\'$nim_machine_name\')\n");

  invoke("$Cmds{'nim'} -Fo reset $nim_machine_name");
  for (my $i = 0; $i < 2; $i++)
  {
    # deallocate operation does not take the verbose attribute
    invoke("/usr/sbin/nim -Fo deallocate -asubclass=all $nim_machine_name");
  }
}

#-------------------------------------------------------------------------------
sub reset
{
  my $this = shift;
  
  log_print("NIM::LPAR::reset()\n");
  reset_by_name($this->{'nim_machine_name'});
}

#-------------------------------------------------------------------------------
sub allocated_resources
{
  my $this = shift;
  
  log_print("NIM::LPAR::allocated_resources()\n");
  
  my @rc = ();

  my $nim_info = $this->{'info'};
  my $nim_machine_name = $this->{'nim_machine_name'};

  $nim_info->refresh("$Lang $Cmds{'lsnim'} -lF $nim_machine_name 2>/dev/null");
  my $machines = $nim_info->locate_machine_by_name($nim_machine_name);
  
  if (! $machines->empty())
  {
    my ($name, $attr_hash) = $machines->get_first_object();
   
    my @resource_types = ('mksysb', 'spot', 'fb_script', 'image_data', 'bosinst_data', 'resolv_conf');
    foreach my $resource_type (@resource_types)
    {
      my $resource_list = $attr_hash->{$resource_type};
      if ($resource_list)
      {
	foreach my $resource_name (@$resource_list)
	{
	  push @rc, ($resource_name);
	}
      }
    }
  }
  log_printf("\t%d allocated resources\n", $#rc + 1);
  return \@rc;
}

#-------------------------------------------------------------------------------
sub delete_resources
{
  my $this = shift;

  log_print("NIM::LPAR::delete_resources()\n");

  my $nim_info = $this->{'info'};
  my $res_group_name = $this->get_nim_name('res_group');
  $this->{'info'}->update("$Lang $Cmds{'lsnim'} -lF $res_group_name 2>/dev/null");

  my $res_groups = $nim_info->locate_resource_group_by_name($res_group_name);
  if ($res_groups->empty())
  {
    $res_group_name = '';
  }
  else
  {
    my ($res_group, $attr_hash) = $res_groups->get_first_object();
    my $max = 99;
    my @members = ();

    for (my $i = 1; $i <= $max; $i++)
    {
      my $member_value = $attr_hash->{"member${i}"};
      if ($member_value)
      {
	my $resources = $nim_info->locate_resource_by_name($member_value->[0]);
	my $location = $resources->get_first_attr_value($member_value->[0], 'location');
	push @members, ($member_value->[0]);

	if ($location && -e $location)
	{
	  unlink($location);
	}
      }
    }

    $this->reset();
    
    foreach my $member (@members)
    {
      invoke("$Cmds{'nim'} -o remove $member");
    }
  }
  return $res_group_name;
}

1;

# __END__

=head1 AUTHOR

IBM

=head1 BUGS

Please report any bugs to the L</"AUTHOR">.

=head1 SUPPORT

=head1 ACKNOWLEDGEMENTS

=head1 SEE ALSO

=begin html

<ul>
<li><a href="LPAR/AIX.html">NIM::LPAR::AIX</a>
<li><a href="LPAR/VIOS.html">NIM::LPAR::VIOS</a>
</ul>

=end html

=cut
