Merge lp:~rvb/maas-test/bmc-params-4 into lp:maas-test

Proposed by Raphaël Badin
Status: Merged
Merged at revision: 49
Proposed branch: lp:~rvb/maas-test/bmc-params-4
Merge into: lp:maas-test
Prerequisite: lp:~rvb/maas-test/bmc-params-3
Diff against target: 207 lines (+85/-42)
2 files modified
maastest/main.py (+50/-38)
maastest/parser.py (+35/-4)
To merge this branch: bzr merge lp:~rvb/maas-test/bmc-params-4
Reviewer Review Type Date Requested Status
Graham Binns (community) Approve
Review via email: mp+196111@code.launchpad.net

Commit message

Add params to pass BMC information.

Description of the change

Still no testing for the parsing code because we're still unsure if this is going to stay exactly like that. Note that I finally the two existing test cases into one since they are really close; as a result, the code is a bit simpler.

To post a comment you must log in.
lp:~rvb/maas-test/bmc-params-4 updated
52. By Raphaël Badin

Merged bmc-params-3 into bmc-params-4.

Revision history for this message
Graham Binns (gmb) :
review: Approve
lp:~rvb/maas-test/bmc-params-4 updated
53. By Raphaël Badin

Merged bmc-params-3 into bmc-params-4.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'maastest/main.py'
2--- maastest/main.py 2013-11-20 10:30:06 +0000
3+++ maastest/main.py 2013-11-21 14:40:46 +0000
4@@ -31,11 +31,9 @@
5
6 class TestMAAS(testtools.TestCase, testresources.ResourcedTestCase):
7
8- direct_interface = None
9-
10 @classmethod
11- def configure(cls, interface):
12- cls.direct_interface = interface
13+ def configure(cls, args):
14+ cls.args = args
15
16 @classmethod
17 def setUpClass(cls):
18@@ -44,7 +42,7 @@
19 architecture = utils.determine_vm_architecture()
20 cls.machine = KVMFixture(
21 series='saucy', architecture=architecture,
22- direct_interface=cls.direct_interface)
23+ direct_interface=cls.args.interface)
24 cls.machine.setUp()
25 try:
26 cls.maas = MAASFixture(cls.machine)
27@@ -108,21 +106,55 @@
28 return relevant_nodes
29
30
31-class TestInteractiveOneNode(TestMAAS):
32- """Test if a node is compatible with MAAS.
33-
34- This is an interactive test: after MAAS is set up inside a virtual
35- machine, it waits for the user to power up the node under test before
36- trying to enlist and commission it."""
37-
38- def test_enlist_node(self):
39- """Enlist node."""
40+class TestOneNode(TestMAAS):
41+ """Test if a node is compatible with MAAS."""
42+
43+ def test_power_up_node(self):
44+ """Power up the node under test.
45+
46+ If maas-test is running in interactive mode, this will ask the user
47+ to power up the node manually. Otherwise it will use the provided
48+ power parameters to power up the node by running 'ipmipower' in the
49+ virtual machine..
50+ """
51 # TODO: only print this in debug/verbose mode.
52 self.print_connection_details()
53+ if self.args.interactive_enlistment:
54+ self.power_up_node_interactive()
55+ else:
56+ self.power_up_node_noninteractive()
57+
58+ def power_up_node_interactive(self):
59+ """Asks the user to power up the node manually."""
60 print(
61 "Power up the node under test and press enter to proceed "
62 "with the testing.")
63 sys.stdin.readline()
64+
65+ def power_up_node_noninteractive(self):
66+ """Power up the node using the provided power parameters."""
67+ # Scan the network to find the IP address of the node's BMC.
68+ for retry in utils.retries(delay=20, timeout=5 * 60):
69+ ip_scan = self.maas.kvm_fixture.get_ip_from_network_scan
70+ power_address = ip_scan(self.args.bmc_mac)
71+ if power_address is not None:
72+ break
73+ if power_address is None:
74+ self.fail("Failed to get the IP address of the BMC.")
75+ # Power-cycle the node.
76+ self.maas.kvm_fixture.run_command([
77+ 'ipmipower', '-h', power_address,
78+ '-u', self.args.bmc_username,
79+ '-p', self.args.bmc_password, '--off'],
80+ check_call=True)
81+ self.maas.kvm_fixture.run_command([
82+ 'ipmipower', '-h', power_address,
83+ '-u', self.args.bmc_username,
84+ '-p', self.args.bmc_password, '--on'],
85+ check_call=True)
86+
87+ def test_enlist_node(self):
88+ """Enlist node."""
89 for retry in utils.retries(delay=10, timeout=10 * 60):
90 nb_enlisted_nodes = len(self.get_node_list(0)) # 0 = 'Declared'.
91 if nb_enlisted_nodes == 1:
92@@ -134,7 +166,8 @@
93 uri = utils.get_uri('nodes/')
94 response = self.maas.admin_maas_client.post(uri, op="accept_all")
95 self.assertEqual(
96- httplib.OK, response.code, "Failed to get accept the node.")
97+ httplib.OK, response.code, "Failed to accept node.")
98+
99 for retry in utils.retries(delay=10, timeout=10 * 60):
100 nb_enlisted_nodes = len(self.get_node_list(4)) # 4 = 'Ready'.
101 if nb_enlisted_nodes == 1:
102@@ -142,17 +175,6 @@
103 self.fail("Failed to commission node.")
104
105
106-class TestOneNode(TestMAAS):
107- """Test if a node is compatible with MAAS.
108-
109- This is a non-interactive test: after MAAS is set up inside a virtual
110- machine, it will enlist the node with the power parameters provided and
111- commission it."""
112-
113- def test_to_do(self):
114- raise NotImplementedError("TODO!")
115-
116-
117 def check_kvm_ok():
118 """Check that this machine is capable of running KVM.
119
120@@ -179,17 +201,7 @@
121 logging.error("Unable to continue without KVM extensions.")
122 return 1
123
124- if args.interactive_enlistment:
125- base_class = TestInteractiveOneNode
126- else:
127- # Blow up right now to avoid creating the VM before blowing up in
128- # TestOneNode.test_to_do.
129- raise NotImplementedError(
130- "Non-interactive mode not yet implemented, use "
131- "--interactive-enlistment for now")
132- base_class = TestOneNode
133-
134- class ConfiguredTestMAAS(base_class):
135+ class ConfiguredTestMAAS(TestOneNode):
136 """A configured version of TestInteractiveOneNode.
137
138 ConfiguredTestMAAS is a TestMAAS use to configure it by calling
139@@ -197,7 +209,7 @@
140 the instance because the KVMFixture TestMAAS instanciates and needs
141 to configure is created at the class level.
142 """
143- ConfiguredTestMAAS.configure(args.interface)
144+ ConfiguredTestMAAS.configure(args)
145
146 # Create a TestLoader which loads the tests in the order in which
147 # they are defined in the test case class.
148
149=== modified file 'maastest/parser.py'
150--- maastest/parser.py 2013-11-20 11:53:52 +0000
151+++ maastest/parser.py 2013-11-21 14:40:46 +0000
152@@ -19,11 +19,29 @@
153 from six import text_type
154
155
156+class MAASTestArgumentParser(argparse.ArgumentParser):
157+
158+ def parse_args(self):
159+ args = super(MAASTestArgumentParser, self).parse_args()
160+ bmc_details = (args.bmc_mac, args.bmc_username, args.bmc_password)
161+ if args.interactive_enlistment:
162+ if bmc_details != (None, None, None):
163+ self.error(
164+ "None of the BMC details should be provided when using "
165+ "--interactive-enlistment.")
166+ else:
167+ if None in bmc_details:
168+ self.error(
169+ "All the BMC details (MAC address, username "
170+ "and password) must be provided.")
171+ return args
172+
173+
174 def prepare_parser():
175 # TODO: This is not tested sinc how maas-test will interface with
176 # checkbox is still in flux. Right now, this is just to get the
177 # testing going.
178- parser = argparse.ArgumentParser(
179+ parser = MAASTestArgumentParser(
180 description="Test whether or not a node is compatible with MAAS.")
181
182 parser.add_argument(
183@@ -39,8 +57,21 @@
184 "e.g. ppa:maas-maintainers/dailybuilds).")
185 parser.add_argument(
186 '--interactive-enlistment', action='store_true',
187- help="Perform an interactive enlistment. Instead of passing the "
188- "IPMI details on the command line, ask for the node to be "
189- "powered up manually and enlist the node when it PXE boots.")
190+ help="Perform an interactive enlistment. Instead of passing the "
191+ "BMC details on the command line, the node will have to be "
192+ "powered up manually.")
193+ # BMC details.
194+ parser.add_argument(
195+ '--bmc-mac', type=text_type,
196+ help="The MAC address of the node's BMC. This will be used to "
197+ "power up the node to enlist it.")
198+ parser.add_argument(
199+ '--bmc-username', type=text_type,
200+ help="The username to use when authenticating with the node's BMC. "
201+ "This will be used to power up the node to enlist it.")
202+ parser.add_argument(
203+ '--bmc-password', type=text_type,
204+ help="The password to use when authenticating with the node's BMC. "
205+ "This will be used to power up the node to enlist it.")
206
207 return parser

Subscribers

People subscribed via source and target branches