diff --git a/sql/database-fill-supplemental.sql b/sql/database-fill-supplemental.sql index efcebdb538ccd2dfaa1d29657e5912857164bd31..8122d46324424da426fbd0b959616646004db65b 100644 --- a/sql/database-fill-supplemental.sql +++ b/sql/database-fill-supplemental.sql @@ -46,6 +46,8 @@ INSERT IGNORE INTO `interface_capabilities` VALUES ('generic_10G','ethernet_defs INSERT INTO `interface_types` VALUES ('ilo2',0,1,'HP','HP iLO 2',1,'RJ45'); INSERT INTO `interface_types` VALUES ('ilo3',0,1,'HP','HP iLO 3',1,'RJ45'); INSERT INTO `interface_types` VALUES ('drac',0,1,'Dell','Dell Drac',1,'RJ45'); +INSERT INTO `interface_types` VALUES ('ipmi15',0,1,'IPMI','IPMI 1.5',1,'RJ45'); +INSERT INTO `interface_types` VALUES ('ipmi20',0,1,'IPMI','IPMI 2.0',1,'RJ45'); -- For the external link support. INSERT INTO `node_types` VALUES ('bbgeni','bbgeni',NULL,NULL,0,0,0,0,0,0,0,0,0,0,0,0); diff --git a/sql/updates/4/373 b/sql/updates/4/373 new file mode 100644 index 0000000000000000000000000000000000000000..344ab254c169b6092ed1a0716b96897103baef91 --- /dev/null +++ b/sql/updates/4/373 @@ -0,0 +1,21 @@ +# +# Add missing interface types we use for ipmi. +# +use strict; +use libdb; + +sub DoUpdate($$$) +{ + my ($dbhandle, $dbname, $version) = @_; + + DBQueryFatal("replace into `interface_types` values ". + "('ipmi15',0,1,'IPMI','IPMI 1.5',1,'RJ45')"); + DBQueryFatal("replace into `interface_types` values ". + "('ipmi20',0,1,'IPMI','IPMI 2.0',1,'RJ45')"); + return 0; +} +1; + +# Local Variables: +# mode:perl +# End: diff --git a/tbsetup/power.in b/tbsetup/power.in index 27d6056cfcce65430ebc793c05f1d7b5c34cb0de..2be542caa3dae5bfe69dbc1286222e2ecd783568 100755 --- a/tbsetup/power.in +++ b/tbsetup/power.in @@ -1,7 +1,7 @@ #!/usr/bin/perl -wT # -# Copyright (c) 2000-2012 University of Utah and the Flux Group. +# Copyright (c) 2000-2013 University of Utah and the Flux Group. # # {{{EMULAB-LICENSE # @@ -358,6 +358,7 @@ foreach my $power_id (keys %outlets) { if ($power_id eq "mail" || $power_id =~ /^whol-/ || $power_id=~ /^rmcp-/ + || $power_id eq 'ipmi15' || $power_id eq 'ipmi20' || $power_id eq 'drac' || $power_id eq 'ilo' || $power_id eq 'ilo2' || $power_id eq 'ilo3') { $type = $power_id; @@ -452,7 +453,7 @@ foreach my $power_id (keys %outlets) { ++$errors; } } elsif ($type eq 'ilo3' || $type eq 'ilo2' || $type eq 'ilo' || - $type eq 'drac') { + $type eq 'drac' || $type eq 'ipmi15' || $type eq 'ipmi20') { if (iloctrl($type,$op,@nodes)) { print "Control of $nodestr failed.\n"; ++$exitval; ++$errors; diff --git a/tbsetup/power_ilo.pm.in b/tbsetup/power_ilo.pm.in index 722001582ca5daac744929abc9ef41d94ea76452..2d0d9044988f4d9c1f28394c216b27bb101b6869 100644 --- a/tbsetup/power_ilo.pm.in +++ b/tbsetup/power_ilo.pm.in @@ -1,7 +1,7 @@ #!/usr/bin/perl -wT # -# Copyright (c) 2008-2010, 2012 University of Utah and the Flux Group. +# Copyright (c) 2008-2013 University of Utah and the Flux Group. # # {{{EMULAB-LICENSE # @@ -26,6 +26,12 @@ # # Handle iLO[23] remote power control. # Also handle DRAC since its so similar. +# +# Even though not that similar, also handle IPMI so that we +# can have per-node passwords not allowed by power_ipmi. +# "ipmi15" uses the IPMI 1.5 "lan" interface, "ipmi20" uses +# the IPMI 2.0 "lanplus" interface. +# # Node must have an interface such that role='mngmnt' and # interface_type='ilo[23]'. # @@ -58,7 +64,7 @@ my %portinfo = (); # # usage: iloctrl(type, cmd, nodes) -# type = { "ilo" | "ilo2" | "ilo3" } +# type = { "ilo" | "ilo2" | "ilo3" | "drac" | "ipmi15" | "ipmi20" } # cmd = { "cycle" | "on" | "off" } # nodes = list of one or more physical node names # @@ -113,7 +119,11 @@ sub iloctrl($$@) { my $tret; eval { - $tret = iloexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$timeout); + if ($type =~ /^ipmi/) { + $tret = ipmiexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$timeout); + } else { + $tret = iloexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$timeout); + } }; if ($@) { print "$@"; @@ -357,4 +367,68 @@ sub iloexec($$$$$$$;$) { return 0; } +# +# Arguments: $node_id,$type,$cmd,$IP,$key_role,$key_uid,$key[,$timeout] +# +sub ipmiexec($$$$$$$;$) { + my ($node_id,$type,$cmd,$IP,$key_role,$key_uid,$key,$timeout) = @_; + + if ($debug) { + print "ipmiexec called with (" . join(',',@_) . ")\n"; + } + + if (!defined($type) || !defined($cmd) || !defined($IP) + || !defined($key_role) || !defined($key_uid) || !defined($key)) { + warn "Incomplete argument list, skipping node" . + (defined($node_id)?" $node_id":""); + + return -1; + } + + if ($cmd =~ /^(cycle|reset|on|off)$/) { + $cmd = $1; + } + else { + warn "Bad IPMI power command $cmd"; + return -11; + } + + my $iface; + if ($type eq 'ipmi15') { + $iface = "lan"; + } elsif ($type eq 'ipmi20') { + $iface = "lanplus"; + } else { + warn "Unsupported IPMI type $type!"; + return -7; + } + + if ($key_role ne 'ipmi-passwd') { + warn "Unsupported IPMI key_role $key_role!"; + return -14; + } + + # XXX IPMI takes about 40 seconds to timeout and doesn't + # have an option to control?! + + my $ipmicmd = "ipmitool -I $iface -H $IP -U $key_uid -P $key power $cmd"; + if ($debug > 1) { + my $str; + ($str = $ipmicmd) =~ s/$key/XXXX/; + print "*** Executing '$str', output:\n"; + } + my $output = `$ipmicmd 2>&1`; + my $stat = $?; + if ($stat || $debug > 1) { + if ($stat) { + my $str; + ($str = $ipmicmd) =~ s/$key/XXXX/; + print "*** '$str' failed (stat=$stat):\n"; + } + print $output; + } + + return $stat; +} + 1;