Merge branch 'master' of ssh://git.code.sf.net/p/xcat/xcat-core

finished test driver for node resource
This commit is contained in:
Bruce Potter 2014-02-26 19:34:58 -05:00
commit 316470c60d
13 changed files with 424 additions and 49 deletions

View File

@ -1824,8 +1824,8 @@ sub enableSSH
} else {
# if not a service node we need to check, before enabling
if (defined($groups_hash)) {
if ($groups_hash->{ALLGROUPS} == 1)
if (keys %$groups_hash) { # not empty
if ($groups_hash->{ALLGROUPS} == 1)
{
$enablessh=1;
}

View File

@ -145,7 +145,7 @@ sub genSSHRootKeys
Returns:
Name of the current default zone from the zone table
Example:
my $defaultzone =xCAT::Zone->getdefaultzone();
my $defaultzone =xCAT::Zone->getdefaultzone($callback);
=cut
#--------------------------------------------------------------------------------
@ -192,9 +192,107 @@ sub iszonedefined
my ($class,$zonename) = @_;
# checks the zone table to see if input zonename already in the table
my $tab = xCAT::Table->new("zone");
my $zone = $tab->getAttribs({zonename => $zonename},'sshkeydir');
$tab->close();
if (defined($zone)) {
my $zonehash = $tab->getAttribs({zonename => $zonename},'sshkeydir');
if ( keys %$zonehash) {
return 1;
}else{
return 0;
}
}
#--------------------------------------------------------------------------------
=head3 getmyzonename
Arguments:
$node -one nodename
Returns:
$zonename
Example:
my $zonename=xCAT::Zone->getmyzonename($node);
=cut
#--------------------------------------------------------------------------------
sub getmyzonename
{
my ($class,$node,$callback) = @_;
my @node;
push @node,$node;
my $zonename;
my $nodelisttab = xCAT::Table->new("nodelist");
my $nodehash = $nodelisttab->getNodesAttribs(\@node, ['zonename']);
$nodelisttab->close();
if ( defined ($nodehash->{$node}->[0]->{zonename})) { # it was defined in the nodelist table
$zonename=$nodehash->{$node}->[0]->{zonename};
} else { # get the default zone
$zonename =xCAT::Zone->getdefaultzone($callback);
}
return $zonename;
}
#--------------------------------------------------------------------------------
=head3 enableSSHbetweennodes
Arguments:
zonename
Returns:
1 if the sshbetweennodes attribute is yes/1 or undefined
0 if the sshbetweennodes attribute is no/0
Example:
xCAT::Zone->enableSSHbetweennodes($zonename);
=cut
#--------------------------------------------------------------------------------
sub enableSSHbetweennodes
{
my ($class,$node,$callback) = @_;
# finds the zone of the node
my $enablessh = 1; # default
my $zonename=xCAT::Zone->getmyzonename($node);
# reads the zone table
my $tab = xCAT::Table->new("zone");
$tab->close();
# read both keys, want to know zone is in the zone table. If sshkeydir is not there
# it is either missing or invalid anyway
my $zonehash = $tab->getAttribs({zonename => $zonename},'sshbetweennodes','sshkeydir');
if (! ( keys %$zonehash)) {
my $rsp = {};
$rsp->{error}->[0] =
"$node has a zonename: $zonename that is not define in the zone table. Remove the zonename from the node, or create the zone using mkzone. The generated mypostscript may not reflect the correct setting for ENABLESSHBETWEENNODES";
xCAT::MsgUtils->message("E", $rsp, $callback);
return $enablessh;
}
my $sshbetweennodes=$zonehash->{sshbetweennodes};
if (defined ($sshbetweennodes)) {
if (($sshbetweennodes =~ /^no$/i) || ($sshbetweennodes eq "0")) {
$enablessh = 0;
} else {
$enablessh = 1;
}
} else { # not defined default yes
$enablessh = 1 ; # default
}
return $enablessh;
}
#--------------------------------------------------------------------------------
=head3 usingzones
Arguments:
none
Returns:
1 if the zone table is not empty
0 if empty
Example:
xCAT::Zone->usingzones;
=cut
#--------------------------------------------------------------------------------
sub usingzones
{
my ($class) = @_;
# reads the zonetable
my $tab = xCAT::Table->new("zone");
my @zone = $tab->getAllAttribs('zonename');
$tab->close();
if (@zone) {
return 1;
}else{
return 0;
@ -275,7 +373,7 @@ sub getzoneinfo
unless ( xCAT::Zone->iszonedefined($zonename)) {
my $rsp = {};
$rsp->{error}->[0] =
"$node has a zonenane: $zonename that is not define in the zone table. Remove the zonename from the node, or create the zone using mkzone.";
"$node has a zonename: $zonename that is not define in the zone table. Remove the zonename from the node, or create the zone using mkzone.";
xCAT::MsgUtils->message("E", $rsp, $callback);
$::GETZONEINFO_RC =1;
return;

View File

@ -72,8 +72,8 @@ class xCATBareMetalDriver(bm_driver.BareMetalDriver):
:param block_device_info: Information about block devices to be
attached to the instance.
"""
import pdb
pdb.set_trace()
#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'],
@ -150,8 +150,8 @@ class xCATBareMetalDriver(bm_driver.BareMetalDriver):
'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):
def destroy(self, instance, network_info, block_device_info=None,
context=None):
"""Destroy (shutdown and delete) the specified instance.
If the instance is not found (for example if networking failed), this
@ -166,8 +166,9 @@ class xCATBareMetalDriver(bm_driver.BareMetalDriver):
be detached from the instance.
:param destroy_disks: Indicates if disks should be destroyed
"""
#import pdb
#pdb.set_trace()
#import pdb
#pdb.set_trace()
context = nova_context.get_admin_context()
try:
node = bm_driver._get_baremetal_node_by_instance_uuid(instance['uuid'])

View File

@ -137,6 +137,7 @@ class xCAT(object):
LOG.warning(errstr)
raise exception.xCATCommandError(errstr)
else:
self._wait_for_node_reboot(nodename)
return power_states.ON
def power_off_node(self, nodename):
@ -199,6 +200,7 @@ class xCAT(object):
if out:
node,status = out.split(": ")
status = status.strip()
if status == "booted":
LOG.info(_("Deployment for node %s completed.")
% nodename)
@ -226,7 +228,7 @@ class xCAT(object):
locals = {'errstr':''}
def _wait_for_reboot():
out,err = self._exec_xcat_command("nodels %s nodelist.status" % nodename)
out,err = self._exec_xcat_command("nodestat %s" % nodename)
if err:
locals['errstr'] = _("Error returned when quering node status"
" for node %s:%s") % (nodename, err)
@ -235,7 +237,8 @@ class xCAT(object):
if out:
node,status = out.split(": ")
if status == "booted":
status = status.strip()
if status == "sshd":
LOG.info(_("Rebooting node %s completed.")
% nodename)
raise loopingcall.LoopingCallDone()

View File

@ -12,23 +12,38 @@ B<opsaddbmnode> [B<-v>|B<--version>]
=head1 DESCRIPTION
The B<opsaddbmnode> command registers xCAT nodes to an OpenStack cloud.
The B<opsaddbmnode> command registers xCAT nodes to an OpenStack cloud. An OpenStack nova baremetal node registration command takes several node attributes:
=over
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
=back
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.
=over
=item ipmi (for BMC ip addresss, user id and password)
=item mac (for MAC address)
=item hwinv (for CPU, memory and disk info.)
=back
=head1 Parameters
I<noderage> is a comma separated node or node group names.
@ -56,7 +71,7 @@ I<noderage> is a comma separated node or node group names.
=over 3
=item 1.
=item 1
To register node1, node2 and node3 to OpenStack, sv1 is the compute host.

View File

@ -90,6 +90,34 @@ setup_ip()
fi
}
#change hostname permanently
change_host_name()
{
str_os_type=$1
str_hostname=$2
hostname $str_hostname
if [ "$str_os_type" = "sles" ];then
echo "Persistently changing the hostname not implemented yet."
#debian ubuntu
elif [ "$str_os_type" = "debian" ];then
conf_file="/etc/hostname"
echo "$str_hostname" > $conf_file
else
conf_file="/etc/sysconfig/network"
if [ ! -f $conf_file ]; then
touch $conf_file
fi
grep 'HOSTNAME' $conf_file 2>&1 > /dev/null
if [ $? -eq 0 ]; then
sed -i "s/HOSTNAME=.*/HOSTNAME=$str_hostname/" $conf_file
else
echo "HOSTNAME=$str_hostname" >> $conf_file
fi
fi
}
str_os_type=$(get_os_type)
echo "os_type=$str_os_type"
@ -101,7 +129,7 @@ fi
#change the hostname
if [[ -n "$1" ]]; then
hostname $1
change_host_name $str_os_type $1
fi
#Add the openstack ip to the node

View File

@ -26,6 +26,34 @@ get_os_type()
echo "$str_os_type"
}
#change hostname permanently
change_host_name()
{
str_os_type=$1
str_hostname=$2
hostname $str_hostname
if [ "$str_os_type" = "sles" ];then
echo "Persistently changing the hostname not implemented yet."
#debian ubuntu
elif [ "$str_os_type" = "debian" ];then
conf_file="/etc/hostname"
echo "$str_hostname" > $conf_file
else
conf_file="/etc/sysconfig/network"
if [ ! -f $conf_file ]; then
touch $conf_file
fi
grep 'HOSTNAME' $conf_file 2>&1 > /dev/null
if [ $? -eq 0 ]; then
sed -i "s/HOSTNAME=.*/HOSTNAME=$str_hostname/" $conf_file
else
echo "HOSTNAME=$str_hostname" >> $conf_file
fi
fi
}
str_os_type=$(get_os_type)
echo "os_type=$str_os_type"
@ -37,7 +65,8 @@ if [ $str_os_type == "aix" ]; then
fi
#change the hostname
hostname $NODE
#hostname $NODE
change_host_name $str_os_type $NODE
#remove the openstack ip from the node
if [[ -n $1 ]]; then

View File

@ -85,9 +85,8 @@ rm -rf $RPM_BUILD_ROOT
%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
cp $RPM_INSTALL_PREFIX0/share/xcat/openstack/postscripts/* /install/postscripts/
fi
exit 0
%preun
#remove postscripts under /installl/postscripts directory on MN only

View File

@ -16,6 +16,7 @@ use xCAT::Utils;
use xCAT::TableUtils;
use xCAT::Template;
use xCAT::SvrUtils;
use xCAT::Zone;
#use Data::Dumper;
use File::Basename;
use Socket;
@ -186,8 +187,8 @@ sub makescript {
if($entries[0]) {
$installroot = $entries[0];
}
my $tmpl="$installroot/postscripts/mypostscript.tmpl"; #the customized mypostscript template
unless ( -r $tmpl) {
$tmpl="$::XCATROOT/share/xcat/mypostscript/mypostscript.tmpl"; #the default xcat mypostscript template
}
@ -367,6 +368,16 @@ sub makescript {
}
$cloudinfo_hash = getcloudinfo($cloud_module_name, $cloud_exists);
}
# see if we are using zones. If we are then sshbetweennodes comes from the zone table not
# from the site table
my $usingzones;
if (xCAT::Zone->usingzones) {
$usingzones=1;
} else {
$usingzones=0;
}
foreach my $n (@$nodes ) {
$node = $n;
@ -477,9 +488,21 @@ sub makescript {
# for #INCLUDE_POSTBOOTSCRIPTS_LIST#
my $postbootscripts;
$postbootscripts = getPostbootScripts($node, $osimgname, $script_hash);
my $enablesshbetweennodes = enableSSHbetweennodes($node, \%::GLOBAL_SN_HASH, $groups_hash);
# if using zones then must go to the zone.sshbetweennodes
# else go to site.sshbetweennodes
my $enablesshbetweennodes;
my $zonename="\'\'";
if ($usingzones) {
$enablesshbetweennodes = enableSSHbetweennodeszones($node,$callback);
$enablesshbetweennodes = enableSSHbetweennodeszones($node,$callback);
my $tmpzonename = xCAT::Zone->getmyzonename($node,$callback);
$zonename="\'";
$zonename .= $tmpzonename;
$zonename .="\'";
} else {
$enablesshbetweennodes = enableSSHbetweennodes($node, \%::GLOBAL_SN_HASH, $groups_hash);
}
my @clients;
my $cfgres;
my $cloudres;
@ -792,7 +815,7 @@ sub getsshbetweennodes
Error:
none
Example:
my $enable = xCAT::TableUtils->enableSSH($node);
my $enable = xCAT::TableUtils->enableSSHbetweennodes($node,$sn_hash, $groups_hash);
Comments:
=cut
@ -818,6 +841,48 @@ sub enableSSHbetweennodes
}
#-------------------------------------------------------------------------------
=head3 enableSSHbetweennodeszones
Description: return how to fill in the ENABLESSHBETWEENNODES export in the mypostscript file
based on the setting in the zone table sshbetweennodes attribute
Arguments:
$node
$callback
Returns:
1 = enable ssh
0 = do not enable ssh
Globals:
none
Error:
none
Example:
my $enable = xCAT::TableUtils->enableSSHbetweennodeszones($node);
Comments:
=cut
#-----------------------------------------------------------------------------
sub enableSSHbetweennodeszones
{
my $node = shift;
my $callback = shift;
my $result;
my $enablessh=xCAT::Zone->enableSSHbetweennodes($node,$callback);
if ($enablessh == 1) {
$result = "'YES'";
} else {
$result = "'NO'";
}
return $result;
}

View File

@ -390,7 +390,8 @@ sub process_request {
# - need domain for this node
my $host = $nodehash{$n}{host};
$domain=$nodedomains{$host};
unless ($domain =~ /^\./) { $domain = '.'.$domain; }
# remove the first . at domain name since it's not accepted by high dns parser
if ($domain =~ /^\./) { $domain =~ s/^\.//;; }
($canonical,$aliasstr) = split /[ \t]+/,$names,2;
if ($aliasstr) {
@ -404,13 +405,13 @@ sub process_request {
xCAT::SvrUtils::sendmsg(":Handling $node in /etc/hosts.", $callback);
unless ($canonical =~ /$domain/) {
$canonical.=$domain;
$canonical.=".".$domain;
}
# for only the sake of comparison, ensure consistant dot suffix
unless ($canonical =~ /\.\z/) { $canonical .= '.' }
foreach my $alias (@aliases) {
unless ($alias =~ /$domain/) {
$alias .= $domain;
$alias .= ".".$domain;
}
unless ($alias =~ /\.\z/) {
$alias .= '.';
@ -505,9 +506,11 @@ sub process_request {
$ctx->{slaves}=\@slave_ips;
}
$ctx->{domain} =~ s/^\.//; # remove . if it's the first char of domain name
$ctx->{zonestotouch}->{$ctx->{domain}}=1;
foreach (@networks) {
if ($_->{domain}) {
$_->{domain} =~ s/^\.//; # remove . if it's the first char of domain name
$ctx->{zonestotouch}->{$_->{domain}}=1;
}
}
@ -796,11 +799,11 @@ sub update_zones {
xCAT::SvrUtils::sendmsg("Updating zones.", $callback);
unless ($domain =~ /^\./) {
$domain = '.'.$domain;
if ($domain =~ /^\./) { # remove . if it's the first char of domain name
$domain =~ s/^\.//;
}
unless ($name =~ /\./) {
$name .= $domain;
$name .= ".".$domain;
}
unless ($name =~ /\.\z/) {
$name .= '.';
@ -1166,9 +1169,9 @@ sub add_or_delete_records {
}
my $domain = $nodedomains{$node};
unless ($domain =~ /^\./) { $domain = '.'.$domain; }
if ($domain =~ /^\./) { $domain =~ s/^\.//; } # remove . if it's the first char of domain name
unless ($name =~ /$domain/) { $name .= $domain } # $name needs to represent fqdn, but must preserve $node as a nodename for cfg lookup
unless ($name =~ /$domain/) { $name .= ".".$domain } # $name needs to represent fqdn, but must preserve $node as a nodename for cfg lookup
if ($ctx->{hoststab} and $ctx->{hoststab}->{$node} and $ctx->{hoststab}->{$node}->[0]->{ip}) {
@ips = ($ctx->{hoststab}->{$node}->[0]->{ip});

View File

@ -111,8 +111,11 @@ sub preprocess_request
$req = &parse_xdcp_cmd($req);
}
# if xdsh need to make sure request has full path to input files
# also process -K flag and use of zones
# will set $::UPDATESNZONEDATA=1, if zones are defined, there are service nodes and using -K
$::UPDATESNZONEDATA=0;
if ($command eq "xdsh") {
$req = &parse_xdsh_cmd($req);
$req = &parse_xdsh_cmd($req,$cb);
}
# there are nodes in the xdsh command, not xdsh to an image
@ -149,6 +152,12 @@ sub preprocess_request
}
}
}
# if servicenodes and xdsh -K and using zones, then we need to sync
# /etc/xcat/sshkeys to the service nodes
if ((@snodes) && ($::UPDATESNZONEDATA==1)) {
$rc =
&syncSNZoneKeys($req, $cb, $sub_req, \@snodes);
}
# if servicenodes and (if xdcp and not pull function or xdsh -e)
# send command to service nodes first and process errors
@ -421,7 +430,9 @@ sub parse_xdcp_cmd
sub parse_xdsh_cmd
{
my $req=shift;
my $cb=shift;
my $args=$req->{arg}; # argument
my $nodes = $req->{node};
my $currpath=$req->{cwd}->[0]; # current path when command was executed
my $orgargarraySize = @{$args}; # get the size of the arg array
@ARGV = @{$args}; # get arguments
@ -498,6 +509,41 @@ sub parse_xdsh_cmd
} # end -e option
# if -k options and there are zones and service nodes, we cannot allow
# servicenodes and compute nodes in the noderange. The /etc/xcat/sshkeys directory must be sync'd
# to the service nodes first. So they must run xdsh -K to the service nodes and then to the compute
# nodes.
if (defined($options{'ssh-setup'})) {
my $tab = xCAT::Table->new("zone"); # check for zones
if ($tab){
my @zones = $tab->getAllAttribs('zonename','defaultzone');
if (@zones) { # there are zones
# check to see if service nodes and compute nodes in node range
my @SN;
my @CN;
xCAT::ServiceNodeUtils->getSNandCPnodes(\@$nodes, \@SN, \@CN);
if ((@SN > 0) && (@CN >0 )) { # there are both SN and CN
my $rsp;
$rsp->{data}->[0] =
"xdsh -K was run with a noderange containing both service nodes and compute nodes. This is not valid if using zones. You must run xdsh -K to the service nodes first to setup the service node to be able to run xdsh -K to the compute nodes. \n";
xCAT::MsgUtils->message("E", $rsp, $cb);
exit 1;
} else{ # if servicenodes for the node range this will force the update of
# the servicenode with /etc/xcat/sshkeys dir first
$::UPDATESNZONEDATA=1;
}
}
} else {
my $rsp = {};
$rsp->{error}->[0] =
"Error reading the zone table. ";
xCAT::MsgUtils->message("E", $rsp, $cb);
}
}
return $req;
}
@ -992,6 +1038,105 @@ sub process_nodes
return $newSNreq;
}
#-------------------------------------------------------
=head3 syncSNZoneKeys
Build the xdcp command to send the zone keys to the service nodes
Return an array of servicenodes that do not have errors
Returns error code:
if = 0, good return continue to process the
nodes.
if = 1, global error need to quit
=cut
#-------------------------------------------------------
sub syncSNZoneKeys
{
my $req = shift;
my $callback = shift;
my $sub_req = shift;
my $sn = shift;
my @snodes = @$sn;
$::RUNCMD_RC = 0;
my $file="/tmp/xcatzonesynclist";
# Run xdcp <servicenodes> -F /tmp/xcatzonesynclist
# can leave it , never changes and is built each time
my $content= "\"/etc/xcat/sshkeys/* -> /etc/xcat/sshkeys/\"";
`echo $content > $file`;
# xdcp rsync the file
my @sn = ();
#build the array of all service nodes
foreach my $node (@snodes)
{
# handle multiple servicenodes for one node
my @sn_list = split ',', $node;
foreach my $snode (@sn_list) {
push @sn, $snode;
}
}
@::good_SN = @sn; # initialize all good
# run the command to the servicenodes
# xdcp <sn> -F <syncfile>
my $addreq;
$addreq->{'_xcatdest'} = $::mnname;
$addreq->{node} = \@sn;
$addreq->{noderange} = \@sn;
# check input request for --nodestatus
my $args=$req->{arg}; # argument
if (grep(/^--nodestatus$/, @$args)) {
push (@{$addreq->{arg}},"--nodestatus"); # return nodestatus
}
push (@{$addreq->{arg}},"-v");
push (@{$addreq->{arg}},"-F");
push (@{$addreq->{arg}},$file);
$addreq->{command}->[0] = "xdcp"; # input command is xdsh, but we need to run xdcp -F
$addreq->{cwd}->[0] = $req->{cwd}->[0];
$addreq->{env} = $req->{env};
&process_request($addreq, $callback, $sub_req);
if ($::FAILED_NODES == 0)
{
@::good_SN = @sn; # all servicenodes were sucessful
}
else
{
@::bad_SN = @::DCP_NODES_FAILED;
# remove all failing nodes from the good list
my @tmpgoodnodes;
foreach my $gnode (@::good_SN) {
if (!grep(/$gnode/,@::bad_SN )) # if not a bad node
{
push @tmpgoodnodes, $gnode;
}
}
@::good_SN = @tmpgoodnodes;
}
# report bad service nodes
if (@::bad_SN)
{
my $rsp = {};
my $badnodes;
foreach my $badnode (@::bad_SN)
{
$badnodes .= $badnode;
$badnodes .= ", ";
}
chop $badnodes;
my $msg =
"\nThe following servicenodes: $badnodes have errors and cannot be updated\n Until the error is fixed, xdcp will not work to nodes serviced by these service nodes.";
$rsp->{data}->[0] = $msg;
xCAT::MsgUtils->message("D", $rsp, $callback);
}
return (0);
}
#-------------------------------------------------------

View File

@ -183,20 +183,6 @@ sub process_request
xCAT::MsgUtils->message("E", $rsp, $callback, 1);
exit 1;
}
# now check for service nodes in noderange. It they exist that is an error also.
my @SN;
my @CN;
xCAT::ServiceNodeUtils->getSNandCPnodes(\@nodes, \@SN, \@CN);
if (scalar(@SN))
{ # SN in the nodelist
my $nodes=join(',', @SN);
my $rsp = {};
$rsp->{error}->[0] =
"You must not run $command and include any service nodes: $nodes.";
xCAT::MsgUtils->message("E", $rsp, $callback, 1);
exit 1;
}
# now check for service nodes in noderange. It they exist that is an error also.
}

View File

@ -9,6 +9,9 @@
ENABLESSHBETWEENNODES=$ENABLESSHBETWEENNODES
export ENABLESSHBETWEENNODES
ZONENAME=$ZONENAME
export ZONENAME
## tabdump(<TABLENAME>) is used to get all the information
## in the <TABLENAME> table
## The <TABLENAME> should only be non-"node key" table