launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #15137
[Merge] lp:~julian-edwards/maas/ephemeral_proxying_bug-1116331 into lp:maas
Scott Moser has proposed merging lp:~julian-edwards/maas/ephemeral_proxying_bug-1116331 into lp:maas.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1116331 in MAAS: "proxy not used in ephemeral or commissioning"
https://bugs.launchpad.net/maas/+bug/1116331
For more details, see:
https://code.launchpad.net/~julian-edwards/maas/ephemeral_proxying_bug-1116331/+merge/147668
--
https://code.launchpad.net/~julian-edwards/maas/ephemeral_proxying_bug-1116331/+merge/147668
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~julian-edwards/maas/ephemeral_proxying_bug-1116331 into lp:maas.
=== modified file 'contrib/preseeds_v2/enlist_userdata'
--- contrib/preseeds_v2/enlist_userdata 2012-11-30 17:35:04 +0000
+++ contrib/preseeds_v2/enlist_userdata 2013-02-11 14:13:23 +0000
@@ -1,7 +1,10 @@
#cloud-config
-# could/should set local mirror here or proxy here
-# apt_proxy: http://{{server_host}}:8000/
+{{if http_proxy}}
+apt_proxy: http_proxy
+{{else}}
+apt_proxy: http://{{server_host}}:8000/
+{{endif}}
misc_bucket:
- &maas_enlist |
=== modified file 'src/maasserver/models/node.py'
--- src/maasserver/models/node.py 2013-01-14 22:06:12 +0000
+++ src/maasserver/models/node.py 2013-02-11 14:13:23 +0000
@@ -635,7 +635,7 @@
from metadataserver.commissioning.user_data import generate_user_data
from metadataserver.models import NodeCommissionResult
- commissioning_user_data = generate_user_data()
+ commissioning_user_data = generate_user_data(nodegroup=self.nodegroup)
NodeCommissionResult.objects.clear_results(self)
self.status = NODE_STATUS.COMMISSIONING
self.owner = user
=== modified file 'src/maasserver/preseed.py'
--- src/maasserver/preseed.py 2012-11-27 10:39:51 +0000
+++ src/maasserver/preseed.py 2013-02-11 14:13:23 +0000
@@ -15,6 +15,7 @@
'compose_preseed_url',
'get_enlist_preseed',
'get_preseed',
+ 'get_preseed_context',
]
from collections import namedtuple
=== modified file 'src/maasserver/tests/test_node.py'
--- src/maasserver/tests/test_node.py 2012-12-19 12:23:48 +0000
+++ src/maasserver/tests/test_node.py 2013-02-11 14:13:23 +0000
@@ -489,6 +489,8 @@
).return_value = user_data
node.start_commissioning(factory.make_admin())
self.assertEqual(user_data, NodeUserData.objects.get_user_data(node))
+ commissioning.user_data.generate_user_data.assert_called_with(
+ nodegroup=node.nodegroup)
def test_start_commissioning_clears_node_commissioning_results(self):
node = factory.make_node(status=NODE_STATUS.DECLARED)
=== modified file 'src/metadataserver/commissioning/tests/test_user_data.py'
--- src/metadataserver/commissioning/tests/test_user_data.py 2012-12-18 12:31:47 +0000
+++ src/metadataserver/commissioning/tests/test_user_data.py 2013-02-11 14:13:23 +0000
@@ -17,6 +17,7 @@
from maasserver.testing.factory import factory
from maasserver.testing.testcase import TestCase
from maastesting.matchers import ContainsAll
+from metadataserver.commissioning import user_data
from metadataserver.commissioning.user_data import (
generate_user_data,
is_snippet,
@@ -24,6 +25,10 @@
read_snippet,
strip_name,
)
+from mock import (
+ Mock,
+ sentinel,
+ )
class TestUserData(TestCase):
@@ -72,3 +77,13 @@
'def authenticate_headers',
'def encode_multipart_data',
}))
+
+ def test_nodegroup_passed_to_get_preseed_context(self):
+ # I don't care about what effect it has, I just want to know
+ # that it was passed as it can affect the contents of
+ # `server_host` in the context.
+ fake_context = dict(http_proxy=factory.getRandomString())
+ user_data.get_preseed_context = Mock(return_value=fake_context)
+ nodegroup = sentinel.nodegroup
+ generate_user_data(nodegroup)
+ user_data.get_preseed_context.assert_called_with(nodegroup=nodegroup)
=== modified file 'src/metadataserver/commissioning/user_data.py'
--- src/metadataserver/commissioning/user_data.py 2012-12-18 12:31:47 +0000
+++ src/metadataserver/commissioning/user_data.py 2013-02-11 14:13:23 +0000
@@ -24,6 +24,7 @@
from os import listdir
import os.path
+from maasserver.preseed import get_preseed_context
import tempita
@@ -58,13 +59,12 @@
return snippet_name.replace('.', '_')
-def generate_user_data():
+def generate_user_data(nodegroup=None):
"""Produce the main commissioning script.
- The script was templated so that code snippets become easier to
- maintain, check for lint, and ideally, unit-test. However its
- contents are static: there are no variables. It's perfectly
- cacheable.
+ The main template file contains references to so-called ``snippets''
+ which are read in here, and substituted. In addition, the regular
+ preseed context variables are available (such as 'http_proxy').
:rtype: `bytes`
"""
@@ -78,4 +78,5 @@
strip_name(name): read_snippet(snippets_dir, name, encoding=encoding)
for name in list_snippets(snippets_dir)
}
+ snippets.update(get_preseed_context(nodegroup=nodegroup))
return template.substitute(snippets).encode('utf-8')
=== modified file 'src/metadataserver/commissioning/user_data.template'
--- src/metadataserver/commissioning/user_data.template 2013-02-06 13:59:35 +0000
+++ src/metadataserver/commissioning/user_data.template 2013-02-11 14:13:23 +0000
@@ -1,356 +1,365 @@
-#!/bin/sh
-#
-# This script carries inside it multiple files. When executed, it creates
-# the files into a temporary directory, downloads and extracts commissioning
-# scripts from the metadata service, and then processes the scripts.
-#
-# The commissioning scripts get run by a close equivalent of run-parts.
-# For each, the main script calls home to maas with maas-signal, posting
-# the script's output as a separate file.
-#
-#### IPMI setup ######
-# If IPMI network settings have been configured statically, you can
-# make them DHCP. If 'true', the IPMI network source will be changed
-# to DHCP.
-IPMI_CHANGE_STATIC_TO_DHCP="false"
-
-# In certain hardware, the parameters for the ipmi_si kernel module
-# might need to be specified. If you wish to send parameters, uncomment
-# the following line.
-#IPMI_SI_PARAMS="type=kcs ports=0xca2"
-
-#### script setup ######
-TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX")
-SCRIPTS_D="${TEMP_D}/commissioning.d"
-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" "$IPMI_CONFIG_D"
-
-### some utility functions ####
-aptget() {
- DEBIAN_FRONTEND=noninteractive apt-get --assume-yes -q "$@" </dev/null
-}
-
-add_bin() {
- cat > "${BIN_D}/$1"
- chmod "${2:-755}" "${BIN_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}"
-}
-
-find_creds_cfg() {
- local config="" file="" found=""
-
- # If the config location is set in environment variable, trust it.
- [ -n "${COMMISSIONING_CREDENTIALS_URL}" ] &&
- _RET="${COMMISSIONING_CREDENTIALS_URL}" && return
-
- # Go looking for local files written by cloud-init.
- for file in /etc/cloud/cloud.cfg.d/*cmdline*.cfg; do
- [ -f "$file" ] && _RET="$file" && return
- done
-
- local opt="" cmdline=""
- if [ -f /proc/cmdline ] && read cmdline < /proc/cmdline; then
- # Search through /proc/cmdline arguments:
- # cloud-config-url trumps url=
- for opt in $cmdline; do
- case "$opt" in
- url=*)
- found=${opt#url=};;
- cloud-config-url=*)
- _RET="${opt#*=}"
- return 0;;
- esac
- done
- [ -n "$found" ] && _RET="$found" && return 0
- fi
- return 1
-}
-
-# Invoke the "signal()" API call to report progress.
-# Usage: signal <status> <message>
-signal() {
- maas-signal "--config=${CRED_CFG}" "$@"
-}
-
-# Report result of a commissioning script: output file, error output
-# file if there was any error output, and return code.
-# Usage: signal <return-value> <message> <stdout-file> <stderr-file>
-signal_result() {
- local result=$1 message="$2" stdout="$3" stderr="$4"
- local files="--file=$stdout"
- if [ -f "$stderr" -a -s "$stderr" ]
- then
- files="$files --file=$stderr"
- fi
- maas-signal \
- "--config=${CRED_CFG}" \
- "--script-result=$result" \
- $files \
- WORKING "$message"
-}
-
-fail() {
- [ -z "$CRED_CFG" ] || signal FAILED "$1"
- echo "FAILED: $1" 1>&2;
- exit 1
-}
-
-write_poweroff_job() {
- cat >/etc/init/maas-poweroff.conf <<EOF
- description "poweroff when maas task is done"
- start on stopped cloud-final
- console output
- task
- script
- [ ! -e /tmp/block-poweroff ] || exit 0
- poweroff
- end script
-EOF
- # reload required due to lack of inotify in overlayfs (LP: #882147)
- initctl reload-configuration
-}
-
-main() {
- write_poweroff_job
-
- # Install tools and load modules.
- aptget update
- aptget install freeipmi-tools
- load_modules
-
- # The main function, actually execute stuff that is written below.
- local script total=0 creds=""
-
- find_creds_cfg ||
- fail "failed to find credential config"
- creds="$_RET"
-
- # Get remote credentials into a local file.
- case "$creds" in
- http://*|https://*)
- wget "$creds" -O "${TEMP_D}/my.creds" ||
- fail "failed to get credentials from $cred_cfg"
- creds="${TEMP_D}/my.creds"
- ;;
- esac
-
- # Use global name read by signal() and fail.
- CRED_CFG="$creds"
-
- # Power settings.
- local pargs=""
- if $IPMI_CHANGE_STATIC_TO_DHCP; then
- pargs="--dhcp-if-static"
- fi
- power_settings=$(maas-ipmi-autodetect --configdir "$IPMI_CONFIG_D" ${pargs})
- if [ ! -z "$power_settings" ]; then
- signal "--power-type=ipmi" "--power-parameters=${power_settings}" WORKING "finished [maas-ipmi-autodetect]"
- fi
-
- # Download and extract commissioning scripts. It will contain a
- # commissioning.d directory, so this is how $SCRIPTS_D is created.
- maas-get --config="${CRED_CFG}" maas-commissioning-scripts | tar -C "${TEMP_D}" -x
-
- # 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
- total=$(($total+1))
- done
-
- local cur=1 numpass=0 name="" failed=""
- for script in "${SCRIPTS_D}/"*; do
- [ -f "$script" -a -f "$script" ] || continue
- name=${script##*/}
- signal WORKING "starting ${name} [$cur/$total]"
- "$script" > "${OUT_D}/${name}.out" 2> "${OUT_D}/${name}.err"
- ret=$?
- signal_result \
- "$ret" "finished $name [$cur/$total]: $ret" \
- "${OUT_D}/${name}.out" \
- "${OUT_D}/${name}.err"
- if [ $ret -eq 0 ]; then
- numpass=$(($numpass+1))
- failed="${failed} ${name}"
- fi
- cur=$(($cur+1))
- done
-
- if [ $numpass -eq $total ]; then
- ( cd "${OUT_D}" &&
- signal OK "finished [$numpass/$total]" )
- return 0
- else
- ( cd "${OUT_D}" &&
- signal FAILED "failed [$numpass/$total] ($failed)" )
- return $(($count-$numpass))
- fi
-
-}
-
-load_modules() {
- modprobe ipmi_msghandler
- modprobe ipmi_devintf
- modprobe ipmi_si ${IPMI_SI_PARAMS}
- udevadm settle
-}
-
-### begin writing files ###
-
-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 glob
-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:
- found = glob.glob("/dev/ipmi[0-9]")
- if len(found):
- return (True, "UNKNOWN: %s" % " ".join(found))
- 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)
- parser.add_argument("--dhcp-if-static", action="store_true",
- dest="dhcp", help="specify config file", default=False)
-
- 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, and
- # '--dhcp-if-static' has been passed, Set it to IPMI to DHCP.
- if not is_ipmi_dhcp() and args.dhcp:
- set_ipmi_network_source("Use_DHCP")
- # allow IPMI 120 seconds to obtain an IP address
- time.sleep(120)
-
- # 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()
- if IPMI_IP_ADDRESS == "0.0.0.0":
- # if IPMI_IP_ADDRESS is 0.0.0.0, wait 60 seconds and retry.
- set_ipmi_network_source("Static")
- time.sleep(2)
- set_ipmi_network_source("Use_DHCP")
- time.sleep(60)
+#cloud-config-archive
+- content: |
+ #cloud-config
+ {{if http_proxy}}
+ apt_proxy: http_proxy
+ {{else}}
+ apt_proxy: http://{{server_host}}:8000/
+ {{endif}}
+- content: |
+ #!/bin/sh
+ #
+ # This script carries inside it multiple files. When executed, it creates
+ # the files into a temporary directory, downloads and extracts commissioning
+ # scripts from the metadata service, and then processes the scripts.
+ #
+ # The commissioning scripts get run by a close equivalent of run-parts.
+ # For each, the main script calls home to maas with maas-signal, posting
+ # the script's output as a separate file.
+ #
+ #### IPMI setup ######
+ # If IPMI network settings have been configured statically, you can
+ # make them DHCP. If 'true', the IPMI network source will be changed
+ # to DHCP.
+ IPMI_CHANGE_STATIC_TO_DHCP="false"
+
+ # In certain hardware, the parameters for the ipmi_si kernel module
+ # might need to be specified. If you wish to send parameters, uncomment
+ # the following line.
+ #IPMI_SI_PARAMS="type=kcs ports=0xca2"
+
+ #### script setup ######
+ TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX")
+ SCRIPTS_D="${TEMP_D}/commissioning.d"
+ 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" "$IPMI_CONFIG_D"
+
+ ### some utility functions ####
+ aptget() {
+ DEBIAN_FRONTEND=noninteractive apt-get --assume-yes -q "$@" </dev/null
+ }
+
+ add_bin() {
+ cat > "${BIN_D}/$1"
+ chmod "${2:-755}" "${BIN_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}"
+ }
+
+ find_creds_cfg() {
+ local config="" file="" found=""
+
+ # If the config location is set in environment variable, trust it.
+ [ -n "${COMMISSIONING_CREDENTIALS_URL}" ] &&
+ _RET="${COMMISSIONING_CREDENTIALS_URL}" && return
+
+ # Go looking for local files written by cloud-init.
+ for file in /etc/cloud/cloud.cfg.d/*cmdline*.cfg; do
+ [ -f "$file" ] && _RET="$file" && return
+ done
+
+ local opt="" cmdline=""
+ if [ -f /proc/cmdline ] && read cmdline < /proc/cmdline; then
+ # Search through /proc/cmdline arguments:
+ # cloud-config-url trumps url=
+ for opt in $cmdline; do
+ case "$opt" in
+ url=*)
+ found=${opt#url=};;
+ cloud-config-url=*)
+ _RET="${opt#*=}"
+ return 0;;
+ esac
+ done
+ [ -n "$found" ] && _RET="$found" && return 0
+ fi
+ return 1
+ }
+
+ # Invoke the "signal()" API call to report progress.
+ # Usage: signal <status> <message>
+ signal() {
+ maas-signal "--config=${CRED_CFG}" "$@"
+ }
+
+ # Report result of a commissioning script: output file, error output
+ # file if there was any error output, and return code.
+ # Usage: signal <return-value> <message> <stdout-file> <stderr-file>
+ signal_result() {
+ local result=$1 message="$2" stdout="$3" stderr="$4"
+ local files="--file=$stdout"
+ if [ -f "$stderr" -a -s "$stderr" ]
+ then
+ files="$files --file=$stderr"
+ fi
+ maas-signal \
+ "--config=${CRED_CFG}" \
+ "--script-result=$result" \
+ $files \
+ WORKING "$message"
+ }
+
+ fail() {
+ [ -z "$CRED_CFG" ] || signal FAILED "$1"
+ echo "FAILED: $1" 1>&2;
+ exit 1
+ }
+
+ write_poweroff_job() {
+ cat >/etc/init/maas-poweroff.conf <<EOF
+ description "poweroff when maas task is done"
+ start on stopped cloud-final
+ console output
+ task
+ script
+ [ ! -e /tmp/block-poweroff ] || exit 0
+ poweroff
+ end script
+ EOF
+ # reload required due to lack of inotify in overlayfs (LP: #882147)
+ initctl reload-configuration
+ }
+
+ main() {
+ write_poweroff_job
+
+ # Install tools and load modules.
+ aptget update
+ aptget install freeipmi-tools
+ load_modules
+
+ # The main function, actually execute stuff that is written below.
+ local script total=0 creds=""
+
+ find_creds_cfg ||
+ fail "failed to find credential config"
+ creds="$_RET"
+
+ # Get remote credentials into a local file.
+ case "$creds" in
+ http://*|https://*)
+ wget "$creds" -O "${TEMP_D}/my.creds" ||
+ fail "failed to get credentials from $cred_cfg"
+ creds="${TEMP_D}/my.creds"
+ ;;
+ esac
+
+ # Use global name read by signal() and fail.
+ CRED_CFG="$creds"
+
+ # Power settings.
+ local pargs=""
+ if $IPMI_CHANGE_STATIC_TO_DHCP; then
+ pargs="--dhcp-if-static"
+ fi
+ power_settings=$(maas-ipmi-autodetect --configdir "$IPMI_CONFIG_D" ${pargs})
+ if [ ! -z "$power_settings" ]; then
+ signal "--power-type=ipmi" "--power-parameters=${power_settings}" WORKING "finished [maas-ipmi-autodetect]"
+ fi
+
+ # Download and extract commissioning scripts. It will contain a
+ # commissioning.d directory, so this is how $SCRIPTS_D is created.
+ maas-get --config="${CRED_CFG}" maas-commissioning-scripts | tar -C "${TEMP_D}" -x
+
+ # 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
+ total=$(($total+1))
+ done
+
+ local cur=1 numpass=0 name="" failed=""
+ for script in "${SCRIPTS_D}/"*; do
+ [ -f "$script" -a -f "$script" ] || continue
+ name=${script##*/}
+ signal WORKING "starting ${name} [$cur/$total]"
+ "$script" > "${OUT_D}/${name}.out" 2> "${OUT_D}/${name}.err"
+ ret=$?
+ signal_result \
+ "$ret" "finished $name [$cur/$total]: $ret" \
+ "${OUT_D}/${name}.out" \
+ "${OUT_D}/${name}.err"
+ if [ $ret -eq 0 ]; then
+ numpass=$(($numpass+1))
+ failed="${failed} ${name}"
+ fi
+ cur=$(($cur+1))
+ done
+
+ if [ $numpass -eq $total ]; then
+ ( cd "${OUT_D}" &&
+ signal OK "finished [$numpass/$total]" )
+ return 0
+ else
+ ( cd "${OUT_D}" &&
+ signal FAILED "failed [$numpass/$total] ($failed)" )
+ return $(($count-$numpass))
+ fi
+
+ }
+
+ load_modules() {
+ modprobe ipmi_msghandler
+ modprobe ipmi_devintf
+ modprobe ipmi_si ${IPMI_SI_PARAMS}
+ udevadm settle
+ }
+
+ ### begin writing files ###
+
+ 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 glob
+ 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:
+ found = glob.glob("/dev/ipmi[0-9]")
+ if len(found):
+ return (True, "UNKNOWN: %s" % " ".join(found))
+ 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)
+ parser.add_argument("--dhcp-if-static", action="store_true",
+ dest="dhcp", help="specify config file", default=False)
+
+ 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, and
+ # '--dhcp-if-static' has been passed, Set it to IPMI to DHCP.
+ if not is_ipmi_dhcp() and args.dhcp:
+ set_ipmi_network_source("Use_DHCP")
+ # allow IPMI 120 seconds to obtain an IP address
+ time.sleep(120)
+
+ # 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()
-
- if IPMI_IP_ADDRESS is None or IPMI_IP_ADDRESS == "0.0.0.0":
- # Exit (to not set power params in MAAS) if no IPMI_IP_ADDRESS
- # has been detected
- exit(1)
-
- 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_api_helper.py" <<"END_MAAS_API_HELPER"
-{{maas_api_helper_py}}
-END_MAAS_API_HELPER
-
-add_bin "maas-signal" <<"END_MAAS_SIGNAL"
-{{maas_signal_py}}
-END_MAAS_SIGNAL
-
-add_bin "maas-get" <<END_MAAS_GET
-{{maas_get_py}}
-END_MAAS_GET
-
-
-main
-exit
+ if IPMI_IP_ADDRESS == "0.0.0.0":
+ # if IPMI_IP_ADDRESS is 0.0.0.0, wait 60 seconds and retry.
+ set_ipmi_network_source("Static")
+ time.sleep(2)
+ set_ipmi_network_source("Use_DHCP")
+ time.sleep(60)
+ IPMI_IP_ADDRESS = get_ipmi_ip_address()
+
+ if IPMI_IP_ADDRESS is None or IPMI_IP_ADDRESS == "0.0.0.0":
+ # Exit (to not set power params in MAAS) if no IPMI_IP_ADDRESS
+ # has been detected
+ exit(1)
+
+ 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_api_helper.py" <<"END_MAAS_API_HELPER"
+ {{maas_api_helper_py}}
+ END_MAAS_API_HELPER
+
+ add_bin "maas-signal" <<"END_MAAS_SIGNAL"
+ {{maas_signal_py}}
+ END_MAAS_SIGNAL
+
+ add_bin "maas-get" <<END_MAAS_GET
+ {{maas_get_py}}
+ END_MAAS_GET
+
+
+ main
+ exit
Follow ups