launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #12894
[Merge] lp:~andreserl/maas/maas_ipmi_autodetection into lp:maas
Andres Rodriguez has proposed merging lp:~andreserl/maas/maas_ipmi_autodetection into lp:maas.
Commit message:
IPMI autodetection during commissioning
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~andreserl/maas/maas_ipmi_autodetection/+merge/127911
--
https://code.launchpad.net/~andreserl/maas/maas_ipmi_autodetection/+merge/127911
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~andreserl/maas/maas_ipmi_autodetection into lp:maas.
=== modified file 'etc/maas/commissioning-user-data'
--- etc/maas/commissioning-user-data 2012-08-03 16:36:26 +0000
+++ etc/maas/commissioning-user-data 2012-10-04 00:07:24 +0000
@@ -6,15 +6,23 @@
# main does a run-parts of all "scripts" and then calls home to maas with
# maas-signal, posting output of each of the files added with add_script()
#
+#### APT setup and installation of required binaries ####
+aptget() {
+ DEBIAN_FRONTEND=noninteractive apt-get --assume-yes -q "$@" </dev/null
+}
+aptget update
+aptget install freeipmi-tools
+
#### script setup ######
TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX")
SCRIPTS_D="${TEMP_D}/scripts"
+IPMI_CONFIG_D="${TEMP_D}/ipmi.d"
BIN_D="${TEMP_D}/bin"
OUT_D="${TEMP_D}/out"
PATH="$BIN_D:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
trap cleanup EXIT
-mkdir -p "$BIN_D" "$OUT_D" "$SCRIPTS_D"
+mkdir -p "$BIN_D" "$OUT_D" "$SCRIPTS_D" "$IPMI_CONFIG_D"
### some utility functions ####
writefile() {
@@ -29,6 +37,10 @@
cat > "${SCRIPTS_D}/$1"
chmod "${2:-755}" "${SCRIPTS_D}/$1"
}
+add_ipmi_config() {
+ cat > "${IPMI_CONFIG_D}/$1"
+ chmod "${2:-644}" "${IPMI_CONFIG_D}/$1"
+}
cleanup() {
[ -n "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
}
@@ -99,6 +111,14 @@
# use global name read by signal() and fail
CRED_CFG="$creds"
+ # power settings
+ local fargs=""
+ power_settings=$(maas-ipmi-autodetect --configdir "$IPMI_CONFIG_D")
+ if [ ! -z "power_settings" ]; then
+ fargs="--power-type=ipmi --power-parameters=$power_settings"
+ signal $fargs WORKING "finished [maas-ipmi-autodetect]"
+ fi
+
# just get a count of how many scripts there are for progress reporting
for script in "${SCRIPTS_D}/"*; do
[ -x "$script" -a -f "$script" ] || continue
@@ -139,12 +159,135 @@
}
+load_modules() {
+ modprobe ipmi_msghandler
+ modprobe ipmi_devintf
+ modprobe ipmi_si type=kcs ports=0xca2
+}
+
+### load modules ###
+load_modules
+
### begin writing files ###
add_script "01-lshw" <<"END_LSHW"
#!/bin/sh
lshw -xml
END_LSHW
+add_ipmi_config "01-user-privileges.ipmi" <<"END_IPMI_USER_PRIVILEGES"
+Section User3
+ Enable_User Yes
+ Lan_Enable_IPMI_Msgs Yes
+ Lan_Privilege_Limit Administrator
+EndSection
+END_IPMI_USER_PRIVILEGES
+
+add_ipmi_config "02-global-config.ipmi" <<"END_IPMI_CONFIG"
+Section Lan_Channel
+ Volatile_Access_Mode Always_Available
+ Volatile_Enable_User_Level_Auth Yes
+ Volatile_Channel_Privilege_Limit Administrator
+ Non_Volatile_Access_Mode Always_Available
+ Non_Volatile_Enable_User_Level_Auth Yes
+ Non_Volatile_Channel_Privilege_Limit Administrator
+EndSection
+END_IPMI_CONFIG
+
+add_bin "maas-ipmi-autodetect" <<"END_MAAS_IPMI_AUTODETECT"
+#!/usr/bin/python
+import os
+import commands
+import re
+import string
+import random
+import time
+
+def detect_ipmi():
+ # TODO: Detection could be improved.
+ (status, output) = commands.getstatusoutput('ipmi-locate')
+ show_re = re.compile('(IPMI\ Version:) (\d\.\d)')
+ res = show_re.search(output)
+ if res == None:
+ return (False, "")
+ return (True, res.group(2))
+
+def is_ipmi_dhcp():
+ (status, output) = commands.getstatusoutput('bmc-config --checkout --key-pair="Lan_Conf:IP_Address_Source"')
+ show_re = re.compile('IP_Address_Source\s+Use_DHCP')
+ res = show_re.search(output)
+ if res == None:
+ return False
+ return True
+
+def set_ipmi_network_source(source):
+ (status, output) = commands.getstatusoutput('bmc-config --commit --key-pair="Lan_Conf:IP_Address_Source=%s"' % source)
+
+def get_ipmi_ip_address():
+ (status, output) = commands.getstatusoutput('bmc-config --checkout --key-pair="Lan_Conf:IP_Address"')
+ show_re = re.compile('([0-9]{1,3}[.]?){4}')
+ res = show_re.search(output)
+ return res.group()
+
+def commit_ipmi_user_settings(user, password):
+ (status, output) = commands.getstatusoutput('bmc-config --commit --key-pair="User3:Username=%s"' % user)
+ (status, output) = commands.getstatusoutput('bmc-config --commit --key-pair="User3:Password=%s"' % password)
+
+def commit_ipmi_settings(config):
+ (status, output) = commands.getstatusoutput('bmc-config --commit --filename %s' % config)
+
+def get_maas_power_settings(user, password, ipaddress):
+ return "%s,%s,%s" % (user, password, ipaddress)
+
+def generate_random_password(min=8,max=15):
+ length=random.randint(min,max)
+ letters=string.ascii_letters+string.digits
+ return ''.join([random.choice(letters) for _ in range(length)])
+
+def main():
+
+ import argparse
+
+ parser = argparse.ArgumentParser(
+ description='send config file to modify IPMI settings with')
+ parser.add_argument("--configdir", metavar="folder",
+ help="specify config file", default=None)
+
+ args = parser.parse_args()
+
+ # Check whether IPMI exists or not.
+ (status, ipmi_version) = detect_ipmi()
+ if status != True:
+ # if False, then failed to detect ipmi
+ exit(1)
+
+ # Check whether IPMI is being set to DHCP
+ # If it is not DHCP, set it to DHCP.
+ if not is_ipmi_dhcp():
+ set_ipmi_network_source("Use_DHCP")
+ # allow IPMI 60 seconds to obtain an IP address
+ time.sleep(60)
+
+ # create user/pass
+ IPMI_MAAS_USER="maas"
+ IPMI_MAAS_PASSWORD=generate_random_password()
+
+ # Configure IPMI user/password
+ commit_ipmi_user_settings(IPMI_MAAS_USER, IPMI_MAAS_PASSWORD)
+
+ # Commit other IPMI settings
+ if args.configdir:
+ for file in os.listdir(args.configdir):
+ commit_ipmi_settings(os.path.join(args.configdir, file))
+
+ # get the IP address
+ IPMI_IP_ADDRESS = get_ipmi_ip_address()
+
+ print get_maas_power_settings(IPMI_MAAS_USER, IPMI_MAAS_PASSWORD, IPMI_IP_ADDRESS)
+
+if __name__ == '__main__':
+ main()
+END_MAAS_IPMI_AUTODETECT
+
add_bin "maas-signal" <<"END_MAAS_SIGNAL"
#!/usr/bin/python
@@ -157,9 +300,11 @@
import time
import urllib2
import yaml
+import json
MD_VERSION = "2012-03-01"
VALID_STATUS = ("OK", "FAILED", "WORKING")
+POWER_TYPES = ("ipmi", "virsh", "ether_wake")
def _encode_field(field_name, data, boundary):
@@ -292,6 +437,12 @@
help="the data source to query", default=None)
parser.add_argument("--file", dest='files',
help="file to post", action='append', default=[])
+ parser.add_argument("--post", dest='posts',
+ help="name=value pairs to post", action='append', default=[])
+ parser.add_argument("--power-type", dest='power_type',
+ help="power type.", choices=POWER_TYPES, default=None)
+ parser.add_argument("--power-parameters", dest='power_parms',
+ help="power parameters.", default=None)
parser.add_argument("status",
help="status", choices=VALID_STATUS, action='store')
@@ -317,6 +468,23 @@
"status": args.status,
"error": args.message}
+ for ent in args.posts:
+ try:
+ (key, val) = ent.split("=", 2)
+ except ValueError:
+ sys.stderr.write("'%s' had no '='" % ent)
+ sys.exit(1)
+ params[key] = val
+
+ if args.power_parms is not None:
+ params["power_type"] = args.power_type
+ power_parms = dict(
+ power_user=args.power_parms.split(",")[0],
+ power_pass=args.power_parms.split(",")[1],
+ power_address=args.power_parms.split(",")[2]
+ )
+ params["power_parameters"] = json.dumps(power_parms)
+
files = {}
for fpath in args.files:
files[os.path.basename(fpath)] = open(fpath, "r")
Follow ups