Merge lp:~jtv/maas-test/bootresources-config into lp:maas-test

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: Jeroen T. Vermeulen
Approved revision: 161
Merged at revision: 148
Proposed branch: lp:~jtv/maas-test/bootresources-config
Merge into: lp:maas-test
Diff against target: 358 lines (+171/-16)
7 files modified
maastest/kvmfixture.py (+2/-1)
maastest/maasfixture.py (+42/-5)
maastest/testing/factory.py (+7/-0)
maastest/tests/test_kvmfixture.py (+8/-2)
maastest/tests/test_maasfixture.py (+104/-4)
maastest/tests/test_utils.py (+4/-1)
maastest/utils.py (+4/-3)
To merge this branch: bzr merge lp:~jtv/maas-test/bootresources-config
Reviewer Review Type Date Requested Status
Julian Edwards (community) Approve
Raphaël Badin (community) Needs Fixing
Review via email: mp+214916@code.launchpad.net

Commit message

Generate bootresources.yaml and upload it to the VM before importing images.

Description of the change

This should make the import script import just the images that are required. This includes i386/generic images as well as those for the requested architecture, all for the requested Ubuntu release series.

At least one change is completely unrelated: a utils test was in the wrong TestCase. I gave it a TestCase of its own. Along the way I also added another utility function to the test factory module.

I initially planned to upload the bootresources config into the ubuntu user's home directory on the VM, and then use the import script's --config option to load it; but Raphaël mentioned that he might like to replace the script invocation with an API call, and then I found that just uploading to /etc/maas/ wasn't much easier anyway. It's an extra sudo invocation, but it saves us having to pass that --config option. The complications for existing tests weren't so bad.

One thing that is not covered by tests, though I don't expect it will matter, is the fact that import_maas_images passes the architectures it gets from mipf_arch_list (not in __all__, so I added it, then actually sorted __all__) and not just [self.architecture].

Jeroen

To post a comment you must log in.
Revision history for this message
Raphaël Badin (rvb) wrote :

[0]

Looks like this doesn't work. I extracted the generated bootresources.yaml generated by this change (http://d-jenkins.ubuntu-ci:8080/view/MAAS/job/maas-test-manual/60/console) and ran the import script manually on canonistack and got http://paste.ubuntu.com/7225943/.

[1]

fwiw, I disagree with the approach taken here. I understand it's been approved by Julian so I won't block this but I really think this is wrong.

Having maas-test generate bootresources.yaml instead of just taking its content from a command line argument will force us to change maas-test every single time we will want to get it to tweak bootresources.yaml: to use a different label, to tweak the keyring or the simplestream path. This is the same mistake we've done with the power parameters settings. maas-test should try to do as little as possible and just pass things around, act as a dumb intermediate whenever possible.

[2]

47 + self.kvm_fixture.upload_file(config.name, 'bootresources.yaml')
48 + self.kvm_fixture.run_command(
49 + ['sudo', 'mv', 'bootresources.yaml', '/etc/maas/'],
50 + check_call=True)

Shouldn't we put the file in /tmp/bootresources.yaml? This looks like it will work just fine but maybe it's best to have the entire path under our control, just to be on the safe side.

[3]

> This includes i386/generic images as well as those for the requested architecture, all for the requested Ubuntu
> release series.

This was https://bugs.launchpad.net/ubuntu/+source/maas/+bug/1181334 and it's fixed now. Since maas-test can only be used to run MAAS 1.5 and up, we might as well be rid of this and avoid downloading the i386 image when testing an amd64 node. I know it has nothing to do with you branch per se, I'm just mentioning it here so that we don't forget.

review: Needs Fixing
Revision history for this message
Gavin Panella (allenap) wrote :
Download full text (6.6 KiB)

Raphaël and I had a long conversation about this. Ultimately we agreed
that this branch out to be put on hold, and we should discuss it
properly in Austin in a few weeks. Can you live with that Jeroen?

Transcript:

allenap: rvba: I think bootresources.yaml is different to power
         parameters. The latter have a number of schemas associated with
         them. Trying to flatten that into a command-line is nearly
         impossible.
   rvba: allenap: my suggestion is to pass the entire file content to
         maas-test.
   rvba: All at once.
allenap: rvba: bootresources.yaml will be transient, but we can use
         capabilities to detect when we should use its successor.
   rvba: allenap: maas-test --bootresources <file>
allenap: rvba: Would that be optional?
   rvba: allenap: yes, of course
allenap: rvba: What’s the purpose?
   rvba: allenap: customize the boot image import: use a different
         label, use a different path, etc
allenap: rvba: I imagine we still need the code in this branch when
         it’s not supplied?
   rvba: allenap: no, we can use the default one.
allenap: rvba: Does that import everything? Using the default one makes
         sense - we’re trying to test how hardware works with MAAS
         out-of-the-box - but if it’s really slow then folk are going
         to tire of it.
allenap: rvba: This is pertinent w.r.t. the “directive” we had about
         default-to-everything.
   rvba: allenap: It imports [i386,amd64]/release/precise
         [i386/amd64]/daily/trusty by default.
allenap: rvba: Is that MAAS’s default, or maas-test’s?
   rvba: MAAS's default
allenap: rvba: When we transition away from bootresources.yaml, what
         will we do with maas-test then?
   rvba: allenap: maybe we won't transition away from
         bootresources.yaml.  Maybe the region will simply generate an
         ad-hoc bootresources.yaml every time the import script it run.
   rvba: allenap: and if we do get away with it, then that's one more
         reason no to spend time getting maas-test capable of writing
         that file.
allenap: rvba: Either way, bootresources.yaml is an implementation
         detail, temporarily exposed to users while we scurry to provide
         API+UI for it. Jeroen has written the code to generate it. I
         think we should use it for now. I suspect we’ll have to
         change maas-test again in any case.
   rvba: allenap: well, I don't agree but I guess I'm outnumbered :)
   rvba: allenap: bootresources.yaml being an implementation detail
         should be yet another reason not to spend time working on code
         to generate it.  We should expose it to user temporarily to
         give them maximum control over what gets imported.  And change
         that when MAAS itself changes.
allenap: rvba: I think we can revisit this at some point. In the
         meantime I think jtv’s branch is an improvement, and is okay
         to land.
   rvba: allenap: we won't be able to offer a unified interface in maas-
         test anyway.
   rvba: allenap: well, apart from the fact that it doesn't work at all.
allenap: rvba: Doesn’t it?
   rvba: allenap: see my point [0]
allenap: rvba: Oh yes...

Read more...

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

On Wednesday 09 Apr 2014 12:19:25 you wrote:
> fwiw, I disagree with the approach taken here. I understand it's been
> approved by Julian so I won't block this but I really think this is wrong.
>
> Having maas-test generate bootresources.yaml instead of just taking its
> content from a command line argument will force us to change maas-test
> every single time we will want to get it to tweak bootresources.yaml: to
> use a different label, to tweak the keyring or the simplestream path. This
> is the same mistake we've done with the power parameters
> settings. maas-test should try to do as little as possible and just pass
> things around, act as a dumb intermediate whenever possible.

bootresources.yaml is going to disappear very soon, so I advised jtv to take
the route that involved the least amount of work.

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

On Wednesday 09 Apr 2014 14:11:32 you wrote:
> allenap: rvba: I don’t know what Julian said, but I’m not thrilled
> about adding it either. It depends somewhat on how you see
> maas-test. I see it as a front-end for non-MAAS users to test
> hardware with MAAS. As such, I don’t think asking them to
> provide config files is good UI.

This is the nub of it, yes.

bootresources.yaml is a shit user-facing interface, I mean really shit. I was
rather frustrated to see the simplestreams filter options appearing in a
config file in the original script work, but that was out of our hands as it
turns out.

We need to be moving as much of the maas-test functionality as possible over
to maas itself so that maas-test ends up being a wrapper to drive some tests
inside maas.

When we have an API/UI to control which boot resources are required (which we
will design with maas-test in mind) then this all becomes much easier.

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

This is madness. We want to make people download gigabytes extra in the release version because we're arguing over a hundred lines of code we could save with a temporary solution with an unfriendly UI that is also doomed from the start? I'm not buying it.

I agree that just passing a bootresources.yaml would be easier (and take about half the code, not “10× less”) but that is not the desired user experience. The difference in code size really isn't that dramatic in absolute numbers, for a user-friendliness issue.

Also, it should be noted for the record that the branch did work properly in the experimental run, but because of it, revealed an outdated default setting in MAAS itself (which was fixed within the hour after Gavin pasted the conversation). That, not a problem with my branch, was what stopped the experiment before it could be completed — but by that point my changes had already completed their work, and MAAS had already accepted it. So far as we know or have reason to expect, no fixes to my branch are needed.

Julian says it's acceptable to keep working with the release images (which does mean maas-test will break until Trusty's release) and add an option to use pre-release images later, using a simpler user interface than letting the user configure paths and labels. It's not very hard, and doesn't differ much from the work we would need to do to pass a configuration file in from the command line.

Our chosen direction is to abolish bootresources.yaml. That file is universally regarded as a problem. We can execute on that plan, or we can keep second-guessing it, but either way my branch does not stand in its way. On the other hand, introducing bootresources.yaml in full detail into the user interface is committing publicly to the status quo.

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

On Thursday 10 Apr 2014 03:36:53 you wrote:
> Our chosen direction is to abolish bootresources.yaml. That file is
> universally regarded as a problem. We can execute on that plan, or we can
> keep second-guessing it, but either way my branch does not stand in its
> way. On the other hand, introducing bootresources.yaml in full detail into
> the user interface is committing publicly to the status quo.

Nail on head.

The user interface is the most important part. Underneath, this will start as
bootresources.yaml and silently migrate to some API calls when the work to fix
maas is done.

Revision history for this message
Julian Edwards (julian-edwards) :
review: Approve
157. By Jeroen T. Vermeulen

Test for coming change: pass user/host spec to scp as part of destination name. Tests: 2 failures.

158. By Jeroen T. Vermeulen

Satisfy tests.

159. By Jeroen T. Vermeulen

Merge trunk, resolve conflicts.

160. By Jeroen T. Vermeulen

Test for coming change: make bootresources.yamll world-readable. Tests: 1 failure.

161. By Jeroen T. Vermeulen

Satisfy test.

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

Turns out there were two small problems in the upload code (Raphaël, did you find these and patch around them in your Q/A run? It would have been useful to know!) but it's passing Q/A tests now. Landing.

For the record, the problems were all in the part that uploads bootresources.yaml — so all work that we would have had to do anyway even if we let users pass in a full bootresources.yaml file. The rest of the code has been no trouble at all.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'maastest/kvmfixture.py'
--- maastest/kvmfixture.py 2014-04-09 06:19:08 +0000
+++ maastest/kvmfixture.py 2014-04-10 06:19:43 +0000
@@ -425,8 +425,9 @@
425 """425 """
426 if dest is None:426 if dest is None:
427 dest = os.path.basename(source)427 dest = os.path.basename(source)
428 remote_dest = self.identity() + ':' + dest
428 run_command(429 run_command(
429 ['scp'] + self._get_base_ssh_options() + [source, dest],430 ['scp'] + self._get_base_ssh_options() + [source, remote_dest],
430 check_call=True)431 check_call=True)
431432
432 def get_ip_from_network_scan(self, mac_address):433 def get_ip_from_network_scan(self, mac_address):
433434
=== modified file 'maastest/maasfixture.py'
--- maastest/maasfixture.py 2014-04-09 11:15:36 +0000
+++ maastest/maasfixture.py 2014-04-10 06:19:43 +0000
@@ -23,7 +23,9 @@
23import logging23import logging
24from random import choice24from random import choice
25from string import ascii_letters25from string import ascii_letters
26from tempfile import NamedTemporaryFile
26from textwrap import dedent27from textwrap import dedent
28import yaml
2729
28from apiclient.creds import convert_string_to_tuple30from apiclient.creds import convert_string_to_tuple
29from apiclient.maas_client import (31from apiclient.maas_client import (
@@ -217,6 +219,43 @@
217 'metadataserver.NodeCommissionResult'219 'metadataserver.NodeCommissionResult'
218 ])220 ])
219221
222 def make_selection(self, series, architecture):
223 """Return a `selections` dict for the `bootresources.yaml` config."""
224 arch, subarch = architecture.split('/')
225 return {
226 'release': series,
227 'arches': [arch],
228 'subarches': [subarch],
229 }
230
231 def compose_import_config(self, series, architectures):
232 """Return a `bootresources.yaml` config file for the image imports."""
233 return yaml.safe_dump({
234 'boot': {
235 'sources': [
236 {
237 'selections': [
238 self.make_selection(series, arch)
239 for arch in architectures
240 ],
241 },
242 ],
243 },
244 })
245
246 def upload_import_config(self, bootresources_yaml):
247 """Upload `bootresources.yaml' into the VM's `/etc/maas/`."""
248 with NamedTemporaryFile() as config:
249 config.write(bootresources_yaml)
250 config.flush()
251 self.kvm_fixture.upload_file(config.name, 'bootresources.yaml')
252 self.kvm_fixture.run_command(
253 ['sudo', 'chmod', 'a+r', 'bootresources.yaml'],
254 check_call=True)
255 self.kvm_fixture.run_command(
256 ['sudo', 'mv', 'bootresources.yaml', '/etc/maas/'],
257 check_call=True)
258
220 def import_maas_images(self, series, architecture,259 def import_maas_images(self, series, architecture,
221 simplestreams_filter=None):260 simplestreams_filter=None):
222 """Import boot images into the MAAS instance.261 """Import boot images into the MAAS instance.
@@ -229,13 +268,11 @@
229 subarchitecture isn't specified, 'generic' is assumed.268 subarchitecture isn't specified, 'generic' is assumed.
230 """269 """
231 arch_list = utils.mipf_arch_list(architecture)270 arch_list = utils.mipf_arch_list(architecture)
232 arch_string = ' '.join(arch_list)
233 logging.info(271 logging.info(
234 "Importing boot images series=%s, architectures=%s..." % (272 "Importing boot images series=%s, architectures=%s..." % (
235 series, arch_string))273 series, ', '.join(arch_list)))
236 # Import boot images.274 self.upload_import_config(
237 # XXX jtv 2014-04-03: Configure /etc/maas/bootresources.yaml to import275 self.compose_import_config(self.series, arch_list))
238 # just the right series & architecture.
239 self.kvm_fixture.run_command(276 self.kvm_fixture.run_command(
240 [277 [
241 'sudo',278 'sudo',
242279
=== modified file 'maastest/testing/factory.py'
--- maastest/testing/factory.py 2014-04-09 06:19:53 +0000
+++ maastest/testing/factory.py 2014-04-10 06:19:43 +0000
@@ -13,11 +13,18 @@
1313
14__metaclass__ = type14__metaclass__ = type
15__all__ = [15__all__ = [
16 'make_arch_with_subarch',
16 'make_file',17 'make_file',
17 ]18 ]
1819
19from fixtures import TempDir20from fixtures import TempDir
20import os.path21import os.path
22from random import randint
23
24
25def make_arch_with_subarch():
26 """Return an arbitrary `arch/subarch` string."""
27 return 'arch-%d/subarch-%d' % (randint(1, 10000000), randint(1, 10000000))
2128
2229
23def make_file(testcase, name=None, content=None):30def make_file(testcase, name=None, content=None):
2431
=== modified file 'maastest/tests/test_kvmfixture.py'
--- maastest/tests/test_kvmfixture.py 2014-04-09 06:19:08 +0000
+++ maastest/tests/test_kvmfixture.py 2014-04-10 06:19:43 +0000
@@ -700,8 +700,11 @@
700 def test_upload_file_uploads_file(self):700 def test_upload_file_uploads_file(self):
701 self.patch(kvmfixture, 'run_command', mock.MagicMock())701 self.patch(kvmfixture, 'run_command', mock.MagicMock())
702 fixture = self.make_KVMFixture(kvm_timeout=None)702 fixture = self.make_KVMFixture(kvm_timeout=None)
703 ip = '10.11.12.%d' % randint(1, 254)
704 fixture.identity = lambda: 'ubuntu@%s' % ip
703 local_file = make_file(self)705 local_file = make_file(self)
704 remote_file = os.path.join(gettempdir(), self.getUniqueString())706 remote_file = os.path.join(gettempdir(), self.getUniqueString())
707 remote_path = 'ubuntu@%s:%s' % (ip, remote_file)
705 fixture.upload_file(local_file, remote_file)708 fixture.upload_file(local_file, remote_file)
706 self.assertEqual(709 self.assertEqual(
707 [710 [
@@ -709,7 +712,7 @@
709 (712 (
710 ['scp'] +713 ['scp'] +
711 fixture._get_base_ssh_options() +714 fixture._get_base_ssh_options() +
712 [local_file, remote_file]715 [local_file, remote_path]
713 ),716 ),
714 check_call=True)717 check_call=True)
715 ],718 ],
@@ -718,12 +721,15 @@
718 def test_upload_file_defaults_to_base_name_in_default_dir(self):721 def test_upload_file_defaults_to_base_name_in_default_dir(self):
719 self.patch(kvmfixture, 'run_command', mock.MagicMock())722 self.patch(kvmfixture, 'run_command', mock.MagicMock())
720 fixture = self.make_KVMFixture(kvm_timeout=None)723 fixture = self.make_KVMFixture(kvm_timeout=None)
724 fixture.identity = lambda: 'ubuntu@192.168.254.99'
721 local_file = make_file(self)725 local_file = make_file(self)
722 fixture.upload_file(local_file)726 fixture.upload_file(local_file)
723 [command] = kvmfixture.run_command.mock_calls727 [command] = kvmfixture.run_command.mock_calls
724 name, args, kwargs = command728 name, args, kwargs = command
725 (command_line,) = args729 (command_line,) = args
726 self.assertEqual(os.path.basename(local_file), command_line[-1])730 self.assertEqual(
731 fixture.identity() + ':' + os.path.basename(local_file),
732 command_line[-1])
727733
728734
729def xml_normalize(snippet):735def xml_normalize(snippet):
730736
=== modified file 'maastest/tests/test_maasfixture.py'
--- maastest/tests/test_maasfixture.py 2014-04-09 11:15:36 +0000
+++ maastest/tests/test_maasfixture.py 2014-04-10 06:19:43 +0000
@@ -22,7 +22,13 @@
22import json22import json
23from random import randint23from random import randint
24from subprocess import check_call24from subprocess import check_call
25from testtools.matchers import (
26 FileExists,
27 HasLength,
28 Not,
29 )
25from textwrap import dedent30from textwrap import dedent
31import yaml
2632
27from apiclient.maas_client import MAASClient33from apiclient.maas_client import MAASClient
28from maastest import (34from maastest import (
@@ -32,7 +38,10 @@
32 )38 )
33from maastest.maas_enums import NODEGROUPINTERFACE_MANAGEMENT39from maastest.maas_enums import NODEGROUPINTERFACE_MANAGEMENT
34from maastest.maasfixture import NoBootImagesError40from maastest.maasfixture import NoBootImagesError
35from maastest.testing.factory import make_file41from maastest.testing.factory import (
42 make_arch_with_subarch,
43 make_file,
44 )
36import mock45import mock
37import netaddr46import netaddr
38from six import text_type47from six import text_type
@@ -68,11 +77,12 @@
68 'droopy', 'i860', proxy_url="http://example.com:8080")77 'droopy', 'i860', proxy_url="http://example.com:8080")
69 fixture.run_command = mock.MagicMock(78 fixture.run_command = mock.MagicMock(
70 return_value=(0, 'stdout output', 'stderr output'))79 return_value=(0, 'stdout output', 'stderr output'))
80 fixture.upload_file = mock.MagicMock()
71 ip_address = '.'.join('%d' % randint(1, 254) for octets in range(4))81 ip_address = '.'.join('%d' % randint(1, 254) for octets in range(4))
72 fixture.ip_address = mock.MagicMock(return_value=ip_address)82 fixture.ip_address = mock.MagicMock(return_value=ip_address)
73 return fixture83 return fixture
7484
75 def make_maas_fixture(self, kvm_fixture=None, proxy_url=None):85 def make_maas_fixture(self, kvm_fixture=None, proxy_url=None, arch=None):
76 """Create a `MAASFixture` with arbitrary series/architecture.86 """Create a `MAASFixture` with arbitrary series/architecture.
7787
78 The maasfixture.MAASClient's post/get/put methods are replaced by a88 The maasfixture.MAASClient's post/get/put methods are replaced by a
@@ -82,7 +92,8 @@
82 if kvm_fixture is None:92 if kvm_fixture is None:
83 kvm_fixture = self.make_kvm_fixture()93 kvm_fixture = self.make_kvm_fixture()
84 series = self.getUniqueString()94 series = self.getUniqueString()
85 arch = self.getUniqueString()95 if arch is None:
96 arch = self.getUniqueString()
86 if proxy_url is None:97 if proxy_url is None:
87 proxy_url = self.getUniqueString()98 proxy_url = self.getUniqueString()
88 filter = self.getUniqueString()99 filter = self.getUniqueString()
@@ -751,7 +762,7 @@
751 series = self.getUniqueString()762 series = self.getUniqueString()
752 arch = self.getUniqueString()763 arch = self.getUniqueString()
753 filter = self.getUniqueString()764 filter = self.getUniqueString()
754 returned_arches = ['amd64', 'i386']765 returned_arches = ['amd64/generic', 'i386/generic']
755 mock_mipf_arch_list = mock.MagicMock(return_value=returned_arches)766 mock_mipf_arch_list = mock.MagicMock(return_value=returned_arches)
756 self.patch(767 self.patch(
757 utils, 'mipf_arch_list', mock_mipf_arch_list)768 utils, 'mipf_arch_list', mock_mipf_arch_list)
@@ -781,6 +792,95 @@
781 'metadataserver.NodeCommissionResult']),792 'metadataserver.NodeCommissionResult']),
782 maas_fixture.kvm_fixture.run_command.mock_calls)793 maas_fixture.kvm_fixture.run_command.mock_calls)
783794
795 def test_compose_import_config_uses_defaults(self):
796 maas_fixture = self.make_maas_fixture()
797 config = yaml.safe_load(
798 maas_fixture.compose_import_config(
799 maas_fixture.series, [make_arch_with_subarch()]))
800 # This config only has the bare essentials. All other keys are left
801 # out so that MAAS can provide defaults.
802 self.assertItemsEqual(['boot'], config.keys())
803 self.assertItemsEqual(['sources'], config['boot'].keys())
804 self.assertThat(config['boot']['sources'], HasLength(1))
805 [source] = config['boot']['sources']
806 self.assertItemsEqual(['selections'], source.keys())
807
808 def test_compose_import_config_imports_requested_images(self):
809 full_arch = make_arch_with_subarch()
810 arch, subarch = full_arch.split('/')
811 maas_fixture = self.make_maas_fixture(arch=full_arch)
812 config = yaml.safe_load(maas_fixture.compose_import_config(
813 maas_fixture.series, [full_arch]))
814 [source] = config['boot']['sources']
815 self.assertEqual(
816 [{
817 'arches': [arch],
818 'subarches': [subarch],
819 'release': maas_fixture.series,
820 }],
821 source['selections'])
822
823 def test_compose_import_config_generates_one_selection_per_arch(self):
824 arches = ['arch1/subarch1', 'arch2/subarch2']
825 maas_fixture = self.make_maas_fixture()
826 config = yaml.safe_load(maas_fixture.compose_import_config(
827 maas_fixture.series, arches))
828 [source] = config['boot']['sources']
829 self.assertEqual(
830 [
831 {
832 'arches': ['arch1'],
833 'subarches': ['subarch1'],
834 'release': maas_fixture.series,
835 },
836 {
837 'arches': ['arch2'],
838 'subarches': ['subarch2'],
839 'release': maas_fixture.series,
840 },
841 ],
842 source['selections'])
843
844 def test_upload_import_config_writes_config_to_temp_file(self):
845
846 class RecordingUpload:
847 """Fake `upload_file` for testing.
848
849 Records the given files path, and its contents.
850 """
851 def __call__(self, local_file, remote_file=None):
852 self.path = local_file
853 with open(self.path, 'rb') as open_file:
854 self.content = open_file.read()
855
856 maas_fixture = self.make_maas_fixture()
857 fake_upload = RecordingUpload()
858 maas_fixture.kvm_fixture.upload_file = fake_upload
859 fake_config = self.getUniqueString()
860 maas_fixture.upload_import_config(fake_config)
861
862 # The uploaded file was temporary; it no longer exists.
863 self.assertThat(fake_upload.path, Not(FileExists()))
864 # But its contents were as given.
865 self.assertEqual(fake_config, fake_upload.content)
866
867 def test_upload_import_config_uploads_bootresources_config(self):
868 maas_fixture = self.make_maas_fixture()
869 maas_fixture.upload_import_config(self.getUniqueString())
870 self.assertEqual(
871 [mock.call(mock.ANY, 'bootresources.yaml')],
872 maas_fixture.kvm_fixture.upload_file.mock_calls)
873 self.assertEqual(
874 [
875 mock.call(
876 ['sudo', 'chmod', 'a+r', 'bootresources.yaml'],
877 check_call=True),
878 mock.call(
879 ['sudo', 'mv', 'bootresources.yaml', '/etc/maas/'],
880 check_call=True),
881 ],
882 maas_fixture.kvm_fixture.run_command.mock_calls)
883
784 def test_wait_until_boot_images_scanned_times_out_eventually(self):884 def test_wait_until_boot_images_scanned_times_out_eventually(self):
785 maas_fixture = self.make_maas_fixture()885 maas_fixture = self.make_maas_fixture()
786 self.patch(886 self.patch(
787887
=== modified file 'maastest/tests/test_utils.py'
--- maastest/tests/test_utils.py 2014-04-04 17:05:59 +0000
+++ maastest/tests/test_utils.py 2014-04-10 06:19:43 +0000
@@ -35,7 +35,7 @@
35 )35 )
3636
3737
38class TestRunCommand(testtools.TestCase):38class TestReadFile(testtools.TestCase):
3939
40 def test_read_file_returns_file_contents_as_bytes(self):40 def test_read_file_returns_file_contents_as_bytes(self):
41 temp_dir = self.useFixture(TempDir())41 temp_dir = self.useFixture(TempDir())
@@ -49,6 +49,9 @@
49 self.assertEqual(contents, read_contents)49 self.assertEqual(contents, read_contents)
50 self.assertIsInstance(contents, bytes)50 self.assertIsInstance(contents, bytes)
5151
52
53class TestRunCommand(testtools.TestCase):
54
52 def test_run_command_calls_Popen(self):55 def test_run_command_calls_Popen(self):
53 mock_Popen = mock.MagicMock()56 mock_Popen = mock.MagicMock()
54 expected_retcode = self.getUniqueInteger()57 expected_retcode = self.getUniqueInteger()
5558
=== modified file 'maastest/utils.py'
--- maastest/utils.py 2014-04-08 06:49:23 +0000
+++ maastest/utils.py 2014-04-10 06:19:43 +0000
@@ -13,15 +13,16 @@
13__all__ = [13__all__ = [
14 "BINARY",14 "BINARY",
15 "binary_content",15 "binary_content",
16 "CasesLoader",
17 "DEFAULT_PIDFILE_DIR",
16 "DEFAULT_STATE_DIR",18 "DEFAULT_STATE_DIR",
19 "determine_vm_architecture",
17 "determine_vm_series",20 "determine_vm_series",
18 "determine_vm_architecture",
19 "get_uri",21 "get_uri",
20 "DEFAULT_PIDFILE_DIR",22 "mipf_arch_list",
21 "read_file",23 "read_file",
22 "retries",24 "retries",
23 "run_command",25 "run_command",
24 "CasesLoader",
25 ]26 ]
2627
2728

Subscribers

People subscribed via source and target branches