Merge lp:~jason-hobbs/maas/fix-ipmi-settings-order-lp-1289456 into lp:~maas-committers/maas/trunk

Proposed by Jason Hobbs
Status: Merged
Approved by: Jason Hobbs
Approved revision: no longer in the source branch.
Merged at revision: 2104
Proposed branch: lp:~jason-hobbs/maas/fix-ipmi-settings-order-lp-1289456
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 153 lines (+78/-12)
2 files modified
etc/maas/templates/commissioning-user-data/snippets/maas_ipmi_autodetect.py (+26/-11)
etc/maas/templates/commissioning-user-data/snippets/tests/test_maas_ipmi_autodetect.py (+52/-1)
To merge this branch: bzr merge lp:~jason-hobbs/maas/fix-ipmi-settings-order-lp-1289456
Reviewer Review Type Date Requested Status
Andres Rodriguez (community) Approve
Review via email: mp+209961@code.launchpad.net

Commit message

Restore the original order used for applying IPMI user settings in maas-ipmi-autodetect.

The order changed during a refactor, because settings were moved from being applied in a sequence of function calls to being applied by iterating over a dict. Now, settings are applied by iterating over an OrderedDict with keys in the same order as the original sequence of function calls.

To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm! Provided this has been tested, make lint passes and test pass. Land it!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'etc/maas/templates/commissioning-user-data/snippets/maas_ipmi_autodetect.py'
2--- etc/maas/templates/commissioning-user-data/snippets/maas_ipmi_autodetect.py 2014-03-04 22:38:39 +0000
3+++ etc/maas/templates/commissioning-user-data/snippets/maas_ipmi_autodetect.py 2014-03-07 18:25:04 +0000
4@@ -37,6 +37,8 @@
5 import subprocess
6 import time
7
8+from collections import OrderedDict
9+
10
11 class IPMIError(Exception):
12 """An error related to IPMI."""
13@@ -194,6 +196,29 @@
14 verify_ipmi_user_settings(ipmi_user_number, user_settings)
15
16
17+def make_ipmi_user_settings(username, password):
18+ """Factory for IPMI user settings."""
19+ # Some BMCs care about the order these settings are applied in,
20+ # particulary what's done prior to the user being enabled. This
21+ # behavior was seen on Dell Poweredge R240 systems, but may affect
22+ # others too. Don't change the order of these without lots of
23+ # testing.
24+ user_settings = OrderedDict((
25+ ('Username', username),
26+ ('Password', password),
27+ ('Enable_User', 'Yes'),
28+ ('Lan_Enable_IPMI_Msgs', 'Yes'),
29+ ('Lan_Privilege_Limit', 'Administrator'),
30+ ))
31+ return user_settings
32+
33+
34+def configure_ipmi_user(username, password):
35+ """Create or configure an IPMI user for remote use."""
36+ user_settings = make_ipmi_user_settings(username, password)
37+ apply_ipmi_user_settings(user_settings)
38+
39+
40 def commit_ipmi_settings(config):
41 run_command(('bmc-config', '--commit', '--filename', config))
42
43@@ -251,17 +276,7 @@
44 IPMI_MAAS_USER = "maas"
45 IPMI_MAAS_PASSWORD = generate_random_password()
46
47- # Configure IPMI user/password
48-
49- user_settings = {
50- 'Username': IPMI_MAAS_USER,
51- 'Password': IPMI_MAAS_PASSWORD,
52- 'Enable_User': 'Yes',
53- 'Lan_Enable_IPMI_Msgs': 'Yes',
54- 'Lan_Privilege_Limit': 'Administrator'
55- }
56-
57- apply_ipmi_user_settings(user_settings)
58+ configure_ipmi_user(IPMI_MAAS_USER, IPMI_MAAS_PASSWORD)
59
60 # Commit other IPMI settings
61 if args.configdir:
62
63=== modified file 'etc/maas/templates/commissioning-user-data/snippets/tests/test_maas_ipmi_autodetect.py'
64--- etc/maas/templates/commissioning-user-data/snippets/tests/test_maas_ipmi_autodetect.py 2014-03-04 22:38:39 +0000
65+++ etc/maas/templates/commissioning-user-data/snippets/tests/test_maas_ipmi_autodetect.py 2014-03-07 18:25:04 +0000
66@@ -17,10 +17,13 @@
67 from collections import OrderedDict
68 import subprocess
69
70+from mock import call
71+
72 from maastesting.factory import factory
73 from maastesting.matchers import (
74 MockAnyCall,
75 MockCalledOnceWith,
76+ MockCallsMatch,
77 )
78 from maastesting.testcase import MAASTestCase
79 from snippets import maas_ipmi_autodetect
80@@ -30,9 +33,11 @@
81 bmc_supports_lan2_0,
82 bmc_user_get,
83 commit_ipmi_settings,
84+ configure_ipmi_user,
85 format_user_key,
86 IPMIError,
87 list_user_numbers,
88+ make_ipmi_user_settings,
89 pick_user_number,
90 pick_user_number_from_list,
91 run_command,
92@@ -381,7 +386,7 @@
93 """Ensure the user settings are committed and verified."""
94 user_number = 'User2'
95 self.patch(maas_ipmi_autodetect,
96- 'pick_user_number').return_value = 'User2'
97+ 'pick_user_number').return_value = user_number
98 bus_mock = self.patch(maas_ipmi_autodetect, 'bmc_user_set')
99 vius_mock = self.patch(maas_ipmi_autodetect,
100 'verify_ipmi_user_settings')
101@@ -395,6 +400,52 @@
102 vius_mock,
103 MockCalledOnceWith(user_number, user_settings))
104
105+ def test_preserves_settings_order(self):
106+ """Ensure user settings are applied in order of iteration."""
107+ user_number = 'User2'
108+ self.patch(maas_ipmi_autodetect,
109+ 'pick_user_number').return_value = user_number
110+ bus_mock = self.patch(maas_ipmi_autodetect, 'bmc_user_set')
111+ self.patch(maas_ipmi_autodetect, 'verify_ipmi_user_settings')
112+ user_settings = OrderedDict((('Username', 1), ('b', 2), ('c', 3)))
113+ apply_ipmi_user_settings(user_settings)
114+ expected_calls = (
115+ call(user_number, key, value)
116+ for key, value in user_settings.iteritems()
117+ )
118+ self.assertThat(bus_mock, MockCallsMatch(*expected_calls))
119+
120+
121+class TestMakeIPMIUserSettings(MAASTestCase):
122+ """Tests for make_ipmi_user_settings()."""
123+
124+ def test_settings_ordered_correctly(self):
125+ """Ensure user settings are listed in the right order."""
126+ settings = make_ipmi_user_settings('user', 'pass')
127+ expected = ['Username', 'Password', 'Enable_User']
128+ self.assertEqual(expected, settings.keys()[:3])
129+
130+ def test_uses_username_and_password(self):
131+ """Ensure username and password supplied are used."""
132+ username = 'user'
133+ password = 'pass'
134+ settings = make_ipmi_user_settings(username, password)
135+ self.assertEquals(username, settings['Username'])
136+ self.assertEquals(password, settings['Password'])
137+
138+
139+class TestConfigureIPMIUser(MAASTestCase):
140+ """Tests for configure_ipmi_user()."""
141+
142+ def test_preserves_setting_order(self):
143+ """Ensure the order of user settings isn't modified."""
144+ expected = OrderedDict((('a', 1), ('b', 2), ('c', 3)))
145+ self.patch(maas_ipmi_autodetect,
146+ 'make_ipmi_user_settings').return_value = expected.copy()
147+ recorder = self.patch(maas_ipmi_autodetect, 'apply_ipmi_user_settings')
148+ configure_ipmi_user('DC', 'DC')
149+ self.assertThat(recorder, MockCalledOnceWith(expected))
150+
151
152 class TestCommitIPMISettings(MAASTestCase):
153 """Test commit_ipmi_settings()."""