Merge lp:~julian-edwards/maas/ipmi-with-mac into lp:~maas-committers/maas/trunk

Proposed by Julian Edwards
Status: Merged
Approved by: Julian Edwards
Approved revision: no longer in the source branch.
Merged at revision: 2029
Proposed branch: lp:~julian-edwards/maas/ipmi-with-mac
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 102 lines (+21/-8)
6 files modified
etc/maas/templates/power/ipmi.template (+6/-0)
src/maasserver/models/node.py (+2/-2)
src/maasserver/models/tests/test_node.py (+6/-4)
src/maasserver/power_parameters.py (+5/-1)
src/provisioningserver/power/tests/test_poweraction.py (+1/-1)
src/provisioningserver/tasks.py (+1/-0)
To merge this branch: bzr merge lp:~julian-edwards/maas/ipmi-with-mac
Reviewer Review Type Date Requested Status
Jeroen T. Vermeulen (community) Approve
Review via email: mp+208286@code.launchpad.net

Commit message

Allow IPMI to define the MAC address of the BMC in its parameters, and use the ARPed IP address in preference to the IP address in power_address. This is the first exploratory step in removing power_address entirely because it is too unreliable in the face of changing DHCP addresses.

Description of the change

This branch has the side effect of fixing an AMT problem I just noticed - if someone was not setting any power parameters and relying on the node's mac address, the power_pass would never get sent to the template!

To post a comment you must log in.
Revision history for this message
Tycho Andersen (tycho-s) wrote :

Looks good, thanks!

Revision history for this message
MAAS Lander (maas-lander) wrote :

Attempt to merge into lp:maas failed due to conflicts:

text conflict in src/maasserver/power_parameters.py

Revision history for this message
Julian Edwards (julian-edwards) wrote :

Let me also add that I have tested this on my Microservers. If the MAC is invalid or can't be found it calls back to the configured IP address, otherwise seems to work fine.

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Well done for actually documenting your intentions. I guess the lookup of the IP address was already in there somewhere.

One thing that still makes me nervous is the "primary MAC" idea — what if an existing installation upgrades, has its power addresses changed, and now finds that a node's primary MAC wasn't on a network that talks to the cluster controller? Once we start auto-discovering networks, we can start making more informed choices.

review: Approve
Revision history for this message
Julian Edwards (julian-edwards) wrote :

Yes, ip_address is populated if mac_address is set. Hence my change to the code you wrote and my questions last night :)

Revision history for this message
MAAS Lander (maas-lander) wrote :

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (15.5 KiB)

The attempt to merge lp:~julian-edwards/maas/ipmi-with-mac into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Hit http://security.ubuntu.com trusty-security Release.gpg
Hit http://security.ubuntu.com trusty-security Release
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Ign http://nova.clouds.archive.ubuntu.com trusty-updates InRelease
Get:1 http://nova.clouds.archive.ubuntu.com trusty Release.gpg [933 B]
Hit http://nova.clouds.archive.ubuntu.com trusty-updates Release.gpg
Get:2 http://nova.clouds.archive.ubuntu.com trusty Release [58.5 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty-updates Release
Hit http://security.ubuntu.com trusty-security/main Sources
Hit http://security.ubuntu.com trusty-security/universe Sources
Hit http://security.ubuntu.com trusty-security/main amd64 Packages
Hit http://security.ubuntu.com trusty-security/universe amd64 Packages
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Get:3 http://nova.clouds.archive.ubuntu.com trusty/main Sources [1,062 kB]
Ign http://security.ubuntu.com trusty-security/main Translation-en_US
Ign http://security.ubuntu.com trusty-security/universe Translation-en_US
Get:4 http://nova.clouds.archive.ubuntu.com trusty/universe Sources [6,404 kB]
Get:5 http://nova.clouds.archive.ubuntu.com trusty/main amd64 Packages [1,344 kB]
Get:6 http://nova.clouds.archive.ubuntu.com trusty/universe amd64 Packages [5,876 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en
Ign http://nova.clouds.archive.ubuntu.com trusty/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en_US
Fetched 14.7 MB in 5s (2,933 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
     --no-install-recommends install apache2 bind9 bind9utils build-essential curl daemontools distro-info dnsutils firefox freeipmi-tools ipython isc-dhcp-common libjs-raphael libjs-yui3-full libjs-yui3-min libpq-dev make postgresql python-amqplib python-bzrlib python-celery python-convoy python-cssselect python-curtin python-dev python-distro-info python-django python-django-piston python-django-south python-djorm-ext-pgarray python-docutils python-formencode python-httplib2 python-jinja2 python-jsonschema python-lockfile python-lxml python-netaddr python-netifaces python-oauth python-oops python-oops-amqp ...

Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (15.7 KiB)

The attempt to merge lp:~julian-edwards/maas/ipmi-with-mac into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Hit http://security.ubuntu.com trusty-security Release.gpg
Ign http://nova.clouds.archive.ubuntu.com trusty-updates InRelease
Hit http://security.ubuntu.com trusty-security Release
Get:1 http://nova.clouds.archive.ubuntu.com trusty Release.gpg [933 B]
Hit http://nova.clouds.archive.ubuntu.com trusty-updates Release.gpg
Get:2 http://nova.clouds.archive.ubuntu.com trusty Release [58.5 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty-updates Release
Hit http://security.ubuntu.com trusty-security/main Sources
Hit http://security.ubuntu.com trusty-security/universe Sources
Hit http://security.ubuntu.com trusty-security/main amd64 Packages
Hit http://security.ubuntu.com trusty-security/universe amd64 Packages
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Get:3 http://nova.clouds.archive.ubuntu.com trusty/main Sources [1,062 kB]
Ign http://security.ubuntu.com trusty-security/main Translation-en_US
Ign http://security.ubuntu.com trusty-security/universe Translation-en_US
Get:4 http://nova.clouds.archive.ubuntu.com trusty/universe Sources [6,404 kB]
Get:5 http://nova.clouds.archive.ubuntu.com trusty/main amd64 Packages [1,344 kB]
Get:6 http://nova.clouds.archive.ubuntu.com trusty/universe amd64 Packages [5,876 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en
Ign http://nova.clouds.archive.ubuntu.com trusty/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en_US
Fetched 14.7 MB in 4s (2,980 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
     --no-install-recommends install apache2 bind9 bind9utils build-essential curl daemontools distro-info dnsutils firefox freeipmi-tools ipython isc-dhcp-common libjs-raphael libjs-yui3-full libjs-yui3-min libpq-dev make postgresql python-amqplib python-bzrlib python-celery python-convoy python-cssselect python-curtin python-dev python-distro-info python-django python-django-piston python-django-south python-djorm-ext-pgarray python-docutils python-formencode python-httplib2 python-jinja2 python-jsonschema python-lockfile python-lxml python-netaddr python-netifaces python-oauth python-oops python-oops-amqp ...

Revision history for this message
Julian Edwards (julian-edwards) wrote :

On 27/02/14 12:49, MaaS Lander wrote:
> FAIL: metadataserver.models.tests.test_commissioningscript.TestLLDPScripts.test_wait_script_waits_for_lldpd
> ----------------------------------------------------------------------
> _StringException: Traceback (most recent call last):
> File "/tmp/tarmac/branch.VURdtZ/src/metadataserver/models/tests/test_commissioningscript.py", line 268, in test_wait_script_waits_for_lldpd
> time.time.return_value))
> File "/home/ubuntu/.buildout/eggs/testtools-0.9.34-py2.7.egg/testtools/testcase.py", line 414, in assertThat
> raise MismatchError(matchee, matcher, mismatch, verbose)
> MismatchError: Expected to be called once. Called 206 times.

ARGHHHHHHHH.

That's it I am disabling that test.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'etc/maas/templates/power/ipmi.template'
--- etc/maas/templates/power/ipmi.template 2013-04-22 16:24:50 +0000
+++ etc/maas/templates/power/ipmi.template 2014-02-27 02:34:14 +0000
@@ -13,6 +13,12 @@
13ipmi_chassis_config={{ipmi_chassis_config}}13ipmi_chassis_config={{ipmi_chassis_config}}
14config={{config_dir}}/{{ipmi_config}}14config={{config_dir}}/{{ipmi_config}}
1515
16# If ip_address was supplied, use it in preference to the power_address,
17# because it gets discovered on-the-fly based on mac_address.
18{{if ip_address}}
19power_address={{ip_address}}
20{{endif}}
21
16# Determines the power command needed to execute the desired22# Determines the power command needed to execute the desired
17# action. This function receives ${power_change} as argument.23# action. This function receives ${power_change} as argument.
18formulate_power_command() {24formulate_power_command() {
1925
=== modified file 'src/maasserver/models/node.py'
--- src/maasserver/models/node.py 2014-02-25 15:53:10 +0000
+++ src/maasserver/models/node.py 2014-02-27 02:34:14 +0000
@@ -774,8 +774,8 @@
774 power_params.setdefault('power_driver', '')774 power_params.setdefault('power_driver', '')
775775
776 # The "mac" parameter defaults to the node's primary MAC776 # The "mac" parameter defaults to the node's primary MAC
777 # address, but only if no power parameters were set at all.777 # address, but only if not already set.
778 if not self.power_parameters:778 if 'mac_address' not in power_params:
779 primary_mac = self.get_primary_mac()779 primary_mac = self.get_primary_mac()
780 if primary_mac is not None:780 if primary_mac is not None:
781 power_params['mac_address'] = primary_mac.mac_address781 power_params['mac_address'] = primary_mac.mac_address
782782
=== modified file 'src/maasserver/models/tests/test_node.py'
--- src/maasserver/models/tests/test_node.py 2014-02-21 09:25:46 +0000
+++ src/maasserver/models/tests/test_node.py 2014-02-27 02:34:14 +0000
@@ -1083,16 +1083,18 @@
1083 self.celery.tasks[0]['kwargs']['mac_address'],1083 self.celery.tasks[0]['kwargs']['mac_address'],
1084 ))1084 ))
10851085
1086 def test_start_nodes_wakeonlan_ignores_invalid_parameters(self):1086 def test_start_nodes_wakeonlan_falls_back_to_primary_mac(self):
1087 # If node.power_params is set but doesn't have "mac_address" in it,1087 # If node.power_params is set but doesn't have "mac_address" in it,
1088 # then the node shouldn't be started.1088 # then use the node's primary MAC.
1089 user = factory.make_user()1089 user = factory.make_user()
1090 node, mac = self.make_node_with_mac(1090 node, mac = self.make_node_with_mac(
1091 user, power_type='ether_wake',1091 user, power_type='ether_wake',
1092 power_parameters=dict(jarjar="binks"))1092 power_parameters=dict(jarjar="binks"))
1093 output = Node.objects.start_nodes([node.system_id], user)1093 output = Node.objects.start_nodes([node.system_id], user)
1094 self.assertItemsEqual([], output)1094 self.assertItemsEqual([node], output)
1095 self.assertEqual([], self.celery.tasks)1095 self.assertEqual(
1096 unicode(node.get_primary_mac()),
1097 self.celery.tasks[0]['kwargs']['mac_address'])
10961098
1097 def test_start_nodes_wakeonlan_ignores_empty_mac_address_parameter(self):1099 def test_start_nodes_wakeonlan_ignores_empty_mac_address_parameter(self):
1098 user = factory.make_user()1100 user = factory.make_user()
10991101
=== modified file 'src/maasserver/power_parameters.py'
--- src/maasserver/power_parameters.py 2014-02-26 16:20:56 +0000
+++ src/maasserver/power_parameters.py 2014-02-27 02:34:14 +0000
@@ -173,9 +173,13 @@
173 make_json_field(173 make_json_field(
174 'power_driver', "Power driver", field_type='choice',174 'power_driver', "Power driver", field_type='choice',
175 choices=IPMI_DRIVER_CHOICES, default=IPMI_DRIVER.LAN_2_0),175 choices=IPMI_DRIVER_CHOICES, default=IPMI_DRIVER.LAN_2_0),
176 make_json_field('power_address', "Power address"),176 make_json_field('power_address', "IP address"),
177 make_json_field('power_user', "Power user"),177 make_json_field('power_user', "Power user"),
178 make_json_field('power_pass', "Power password"),178 make_json_field('power_pass', "Power password"),
179 make_json_field(
180 'mac_address',
181 "MAC address - the IP is looked up with ARP and overrides "
182 "IP address"),
179 ],183 ],
180 },184 },
181 {185 {
182186
=== modified file 'src/provisioningserver/power/tests/test_poweraction.py'
--- src/provisioningserver/power/tests/test_poweraction.py 2014-01-14 01:03:56 +0000
+++ src/provisioningserver/power/tests/test_poweraction.py 2014-02-27 02:34:14 +0000
@@ -207,7 +207,7 @@
207 action.get_template(), power_change='on',207 action.get_template(), power_change='on',
208 power_address='mystystem', power_user='me', power_pass='me',208 power_address='mystystem', power_user='me', power_pass='me',
209 ipmipower='echo', ipmi_chassis_config='echo', config_dir='dir',209 ipmipower='echo', ipmi_chassis_config='echo', config_dir='dir',
210 ipmi_config='file.conf', power_driver='LAN')210 ipmi_config='file.conf', power_driver='LAN', ip_address='')
211 self.assertIn(conf_dir, script)211 self.assertIn(conf_dir, script)
212212
213 def test_moonshot_checks_state(self):213 def test_moonshot_checks_state(self):
214214
=== modified file 'src/provisioningserver/tasks.py'
--- src/provisioningserver/tasks.py 2014-02-24 01:42:18 +0000
+++ src/provisioningserver/tasks.py 2014-02-27 02:34:14 +0000
@@ -137,6 +137,7 @@
137 kwargs['power_change'] = power_change137 kwargs['power_change'] = power_change
138 if 'mac_address' in kwargs:138 if 'mac_address' in kwargs:
139 kwargs['ip_address'] = find_ip_via_arp(kwargs['mac_address'])139 kwargs['ip_address'] = find_ip_via_arp(kwargs['mac_address'])
140 kwargs.setdefault('ip_address', None)
140 try:141 try:
141 pa = PowerAction(power_type)142 pa = PowerAction(power_type)
142 pa.execute(**kwargs)143 pa.execute(**kwargs)