launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #11029
[Merge] lp:~rvb/maas/wol-bug-1036005 into lp:maas
Raphaël Badin has proposed merging lp:~rvb/maas/wol-bug-1036005 into lp:maas.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~rvb/maas/wol-bug-1036005/+merge/119726
This branch changes the power parameters used with WoL.
The previous situation was really broken: the power parameters for WoL were reduced to only a CharField named 'power_address' and that was not used in the WoL template at all! The only trick is that, if a node's power parameters are empty, the 'mac' power parameter was dynamically added to the parameters (in node.get_effective_power_parameters).
Since 'power_address' is simply not used at all in the template, I decided to simply remove it. Of the two tools used by the script (etherwake and wakeonlan), only wakeonlan could use an IP address to send the magic packet to a specific IP address in place of the default [the limited broadcast address (255.255.255.255)]. But since the nodes are supposed to be on the same network as the worker, I'm not sure this is really useful. Anyway, this isn't used in the script so I choose to remove it for now.
In case one wants to have the WoL command sent to a different MAC Address (given the trick in get_effective_power_parameters, I guess that's why we have the power parameters in the WoL case), I've added a 'mac_address' field to the power_parameter for WoL. That field forces its content to be a MAC address.
--
https://code.launchpad.net/~rvb/maas/wol-bug-1036005/+merge/119726
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/wol-bug-1036005 into lp:maas.
=== modified file 'src/maasserver/models/node.py'
--- src/maasserver/models/node.py 2012-08-10 14:55:04 +0000
+++ src/maasserver/models/node.py 2012-08-15 14:45:24 +0000
@@ -314,7 +314,7 @@
power_params = node.get_effective_power_parameters()
node_power_type = node.get_effective_power_type()
if node_power_type == POWER_TYPE.WAKE_ON_LAN:
- mac = power_params.get('mac')
+ mac = power_params.get('mac_address')
do_start = (mac != '' and mac is not None)
else:
do_start = True
@@ -587,7 +587,7 @@
if not self.power_parameters:
primary_mac = self.get_primary_mac()
if primary_mac is not None:
- power_params['mac'] = primary_mac.mac_address
+ power_params['mac_address'] = primary_mac.mac_address
return power_params
def acquire(self, user, token=None):
=== modified file 'src/maasserver/power_parameters.py'
--- src/maasserver/power_parameters.py 2012-07-16 12:33:43 +0000
+++ src/maasserver/power_parameters.py 2012-08-15 14:45:24 +0000
@@ -32,6 +32,7 @@
from django import forms
from maasserver.config_forms import DictCharField
+from maasserver.fields import MACAddressFormField
from provisioningserver.enum import POWER_TYPE
@@ -42,8 +43,8 @@
DictCharField(
[
(
- 'power_address',
- forms.CharField(label="Address", required=False)),
+ 'mac_address',
+ MACAddressFormField(label="MAC Address", required=False)),
],
required=False,
skip_check=True),
=== modified file 'src/maasserver/tests/test_api.py'
--- src/maasserver/tests/test_api.py 2012-08-15 03:20:44 +0000
+++ src/maasserver/tests/test_api.py 2012-08-15 14:45:24 +0000
@@ -53,6 +53,7 @@
NODE_STATUS_CHOICES_DICT,
)
from maasserver.exceptions import Unauthorized
+from maasserver.fields import mac_error_msg
from maasserver.kernel_opts import (
compose_enlistment_preseed_url,
compose_preseed_url,
@@ -593,13 +594,13 @@
def test_POST_new_sets_power_parameters_field(self):
# The api allows the setting of a Node's power_parameters field.
# Create a power_parameter valid for the selected power_type.
- new_power_address = factory.getRandomString()
+ new_mac_address = factory.getRandomMACAddress()
response = self.client.post(
self.get_uri('nodes/'), {
'op': 'new',
'architecture': factory.getRandomChoice(ARCHITECTURE_CHOICES),
'power_type': POWER_TYPE.WAKE_ON_LAN,
- 'power_parameters_power_address': new_power_address,
+ 'power_parameters_mac_address': new_mac_address,
'mac_addresses': ['AA:BB:CC:DD:EE:FF'],
})
@@ -607,7 +608,7 @@
system_id=json.loads(response.content)['system_id'])
self.assertEqual(httplib.OK, response.status_code)
self.assertEqual(
- {'power_address': new_power_address},
+ {'mac_address': new_mac_address},
reload_object(node).power_parameters)
def test_POST_updates_power_parameters_rejects_unknown_param(self):
@@ -1127,16 +1128,35 @@
owner=self.logged_in_user,
power_type=POWER_TYPE.WAKE_ON_LAN)
# Create a power_parameter valid for the selected power_type.
- new_power_address = factory.getRandomString()
+ new_power_address = factory.getRandomMACAddress()
response = self.client.put(
self.get_node_uri(node),
- {'power_parameters_power_address': new_power_address})
+ {'power_parameters_mac_address': new_power_address})
self.assertEqual(httplib.OK, response.status_code)
self.assertEqual(
- {'power_address': new_power_address},
+ {'mac_address': new_power_address},
reload_object(node).power_parameters)
+ def test_PUT_updates_power_parameters_accepts_only_mac_for_wol(self):
+ self.become_admin()
+ node = factory.make_node(
+ owner=self.logged_in_user,
+ power_type=POWER_TYPE.WAKE_ON_LAN)
+ # Create an invalid power_parameter for WoL (not a valid
+ # MAC address).
+ new_power_address = factory.getRandomString()
+ response = self.client.put(
+ self.get_node_uri(node),
+ {'power_parameters_mac_address': new_power_address})
+
+ self.assertEqual(
+ (
+ httplib.BAD_REQUEST,
+ {'power_parameters': ["MAC Address: %s" % mac_error_msg]},
+ ),
+ (response.status_code, json.loads(response.content)))
+
def test_PUT_updates_power_parameters_rejects_unknown_param(self):
self.become_admin()
power_parameters = factory.getRandomString()
@@ -1250,11 +1270,11 @@
power_parameters=factory.getRandomString())
response = self.client.put(
self.get_node_uri(node),
- {'power_parameters_power_address': ''})
+ {'power_parameters_mac_address': ''})
self.assertEqual(httplib.OK, response.status_code)
self.assertEqual(
- {'power_address': ''},
+ {'mac_address': ''},
reload_object(node).power_parameters)
def test_DELETE_deletes_node(self):
=== modified file 'src/maasserver/tests/test_node.py'
--- src/maasserver/tests/test_node.py 2012-08-10 14:55:04 +0000
+++ src/maasserver/tests/test_node.py 2012-08-15 14:45:24 +0000
@@ -210,7 +210,8 @@
node = factory.make_node()
mac = factory.getRandomMACAddress()
node.add_mac_address(mac)
- self.assertEqual(mac, node.get_effective_power_parameters()['mac'])
+ self.assertEqual(
+ mac, node.get_effective_power_parameters()['mac_address'])
def test_get_effective_power_parameters_adds_no_mac_if_params_set(self):
node = factory.make_node(power_parameters={'foo': 'bar'})
@@ -671,7 +672,7 @@
(
len(self.celery.tasks),
self.celery.tasks[0]['task'].name,
- self.celery.tasks[0]['kwargs']['mac'],
+ self.celery.tasks[0]['kwargs']['mac_address'],
))
def test_start_nodes_sets_commissioning_profile(self):
@@ -721,7 +722,7 @@
preferred_mac = factory.getRandomMACAddress()
node, mac = self.make_node_with_mac(
user, power_type=POWER_TYPE.WAKE_ON_LAN,
- power_parameters=dict(mac=preferred_mac))
+ power_parameters=dict(mac_address=preferred_mac))
output = Node.objects.start_nodes([node.system_id], user)
self.assertItemsEqual([node], output)
@@ -730,12 +731,12 @@
(
len(self.celery.tasks),
self.celery.tasks[0]['task'].name,
- self.celery.tasks[0]['kwargs']['mac'],
+ self.celery.tasks[0]['kwargs']['mac_address'],
))
def test_start_nodes_wakeonlan_ignores_invalid_parameters(self):
- # If node.power_params is set but doesn't have "mac" in it, then
- # the node shouldn't be started.
+ # If node.power_params is set but doesn't have "mac_address" in it,
+ # then the node shouldn't be started.
user = factory.make_user()
node, mac = self.make_node_with_mac(
user, power_type=POWER_TYPE.WAKE_ON_LAN,
@@ -744,11 +745,11 @@
self.assertItemsEqual([], output)
self.assertEqual([], self.celery.tasks)
- def test_start_nodes_wakeonlan_ignores_empty_mac_parameter(self):
+ def test_start_nodes_wakeonlan_ignores_empty_mac_address_parameter(self):
user = factory.make_user()
node, mac = self.make_node_with_mac(
user, power_type=POWER_TYPE.WAKE_ON_LAN,
- power_parameters=dict(mac=""))
+ power_parameters=dict(mac_address=""))
output = Node.objects.start_nodes([node.system_id], user)
self.assertItemsEqual([], output)
self.assertEqual([], self.celery.tasks)
=== modified file 'src/provisioningserver/power/templates/ether_wake.template'
--- src/provisioningserver/power/templates/ether_wake.template 2012-06-08 16:05:50 +0000
+++ src/provisioningserver/power/templates/ether_wake.template 2012-08-15 14:45:24 +0000
@@ -3,7 +3,7 @@
# Control node power through WOL, via `wakeonlan` or `etherwake`.
#
-mac={{mac}}
+mac_address={{mac_address}}
power_change={{power_change}}
if [ "${power_change}" != 'on' ]
@@ -12,10 +12,10 @@
exit 1
elif [ -x /usr/bin/wakeonlan ]
then
- /usr/bin/wakeonlan $mac
+ /usr/bin/wakeonlan $mac_address
elif [ -x /usr/sbin/etherwake ]
then
- /usr/sbin/etherwake $mac
+ /usr/sbin/etherwake $mac_address
else
echo "No wakeonlan or etherwake program found." >&2
fi
=== modified file 'src/provisioningserver/tests/test_tasks.py'
--- src/provisioningserver/tests/test_tasks.py 2012-08-13 05:41:02 +0000
+++ src/provisioningserver/tests/test_tasks.py 2012-08-15 14:45:24 +0000
@@ -145,7 +145,8 @@
PowerActionFail, power_on.delay, POWER_TYPE.WAKE_ON_LAN)
def test_ether_wake_power_on(self):
- result = power_on.delay(POWER_TYPE.WAKE_ON_LAN, mac=arbitrary_mac)
+ result = power_on.delay(
+ POWER_TYPE.WAKE_ON_LAN, mac_address=arbitrary_mac)
self.assertTrue(result.successful())
def test_ether_wake_does_not_support_power_off(self):
Follow ups