xCAT baremetal driver for OpenStack
This commit is contained in:
		
							
								
								
									
										778
									
								
								xCAT-OpenStack-baremetal/lib/perl/xCAT_plugin/openstack.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										778
									
								
								xCAT-OpenStack-baremetal/lib/perl/xCAT_plugin/openstack.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,778 @@
 | 
			
		||||
# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
package xCAT_plugin::openstack;
 | 
			
		||||
BEGIN
 | 
			
		||||
{
 | 
			
		||||
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | 
			
		||||
}
 | 
			
		||||
use lib "$::XCATROOT/lib/perl";
 | 
			
		||||
use xCAT::Utils;
 | 
			
		||||
use xCAT::TableUtils;
 | 
			
		||||
use xCAT::SvrUtils;
 | 
			
		||||
use xCAT::NetworkUtils;
 | 
			
		||||
use xCAT::Table;
 | 
			
		||||
use Data::Dumper;
 | 
			
		||||
use File::Path;
 | 
			
		||||
use File::Copy;
 | 
			
		||||
use Getopt::Long;
 | 
			
		||||
Getopt::Long::Configure("bundling");
 | 
			
		||||
Getopt::Long::Configure("pass_through");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sub handled_commands {
 | 
			
		||||
    return {
 | 
			
		||||
		opsaddbmnode => "openstack",  #external command
 | 
			
		||||
		opsaddimage => "openstack",   #external command
 | 
			
		||||
		deploy_ops_bm_node => "openstack",   #internal command called from the baremetal driver
 | 
			
		||||
		cleanup_ops_bm_node => "openstack",  #internal command called from the baremetal driver
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub process_request {
 | 
			
		||||
	my $request = shift;
 | 
			
		||||
	my $callback = shift;
 | 
			
		||||
	my $doreq = shift;
 | 
			
		||||
	my $command = $request->{command}->[0];
 | 
			
		||||
	
 | 
			
		||||
	if ($command eq "opsaddbmnode") {
 | 
			
		||||
		return opsaddbmnode($request, $callback, $doreq);
 | 
			
		||||
	} elsif ($command eq "opsaddimage") {
 | 
			
		||||
		return opsaddimage($request, $callback, $doreq);
 | 
			
		||||
	} elsif ($command eq "deploy_ops_bm_node") {
 | 
			
		||||
		return deploy_ops_bm_node($request, $callback, $doreq);
 | 
			
		||||
	} elsif ($command eq "cleanup_ops_bm_node") {
 | 
			
		||||
		return cleanup_ops_bm_node($request, $callback, $doreq);
 | 
			
		||||
	} else {
 | 
			
		||||
		$callback->({error=>["Unsupported command: $command."],errorcode=>[1]});
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  opsaddbmnode
 | 
			
		||||
     This function takes the xCAT nodes and register them
 | 
			
		||||
     as the OpenStack baremetal nodes
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub opsaddbmnode {
 | 
			
		||||
	my $request = shift;
 | 
			
		||||
	my $callback = shift;
 | 
			
		||||
	my $doreq = shift;
 | 
			
		||||
	
 | 
			
		||||
	@ARGV = @{$request->{arg}};
 | 
			
		||||
	Getopt::Long::Configure("bundling");
 | 
			
		||||
	Getopt::Long::Configure("no_pass_through");
 | 
			
		||||
	
 | 
			
		||||
	my $help;
 | 
			
		||||
	my $version;
 | 
			
		||||
	my $host;
 | 
			
		||||
	
 | 
			
		||||
    if(!GetOptions(
 | 
			
		||||
            'h|help'      => \$help,
 | 
			
		||||
            'v|version'   => \$version,
 | 
			
		||||
            's=s'         => \$host,
 | 
			
		||||
       ))
 | 
			
		||||
    {
 | 
			
		||||
        &opsaddbmnode_usage($callback);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    # display the usage if -h or --help is specified
 | 
			
		||||
    if ($help) {
 | 
			
		||||
        &opsaddbmnode_usage($callback);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    # display the version statement if -v or --verison is specified
 | 
			
		||||
    if ($version)
 | 
			
		||||
    {
 | 
			
		||||
        my $rsp={};
 | 
			
		||||
        $rsp->{data}->[0]= xCAT::Utils->Version();
 | 
			
		||||
        $callback->($rsp);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
	
 | 
			
		||||
	if (!$request->{node}) {
 | 
			
		||||
		$callback->({error=>["Please specify at least one node."],errorcode=>[1]});
 | 
			
		||||
		return 1;  
 | 
			
		||||
	}
 | 
			
		||||
	if (!$host) {
 | 
			
		||||
		$callback->({error=>["Please specify the OpenStack compute host name with -s flag."],errorcode=>[1]});
 | 
			
		||||
		return 1;  
 | 
			
		||||
	}
 | 
			
		||||
    
 | 
			
		||||
    my $nodes = $request->{node};
 | 
			
		||||
 | 
			
		||||
    #get bmc info for the nodes
 | 
			
		||||
	my $ipmitab = xCAT::Table->new("ipmi", -create => 0);
 | 
			
		||||
	my $tmp_ipmi;
 | 
			
		||||
	if ($ipmitab) {
 | 
			
		||||
		$tmp_ipmi = $ipmitab->getNodesAttribs($nodes, ['bmc','username', 'password'], prefetchcache=>1);
 | 
			
		||||
		#print Dumper($tmp_ipmi);
 | 
			
		||||
	} else {
 | 
			
		||||
		$callback->({error=>["Cannot open the ipmi table."],errorcode=>[1]});
 | 
			
		||||
		return 1;		
 | 
			
		||||
	}
 | 
			
		||||
    #get mac for the nodes
 | 
			
		||||
	my $mactab = xCAT::Table->new("mac", -create => 0);
 | 
			
		||||
	my $tmp_mac;
 | 
			
		||||
	if ($mactab) {
 | 
			
		||||
		$tmp_mac = $mactab->getNodesAttribs($nodes, ['mac'], prefetchcache=>1);
 | 
			
		||||
		#print Dumper($tmp_mac);
 | 
			
		||||
	} else {
 | 
			
		||||
		$callback->({error=>["Cannot open the mac table."],errorcode=>[1]});
 | 
			
		||||
		return 1;		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    #get cpu, memory and disk info for the nodes
 | 
			
		||||
	my $hwinvtab = xCAT::Table->new("hwinv", -create => 0);
 | 
			
		||||
	my $tmp_hwinv;
 | 
			
		||||
	if ($hwinvtab) {
 | 
			
		||||
		$tmp_hwinv = $hwinvtab->getNodesAttribs($nodes, ['cpucount', 'memory', 'disksize'], prefetchcache=>1);
 | 
			
		||||
		#print Dumper($tmp_hwinv);
 | 
			
		||||
	} else {
 | 
			
		||||
		$callback->({error=>["Cannot open the hwinv table."],errorcode=>[1]});
 | 
			
		||||
		return 1;		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	foreach my $node (@$nodes) {
 | 
			
		||||
        #collect the node infomation needed for each node, some info
 | 
			
		||||
        #may not be defined in the xCAT db
 | 
			
		||||
		my ($bmc, $bmc_user, $bmc_password, $mac, $cpu, $memory, $disk);
 | 
			
		||||
		my $ref_ipmi = $tmp_ipmi->{$node}->[0]; 
 | 
			
		||||
	    if ($ref_ipmi) {
 | 
			
		||||
			if (exists($ref_ipmi->{bmc})) {
 | 
			
		||||
				$bmc = $ref_ipmi->{bmc};
 | 
			
		||||
			}
 | 
			
		||||
			if (exists($ref_ipmi->{username})) {
 | 
			
		||||
				$bmc_user = $ref_ipmi->{username};
 | 
			
		||||
			}
 | 
			
		||||
			if (exists($ref_ipmi->{password})) {
 | 
			
		||||
				$bmc_password = $ref_ipmi->{password};
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		$ref_mac = $tmp_mac->{$node}->[0]; 
 | 
			
		||||
	    if ($ref_mac) {
 | 
			
		||||
			if (exists($ref_mac->{mac})) {
 | 
			
		||||
				$mac = $ref_mac->{mac};
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		$ref_hwinv = $tmp_hwinv->{$node}->[0]; 
 | 
			
		||||
	    if ($ref_hwinv) {
 | 
			
		||||
			if (exists($ref_hwinv->{cpucount})) {
 | 
			
		||||
				$cpu = $ref_hwinv->{cpucount};
 | 
			
		||||
			}
 | 
			
		||||
			if (exists($ref_hwinv->{memory})) {
 | 
			
		||||
				$memory = $ref_hwinv->{memory};
 | 
			
		||||
                #TODO: what if the unit is not in MB? We need to convert it to MB
 | 
			
		||||
				$memory =~ s/MB|mb//g;
 | 
			
		||||
			}
 | 
			
		||||
			if (exists($ref_hwinv->{disksize})) {
 | 
			
		||||
				#The format of the the disk size is: sda:250GB,sdb:250GB or just 250GB
 | 
			
		||||
                #We need to get the size of the first one
 | 
			
		||||
				$disk = $ref_hwinv->{disksize};
 | 
			
		||||
				my @a = split(',', $disk);
 | 
			
		||||
				my @b = split(':', $a[0]);
 | 
			
		||||
				if (@b > 1) {
 | 
			
		||||
					$disk = $b[1];
 | 
			
		||||
				} else {
 | 
			
		||||
					$disk = $b[0];
 | 
			
		||||
				}
 | 
			
		||||
                print "a=@a, b=@b\n";
 | 
			
		||||
                #TODO: what if the unit is not in GB? We need to convert it to MB
 | 
			
		||||
				$disk =~ s/GB|gb//g;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		#some info are mendatory
 | 
			
		||||
        if (!$mac) {
 | 
			
		||||
			$callback->({error=>["Mac address is not defined in the mac table for node $node."],errorcode=>[1]});
 | 
			
		||||
			next;
 | 
			
		||||
		}
 | 
			
		||||
		if (!$cpu) {
 | 
			
		||||
			#default cpu count is 1
 | 
			
		||||
			$cpu = 1;
 | 
			
		||||
		}
 | 
			
		||||
		if (!$memory) {
 | 
			
		||||
			#default memory size is 1024MB=1GB
 | 
			
		||||
			$memory = 1024;
 | 
			
		||||
		}
 | 
			
		||||
		if (!$disk) {
 | 
			
		||||
			#default disk size is 1GB
 | 
			
		||||
			$disk = 1;
 | 
			
		||||
		}				
 | 
			
		||||
		
 | 
			
		||||
		#print "$bmc, $bmc_user, $bmc_password, $mac, $cpu, $memory, $disk\n";
 | 
			
		||||
 | 
			
		||||
		#call OpenStack command to add the node into the OpenStack as
 | 
			
		||||
        #a baremetal node.
 | 
			
		||||
        my $cmd_tmp = "nova baremetal-node-create";
 | 
			
		||||
		if ($bmc) {
 | 
			
		||||
			#make sure it is an ip address
 | 
			
		||||
			if (($bmc !~ /\d+\.\d+\.\d+\.\d+/) && ($bmc !~ /:/)) {
 | 
			
		||||
				$bmc =  xCAT::NetworkUtils->getipaddr($bmc);
 | 
			
		||||
			}
 | 
			
		||||
			$cmd_tmp .= " --pm_address=$bmc";			
 | 
			
		||||
		}
 | 
			
		||||
		if ($bmc_user) {
 | 
			
		||||
			$cmd_tmp .= " --pm_user=$bmc_user";
 | 
			
		||||
		}
 | 
			
		||||
		if ($bmc_password) {
 | 
			
		||||
			$cmd_tmp .= " --pm_password=$bmc_password";
 | 
			
		||||
		}
 | 
			
		||||
		$cmd_tmp .= " $host $cpu $memory $disk $mac";
 | 
			
		||||
 
 | 
			
		||||
		my $cmd = qq~source \~/openrc;$cmd_tmp~;
 | 
			
		||||
		#print "cmd=$cmd\n";
 | 
			
		||||
		my $output =
 | 
			
		||||
			xCAT::InstUtils->xcmd($callback, $doreq, "xdsh", [$host], $cmd, 0);
 | 
			
		||||
		if ($::RUNCMD_RC != 0) {
 | 
			
		||||
			my $rsp;
 | 
			
		||||
			push @{$rsp->{data}}, "OpenStack creating baremetal node $node:";
 | 
			
		||||
			push @{$rsp->{data}}, "$output";
 | 
			
		||||
			xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  opsaddimage
 | 
			
		||||
     This function takes the xCAT nodes and register them
 | 
			
		||||
     as the OpenStack baremetal nodes
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub opsaddimage {
 | 
			
		||||
	my $request = shift;
 | 
			
		||||
	my $callback = shift;
 | 
			
		||||
	my $doreq = shift;
 | 
			
		||||
	
 | 
			
		||||
	@ARGV = @{$request->{arg}};
 | 
			
		||||
	Getopt::Long::Configure("bundling");
 | 
			
		||||
	Getopt::Long::Configure("no_pass_through");
 | 
			
		||||
	
 | 
			
		||||
	my $help;
 | 
			
		||||
	my $version;
 | 
			
		||||
	#my $cloud;
 | 
			
		||||
	my $ops_img_names;
 | 
			
		||||
    my $controller;
 | 
			
		||||
	
 | 
			
		||||
    if(!GetOptions(
 | 
			
		||||
            'h|help'      => \$help,
 | 
			
		||||
            'v|version'   => \$version,
 | 
			
		||||
            'c=s'         => \$controller,
 | 
			
		||||
			'n=s'         => \$ops_img_names,
 | 
			
		||||
       ))
 | 
			
		||||
    {
 | 
			
		||||
        &opsaddimage_usage($callback);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    # display the usage if -h or --help is specified
 | 
			
		||||
    if ($help) {
 | 
			
		||||
        &opsaddimage_usage($callback);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    # display the version statement if -v or --verison is specified
 | 
			
		||||
    if ($version)
 | 
			
		||||
    {
 | 
			
		||||
        my $rsp={};
 | 
			
		||||
        $rsp->{data}->[0]= xCAT::Utils->Version();
 | 
			
		||||
        $callback->($rsp);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
	
 | 
			
		||||
	if (@ARGV ==0) {
 | 
			
		||||
		$callback->({error=>["Please specify an image name or a list of image names."],errorcode=>[1]});
 | 
			
		||||
		return 1;  
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#make sure the input cloud name is valid.
 | 
			
		||||
	#if (!$cloud) {
 | 
			
		||||
	#	$callback->({error=>["Please specify the name of the cloud with -c flag."],errorcode=>[1]});
 | 
			
		||||
	#	return 1;  
 | 
			
		||||
	#} else {
 | 
			
		||||
	#	my $cloudstab = xCAT::Table->new('clouds', -create => 0);
 | 
			
		||||
	#	my @et = $cloudstab->getAllAttribs('name', 'controller');
 | 
			
		||||
	#	if(@et) {
 | 
			
		||||
	#		foreach my $tmp_et (@et) {
 | 
			
		||||
	#			if ($tmp_et->{name} eq $cloud) {
 | 
			
		||||
	#				if ($tmp_et->{controller}) {
 | 
			
		||||
	#					$controller = $tmp_et->{controller};
 | 
			
		||||
	#					last;
 | 
			
		||||
	#				} else {
 | 
			
		||||
	#					$callback->({error=>["Please specify the controller in the clouds table for the cloud: $cloud."],errorcode=>[1]});
 | 
			
		||||
	#					return 1;  	
 | 
			
		||||
	#				}
 | 
			
		||||
	#			}
 | 
			
		||||
	#		}
 | 
			
		||||
	#	}
 | 
			
		||||
	
 | 
			
		||||
	if (!$controller) {
 | 
			
		||||
		$callback->({error=>["Please specify the OpenStack controller node name with -c."],errorcode=>[1]});
 | 
			
		||||
		return 1;  			
 | 
			
		||||
	}
 | 
			
		||||
	#}
 | 
			
		||||
 | 
			
		||||
	#make sure that the images from the command are valid image names
 | 
			
		||||
    @images = split(',', $ARGV[0]);
 | 
			
		||||
    @new_names = ();
 | 
			
		||||
	if ($ops_img_names) {
 | 
			
		||||
		@new_names = split(',', $ops_img_names);
 | 
			
		||||
	}
 | 
			
		||||
	#print "images=@images, new image names=@new_names, controller=$controller\n";
 | 
			
		||||
 | 
			
		||||
	my $image_hash = {};
 | 
			
		||||
    my $osimgtab = xCAT::Table->new('osimage', -create => 0);
 | 
			
		||||
    my @et = $osimgtab->getAllAttribs('imagename');
 | 
			
		||||
	if(@et) {
 | 
			
		||||
		foreach my $tmp_et (@et) {
 | 
			
		||||
			$image_hash->{$tmp_et->{imagename}}{'xCAT'} = 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	my @bad_images;
 | 
			
		||||
	foreach my $image (@images) {
 | 
			
		||||
		if (!exists($image_hash->{$image})) {
 | 
			
		||||
			push @bad_images, $image;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (@bad_images > 0) {
 | 
			
		||||
		$callback->({error=>["The following images cannot be found in xCAT osimage table:\n  " . join("\n  ", @bad_images) . "\n"],errorcode=>[1]});
 | 
			
		||||
		return 1;  
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	my $index=0;
 | 
			
		||||
 	foreach my $image (@images) {
 | 
			
		||||
		my $new_name = shift(@new_names);
 | 
			
		||||
		if (!$new_name) {
 | 
			
		||||
			$new_name = $image; #the default new name is xCAT image name
 | 
			
		||||
		}
 | 
			
		||||
        my $cmd_tmp = "glance image-create --name $new_name --public --disk-format qcow2 --container-format bare --property xcat_image_name=\'$image\' < /tmp/$image.qcow2";
 | 
			
		||||
 | 
			
		||||
		my $cmd = qq~touch /tmp/$image.qcow2;source \~/openrc;$cmd_tmp;rm /tmp/$image.qcow2~;
 | 
			
		||||
		#print "cmd=$cmd\ncontroller=$controller\n";
 | 
			
		||||
		my $output =
 | 
			
		||||
			xCAT::InstUtils->xcmd($callback, $doreq, "xdsh", [$controller], $cmd, 0);
 | 
			
		||||
		if ($::RUNCMD_RC != 0) {
 | 
			
		||||
			my $rsp;
 | 
			
		||||
			push @{$rsp->{data}}, "OpenStack creating image $new_name:";
 | 
			
		||||
			push @{$rsp->{data}}, "$output";
 | 
			
		||||
			xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
			
		||||
		}		 
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  deploy_ops_bm_node
 | 
			
		||||
	This is a internel command called by OpenStack xCAT-baremetal driver. 
 | 
			
		||||
	It prepares the node by adding the config_ops_bm_node postbootscript 
 | 
			
		||||
	to the postscript table for the node, then call nodeset and then boot 
 | 
			
		||||
	the node up.
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub deploy_ops_bm_node {
 | 
			
		||||
	my $request = shift;
 | 
			
		||||
	my $callback = shift;
 | 
			
		||||
	my $doreq = shift;
 | 
			
		||||
	
 | 
			
		||||
	@ARGV = @{$request->{arg}};
 | 
			
		||||
	Getopt::Long::Configure("bundling");
 | 
			
		||||
	Getopt::Long::Configure("no_pass_through");
 | 
			
		||||
 | 
			
		||||
	my $node = $request->{node}->[0];
 | 
			
		||||
	
 | 
			
		||||
	my $help;
 | 
			
		||||
	my $version;
 | 
			
		||||
	my $img_name;
 | 
			
		||||
    my $hostname;
 | 
			
		||||
	my $fixed_ip;
 | 
			
		||||
	my $netmask;
 | 
			
		||||
	
 | 
			
		||||
    if(!GetOptions(
 | 
			
		||||
            'h|help'      => \$help,
 | 
			
		||||
            'v|version'   => \$version,
 | 
			
		||||
            'image=s'     => \$img_name,
 | 
			
		||||
			'host=s'      => \$hostname,
 | 
			
		||||
			'ip=s'        => \$fixed_ip,
 | 
			
		||||
			'mask=s'      => \$netmask,
 | 
			
		||||
       ))
 | 
			
		||||
    {
 | 
			
		||||
        &deploy_ops_bm_node_usage($callback);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    # display the usage if -h or --help is specified
 | 
			
		||||
    if ($help) {
 | 
			
		||||
        &deploy_ops_bm_node_usage($callback);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    # display the version statement if -v or --verison is specified
 | 
			
		||||
    if ($version)
 | 
			
		||||
    {
 | 
			
		||||
        my $rsp={};
 | 
			
		||||
        $rsp->{data}->[0]= xCAT::Utils->Version();
 | 
			
		||||
        $callback->($rsp);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
	print "node=$node, image=$img_name, host=$hostname, ip=$fixed_ip, mask=$netmask\n";
 | 
			
		||||
 | 
			
		||||
	#validate the image name
 | 
			
		||||
    my $osimagetab = xCAT::Table->new('osimage', -create=>1);
 | 
			
		||||
	my $ref = $osimagetab->getAttribs({imagename => $img_name}, 'imagename');
 | 
			
		||||
	if (!$ref) {
 | 
			
		||||
		$callback->({error=>["Invalid image name: $img_name."],errorcode=>[1]});
 | 
			
		||||
		return 1;  
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#check if the fixed ip is within the xCAT management network.
 | 
			
		||||
	#get the master ip address for the node then check if the master ip and 
 | 
			
		||||
	#the OpenStack fixed_ip are on the same subnet.
 | 
			
		||||
	#my $same_nw = 0;
 | 
			
		||||
	#my $master = xCAT::TableUtils->GetMasterNodeName($node);
 | 
			
		||||
	#my $master_ip = xCAT::NetworkUtils->toIP($master);
 | 
			
		||||
	#if (xCAT::NetworkUtils::isInSameSubnet($master_ip, $fixed_ip, $netmask, 0)) {
 | 
			
		||||
	#	$same_nw = 1;
 | 
			
		||||
	#}
 | 
			
		||||
	   
 | 
			
		||||
	
 | 
			
		||||
	#add config_ops_bm_node to the node's postbootscript
 | 
			
		||||
	my $script = "config_ops_bm_node $hostname $fixed_ip $netmask";
 | 
			
		||||
	add_postscript($callback, $node, $script);
 | 
			
		||||
 | 
			
		||||
    #run nodeset 
 | 
			
		||||
	my $cmd = qq~osimage=$img_name~;
 | 
			
		||||
	my $output = xCAT::Utils->runxcmd(
 | 
			
		||||
		{command => ["nodeset"],
 | 
			
		||||
		 node    => [$node], 
 | 
			
		||||
		 arg     => [$cmd]},
 | 
			
		||||
		$doreq, -1, 1);
 | 
			
		||||
	if ($::RUNCMD_RC != 0) {
 | 
			
		||||
		my $rsp;
 | 
			
		||||
		push @{$rsp->{data}}, "nodeset:";
 | 
			
		||||
		push @{$rsp->{data}}, "$output";
 | 
			
		||||
		xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}		
 | 
			
		||||
 
 | 
			
		||||
    #set boot order, assuming it is ipmi nodes for now
 | 
			
		||||
    # TODO: add support for system power hw.
 | 
			
		||||
	my $cmd = qq~net~;
 | 
			
		||||
	my $output = xCAT::Utils->runxcmd(
 | 
			
		||||
		{command => ["rsetboot"],
 | 
			
		||||
		 node    => [$node], 
 | 
			
		||||
		 arg     => [$cmd]},
 | 
			
		||||
		$doreq, -1, 1);
 | 
			
		||||
	if ($::RUNCMD_RC != 0) {
 | 
			
		||||
		my $rsp;
 | 
			
		||||
		push @{$rsp->{data}}, "rsetboot:";
 | 
			
		||||
		push @{$rsp->{data}}, "$output";
 | 
			
		||||
		xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
			
		||||
	}		
 | 
			
		||||
	
 | 
			
		||||
    #reboot the node
 | 
			
		||||
	my $cmd = qq~boot~;
 | 
			
		||||
	my $output = xCAT::Utils->runxcmd(
 | 
			
		||||
		{command => ["rpower"],
 | 
			
		||||
		 node    => [$node], 
 | 
			
		||||
		 arg     => [$cmd]},
 | 
			
		||||
		$doreq, -1, 1);
 | 
			
		||||
	if ($::RUNCMD_RC != 0) {
 | 
			
		||||
		my $rsp;
 | 
			
		||||
		push @{$rsp->{data}}, "rpower:";
 | 
			
		||||
		push @{$rsp->{data}}, "$output";
 | 
			
		||||
		xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}		
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  cleanup_ops_bm_node
 | 
			
		||||
	This is a internel command called by OpenStack xCAT-baremetal driver.
 | 
			
		||||
	It undoes all the changes made by deploy_ops_bm_node command. It removes
 | 
			
		||||
	the config_ops_bmn_ode postbootscript from the postscript table for the 
 | 
			
		||||
	node, removes the alias ip and then power off the node.
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub cleanup_ops_bm_node {
 | 
			
		||||
	my $request = shift;
 | 
			
		||||
	my $callback = shift;
 | 
			
		||||
	my $doreq = shift;
 | 
			
		||||
	
 | 
			
		||||
	@ARGV = @{$request->{arg}};
 | 
			
		||||
	Getopt::Long::Configure("bundling");
 | 
			
		||||
	Getopt::Long::Configure("no_pass_through");
 | 
			
		||||
 | 
			
		||||
	my $node = $request->{node}->[0];
 | 
			
		||||
	
 | 
			
		||||
	my $help;
 | 
			
		||||
	my $version;
 | 
			
		||||
 	my $fixed_ip;
 | 
			
		||||
	
 | 
			
		||||
    if(!GetOptions(
 | 
			
		||||
            'h|help'      => \$help,
 | 
			
		||||
            'v|version'   => \$version,
 | 
			
		||||
			'ip=s'        => \$fixed_ip,
 | 
			
		||||
       ))
 | 
			
		||||
    {
 | 
			
		||||
        &cleanup_ops_bm_node_usage($callback);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    # display the usage if -h or --help is specified
 | 
			
		||||
    if ($help) {
 | 
			
		||||
        &cleanup_ops_bm_node_usage($callback);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    # display the version statement if -v or --verison is specified
 | 
			
		||||
    if ($version)
 | 
			
		||||
    {
 | 
			
		||||
        my $rsp={};
 | 
			
		||||
        $rsp->{data}->[0]= xCAT::Utils->Version();
 | 
			
		||||
        $callback->($rsp);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
	#print "node=$node, ip=$fixed_ip\n";   
 | 
			
		||||
	
 | 
			
		||||
	#removes the config_ops_bm_node postbootscript from the postscripts table
 | 
			
		||||
	remove_postscript($callback, $node, "config_ops_bm_node");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	#run updatenode to remove the ip alias 
 | 
			
		||||
	my $cmd = qq~-P deconfig_ops_bm_node $fixed_ip~;
 | 
			
		||||
	my $output = xCAT::Utils->runxcmd(
 | 
			
		||||
		{command => ["updatenode"],
 | 
			
		||||
		 node    => [$node], 
 | 
			
		||||
		 arg     => [$cmd]},
 | 
			
		||||
		$doreq, -1, 1);
 | 
			
		||||
	if ($::RUNCMD_RC != 0) {
 | 
			
		||||
		my $rsp;
 | 
			
		||||
		push @{$rsp->{data}}, "updatenode:";
 | 
			
		||||
		push @{$rsp->{data}}, "$output";
 | 
			
		||||
		xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
    #turn the node power off
 | 
			
		||||
	$ssh_ok = 0;
 | 
			
		||||
	my $cmd = qq~stat~;
 | 
			
		||||
	my $output = xCAT::Utils->runxcmd(
 | 
			
		||||
		{command => ["rpower"],
 | 
			
		||||
		 node    => [$node], 
 | 
			
		||||
		 arg     => [$cmd]},
 | 
			
		||||
		$doreq, -1, 1);
 | 
			
		||||
 | 
			
		||||
	if ($::RUNCMD_RC != 0) {
 | 
			
		||||
		my $rsp;
 | 
			
		||||
		push @{$rsp->{data}}, "rpower:";
 | 
			
		||||
		push @{$rsp->{data}}, "$output";
 | 
			
		||||
		xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}   else {
 | 
			
		||||
		if ($output !~ /: off/) {
 | 
			
		||||
			#power off the node
 | 
			
		||||
			my $cmd = qq~off~;
 | 
			
		||||
			my $output = xCAT::Utils->runxcmd(
 | 
			
		||||
				{command => ["rpower"],
 | 
			
		||||
				 node    => [$node], 
 | 
			
		||||
				 arg     => [$cmd]},
 | 
			
		||||
				$doreq, -1, 1);
 | 
			
		||||
			if ($::RUNCMD_RC != 0) {
 | 
			
		||||
				my $rsp;
 | 
			
		||||
				push @{$rsp->{data}}, "rpower:";
 | 
			
		||||
				push @{$rsp->{data}}, "$output";
 | 
			
		||||
				xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
			
		||||
				return 1;
 | 
			
		||||
			}		
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
=head3  add_postscript
 | 
			
		||||
 | 
			
		||||
	It adds the 'config_ops_bm_node' postbootscript to the 
 | 
			
		||||
	postscript table for the given node.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
sub  add_postscript {
 | 
			
		||||
    my $callback=shift;
 | 
			
		||||
    my $node=shift;
 | 
			
		||||
	my $script=shift;
 | 
			
		||||
	print "script=$script\n";
 | 
			
		||||
 | 
			
		||||
    my $posttab=xCAT::Table->new("postscripts", -create =>1);
 | 
			
		||||
	my %setup_hash;
 | 
			
		||||
	my $ref = $posttab->getNodeAttribs($node,[qw(postscripts postbootscripts)]);
 | 
			
		||||
	my $found=0;
 | 
			
		||||
	if ($ref) {
 | 
			
		||||
		if (exists($ref->{postscripts})) {
 | 
			
		||||
		    my @a = split(/,/, $ref->{postscripts});
 | 
			
		||||
		    if (grep(/^config_ops_bm_node/, @a)) {
 | 
			
		||||
				$found = 1;
 | 
			
		||||
				if (!grep(/^$script$/, @a)) {
 | 
			
		||||
					#not exact match, must replace it with the new script
 | 
			
		||||
					for (@a) {
 | 
			
		||||
						s/^config_ops_bm_node.*$/$script/;
 | 
			
		||||
					}
 | 
			
		||||
					my $new_post = join(',', @a);
 | 
			
		||||
					$setup_hash{$node}={postscripts=>"$new_post"};
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		if (exists($ref->{postbootscripts})) {
 | 
			
		||||
		    my $post=$ref->{postbootscripts};
 | 
			
		||||
		    my @old_a=split(',', $post);
 | 
			
		||||
		    if (grep(/^config_ops_bm_node/, @old_a)) {
 | 
			
		||||
				if (!grep(/^$script$/, @old_a)) {
 | 
			
		||||
					#not exact match, will replace it with new script
 | 
			
		||||
					for (@old_a) {
 | 
			
		||||
						s/^config_ops_bm_node.*$/$script/;
 | 
			
		||||
					}
 | 
			
		||||
					my $new_postboot = join(',', @old_a);
 | 
			
		||||
					$setup_hash{$node}={postbootscripts=>"$new_postboot"};
 | 
			
		||||
				}
 | 
			
		||||
		    } else {
 | 
			
		||||
				if (! $found) {
 | 
			
		||||
					$setup_hash{$node}={postbootscripts=>"$post,$script"};
 | 
			
		||||
				}
 | 
			
		||||
		    }
 | 
			
		||||
		} else {
 | 
			
		||||
            if (! $found) {
 | 
			
		||||
				$setup_hash{$node}={postbootscripts=>"$script"};
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		$setup_hash{$node}={postbootscripts=>"$script"};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (keys(%setup_hash) > 0) {
 | 
			
		||||
	    $posttab->setNodesAttribs(\%setup_hash);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
=head3  remove_postscript
 | 
			
		||||
 | 
			
		||||
	It removes the 'config_ops_bm_node' postbootscript from 
 | 
			
		||||
	the postscript table for the given node.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
sub  remove_postscript {
 | 
			
		||||
    my $callback=shift;
 | 
			
		||||
    my $node=shift;
 | 
			
		||||
	my $script=shift;
 | 
			
		||||
 | 
			
		||||
    my $posttab=xCAT::Table->new("postscripts", -create =>1);
 | 
			
		||||
	my %setup_hash;
 | 
			
		||||
	my $ref = $posttab->getNodeAttribs($node,[qw(postscripts postbootscripts)]);
 | 
			
		||||
	my $found=0;
 | 
			
		||||
	if ($ref) {
 | 
			
		||||
		if (exists($ref->{postscripts})) {
 | 
			
		||||
		    my @old_a = split(/,/, $ref->{postscripts});
 | 
			
		||||
		    my @new_a = grep(!/^$script/, @old_a);
 | 
			
		||||
			if (scalar(@new_a) != scalar(@old_a)) {
 | 
			
		||||
				my $new_post = join(',', @new_a);
 | 
			
		||||
				$setup_hash{$node}={postscripts=>"$new_post"};
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (exists($ref->{postbootscripts})) {
 | 
			
		||||
		    my @old_b = split(/,/, $ref->{postbootscripts});
 | 
			
		||||
		    my @new_b = grep(!/^$script/, @old_b);
 | 
			
		||||
			if (scalar(@new_b) != scalar(@old_b)) {
 | 
			
		||||
				my $new_post = join(',', @new_b);
 | 
			
		||||
				$setup_hash{$node}={postbootscripts=>"$new_post"};
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (keys(%setup_hash) > 0) {
 | 
			
		||||
	    $posttab->setNodesAttribs(\%setup_hash);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  opsaddbmnode_usage
 | 
			
		||||
	The usage text for opsaddbmnode command.
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub opsaddbmnode_usage {
 | 
			
		||||
    my $cb=shift;
 | 
			
		||||
    my $rsp={};
 | 
			
		||||
 | 
			
		||||
    $rsp->{data}->[0]= "Usage: opsaddbmnode -h";
 | 
			
		||||
    $rsp->{data}->[1]= "       opsaddbmnode -v";
 | 
			
		||||
    $rsp->{data}->[2]= "       opsaddbmnode <noderange> -s <service_host>";
 | 
			
		||||
    $cb->($rsp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  opsaddimage_usage
 | 
			
		||||
	The usage text for opsaddimage command.
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub opsaddimage_usage {
 | 
			
		||||
    my $cb=shift;
 | 
			
		||||
    my $rsp={};
 | 
			
		||||
 | 
			
		||||
    $rsp->{data}->[0]= "Usage: opsaddimage -h";
 | 
			
		||||
    $rsp->{data}->[1]= "       opsaddimage -v";
 | 
			
		||||
    $rsp->{data}->[2]= "       opsaddimage <image1,image2...> [-n <new_name1,new_name2...> -c <controller>";
 | 
			
		||||
    $cb->($rsp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3   deploy_ops_bm_node_usage
 | 
			
		||||
	The usage text for deploy_ops_bm_node command.
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub deploy_ops_bm_node_usage {
 | 
			
		||||
    my $cb=shift;
 | 
			
		||||
    my $rsp={};
 | 
			
		||||
 | 
			
		||||
    $rsp->{data}->[0]= "Usage: deploy_ops_bm_node -h";
 | 
			
		||||
    $rsp->{data}->[1]= "       deploy_ops_bm_node -v";
 | 
			
		||||
    $rsp->{data}->[2]= "       deploy_ops_bm_node <node> --image <image_name> --host <ops_hostname> --ip <ops_fixed_ip> --mask <netmask>";
 | 
			
		||||
    $cb->($rsp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  cleanup_ops_bm_node_usage
 | 
			
		||||
	The usage text cleanup_ops_bm_node command.
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub cleanup_ops_bm_node_usage {
 | 
			
		||||
    my $cb=shift;
 | 
			
		||||
    my $rsp={};
 | 
			
		||||
 | 
			
		||||
    $rsp->{data}->[0]= "Usage: cleanup_ops_bm_node -h";
 | 
			
		||||
    $rsp->{data}->[1]= "       cleanup_ops_bm_node -v";
 | 
			
		||||
    $rsp->{data}->[2]= "       cleanup_ops_bm_node <node> [--ip <ops_fixed_ip>]";
 | 
			
		||||
    $cb->($rsp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
@@ -0,0 +1,17 @@
 | 
			
		||||
# Copyright (c) 2012 NTT DOCOMO, INC.
 | 
			
		||||
# All Rights Reserved.
 | 
			
		||||
#
 | 
			
		||||
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
			
		||||
#    not use this file except in compliance with the License. You may obtain
 | 
			
		||||
#    a copy of the License at
 | 
			
		||||
#
 | 
			
		||||
#         http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
#
 | 
			
		||||
#    Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
#    License for the specific language governing permissions and limitations
 | 
			
		||||
#    under the License.
 | 
			
		||||
from xcat.openstack.baremetal import driver
 | 
			
		||||
 | 
			
		||||
BareMetalDriver = driver.xCATBareMetalDriver
 | 
			
		||||
@@ -0,0 +1,255 @@
 | 
			
		||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 | 
			
		||||
# coding=utf-8
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
A driver for Bare-metal platform.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from oslo.config import cfg
 | 
			
		||||
 | 
			
		||||
from nova.compute import power_state
 | 
			
		||||
from nova import context as nova_context
 | 
			
		||||
from nova import exception
 | 
			
		||||
from nova.openstack.common import excutils
 | 
			
		||||
from nova.openstack.common.gettextutils import _
 | 
			
		||||
from nova.openstack.common import importutils
 | 
			
		||||
from nova.openstack.common import jsonutils
 | 
			
		||||
from nova.openstack.common import log as logging
 | 
			
		||||
from nova.virt.baremetal import baremetal_states
 | 
			
		||||
from nova.virt.baremetal import db
 | 
			
		||||
from nova.virt.baremetal import driver as bm_driver
 | 
			
		||||
from nova.virt.baremetal import utils as bm_utils
 | 
			
		||||
from nova.virt import driver
 | 
			
		||||
from nova.virt import firewall
 | 
			
		||||
from nova.virt.libvirt import imagecache
 | 
			
		||||
from xcat.openstack.baremetal import xcat_driver
 | 
			
		||||
from xcat.openstack.baremetal import exception as xcat_exception
 | 
			
		||||
from xcat.openstack.baremetal import power_states
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
CONF = cfg.CONF
 | 
			
		||||
CONF.import_opt('use_ipv6', 'nova.netconf')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class xCATBareMetalDriver(bm_driver.BareMetalDriver):
 | 
			
		||||
    """BareMetal hypervisor driver."""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, virtapi, read_only=False):
 | 
			
		||||
        super(xCATBareMetalDriver, self).__init__(virtapi)
 | 
			
		||||
        self.xcat = xcat_driver.xCAT()
 | 
			
		||||
 | 
			
		||||
    def _get_xCAT_image_name(self, image_meta):
 | 
			
		||||
        prop = image_meta.get('properties')
 | 
			
		||||
        xcat_image_name = prop.get('xcat_image_name')
 | 
			
		||||
        if xcat_image_name:
 | 
			
		||||
            return xcat_image_name
 | 
			
		||||
        else:
 | 
			
		||||
            raise xcat_exception.xCATInvalidImageError(image=image_meta.get('name'))
 | 
			
		||||
 | 
			
		||||
    def spawn(self, context, instance, image_meta, injected_files,
 | 
			
		||||
              admin_password, network_info=None, block_device_info=None):
 | 
			
		||||
        """
 | 
			
		||||
        Create a new instance/VM/domain on the virtualization platform.
 | 
			
		||||
 | 
			
		||||
        Once this successfully completes, the instance should be
 | 
			
		||||
        running (power_state.RUNNING).
 | 
			
		||||
 | 
			
		||||
        If this fails, any partial instance should be completely
 | 
			
		||||
        cleaned up, and the virtualization platform should be in the state
 | 
			
		||||
        that it was before this call began.
 | 
			
		||||
 | 
			
		||||
        :param context: security context
 | 
			
		||||
        :param instance: Instance object as returned by DB layer.
 | 
			
		||||
                         This function should use the data there to guide
 | 
			
		||||
                         the creation of the new instance.
 | 
			
		||||
        :param image_meta: image object returned by nova.image.glance that
 | 
			
		||||
                           defines the image from which to boot this instance
 | 
			
		||||
        :param injected_files: User files to inject into instance.
 | 
			
		||||
        :param admin_password: Administrator password to set in instance.
 | 
			
		||||
        :param network_info:
 | 
			
		||||
           :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
 | 
			
		||||
        :param block_device_info: Information about block devices to be
 | 
			
		||||
                                  attached to the instance.
 | 
			
		||||
        """
 | 
			
		||||
 	import pdb
 | 
			
		||||
	pdb.set_trace()
 | 
			
		||||
        node_uuid = self._require_node(instance)
 | 
			
		||||
        node = db.bm_node_associate_and_update(context, node_uuid,
 | 
			
		||||
                    {'instance_uuid': instance['uuid'],
 | 
			
		||||
                     'instance_name': instance['hostname'],
 | 
			
		||||
                     'task_state': baremetal_states.BUILDING})
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self._plug_vifs(instance, network_info, context=context)
 | 
			
		||||
            self._attach_block_devices(instance, block_device_info)
 | 
			
		||||
            self._start_firewall(instance, network_info)
 | 
			
		||||
 | 
			
		||||
            macs = self.macs_for_instance(instance)
 | 
			
		||||
            nodename = self.xcat.get_xcat_node_name(macs)
 | 
			
		||||
            imagename = self._get_xCAT_image_name(image_meta)
 | 
			
		||||
            hostname = instance.get('hostname')
 | 
			
		||||
            
 | 
			
		||||
            #get the network information for the new node
 | 
			
		||||
            interfaces = bm_utils.map_network_interfaces(network_info, CONF.use_ipv6)
 | 
			
		||||
            if CONF.use_ipv6:
 | 
			
		||||
                fixed_ip = interfaces[0].get('address_v6')
 | 
			
		||||
                netmask = interfaces[0].get('netmask_v6')
 | 
			
		||||
                gateway = interfaces[0].get('gateway_v6')
 | 
			
		||||
            else:
 | 
			
		||||
                fixed_ip = interfaces[0].get('address')
 | 
			
		||||
                netmask = interfaces[0].get('netmask')
 | 
			
		||||
                gateway = interfaces[0].get('gateway')
 | 
			
		||||
            #convert netmask from IPAddress to unicode string
 | 
			
		||||
            if netmask:
 | 
			
		||||
                netmask = unicode(netmask)
 | 
			
		||||
 | 
			
		||||
            #let xCAT install it
 | 
			
		||||
            bm_driver._update_state(context, node, instance, baremetal_states.DEPLOYING)
 | 
			
		||||
            self.xcat.deploy_node(nodename, imagename, hostname, fixed_ip, netmask, gateway)
 | 
			
		||||
            bm_driver._update_state(context, node, instance, baremetal_states.ACTIVE)
 | 
			
		||||
        except Exception as e: 
 | 
			
		||||
            with excutils.save_and_reraise_exception():
 | 
			
		||||
                LOG.error(_("Error occured while deploying instance %(instance)s "
 | 
			
		||||
                            "on baremetal node %(node)s: %(error)s") %
 | 
			
		||||
                          {'instance': instance['uuid'],
 | 
			
		||||
                           'node': node['uuid'],
 | 
			
		||||
                           'error':str(e)})
 | 
			
		||||
                bm_driver._update_state(context, node, instance, baremetal_states.ERROR)
 | 
			
		||||
 | 
			
		||||
    def reboot(self, context, instance, network_info, reboot_type,
 | 
			
		||||
               block_device_info=None, bad_volumes_callback=None):
 | 
			
		||||
        """Reboot the specified instance.
 | 
			
		||||
 | 
			
		||||
        After this is called successfully, the instance's state
 | 
			
		||||
        goes back to power_state.RUNNING. The virtualization
 | 
			
		||||
        platform should ensure that the reboot action has completed
 | 
			
		||||
        successfully even in cases in which the underlying domain/vm
 | 
			
		||||
        is paused or halted/stopped.
 | 
			
		||||
 | 
			
		||||
        :param instance: Instance object as returned by DB layer.
 | 
			
		||||
        :param network_info:
 | 
			
		||||
           :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
 | 
			
		||||
        :param reboot_type: Either a HARD or SOFT reboot
 | 
			
		||||
        :param block_device_info: Info pertaining to attached volumes
 | 
			
		||||
        :param bad_volumes_callback: Function to handle any bad volumes
 | 
			
		||||
            encountered
 | 
			
		||||
        """
 | 
			
		||||
        try: 
 | 
			
		||||
            node = bm_driver._get_baremetal_node_by_instance_uuid(instance['uuid'])
 | 
			
		||||
            macs = self.macs_for_instance(instance)
 | 
			
		||||
            nodename = self.xcat.get_xcat_node_name(macs)
 | 
			
		||||
            self.xcat.reboot_node(nodename)
 | 
			
		||||
            bm_driver._update_state(context, node, instance, baremetal_states.RUNNING)
 | 
			
		||||
        except xcat_exception.xCATCommandError as e: 
 | 
			
		||||
            with excutils.save_and_reraise_exception():
 | 
			
		||||
                LOG.error(_("Error occured while rebooting instance %(instance)s "
 | 
			
		||||
                            "on baremetal node %(node)s: %(error)s") %
 | 
			
		||||
                            {'instance': instance['uuid'],
 | 
			
		||||
                             'node': node['uuid'],
 | 
			
		||||
                             'error':str(e)})
 | 
			
		||||
                bm_driver._update_state(context, node, instance, baremetal_states.ERROR)
 | 
			
		||||
 | 
			
		||||
    def destroy(self, context, instance, network_info, block_device_info=None,
 | 
			
		||||
                destroy_disks=True):
 | 
			
		||||
        """Destroy (shutdown and delete) the specified instance.
 | 
			
		||||
 | 
			
		||||
        If the instance is not found (for example if networking failed), this
 | 
			
		||||
        function should still succeed.  It's probably a good idea to log a
 | 
			
		||||
        warning in that case.
 | 
			
		||||
 | 
			
		||||
        :param context: security context
 | 
			
		||||
        :param instance: Instance object as returned by DB layer.
 | 
			
		||||
        :param network_info:
 | 
			
		||||
           :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
 | 
			
		||||
        :param block_device_info: Information about block devices that should
 | 
			
		||||
                                  be detached from the instance.
 | 
			
		||||
        :param destroy_disks: Indicates if disks should be destroyed
 | 
			
		||||
        """
 | 
			
		||||
 	#import pdb
 | 
			
		||||
	#pdb.set_trace()
 | 
			
		||||
        try:
 | 
			
		||||
            node = bm_driver._get_baremetal_node_by_instance_uuid(instance['uuid'])
 | 
			
		||||
            
 | 
			
		||||
        except exception.InstanceNotFound:
 | 
			
		||||
            LOG.warning(_("Destroy function called on a non-existing instance %s")
 | 
			
		||||
                        % instance['uuid'])
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            macs = self.macs_for_instance(instance)
 | 
			
		||||
            nodename = self.xcat.get_xcat_node_name(macs)
 | 
			
		||||
            interfaces = bm_utils.map_network_interfaces(network_info, CONF.use_ipv6)
 | 
			
		||||
            fixed_ip=None
 | 
			
		||||
            if interfaces and interfaces[0]: 
 | 
			
		||||
                if CONF.use_ipv6:
 | 
			
		||||
                    fixed_ip = interfaces[0].get('address_v6')
 | 
			
		||||
                else:
 | 
			
		||||
                    fixed_ip = interfaces[0].get('address')
 | 
			
		||||
            if fixed_ip:
 | 
			
		||||
                self.xcat.cleanup_node(nodename, fixed_ip)
 | 
			
		||||
            else:
 | 
			
		||||
                self.xcat.cleanup_node(nodename)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            #just log it and move on
 | 
			
		||||
            LOG.warning(_("Destroy called with xCAT error:" + str(e)))
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self._detach_block_devices(instance, block_device_info)
 | 
			
		||||
            self._stop_firewall(instance, network_info)
 | 
			
		||||
            self._unplug_vifs(instance, network_info)
 | 
			
		||||
            
 | 
			
		||||
            bm_driver._update_state(context, node, None, baremetal_states.DELETED)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            with excutils.save_and_reraise_exception():
 | 
			
		||||
                LOG.error(_("Error occurred while destroying instance %s: %s") 
 | 
			
		||||
                          % (instance['uuid'], str(e)))
 | 
			
		||||
                bm_driver._update_state(context, node, instance,
 | 
			
		||||
                                        baremetal_states.ERROR)
 | 
			
		||||
 | 
			
		||||
    def power_off(self, instance, node=None):
 | 
			
		||||
        """Power off the specified instance."""
 | 
			
		||||
        macs = self.macs_for_instance(instance)
 | 
			
		||||
        nodename = self.xcat.get_xcat_node_name(macs)
 | 
			
		||||
        self.xcat.power_off_node(nodename)
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
    def power_on(self, context, instance, network_info, block_device_info=None,
 | 
			
		||||
                 node=None):
 | 
			
		||||
        """Power on the specified instance."""
 | 
			
		||||
        macs = self.macs_for_instance(instance)
 | 
			
		||||
        nodename = self.xcat.get_xcat_node_name(macs)
 | 
			
		||||
        self.xcat.power_on_node(nodename)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def get_console_output(self, instance):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def get_info(self, instance):
 | 
			
		||||
        """Get the current status of an instance, by name (not ID!)
 | 
			
		||||
 | 
			
		||||
        Returns a dict containing:
 | 
			
		||||
        :state:           the running state, one of the power_state codes
 | 
			
		||||
        :max_mem:         (int) the maximum memory in KBytes allowed
 | 
			
		||||
        :mem:             (int) the memory in KBytes used by the domain
 | 
			
		||||
        :num_cpu:         (int) the number of virtual CPUs for the domain
 | 
			
		||||
        :cpu_time:        (int) the CPU time used in nanoseconds
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        node = bm_driver._get_baremetal_node_by_instance_uuid(instance['uuid'])
 | 
			
		||||
        macs = self.macs_for_instance(instance)
 | 
			
		||||
        nodename = self.xcat.get_xcat_node_name(macs)
 | 
			
		||||
 | 
			
		||||
        ps = self.xcat.get_node_power_state(nodename)
 | 
			
		||||
        if ps == power_states.ON:
 | 
			
		||||
            pstate = power_state.RUNNING
 | 
			
		||||
        elif ps == power_states.OFF:
 | 
			
		||||
            pstate = power_state.SHUTDOWN
 | 
			
		||||
        else:
 | 
			
		||||
            pstate = power_state.NOSTATE
 | 
			
		||||
 | 
			
		||||
        return {'state': pstate,
 | 
			
		||||
                'max_mem': node['memory_mb'],
 | 
			
		||||
                'mem': node['memory_mb'],
 | 
			
		||||
                'num_cpu': node['cpus'],
 | 
			
		||||
                'cpu_time': 0}
 | 
			
		||||
@@ -0,0 +1,41 @@
 | 
			
		||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 | 
			
		||||
 | 
			
		||||
"""xCAT baremtal exceptions.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import functools
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
from oslo.config import cfg
 | 
			
		||||
import webob.exc
 | 
			
		||||
 | 
			
		||||
from nova.openstack.common import excutils
 | 
			
		||||
from nova.openstack.common.gettextutils import _
 | 
			
		||||
from nova.openstack.common import log as logging
 | 
			
		||||
from nova import safe_utils
 | 
			
		||||
from nova import exception as nova_exception
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
class xCATException(Exception):
 | 
			
		||||
    errmsg = _("xCAT general exception")
 | 
			
		||||
 | 
			
		||||
    def __init__(self, errmsg=None, **kwargs):
 | 
			
		||||
        if not errmsg:
 | 
			
		||||
            errmsg = self.errmsg
 | 
			
		||||
            errmsg = errmsg % kwargs
 | 
			
		||||
 | 
			
		||||
        super(xCATException, self).__init__(errmsg)
 | 
			
		||||
 | 
			
		||||
class xCATCommandError(xCATException):
 | 
			
		||||
    errmsg =  _("Error returned when calling xCAT command %(cmd)s"
 | 
			
		||||
                " for node %(node)s:%(error)s")
 | 
			
		||||
 | 
			
		||||
class xCATInvalidImageError(xCATException):
 | 
			
		||||
    errmsg = _("The image %(image)s is not an xCAT image")
 | 
			
		||||
 | 
			
		||||
class xCATDeploymentFailure(xCATException):    
 | 
			
		||||
    errmsg = _("xCAT node deployment failed for node %(node)s:%(error)s")
 | 
			
		||||
 | 
			
		||||
class xCATRebootFailure(xCATException):    
 | 
			
		||||
    errmsg = _("xCAT node rebooting failed for node %(node)s:%(error)s")
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Possible xCAT node power states.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
OFF = 'off'
 | 
			
		||||
ON = 'on'
 | 
			
		||||
ERROR = 'error'
 | 
			
		||||
@@ -0,0 +1,257 @@
 | 
			
		||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 | 
			
		||||
# coding=utf-8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Baremetal xCAT power manager.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
import stat
 | 
			
		||||
from oslo.config import cfg
 | 
			
		||||
import datetime
 | 
			
		||||
 | 
			
		||||
from nova import context as nova_context
 | 
			
		||||
from nova.virt.baremetal import baremetal_states
 | 
			
		||||
from nova.openstack.common.gettextutils import _
 | 
			
		||||
from nova.openstack.common import log as logging
 | 
			
		||||
from nova.openstack.common import loopingcall
 | 
			
		||||
from nova.openstack.common import timeutils
 | 
			
		||||
from nova import paths
 | 
			
		||||
from nova import utils
 | 
			
		||||
from xcat.openstack.baremetal import exception
 | 
			
		||||
from xcat.openstack.baremetal import power_states
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
# register configuration options
 | 
			
		||||
xcat_opts = [
 | 
			
		||||
    cfg.IntOpt('deploy_timeout',
 | 
			
		||||
                help='Timeout for node deployment. Default: 0 second (unlimited)',
 | 
			
		||||
                default=0),
 | 
			
		||||
    cfg.IntOpt('reboot_timeout',
 | 
			
		||||
                help='Timeout for rebooting a node. Default: 0 second (unlimited)',
 | 
			
		||||
                default=0),    
 | 
			
		||||
    cfg.IntOpt('deploy_checking_interval',
 | 
			
		||||
                help='Checking interval for node deployment. Default: 10 seconds',
 | 
			
		||||
                default=10),
 | 
			
		||||
    cfg.IntOpt('reboot_checking_interval',
 | 
			
		||||
                help='Checking interval for rebooting a node. Default: 5 seconds',
 | 
			
		||||
                default=5),    
 | 
			
		||||
   ]
 | 
			
		||||
xcat_group = cfg.OptGroup(name='xcat',
 | 
			
		||||
                          title='xCAT Options')
 | 
			
		||||
CONF = cfg.CONF
 | 
			
		||||
CONF.register_group(xcat_group)
 | 
			
		||||
CONF.register_opts(xcat_opts, xcat_group)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class xCAT(object):
 | 
			
		||||
    """A driver that calls xCAT funcions"""
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        #setup the path for xCAT commands
 | 
			
		||||
        #xcatroot = os.getenv('XCATROOT', '/opt/xcat/')
 | 
			
		||||
        #sys.path.append("%s/bin" % xcatroot)
 | 
			
		||||
        #sys.path.append("%s/sbin" % xcatroot)
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def _exec_xcat_command(self, command):
 | 
			
		||||
        """Calls xCAT command."""
 | 
			
		||||
        args = command.split(" ")
 | 
			
		||||
        out, err = utils.execute(*args, run_as_root=True)
 | 
			
		||||
        LOG.debug(_("xCAT command stdout: '%(out)s', stderr: '%(err)s'"),
 | 
			
		||||
                  {'out': out, 'err': err})
 | 
			
		||||
        return out, err
 | 
			
		||||
 | 
			
		||||
    def get_xcat_node_name(self, macs):
 | 
			
		||||
        """Get the xcat node name given mac addressed.
 | 
			
		||||
 | 
			
		||||
        It uses the mac address to search for the node name in xCAT.
 | 
			
		||||
        """
 | 
			
		||||
        for mac in macs:
 | 
			
		||||
            out, err = self._exec_xcat_command("lsdef -w mac=%s" % mac)
 | 
			
		||||
            if out:
 | 
			
		||||
                return out.split(" ")[0]
 | 
			
		||||
        
 | 
			
		||||
        errstr='No node found in xCAT with the following mac address: ' \
 | 
			
		||||
            + ','.join(macs)
 | 
			
		||||
        LOG.warning(errstr)
 | 
			
		||||
        raise exception.xCATCommandError(errstr)
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
    def deploy_node(self, nodename, imagename, hostname, fixed_ip, netmask, gateway):
 | 
			
		||||
        """
 | 
			
		||||
        Install the node.
 | 
			
		||||
 | 
			
		||||
        It calls xCAT command deploy_ops_bmnode which prepares the node
 | 
			
		||||
        by adding the config_ops_bm_node postbootscript to the postscript
 | 
			
		||||
        table for the node, then call nodeset and then boot the node up.
 | 
			
		||||
        """
 | 
			
		||||
        out, err = self._exec_xcat_command(
 | 
			
		||||
            "deploy_ops_bm_node %(node)s --image %(image)s"
 | 
			
		||||
            " --host %(host)s --ip %(ip)s --mask %(mask)s" 
 | 
			
		||||
            % {'node': nodename,
 | 
			
		||||
               'image': imagename,
 | 
			
		||||
               'host': hostname,
 | 
			
		||||
               'ip': fixed_ip,
 | 
			
		||||
               'mask': netmask,
 | 
			
		||||
            })
 | 
			
		||||
        if err:
 | 
			
		||||
            errstr = _("Error returned when calling xCAT deploy_ops_bm_node"
 | 
			
		||||
                       " command for node %s:%s") % (nodename, err)
 | 
			
		||||
            LOG.warning(errstr)
 | 
			
		||||
            raise exception.xCATCommandError(errstr)
 | 
			
		||||
        self._wait_for_node_deploy(nodename)
 | 
			
		||||
 | 
			
		||||
    def cleanup_node(self, nodename, fixed_ip=None):
 | 
			
		||||
        """
 | 
			
		||||
        Undo all the changes made to the node by deploy_node function.
 | 
			
		||||
 | 
			
		||||
        It calls xCAT command cleanup_ops_bm_node which removes the
 | 
			
		||||
        config_ops_bm_node postbootscript from the postscript table
 | 
			
		||||
        for the node, removes the alias ip and then power the node off.
 | 
			
		||||
        """
 | 
			
		||||
        cmd = "cleanup_ops_bm_node %s" % nodename
 | 
			
		||||
        if fixed_ip:
 | 
			
		||||
            cmd += " --ip %s" % fixed_ip
 | 
			
		||||
        out, err = self._exec_xcat_command(cmd)
 | 
			
		||||
 | 
			
		||||
        if err:
 | 
			
		||||
            errstr = _("Error returned when calling xCAT cleanup_ops_bm_node"
 | 
			
		||||
                       " command for node %s:%s") % (nodename, err)
 | 
			
		||||
            LOG.warning(errstr)
 | 
			
		||||
            raise exception.xCATCommandError(errstr)
 | 
			
		||||
 | 
			
		||||
    def power_on_node(self, nodename):
 | 
			
		||||
        """Power on the node."""
 | 
			
		||||
        state = self.get_node_power_state(nodename)
 | 
			
		||||
        if state ==  power_states.ON:
 | 
			
		||||
            LOG.warning(_("Powring on node called, but the node %s "
 | 
			
		||||
                          "is already on") % nodename)
 | 
			
		||||
        out, err = self._exec_xcat_command("rpower %s on" % nodename)
 | 
			
		||||
        if err:
 | 
			
		||||
            errstr = _("Error returned when calling xCAT rpower on"
 | 
			
		||||
                    " for node %s:%s") % (nodename, err)
 | 
			
		||||
            LOG.warning(errstr)
 | 
			
		||||
            raise exception.xCATCommandError(errstr)
 | 
			
		||||
        else:
 | 
			
		||||
            return power_states.ON
 | 
			
		||||
    
 | 
			
		||||
    def power_off_node(self, nodename):
 | 
			
		||||
        """Power off the node."""
 | 
			
		||||
        state = self.get_node_power_state(nodename)
 | 
			
		||||
        if state ==  power_states.OFF:
 | 
			
		||||
            LOG.warning(_("Powring off node called, but the node %s "
 | 
			
		||||
                          "is already off") % nodename)
 | 
			
		||||
        out, err = self._exec_xcat_command("rpower %s off" % nodename)
 | 
			
		||||
        if err:
 | 
			
		||||
            errstr = _("Error returned when calling xCAT rpower off"
 | 
			
		||||
                    " for node %s:%s") % (nodename, err)
 | 
			
		||||
            LOG.warning(errstr)
 | 
			
		||||
            raise exception.xCATCommandError(errstr)
 | 
			
		||||
        else:
 | 
			
		||||
            return power_states.OFF
 | 
			
		||||
 | 
			
		||||
    def reboot_node(self, nodename):
 | 
			
		||||
        """Reboot the node."""
 | 
			
		||||
        out, err = self._exec_xcat_command("rpower %s boot" % nodename)
 | 
			
		||||
        if err:
 | 
			
		||||
            errstr = _("Error returned when calling xCAT rpower boot"
 | 
			
		||||
                    " for node %s:%s") % (nodename, err)
 | 
			
		||||
            LOG.warning(errstr)
 | 
			
		||||
            raise exception.xCATCommandError(errstr)
 | 
			
		||||
        
 | 
			
		||||
        self._wait_for_node_reboot(nodename)
 | 
			
		||||
        return power_states.ON
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    def get_node_power_state(self, nodename):
 | 
			
		||||
        out, err = self._exec_xcat_command("rpower %s stat" % nodename)
 | 
			
		||||
        if err:
 | 
			
		||||
            errstr = _("Error returned when calling xCAT rpower stat"
 | 
			
		||||
                    " for node %s:%s") % (nodename, err)
 | 
			
		||||
            LOG.warning(errstr)
 | 
			
		||||
            raise exception.xCATCommandError(errstr)
 | 
			
		||||
        else:
 | 
			
		||||
            state = out.split(":")[1]
 | 
			
		||||
            if state:
 | 
			
		||||
                state = state.strip()
 | 
			
		||||
                if state == 'on':
 | 
			
		||||
                    return power_states.ON
 | 
			
		||||
                elif state == 'off':
 | 
			
		||||
                    return power_states.OFF
 | 
			
		||||
            
 | 
			
		||||
            return power_states.ERROR
 | 
			
		||||
            
 | 
			
		||||
    def _wait_for_node_deploy(self, nodename):
 | 
			
		||||
        """Wait for xCAT node deployment to complete."""
 | 
			
		||||
        locals = {'errstr':''}
 | 
			
		||||
 | 
			
		||||
        def _wait_for_deploy():
 | 
			
		||||
            out,err = self._exec_xcat_command("nodels %s nodelist.status" % nodename)
 | 
			
		||||
            if err:
 | 
			
		||||
                locals['errstr'] = _("Error returned when quering node status"
 | 
			
		||||
                           " for node %s:%s") % (nodename, err)
 | 
			
		||||
                LOG.warning(locals['errstr'])
 | 
			
		||||
                raise loopingcall.LoopingCallDone()
 | 
			
		||||
 | 
			
		||||
            if out:
 | 
			
		||||
                node,status = out.split(": ")
 | 
			
		||||
                if status == "booted":
 | 
			
		||||
                    LOG.info(_("Deployment for node %s completed.")
 | 
			
		||||
                             % nodename)
 | 
			
		||||
                    raise loopingcall.LoopingCallDone()
 | 
			
		||||
 | 
			
		||||
            if (CONF.xcat.deploy_timeout and
 | 
			
		||||
                    timeutils.utcnow() > expiration):
 | 
			
		||||
                locals['errstr'] = _("Timeout while waiting for"
 | 
			
		||||
                           " deployment of node %s.") % nodename
 | 
			
		||||
                LOG.warning(locals['errstr'])
 | 
			
		||||
                raise loopingcall.LoopingCallDone()
 | 
			
		||||
 | 
			
		||||
        expiration = timeutils.utcnow() + datetime.timedelta(
 | 
			
		||||
                seconds=CONF.xcat.deploy_timeout)
 | 
			
		||||
        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_deploy)
 | 
			
		||||
        # default check every 10 seconds
 | 
			
		||||
        timer.start(interval=CONF.xcat.deploy_checking_interval).wait()
 | 
			
		||||
 | 
			
		||||
        if locals['errstr']:
 | 
			
		||||
            raise exception.xCATDeploymentFailure(locals['errstr'])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def _wait_for_node_reboot(self, nodename):
 | 
			
		||||
        """Wait for xCAT node boot to complete."""
 | 
			
		||||
        locals = {'errstr':''}
 | 
			
		||||
 | 
			
		||||
        def _wait_for_reboot():
 | 
			
		||||
            out,err = self._exec_xcat_command("nodels %s nodelist.status" % nodename)
 | 
			
		||||
            if err:
 | 
			
		||||
                locals['errstr'] = _("Error returned when quering node status"
 | 
			
		||||
                           " for node %s:%s") % (nodename, err)
 | 
			
		||||
                LOG.warning(locals['errstr'])
 | 
			
		||||
                raise loopingcall.LoopingCallDone()
 | 
			
		||||
 | 
			
		||||
            if out:
 | 
			
		||||
                node,status = out.split(": ")
 | 
			
		||||
                if status == "booted":
 | 
			
		||||
                    LOG.info(_("Rebooting node %s completed.")
 | 
			
		||||
                             % nodename)
 | 
			
		||||
                    raise loopingcall.LoopingCallDone()
 | 
			
		||||
 | 
			
		||||
            if (CONF.xcat.reboot_timeout and
 | 
			
		||||
                    timeutils.utcnow() > expiration):
 | 
			
		||||
                locals['errstr'] = _("Timeout while waiting for"
 | 
			
		||||
                           " rebooting node %s.") % nodename
 | 
			
		||||
                LOG.warning(locals['errstr'])
 | 
			
		||||
                raise loopingcall.LoopingCallDone()
 | 
			
		||||
 | 
			
		||||
        expiration = timeutils.utcnow() + datetime.timedelta(
 | 
			
		||||
                seconds=CONF.xcat.reboot_timeout)
 | 
			
		||||
        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_reboot)
 | 
			
		||||
        # default check every 5 seconds
 | 
			
		||||
        timer.start(interval=CONF.xcat.reboot_checking_interval).wait()
 | 
			
		||||
 | 
			
		||||
        if locals['errstr']:
 | 
			
		||||
            raise exception.xCATRebootFailure(locals['errstr'])
 | 
			
		||||
							
								
								
									
										75
									
								
								xCAT-OpenStack-baremetal/pods/man1/opsaddbmnode.1.pod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								xCAT-OpenStack-baremetal/pods/man1/opsaddbmnode.1.pod
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
B<opsaddbmnode> - It adds xCAT baremetal nodes to an OpenStack cloud.
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
B<opsaddbmnode> I<noderange> B<-s> I<service_host>
 | 
			
		||||
 | 
			
		||||
B<opsaddbmnode> [B<-h>|B<--help>]
 | 
			
		||||
 | 
			
		||||
B<opsaddbmnode> [B<-v>|B<--version>]
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
The B<opsaddbmnode> command registers xCAT nodes to an OpenStack cloud. 
 | 
			
		||||
 | 
			
		||||
An OpenStack nova baremetal node registration command takes several node attributes:
 | 
			
		||||
=item BMC ip addresss, user id and password
 | 
			
		||||
=item Name of nova compute host which will control this baremetal node
 | 
			
		||||
=item Number of CPUs in the node
 | 
			
		||||
=item Memory in the node (MB)
 | 
			
		||||
=item Local hard disk in the node (GB)
 | 
			
		||||
=item MAC address to provision the node
 | 
			
		||||
 | 
			
		||||
The opsaddbmnode command pulls the above baremetal node information from xCAT tables and calls "nova baremetal-node-create" to register the baremetal node with the OpenStack cloud.
 | 
			
		||||
 | 
			
		||||
Please make sure the following xCAT tables are filled with correct information for the given nodes before calling this command.
 | 
			
		||||
=item ipmi (for BMC ip addresss, user id and password)
 | 
			
		||||
=item mac (for MAC address)
 | 
			
		||||
=item hwinv (for CPU, memory and disk info.)
 | 
			
		||||
 | 
			
		||||
=head1 Parameters
 | 
			
		||||
 | 
			
		||||
I<noderage> is a comma separated node or node group names. 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head1 OPTIONS
 | 
			
		||||
 | 
			
		||||
=over 10
 | 
			
		||||
 | 
			
		||||
=item B<-s>    The node name of the OpenStack compute host that hosts the baremetal nodes. 
 | 
			
		||||
 | 
			
		||||
=item B<-h|--help>     Display usage message.
 | 
			
		||||
 | 
			
		||||
=item B<-v|--version>  The Command Version.
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 RETURN VALUE
 | 
			
		||||
 | 
			
		||||
0  The command completed successfully.
 | 
			
		||||
 | 
			
		||||
1  An error has occurred.
 | 
			
		||||
 | 
			
		||||
=head1 EXAMPLES
 | 
			
		||||
 | 
			
		||||
=over 3
 | 
			
		||||
 | 
			
		||||
=item 1.
 | 
			
		||||
 | 
			
		||||
To register node1, node2 and node3 to OpenStack, sv1 is the compute host.
 | 
			
		||||
 | 
			
		||||
   opsassbmnode node1,node2,node3 -s sv1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 FILES
 | 
			
		||||
 | 
			
		||||
/opt/xcat/bin/opadddbmnode
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<opsaddimage(1)|opsaddimage.1>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										65
									
								
								xCAT-OpenStack-baremetal/pods/man1/opsaddimage.1.pod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								xCAT-OpenStack-baremetal/pods/man1/opsaddimage.1.pod
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
B<opsaddimage> - It adds or removes nodes for the vlan.
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
B<opsaddimage> I<image1,image2,...> B<-n> I<new_name1,new_name2,...> [B<-c> I<controller>]  
 | 
			
		||||
 | 
			
		||||
B<opsaddimage> [B<-h>|B<--help>]
 | 
			
		||||
 | 
			
		||||
B<opsaddimage> [B<-v>|B<--version>]
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
The B<opsaddimage> command adds a list of xCAT images into the OpenStack cloud. 
 | 
			
		||||
 | 
			
		||||
Under the cover, it creates a fake imgae and registers the fake image into OpenStack with command B<glance image-create>. It sets the property in the image to indicate that this is an xCAT image and also stores the original xCAT image name in the property for further reference. 
 | 
			
		||||
 | 
			
		||||
The xCAT image names can be listed using B<lsdef -t osimage> command.      
 | 
			
		||||
 | 
			
		||||
=head1 Parameters
 | 
			
		||||
 | 
			
		||||
I<image1,image1...> a comma separated xCAT images names. 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head1 OPTIONS
 | 
			
		||||
 | 
			
		||||
=over 10
 | 
			
		||||
 | 
			
		||||
=item B<-n>    a comma separated new image names in the OpenStack. If omitted, the default is the original xCAT image nanme.  
 | 
			
		||||
 | 
			
		||||
=item B<-c>  the node name of the OpenStack controller. This node must be an xCAT managed node.
 | 
			
		||||
 | 
			
		||||
=item B<-h|--help>     Display usage message.
 | 
			
		||||
 | 
			
		||||
=item B<-v|--version>  The Command Version.
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 RETURN VALUE
 | 
			
		||||
 | 
			
		||||
0  The command completed successfully.
 | 
			
		||||
 | 
			
		||||
1  An error has occurred.
 | 
			
		||||
 | 
			
		||||
=head1 EXAMPLES
 | 
			
		||||
 | 
			
		||||
=over 3
 | 
			
		||||
 | 
			
		||||
=item 1.
 | 
			
		||||
 | 
			
		||||
To register xCAT image rhels6.3-x86_64-install-compute into OpenStack.
 | 
			
		||||
 | 
			
		||||
  opsaddimage rhels6.3-x86_64-install-compute -c sv2
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 FILES
 | 
			
		||||
 | 
			
		||||
/opt/xcat/bin/opsaddimage
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<opsaddbmnode(1)|opsaddbmnode.1>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										187
									
								
								xCAT-OpenStack-baremetal/share/xcat/openstack/postscripts/config_ops_bm_node
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										187
									
								
								xCAT-OpenStack-baremetal/share/xcat/openstack/postscripts/config_ops_bm_node
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,187 @@
 | 
			
		||||
#!/bin/sh 
 | 
			
		||||
# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 | 
			
		||||
# xCAT post script for configuring the openstack baremetal node.
 | 
			
		||||
# The format is:
 | 
			
		||||
# config_ops_bm_node ops_hostname ops_ip ops_netmask
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
get_os_type()
 | 
			
		||||
{
 | 
			
		||||
    #get os type
 | 
			
		||||
	str_os_type=`uname | tr 'A-Z' 'a-z'`
 | 
			
		||||
	str_temp=''
 | 
			
		||||
	if [ "$str_os_type" = "linux" ];then
 | 
			
		||||
		str_temp=`echo $OSVER | grep -E '(sles|suse)'`
 | 
			
		||||
		if [ -f "/etc/debian_version" ];then
 | 
			
		||||
			str_os_type="debian"
 | 
			
		||||
		elif [ -f "/etc/SuSE-release" -o -n "$str_temp" ];then
 | 
			
		||||
			str_os_type="sles"
 | 
			
		||||
		else
 | 
			
		||||
			str_os_type="redhat"
 | 
			
		||||
		fi
 | 
			
		||||
	else
 | 
			
		||||
		str_os_type="aix"
 | 
			
		||||
	fi
 | 
			
		||||
	echo "$str_os_type"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
setup_ip()
 | 
			
		||||
{
 | 
			
		||||
	str_os_type=$1
 | 
			
		||||
    str_if_name=$2
 | 
			
		||||
    str_v4ip=$3
 | 
			
		||||
    str_v4mask=$4
 | 
			
		||||
 | 
			
		||||
	ret=`ifconfig $str_if_name |grep "inet addr" 2>&1`
 | 
			
		||||
    if [ $? -eq 0 ]; then
 | 
			
		||||
		old_ip=`echo $ret|cut -d':' -f2 |cut -d' ' -f1`
 | 
			
		||||
		old_mask=`echo $ret|cut -d':' -f4`
 | 
			
		||||
		#echo "old ip = $old_ip, old mask=$old_mask"
 | 
			
		||||
		if [ "$old_ip" == "$str_v4ip" -a "$old_mask" == "$str_v4mask" ]; then
 | 
			
		||||
			#if nic is up and the address is the same, then donothing
 | 
			
		||||
			#echo "do nothing"
 | 
			
		||||
			exit 0
 | 
			
		||||
		else
 | 
			
		||||
			#bring down the nic and reconstruct it.
 | 
			
		||||
			#echo "bring down the old nic"
 | 
			
		||||
			ifconfig $str_if_name del $old_ip
 | 
			
		||||
        fi
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
    if [ "$str_os_type" = "sles" ];then
 | 
			
		||||
        str_conf_file="/etc/sysconfig/network/ifcfg-${str_if_name}"
 | 
			
		||||
		if [ -f $str_conf_file ]; then
 | 
			
		||||
			rm $str_conf_file
 | 
			
		||||
		fi
 | 
			
		||||
        echo "DEVICE=${str_if_name}" > $str_conf_file
 | 
			
		||||
        echo "BOOTPROTO=static" >> $str_conf_file
 | 
			
		||||
        echo "IPADDR=${str_v4ip}" >> $str_conf_file
 | 
			
		||||
        echo "NETMASK=${str_v4mask}" >> $str_conf_file
 | 
			
		||||
		echo "NETWORK=''" >> $str_conf_file
 | 
			
		||||
        echo "STARTMODE=onboot" >> $str_conf_file
 | 
			
		||||
        echo "USERCONTROL=no" >> $str_conf_file
 | 
			
		||||
		ifup $str_if_name
 | 
			
		||||
    #debian ubuntu
 | 
			
		||||
    elif [ "$str_os_type" = "debian" ];then
 | 
			
		||||
        str_conf_file="/etc/network/interfaces.d/${str_if_name}"
 | 
			
		||||
		if [ -f $str_conf_file ]; then
 | 
			
		||||
			rm $str_conf_file
 | 
			
		||||
		fi
 | 
			
		||||
        echo "auto ${str_if_name}" > $str_conf_file
 | 
			
		||||
        echo "iface ${str_if_name} inet static" >> $str_conf_file
 | 
			
		||||
        echo "  address ${str_v4ip}" >> $str_conf_file
 | 
			
		||||
        echo "  netmask ${str_v4mask}" >> $str_conf_file
 | 
			
		||||
		ifconfig $str_if_name up
 | 
			
		||||
    else
 | 
			
		||||
        # Write the info to the ifcfg file for redhat
 | 
			
		||||
        str_conf_file="/etc/sysconfig/network-scripts/ifcfg-${str_if_name}"
 | 
			
		||||
		if [ -f $str_conf_file ]; then
 | 
			
		||||
			rm $str_conf_file
 | 
			
		||||
		fi
 | 
			
		||||
        echo "DEVICE=${str_if_name}" > $str_conf_file
 | 
			
		||||
        echo "BOOTPROTO=static" >> $str_conf_file
 | 
			
		||||
        echo "NM_CONTROLLED=no" >> $str_conf_file
 | 
			
		||||
        echo "IPADDR=${str_v4ip}" >> $str_conf_file
 | 
			
		||||
        echo "NETMASK=${str_v4mask}" >> $str_conf_file
 | 
			
		||||
        echo "ONBOOT=yes" >> $str_conf_file
 | 
			
		||||
		ifup $str_if_name
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
str_os_type=$(get_os_type)
 | 
			
		||||
echo "os_type=$str_os_type"
 | 
			
		||||
if [ "$str_os_type" = "aix" ]; then
 | 
			
		||||
	logger -t xcat "config_ops_bm_node dose not support AIX."
 | 
			
		||||
	echo "config_ops_bm_node dose not support AIX."
 | 
			
		||||
	exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
#change the hostname
 | 
			
		||||
if [[ -n "$1" ]]; then
 | 
			
		||||
    hostname $1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
#Add the openstack ip to the node
 | 
			
		||||
if [[ -n $2 ]]; then
 | 
			
		||||
    ops_ip=$2
 | 
			
		||||
	
 | 
			
		||||
	if [[ -z $3 ]]; then
 | 
			
		||||
        logger -t xcat "config_ops_bm_node: Please specify the netmask."
 | 
			
		||||
		echo "config_ops_bm_node: Please specify the netmask."
 | 
			
		||||
		exit 1
 | 
			
		||||
	else
 | 
			
		||||
		ops_mask=$3
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	#figure out the install nic
 | 
			
		||||
    if [[ -n $MACADDRESS ]]; then
 | 
			
		||||
        pos=0
 | 
			
		||||
        #mac has the following format: 01:02:03:04:05:0E!node5|01:02:03:05:0F!node6-eth1
 | 
			
		||||
        for x in `echo "$MACADDRESS" | tr "|" "\n"`
 | 
			
		||||
        do
 | 
			
		||||
            node=""
 | 
			
		||||
            mac=""
 | 
			
		||||
            pos=$((pos+1))
 | 
			
		||||
            i=`expr index $x !`
 | 
			
		||||
            if [[ $i -gt 0 ]]; then
 | 
			
		||||
                node=`echo ${x##*!}`
 | 
			
		||||
                mac_tmp=`echo ${x%%!*}`
 | 
			
		||||
            else
 | 
			
		||||
                mac_tmp=$x
 | 
			
		||||
            fi
 | 
			
		||||
			
 | 
			
		||||
            if [[ $pos -eq 1 ]]; then
 | 
			
		||||
                mac1=$mac_tmp
 | 
			
		||||
            fi
 | 
			
		||||
			
 | 
			
		||||
            if [[ "$PRIMARYNIC" = "$mac_tmp" ]]; then
 | 
			
		||||
                mac=$mac_tmp
 | 
			
		||||
                break
 | 
			
		||||
            fi
 | 
			
		||||
 | 
			
		||||
            if [[ -z "$PRIMARYNIC" ]] || [[ "$PRIMARYNIC" = "mac" ]]; then
 | 
			
		||||
                if [[ -z $node ]] || [[ "$node" = "$NODE" ]]; then
 | 
			
		||||
                    mac=$mac_tmp
 | 
			
		||||
                    break
 | 
			
		||||
                fi
 | 
			
		||||
            fi
 | 
			
		||||
        done
 | 
			
		||||
 | 
			
		||||
        if [[ -z $mac ]]; then
 | 
			
		||||
            if [[ -z "$PRIMARYNIC" ]] || [[ "$PRIMARYNIC" = "mac" ]]; then
 | 
			
		||||
                mac=$mac1 #if nothing mathes, take the first mac
 | 
			
		||||
            else
 | 
			
		||||
                nic=$PRIMARYNIC #or the primary nic itself is the nic
 | 
			
		||||
            fi
 | 
			
		||||
        fi
 | 
			
		||||
    else
 | 
			
		||||
        logger -t xcat "config_ops_bm_node: no mac addresses are defined in the mac table for the node $NODE"
 | 
			
		||||
        echo "config_ops_bm_node: no mac addresses are defined in the mac table for the node $NODE"
 | 
			
		||||
        index=$((index+1))
 | 
			
		||||
        continue
 | 
			
		||||
    fi
 | 
			
		||||
	echo "mac=$mac"
 | 
			
		||||
    
 | 
			
		||||
    #find the nic that has the mac
 | 
			
		||||
    if [[ -z $nic ]];  then
 | 
			
		||||
        #go to each nic to match the mac address
 | 
			
		||||
        ret=`ifconfig |grep -i $mac 2>&1`;
 | 
			
		||||
        if [ $? -eq 0 ]; then
 | 
			
		||||
           nic=`echo $ret |head -n1|cut -d' ' -f 1`
 | 
			
		||||
        else
 | 
			
		||||
            logger -t xcat "config_ops_bm_node: The mac address for the network for $NODE is not defined."
 | 
			
		||||
            echo "config_ops_bm_node: The mac address for the network for $NODE is not defined."
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
    echo "nic=$nic"
 | 
			
		||||
 | 
			
		||||
	#now setup the ip alias
 | 
			
		||||
    setup_ip $str_os_type $nic:0 $ops_ip $ops_mask 
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,65 @@
 | 
			
		||||
#!/bin/sh 
 | 
			
		||||
# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 | 
			
		||||
# xCAT post script for deconfiguring the openstack baremetal node.
 | 
			
		||||
# The format is:
 | 
			
		||||
# deconfig_ops_bm_node ops_ip
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
get_os_type()
 | 
			
		||||
{
 | 
			
		||||
    #get os type
 | 
			
		||||
	str_os_type=`uname | tr 'A-Z' 'a-z'`
 | 
			
		||||
	str_temp=''
 | 
			
		||||
	if [ "$str_os_type" = "linux" ];then
 | 
			
		||||
		str_temp=`echo $OSVER | grep -E '(sles|suse)'`
 | 
			
		||||
		if [ -f "/etc/debian_version" ];then
 | 
			
		||||
			str_os_type="debian"
 | 
			
		||||
		elif [ -f "/etc/SuSE-release" -o -n "$str_temp" ];then
 | 
			
		||||
			str_os_type="sles"
 | 
			
		||||
		else
 | 
			
		||||
			str_os_type="redhat"
 | 
			
		||||
		fi
 | 
			
		||||
	else
 | 
			
		||||
		str_os_type="aix"
 | 
			
		||||
	fi
 | 
			
		||||
	echo "$str_os_type"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
str_os_type=$(get_os_type)
 | 
			
		||||
echo "os_type=$str_os_type"
 | 
			
		||||
 | 
			
		||||
if [ $str_os_type == "aix" ]; then
 | 
			
		||||
	logger -t xcat "deconfig_ops_bm_node dose not support AIX."
 | 
			
		||||
	echo "deconfig_ops_bm_node dose not support AIX."
 | 
			
		||||
	exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
#change the hostname
 | 
			
		||||
hostname $NODE
 | 
			
		||||
 | 
			
		||||
#remove the openstack ip from the node
 | 
			
		||||
if [[ -n $1 ]]; then
 | 
			
		||||
    ops_ip=$1
 | 
			
		||||
	nic=$(ip addr | grep $ops_ip | awk '{print $NF}')	
 | 
			
		||||
	echo "nic=$nic, ops_ip=$ops_ip"
 | 
			
		||||
 | 
			
		||||
	ifconfig $nic del $ops_ip
 | 
			
		||||
 
 | 
			
		||||
	#delete the configuration file
 | 
			
		||||
    if [ "$str_os_type" = "sles" ]; then
 | 
			
		||||
        str_conf_file="/etc/sysconfig/network/ifcfg-$nic"
 | 
			
		||||
    elif [ "$str_os_type" = "debian" ]; then  #debian ubuntu
 | 
			
		||||
        str_conf_file="/etc/network/interfaces.d/$nic"
 | 
			
		||||
    else #redhat
 | 
			
		||||
        str_conf_file="/etc/sysconfig/network-scripts/ifcfg-$nic"
 | 
			
		||||
    fi
 | 
			
		||||
	if [ -f $str_conf_file ]; then
 | 
			
		||||
		rm $str_conf_file
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										103
									
								
								xCAT-OpenStack-baremetal/xCAT-OpenStack-baremetal.spec
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								xCAT-OpenStack-baremetal/xCAT-OpenStack-baremetal.spec
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
Summary: Executables and data of the xCAT baremetal driver for OpenStack
 | 
			
		||||
Name: xCAT-OpenStack-baremetal
 | 
			
		||||
Version: %(cat Version)
 | 
			
		||||
Release: snap%(date +"%Y%m%d%H%M")
 | 
			
		||||
Epoch: 4
 | 
			
		||||
License: IBM
 | 
			
		||||
Group: Applications/System
 | 
			
		||||
Source: xCAT-OpenStack-baremetal-%{version}.tar.gz
 | 
			
		||||
Packager: IBM Corp.
 | 
			
		||||
Vendor: IBM Corp.
 | 
			
		||||
Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}}
 | 
			
		||||
Prefix: /opt/xcat
 | 
			
		||||
BuildRoot: /var/tmp/%{name}-%{version}-%{release}-root
 | 
			
		||||
 | 
			
		||||
%ifos linux
 | 
			
		||||
BuildArch: noarch
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Provides: xCAT-OpenStack-baremetal = %{epoch}:%{version}
 | 
			
		||||
 | 
			
		||||
Requires: xCAT-client
 | 
			
		||||
 | 
			
		||||
%description
 | 
			
		||||
xCAT-OpenStack-baremetal provides the baremetal driver for OpenStack.
 | 
			
		||||
 | 
			
		||||
%prep
 | 
			
		||||
%setup -q -n xCAT-OpenStack-baremetal
 | 
			
		||||
%build
 | 
			
		||||
 | 
			
		||||
# Convert pods to man pages and html pages
 | 
			
		||||
./xpod2man
 | 
			
		||||
 | 
			
		||||
%install
 | 
			
		||||
# The install phase puts all of the files in the paths they should be in when the rpm is
 | 
			
		||||
# installed on a system.  The RPM_BUILD_ROOT is a simulated root file system and usually
 | 
			
		||||
# has a value like: /var/tmp/xCAT-OpenStack-baremetal-2.0-snap200802270932-root
 | 
			
		||||
rm -rf $RPM_BUILD_ROOT
 | 
			
		||||
 | 
			
		||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/bin
 | 
			
		||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/sbin
 | 
			
		||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin
 | 
			
		||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/python/xcat/openstack/baremetal
 | 
			
		||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/openstack/postscripts
 | 
			
		||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/man/man1
 | 
			
		||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/man1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
set +x
 | 
			
		||||
 | 
			
		||||
cp -R lib/* $RPM_BUILD_ROOT/%{prefix}/lib
 | 
			
		||||
cp share/xcat/openstack/postscripts/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/openstack/postscripts
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# These were built dynamically in the build phase
 | 
			
		||||
cp share/man/man1/* $RPM_BUILD_ROOT/%{prefix}/share/man/man1
 | 
			
		||||
chmod 444 $RPM_BUILD_ROOT/%{prefix}/share/man/man1/*
 | 
			
		||||
 | 
			
		||||
# These were built dynamically during the build phase
 | 
			
		||||
cp share/doc/man1/* $RPM_BUILD_ROOT/%{prefix}/share/doc/man1
 | 
			
		||||
chmod 644 $RPM_BUILD_ROOT/%{prefix}/share/doc/man1/*
 | 
			
		||||
 | 
			
		||||
# These links get made in the RPM_BUILD_ROOT/prefix area
 | 
			
		||||
ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/sbin/deploy_ops_bm_node
 | 
			
		||||
ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/sbin/cleanup_ops_bm_node
 | 
			
		||||
ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/opsaddbmnode
 | 
			
		||||
ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/opsaddimage
 | 
			
		||||
 | 
			
		||||
set -x
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%clean
 | 
			
		||||
# This step does not happen until *after* the %files packaging below
 | 
			
		||||
rm -rf $RPM_BUILD_ROOT
 | 
			
		||||
 | 
			
		||||
%files
 | 
			
		||||
%defattr(-,root,root)
 | 
			
		||||
#%doc LICENSE.html
 | 
			
		||||
# Just package everything that has been copied into RPM_BUILD_ROOT
 | 
			
		||||
%{prefix}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%changelog
 | 
			
		||||
 | 
			
		||||
%post
 | 
			
		||||
#copy the postscripts under /installl/postscripts directory on MN only
 | 
			
		||||
if [ -f "/etc/xCATMN" ]; then
 | 
			
		||||
	cp $RPM_INSTALL_PREFIX0/share/xcat/openstack/postscripts/* /install/postscripts
 | 
			
		||||
fi
 | 
			
		||||
exit 0
 | 
			
		||||
 | 
			
		||||
%preun
 | 
			
		||||
#remove postscripts under /installl/postscripts directory on MN only
 | 
			
		||||
if [ -f "/etc/xCATMN" ]; then
 | 
			
		||||
	for fn in $RPM_INSTALL_PREFIX0/share/xcat/openstack/postscripts/*
 | 
			
		||||
	do
 | 
			
		||||
		bn=`basename $fn`
 | 
			
		||||
		rm /install/postscripts/$bn
 | 
			
		||||
	done
 | 
			
		||||
fi
 | 
			
		||||
exit 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										213
									
								
								xCAT-OpenStack-baremetal/xpod2man
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										213
									
								
								xCAT-OpenStack-baremetal/xpod2man
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,213 @@
 | 
			
		||||
#!/usr/bin/perl
 | 
			
		||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 | 
			
		||||
# First builds the xCAT summary man page from Synopsis of each man page.
 | 
			
		||||
# Then converts all of the pod man pages into html (including links to each other)
 | 
			
		||||
 | 
			
		||||
# We assume that this script is run in the xCAT-vlan-2.0 dir, so everything is
 | 
			
		||||
# done relative to that.
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
#use lib '.';
 | 
			
		||||
use Pod::Man;
 | 
			
		||||
use Pod::Html;
 | 
			
		||||
 | 
			
		||||
my $poddir = 'pods';
 | 
			
		||||
my $mandir = 'share/man';
 | 
			
		||||
my $htmldir = 'share/doc';
 | 
			
		||||
my $cachedir = '/tmp';
 | 
			
		||||
 | 
			
		||||
my @pods = getPodList($poddir);
 | 
			
		||||
#foreach (@pods) { print "$_\n"; } exit;
 | 
			
		||||
 | 
			
		||||
# Build the cmd overview page.
 | 
			
		||||
writesummarypage("$poddir/man1/xcat.1.pod", @pods);
 | 
			
		||||
 | 
			
		||||
# Build the man page for each pod.
 | 
			
		||||
#mkdir($mandir) or die "Error: could not create $mandir.\n";
 | 
			
		||||
print "Converting PODs to man pages...\n";
 | 
			
		||||
foreach my $podfile (@pods) {
 | 
			
		||||
    my $manfile = $podfile;
 | 
			
		||||
    $manfile =~ s/^$poddir/$mandir/;      # change the beginning of the path
 | 
			
		||||
    $manfile =~ s/\.pod$//;			# change the ending
 | 
			
		||||
    my $mdir = $manfile;
 | 
			
		||||
    $mdir =~ s|/[^/]*$||;			# get rid of the basename part
 | 
			
		||||
	if (system("mkdir -p $mdir")) { die "Error: could not create $mdir.\n"; }
 | 
			
		||||
	my ($section) = $podfile =~ /\.(\d+)\.pod$/;
 | 
			
		||||
    convertpod2man($podfile, $manfile, $section);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
my @dummyPods = createDummyPods($poddir, \@pods);
 | 
			
		||||
 | 
			
		||||
# Build the html page for each pod.
 | 
			
		||||
#mkdir($htmldir) or die "Error: could not create $htmldir.\n";
 | 
			
		||||
print "Converting PODs to HTML pages...\n";
 | 
			
		||||
# have to clear the cache, because old entries can cause a problem
 | 
			
		||||
unlink("$cachedir/pod2htmd.tmp", "$cachedir/pod2htmi.tmp");
 | 
			
		||||
foreach my $podfile (@pods) {
 | 
			
		||||
    my $htmlfile = $podfile;
 | 
			
		||||
    $htmlfile =~ s/^$poddir/$htmldir/;      # change the beginning of the path
 | 
			
		||||
    $htmlfile =~ s/\.pod$/\.html/;			# change the ending
 | 
			
		||||
    my $hdir = $htmlfile;
 | 
			
		||||
    $hdir =~ s|/[^/]*$||;			# get rid of the basename part
 | 
			
		||||
	if (system("mkdir -p $hdir")) { die "Error: could not create $hdir.\n"; }
 | 
			
		||||
    #print "$podfile, $htmlfile, $poddir, $htmldir\n";
 | 
			
		||||
    convertpod2html($podfile, $htmlfile, $poddir, $htmldir);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Remove the dummy pods
 | 
			
		||||
unlink @dummyPods;
 | 
			
		||||
rmdir "$poddir/man7";
 | 
			
		||||
 | 
			
		||||
exit;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# To enable linking between the cmd man pages and the db man pages, need to:
 | 
			
		||||
#	grep thru the cmd pods searching for references (L<>) to any section 5 man page
 | 
			
		||||
#	if that pod does not exist, create an empty one that will satisfy pod2html
 | 
			
		||||
#	keep track of all dummy pods created, so they can be removed later
 | 
			
		||||
sub createDummyPods {
 | 
			
		||||
	my ($poddir, $pods) = @_;
 | 
			
		||||
	my $cmd = "grep -r -E 'L<.+\\([57]\\)\\|.+\\.[57]>' " . $poddir;
 | 
			
		||||
	#print "Running cmd: ", $cmd, "\n";
 | 
			
		||||
	my @lines = `$cmd`;
 | 
			
		||||
	if ($?) { print "Error running:  $cmd\n"; print join('', @lines); }
 | 
			
		||||
	#my @lines;
 | 
			
		||||
	#system($cmd);
 | 
			
		||||
	my @dummyPods;
 | 
			
		||||
	foreach my $l (@lines) {
 | 
			
		||||
		#print "$l\n";
 | 
			
		||||
		my @matches = $l =~ /L<([^\(]+)\(([57])\)\|\1\.[57]>/g;		# get all the matches in the line
 | 
			
		||||
		# The above line should create the array with every other entry being the man page name
 | 
			
		||||
		# and every other entry is the section # (5 or 7)
 | 
			
		||||
		my $cmd;
 | 
			
		||||
		while ($cmd=shift @matches) {
 | 
			
		||||
			#foreach my $m (@matches) {
 | 
			
		||||
			my $section = shift @matches;
 | 
			
		||||
			my $filename = "$poddir/man$section/$cmd.$section.pod";
 | 
			
		||||
			#print "$filename\n";
 | 
			
		||||
			if (!(grep /^$filename$/, @$pods) && !(grep /^$filename$/, @dummyPods)) { push @dummyPods, $filename; }
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	# Create these empty files
 | 
			
		||||
	print "Creating empty linked-to files: ", join(', ', @dummyPods), "\n";
 | 
			
		||||
	mkdir "$poddir/man7";
 | 
			
		||||
	foreach my $d (@dummyPods) {
 | 
			
		||||
		if (!open(TMP, ">>$d")) { warn "Could not create dummy pod file $d ($!)\n"; }
 | 
			
		||||
		else { close TMP; }
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return @dummyPods;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Recursively get the list of pod man page files.
 | 
			
		||||
sub getPodList {
 | 
			
		||||
	my $poddir = shift;
 | 
			
		||||
	my @files;
 | 
			
		||||
 | 
			
		||||
	# 1st get toplevel dir listing
 | 
			
		||||
	opendir(DIR, $poddir) or die "Error: could not read $poddir.\n";
 | 
			
		||||
	my @topdir = grep !/^\./, readdir(DIR);		# /
 | 
			
		||||
	close(DIR);
 | 
			
		||||
 | 
			
		||||
	# Now go thru each subdir (these are man1, man3, etc.)
 | 
			
		||||
	foreach my $mandir (@topdir) {
 | 
			
		||||
		opendir(DIR, "$poddir/$mandir") or die "Error: could not read $poddir/$mandir.\n";
 | 
			
		||||
		my @dir = grep !/^\./, readdir(DIR);		# /
 | 
			
		||||
		close(DIR);
 | 
			
		||||
		foreach my $file (@dir) {
 | 
			
		||||
			push @files, "$poddir/$mandir/$file";
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return sort @files;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Create the xcat man page that gives a summary description of each xcat cmd.
 | 
			
		||||
sub writesummarypage {
 | 
			
		||||
	my $file = shift;       # relative path file name of the man page
 | 
			
		||||
	# the rest of @_ contains the pod files that describe each cmd
 | 
			
		||||
 | 
			
		||||
	open(FILE, ">$file") or die "Error: could not open $file for writing.\n";
 | 
			
		||||
 | 
			
		||||
	print FILE <<'EOS1';
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
B<xcat> - extreme Cluster Administration Tool.
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
Extreme Cluster Administration Toolkit (xCAT). xCAT is a scalable distributed computing management
 | 
			
		||||
and provisioning tool that provides a unified interface for hardware control, discovery, and
 | 
			
		||||
OS diskful/diskfree deployment.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head1 XCAT DATABASE
 | 
			
		||||
 | 
			
		||||
All of the cluster configuration information is in the xCAT database.  See L<xcatdb(5)|xcatdb.5> for
 | 
			
		||||
descriptions of every table in the database.
 | 
			
		||||
 | 
			
		||||
=head1 XCAT COMMANDS
 | 
			
		||||
 | 
			
		||||
What follows is a short description of each xCAT command.  To get more information about a particular
 | 
			
		||||
command, see its man page.  Note that the commands are listed in alphabetical order B<within each section>,
 | 
			
		||||
i.e. all the commands in section 1, then the commands in section 3, etc.
 | 
			
		||||
 | 
			
		||||
=over 12
 | 
			
		||||
EOS1
 | 
			
		||||
 | 
			
		||||
# extract the summary for each cmd from its man page
 | 
			
		||||
foreach my $manpage (@_) {
 | 
			
		||||
	my ($sectionnum) = $manpage =~ /\.(\d+)\.pod$/;
 | 
			
		||||
	# Suck in the whole file, then we will parse it.
 | 
			
		||||
	open(MANPAGE, "$manpage") or die "Error: could not open $manpage for reading.\n";
 | 
			
		||||
	my @contents = <MANPAGE>;
 | 
			
		||||
	my $wholemanpage = join('', @contents);
 | 
			
		||||
	close(MANPAGE);
 | 
			
		||||
	# This regex matches: optional space, =head1, space, title, space, cmd, space, description, newline
 | 
			
		||||
	my ($cmd, $description) = $wholemanpage =~ /^\s*=head1\s+\S+\s+(\S+)\s+(.+?)\n/si;
 | 
			
		||||
	if (!defined($cmd)) { print "Warning: $manpage is not in a recognized structure.  It will be ignored.\n"; next; }
 | 
			
		||||
	if (!defined($description)) { print "Warning: $manpage does not have a description for $cmd.  It will be ignored.\n"; next; }
 | 
			
		||||
	$cmd =~ s/^.<(.+)>$/$1/;		# if the cmd name has pod formatting around it, strip it off
 | 
			
		||||
	$description =~ s/^-\s*//;		# if the description has a leading hypen, strip it off
 | 
			
		||||
	print FILE "\n=item L<$cmd($sectionnum)|$cmd.$sectionnum>\n\n".$description."\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Artificially add the xcattest cmd, because the xCAT-test rpm will add this
 | 
			
		||||
print FILE "\n=item L<xcattest(1)|xcattest.1>\n\nRun automated xCAT test cases.\n";
 | 
			
		||||
 | 
			
		||||
	print FILE <<"EOS3";
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
EOS3
 | 
			
		||||
 | 
			
		||||
	close FILE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Create the html page for one pod.
 | 
			
		||||
sub convertpod2html {
 | 
			
		||||
	my ($podfile, $htmlfile, $poddir, $htmldir) = @_;
 | 
			
		||||
 | 
			
		||||
	#TODO: use --css=<stylesheet> and --title=<pagetitle> to make the pages look better
 | 
			
		||||
	pod2html($podfile,
 | 
			
		||||
			"--outfile=$htmlfile",
 | 
			
		||||
			"--podpath=man1",
 | 
			
		||||
			"--podroot=$poddir",
 | 
			
		||||
			"--htmldir=$htmldir",
 | 
			
		||||
			"--recurse",
 | 
			
		||||
			"--cachedir=$cachedir",
 | 
			
		||||
			);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Create the man page for one pod.
 | 
			
		||||
sub convertpod2man {
 | 
			
		||||
	my ($podfile, $manfile, $section) = @_;
 | 
			
		||||
 | 
			
		||||
	my $parser = Pod::Man->new(section => $section);
 | 
			
		||||
    $parser->parse_from_file($podfile, $manfile);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user