Merge lp:~jameinel/maas/1.2-remove-kernel-opts into lp:maas/trunk

Proposed by John A Meinel on 2012-11-08
Status: Superseded
Proposed branch: lp:~jameinel/maas/1.2-remove-kernel-opts
Merge into: lp:maas/trunk
Diff against target: 601 lines (+378/-33) (has conflicts)
11 files modified
src/maasserver/api.py (+16/-3)
src/maasserver/forms.py (+13/-0)
src/maasserver/templates/maasserver/node_list.html (+5/-0)
src/maasserver/tests/test_api.py (+56/-0)
src/maasserver/tests/test_forms.py (+75/-30)
src/maasserver/tests/test_views_nodes.py (+60/-0)
src/maasserver/utils/__init__.py (+25/-0)
src/maasserver/utils/tests/test_utils.py (+78/-0)
src/provisioningserver/boot_images.py (+4/-0)
src/provisioningserver/tasks.py (+16/-0)
src/provisioningserver/tests/test_tasks.py (+30/-0)
Text conflict in src/maasserver/api.py
Text conflict in src/maasserver/forms.py
Text conflict in src/maasserver/templates/maasserver/node_list.html
Text conflict in src/maasserver/tests/test_api.py
Text conflict in src/maasserver/tests/test_forms.py
Text conflict in src/maasserver/tests/test_views_nodes.py
Text conflict in src/maasserver/utils/__init__.py
Text conflict in src/maasserver/utils/tests/test_utils.py
Text conflict in src/provisioningserver/boot_images.py
Text conflict in src/provisioningserver/tasks.py
Text conflict in src/provisioningserver/tests/test_tasks.py
To merge this branch: bzr merge lp:~jameinel/maas/1.2-remove-kernel-opts
Reviewer Review Type Date Requested Status
Launchpad code reviewers 2012-11-08 Pending
Review via email: mp+133424@code.launchpad.net

This proposal has been superseded by a proposal from 2012-11-08.

Commit Message

This removes the recent patches to add kernel_opts to the 1.2 branch.

We'll land it instead on trunk, and then it will get backported in the future once a bugfix only SRU was done.

To post a comment you must log in.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'etc/celeryconfig_common.py'
2=== modified file 'src/maasserver/api.py'
3--- src/maasserver/api.py 2012-11-08 09:12:44 +0000
4+++ src/maasserver/api.py 2012-11-08 09:19:27 +0000
5@@ -745,9 +745,22 @@
6
7 When a node has been added to MAAS by an admin MAAS user, it is
8 ready for allocation to services running on the MAAS.
9- The minimum data required is:
10- architecture=<arch string> (e.g "i386/generic")
11- mac_address=<value>
12+<<<<<<< TREE
13+ The minimum data required is:
14+ architecture=<arch string> (e.g "i386/generic")
15+ mac_address=<value>
16+=======
17+ The minimum data required is:
18+ architecture=<arch string> (e.g "i386/generic")
19+ mac_address=<value>
20+
21+ :param architecture: A string containing the architecture type of
22+ the node.
23+ :param mac_address: The MAC address of the node.
24+ :param hostname: A hostname. If not given, one will be generated.
25+ :param powertype: A power management type, if applicable (e.g.
26+ "virsh", "ipmi").
27+>>>>>>> MERGE-SOURCE
28 """
29 node = create_node(request)
30 if request.user.is_superuser:
31
32=== modified file 'src/maasserver/forms.py'
33--- src/maasserver/forms.py 2012-11-01 15:13:10 +0000
34+++ src/maasserver/forms.py 2012-11-08 09:19:27 +0000
35@@ -394,6 +394,7 @@
36 node.save()
37 for mac in self.cleaned_data['mac_addresses']:
38 node.add_mac_address(mac)
39+<<<<<<< TREE
40 hostname = self.cleaned_data['hostname']
41 stripped_hostname = strip_domain(hostname)
42 # Generate a hostname for this node if the provided hostname is
43@@ -404,6 +405,18 @@
44 IP_BASED_HOSTNAME_REGEXP.match(stripped_hostname) != None)
45 if generate_hostname:
46 node.set_random_hostname()
47+=======
48+ hostname = self.cleaned_data['hostname']
49+ stripped_hostname = strip_domain(hostname)
50+ # Generate a hostname for this node if the provided hostname is
51+ # IP-based (because this means that this name comes from a DNS
52+ # reverse query to the MAAS DNS) or an empty string.
53+ generate_hostname = (
54+ hostname == "" or
55+ IP_BASED_HOSTNAME_REGEXP.match(stripped_hostname) != None)
56+ if generate_hostname:
57+ node.set_mac_based_hostname(self.cleaned_data['mac_addresses'][0])
58+>>>>>>> MERGE-SOURCE
59 return node
60
61
62
63=== modified file 'src/maasserver/models/node.py'
64=== modified file 'src/maasserver/models/nodegroup.py'
65=== modified file 'src/maasserver/templates/maasserver/node_list.html'
66--- src/maasserver/templates/maasserver/node_list.html 2012-10-24 12:51:10 +0000
67+++ src/maasserver/templates/maasserver/node_list.html 2012-11-08 09:19:27 +0000
68@@ -38,8 +38,13 @@
69 {% if input_query_error %}
70 <p class="form-errors">{{input_query_error}}</p>
71 {% endif %}
72+<<<<<<< TREE
73 {% include "maasserver/nodes_listing.html" with sorting="true" %}
74 {% include "maasserver/pagination.html" %}
75+=======
76+ {% include "maasserver/nodes_listing.html" %}
77+ {% include "maasserver/pagination.html" %}
78+>>>>>>> MERGE-SOURCE
79 <a id="addnode" href="#" class="button right space-top">+ Add node</a>
80 <div class="clear"></div>
81 <a class="right space-top" href="{% url "enlist-preseed-view" %}">View enlistment preseed</a>
82
83=== modified file 'src/maasserver/testing/factory.py'
84=== modified file 'src/maasserver/tests/test_api.py'
85--- src/maasserver/tests/test_api.py 2012-11-08 09:12:44 +0000
86+++ src/maasserver/tests/test_api.py 2012-11-08 09:19:27 +0000
87@@ -122,11 +122,18 @@
88 NodeUserData,
89 )
90 from metadataserver.nodeinituser import get_node_init_user
91+<<<<<<< TREE
92 from mock import (
93 ANY,
94 call,
95 Mock,
96 )
97+=======
98+from mock import (
99+ ANY,
100+ Mock,
101+ )
102+>>>>>>> MERGE-SOURCE
103 from provisioningserver import (
104 boot_images,
105 kernel_opts,
106@@ -4433,6 +4440,7 @@
107 self.assertSetEqual(
108 {"doc", "handlers", "resources"}, set(description))
109 self.assertIsInstance(description["handlers"], list)
110+<<<<<<< TREE
111
112
113 class TestDescribeAbsoluteURIs(AnonAPITestCase):
114@@ -4513,3 +4521,51 @@
115 resources = description["resources"]
116 self.assertNotEqual([], resources)
117 self.assertThat(resources, AllMatch(expected_resource))
118+=======
119+
120+
121+class TestDescribeAbsoluteURIs(AnonAPITestCase):
122+ """Tests for the `describe` view's URI manipulation."""
123+
124+ scenarios_schemes = (
125+ ("http", dict(scheme="http")),
126+ ("https", dict(scheme="https")),
127+ )
128+
129+ scenarios_paths = (
130+ ("script-at-root", dict(script_name="", path_info="")),
131+ ("script-below-root-1", dict(script_name="/foo/bar", path_info="")),
132+ ("script-below-root-2", dict(script_name="/foo", path_info="/bar")),
133+ )
134+
135+ scenarios = multiply_scenarios(
136+ scenarios_schemes, scenarios_paths)
137+
138+ def test_handler_uris_are_absolute(self):
139+ server = factory.make_name("server").lower()
140+ extra = {
141+ "PATH_INFO": self.path_info,
142+ "SCRIPT_NAME": self.script_name,
143+ "SERVER_NAME": server,
144+ "wsgi.url_scheme": self.scheme,
145+ }
146+ request = RequestFactory().get(
147+ "/%s/describe" % factory.make_name("path"), **extra)
148+ response = describe(request)
149+ self.assertEqual(httplib.OK, response.status_code, response.content)
150+ description = json.loads(response.content)
151+ expected_uri = AfterPreprocessing(
152+ urlparse, MatchesStructure(
153+ scheme=Equals(self.scheme), hostname=Equals(server),
154+ # The path is always the script name followed by "api/"
155+ # because all API calls are within the "api" tree.
156+ path=StartsWith(self.script_name + "/api/")))
157+ expected_handler = MatchesAny(
158+ Is(None), AfterPreprocessing(itemgetter("uri"), expected_uri))
159+ expected_resource = MatchesAll(
160+ AfterPreprocessing(itemgetter("anon"), expected_handler),
161+ AfterPreprocessing(itemgetter("auth"), expected_handler))
162+ resources = description["resources"]
163+ self.assertNotEqual([], resources)
164+ self.assertThat(resources, AllMatch(expected_resource))
165+>>>>>>> MERGE-SOURCE
166
167=== modified file 'src/maasserver/tests/test_dhcplease.py'
168=== modified file 'src/maasserver/tests/test_forms.py'
169--- src/maasserver/tests/test_forms.py 2012-11-01 11:11:48 +0000
170+++ src/maasserver/tests/test_forms.py 2012-11-08 09:19:27 +0000
171@@ -350,36 +350,81 @@
172 after_commissioning_action, node.after_commissioning_action)
173 self.assertEqual(power_type, node.power_type)
174
175- def test_AdminNodeForm_refuses_to_update_hostname_on_allocated_node(self):
176- old_name = factory.make_name('old-hostname')
177- new_name = factory.make_name('new-hostname')
178- node = factory.make_node(
179- hostname=old_name, status=NODE_STATUS.ALLOCATED)
180- form = AdminNodeForm(
181- data={
182- 'hostname': new_name,
183- 'architecture': node.architecture,
184- },
185- instance=node)
186- self.assertFalse(form.is_valid())
187- self.assertEqual(
188- ["Can't change hostname to %s: node is in use." % new_name],
189- form._errors['hostname'])
190-
191- def test_AdminNodeForm_accepts_unchanged_hostname_on_allocated_node(self):
192- old_name = factory.make_name('old-hostname')
193- node = factory.make_node(
194- hostname=old_name, status=NODE_STATUS.ALLOCATED)
195- form = AdminNodeForm(
196- data={
197- 'hostname': old_name,
198- 'architecture': node.architecture,
199- },
200- instance=node)
201- self.assertTrue(form.is_valid(), form._errors)
202- form.save()
203- self.assertEqual(old_name, reload_object(node).hostname)
204-
205+<<<<<<< TREE
206+ def test_AdminNodeForm_refuses_to_update_hostname_on_allocated_node(self):
207+ old_name = factory.make_name('old-hostname')
208+ new_name = factory.make_name('new-hostname')
209+ node = factory.make_node(
210+ hostname=old_name, status=NODE_STATUS.ALLOCATED)
211+ form = AdminNodeForm(
212+ data={
213+ 'hostname': new_name,
214+ 'architecture': node.architecture,
215+ },
216+ instance=node)
217+ self.assertFalse(form.is_valid())
218+ self.assertEqual(
219+ ["Can't change hostname to %s: node is in use." % new_name],
220+ form._errors['hostname'])
221+
222+ def test_AdminNodeForm_accepts_unchanged_hostname_on_allocated_node(self):
223+ old_name = factory.make_name('old-hostname')
224+ node = factory.make_node(
225+ hostname=old_name, status=NODE_STATUS.ALLOCATED)
226+ form = AdminNodeForm(
227+ data={
228+ 'hostname': old_name,
229+ 'architecture': node.architecture,
230+ },
231+ instance=node)
232+ self.assertTrue(form.is_valid(), form._errors)
233+ form.save()
234+ self.assertEqual(old_name, reload_object(node).hostname)
235+
236+=======
237+ def test_AdminNodeForm_refuses_to_update_hostname_on_allocated_node(self):
238+ old_name = factory.make_name('old-hostname')
239+ new_name = factory.make_name('new-hostname')
240+ node = factory.make_node(
241+ hostname=old_name, status=NODE_STATUS.ALLOCATED)
242+ form = AdminNodeForm(
243+ data={
244+ 'hostname': new_name,
245+ 'architecture': node.architecture,
246+ },
247+ instance=node)
248+ self.assertFalse(form.is_valid())
249+ self.assertEqual(
250+ ["Can't change hostname to %s: node is in use." % new_name],
251+ form._errors['hostname'])
252+
253+ def test_AdminNodeForm_accepts_unchanged_hostname_on_allocated_node(self):
254+ old_name = factory.make_name('old-hostname')
255+ node = factory.make_node(
256+ hostname=old_name, status=NODE_STATUS.ALLOCATED)
257+ form = AdminNodeForm(
258+ data={
259+ 'hostname': old_name,
260+ 'architecture': node.architecture,
261+ },
262+ instance=node)
263+ self.assertTrue(form.is_valid(), form._errors)
264+ form.save()
265+ self.assertEqual(old_name, reload_object(node).hostname)
266+
267+ def test_AdminNodeForm_accepts_omitted_hostname_on_allocated_node(self):
268+ node = factory.make_node(status=NODE_STATUS.ALLOCATED)
269+ old_name = node.hostname
270+ form = AdminNodeForm(
271+ data={
272+ 'architecture': node.architecture,
273+ },
274+ instance=node)
275+ self.assertTrue(form.is_valid())
276+ form.save()
277+ self.assertEqual(old_name, reload_object(node).hostname)
278+
279+>>>>>>> MERGE-SOURCE
280 def test_remove_None_values_removes_None_values_in_dict(self):
281 random_input = factory.getRandomString()
282 self.assertEqual(
283
284=== modified file 'src/maasserver/tests/test_node.py'
285=== modified file 'src/maasserver/tests/test_views_nodes.py'
286--- src/maasserver/tests/test_views_nodes.py 2012-11-01 15:59:22 +0000
287+++ src/maasserver/tests/test_views_nodes.py 2012-11-08 09:19:27 +0000
288@@ -532,6 +532,7 @@
289 "//div[@id='nodes']/table//td/a/@href")
290 self.assertEqual([node2_link], node_links)
291
292+<<<<<<< TREE
293 def test_node_list_paginates(self):
294 """Node listing is split across multiple pages with links"""
295 # Set a very small page size to save creating lots of nodes
296@@ -591,6 +592,65 @@
297 [(a.text.lower(), a.get("href"))
298 for a in document.xpath("//div[@class='pagination']//a")])
299
300+=======
301+ def test_node_list_paginates(self):
302+ """Node listing is split across multiple pages with links"""
303+ # Set a very small page size to save creating lots of nodes
304+ page_size = 2
305+ self.patch(nodes_views.NodeListView, 'paginate_by', page_size)
306+ nodes = [factory.make_node(created="2012-10-12 12:00:%02d" % i)
307+ for i in range(page_size * 2 + 1)]
308+ # Order node links with newest first as the view is expected to
309+ node_links = [reverse('node-view', args=[node.system_id])
310+ for node in reversed(nodes)]
311+ expr_node_links = XPath("//div[@id='nodes']/table//a/@href")
312+ expr_page_anchors = XPath("//div[@class='pagination']//a")
313+ # Fetch first page, should link newest two nodes and page 2
314+ response = self.client.get(reverse('node-list'))
315+ page1 = fromstring(response.content)
316+ self.assertEqual(node_links[:page_size], expr_node_links(page1))
317+ self.assertEqual([("next", "?page=2"), ("last", "?page=3")],
318+ [(a.text.lower(), a.get("href"))
319+ for a in expr_page_anchors(page1)])
320+ # Fetch second page, should link next nodes and adjacent pages
321+ response = self.client.get(reverse('node-list'), {"page": 2})
322+ page2 = fromstring(response.content)
323+ self.assertEqual(node_links[page_size:page_size * 2],
324+ expr_node_links(page2))
325+ self.assertEqual([("first", "."), ("previous", "."),
326+ ("next", "?page=3"), ("last", "?page=3")],
327+ [(a.text.lower(), a.get("href"))
328+ for a in expr_page_anchors(page2)])
329+ # Fetch third page, should link oldest node and node list page
330+ response = self.client.get(reverse('node-list'), {"page": 3})
331+ page3 = fromstring(response.content)
332+ self.assertEqual(node_links[page_size * 2:], expr_node_links(page3))
333+ self.assertEqual([("first", "."), ("previous", "?page=2")],
334+ [(a.text.lower(), a.get("href"))
335+ for a in expr_page_anchors(page3)])
336+
337+ def test_node_list_query_paginates(self):
338+ """Node list query subset is split across multiple pages with links"""
339+ # Set a very small page size to save creating lots of nodes
340+ self.patch(nodes_views.NodeListView, 'paginate_by', 2)
341+ nodes = [factory.make_node(created="2012-10-12 12:00:%02d" % i)
342+ for i in range(10)]
343+ tag = factory.make_tag("odd")
344+ for node in nodes[::2]:
345+ node.tags = [tag]
346+ last_node_link = reverse('node-view', args=[nodes[0].system_id])
347+ response = self.client.get(reverse('node-list'),
348+ {"query": "maas-tags=odd", "page": 3})
349+ document = fromstring(response.content)
350+ self.assertIn("5 matching nodes", document.xpath("string(//h1)"))
351+ self.assertEqual([last_node_link],
352+ document.xpath("//div[@id='nodes']/table//a/@href"))
353+ self.assertEqual([("first", "?query=maas-tags%3Dodd"),
354+ ("previous", "?query=maas-tags%3Dodd&page=2")],
355+ [(a.text.lower(), a.get("href"))
356+ for a in document.xpath("//div[@class='pagination']//a")])
357+
358+>>>>>>> MERGE-SOURCE
359
360 class NodePreseedViewTest(LoggedInTestCase):
361
362
363=== modified file 'src/maasserver/tests/test_views_settings.py'
364=== modified file 'src/maasserver/utils/__init__.py'
365--- src/maasserver/utils/__init__.py 2012-11-07 19:00:22 +0000
366+++ src/maasserver/utils/__init__.py 2012-11-08 09:19:27 +0000
367@@ -84,6 +84,7 @@
368 if query is not None:
369 url += '?%s' % urlencode(query, doseq=True)
370 return url
371+<<<<<<< TREE
372
373
374 def build_absolute_uri(request, path):
375@@ -103,3 +104,27 @@
376 def strip_domain(hostname):
377 """Return `hostname` with the domain part removed."""
378 return hostname.split('.', 1)[0]
379+=======
380+
381+
382+def build_absolute_uri(request, path):
383+ """Given a full app-relative path, returns an absolute URI.
384+
385+ The path ordinarily starts with a forward-slash... imagine that you've
386+ magically chroot'ed to your Django application; the path is the absolute
387+ path to the view within that environment.
388+
389+ The URI returned uses the request to figure out how to make an absolute
390+ URL. This means that the URI returned will use the same IP address or
391+ alias that the request came in on.
392+ """
393+ script_name = request.META["SCRIPT_NAME"]
394+ return "%s://%s%s%s" % (
395+ "https" if request.is_secure() else "http",
396+ request.get_host(), script_name, path)
397+
398+
399+def strip_domain(hostname):
400+ """Return `hostname` with the domain part removed."""
401+ return hostname.split('.', 1)[0]
402+>>>>>>> MERGE-SOURCE
403
404=== modified file 'src/maasserver/utils/tests/test_utils.py'
405--- src/maasserver/utils/tests/test_utils.py 2012-11-07 19:00:22 +0000
406+++ src/maasserver/utils/tests/test_utils.py 2012-11-08 09:19:27 +0000
407@@ -107,6 +107,7 @@
408 NODE_STATUS_CHOICES, but_not=[status])
409 node.status = another_status
410 self.assertEqual(status, get_db_state(node, 'status'))
411+<<<<<<< TREE
412
413
414 class TestBuildAbsoluteURI(TestCase):
415@@ -175,3 +176,80 @@
416 inputs = [input for input, _ in input_and_results]
417 results = [result for _, result in input_and_results]
418 self.assertEqual(results, map(strip_domain, inputs))
419+=======
420+
421+
422+class TestBuildAbsoluteURI(TestCase):
423+ """Tests for `build_absolute_uri`."""
424+
425+ def make_request(self, host="example.com", port=80, script_name="",
426+ is_secure=False):
427+ """Return a :class:`HttpRequest` with the given parameters."""
428+ request = HttpRequest()
429+ request.META["SERVER_NAME"] = host
430+ request.META["SERVER_PORT"] = port
431+ request.META["SCRIPT_NAME"] = script_name
432+ request.is_secure = lambda: is_secure
433+ return request
434+
435+ def test_simple(self):
436+ request = self.make_request()
437+ self.assertEqual(
438+ "http://example.com/fred",
439+ build_absolute_uri(request, "/fred"))
440+
441+ def test_different_port(self):
442+ request = self.make_request(port=1234)
443+ self.assertEqual(
444+ "http://example.com:1234/fred",
445+ build_absolute_uri(request, "/fred"))
446+
447+ def test_script_name_is_prefixed(self):
448+ # The script name is always prefixed to the given path.
449+ request = self.make_request(script_name="/foo/bar")
450+ self.assertEqual(
451+ "http://example.com/foo/bar/fred",
452+ build_absolute_uri(request, "/fred"))
453+
454+ def test_secure(self):
455+ request = self.make_request(port=443, is_secure=True)
456+ self.assertEqual(
457+ "https://example.com/fred",
458+ build_absolute_uri(request, "/fred"))
459+
460+ def test_different_port_and_secure(self):
461+ request = self.make_request(port=9443, is_secure=True)
462+ self.assertEqual(
463+ "https://example.com:9443/fred",
464+ build_absolute_uri(request, "/fred"))
465+
466+ def test_no_leading_forward_slash(self):
467+ # No attempt is made to ensure that the given path is separated from
468+ # the to-be-prefixed path.
469+ request = self.make_request(script_name="/foo")
470+ self.assertEqual(
471+ "http://example.com/foobar",
472+ build_absolute_uri(request, "bar"))
473+
474+ def test_preserve_two_leading_slashes(self):
475+ # Whilst this shouldn't ordinarily happen, two leading slashes in the
476+ # path should be preserved, and not treated specially.
477+ request = self.make_request(script_name="//foo")
478+ self.assertEqual(
479+ "http://example.com//foo/fred",
480+ build_absolute_uri(request, "/fred"))
481+
482+
483+class TestStripDomain(TestCase):
484+
485+ def test_strip_domain(self):
486+ input_and_results = [
487+ ('name.domain', 'name'),
488+ ('name', 'name'),
489+ ('name.domain.what', 'name'),
490+ ('name..domain', 'name'),
491+ ]
492+ inputs = [input for input, _ in input_and_results]
493+ results = [result for _, result in input_and_results]
494+ self.assertEqual(results, map(strip_domain, inputs))
495+>>>>>>> MERGE-SOURCE
496
497=== modified file 'src/maasserver/views/nodes.py'
498=== modified file 'src/provisioningserver/boot_images.py'
499--- src/provisioningserver/boot_images.py 2012-10-25 07:27:24 +0000
500+++ src/provisioningserver/boot_images.py 2012-11-08 09:19:27 +0000
501@@ -32,10 +32,14 @@
502 )
503 from provisioningserver.config import Config
504 from provisioningserver.pxe import tftppath
505+<<<<<<< TREE
506 from provisioningserver.start_cluster_controller import get_cluster_uuid
507
508
509 task_logger = get_task_logger(name=__name__)
510+=======
511+from provisioningserver.start_cluster_controller import get_cluster_uuid
512+>>>>>>> MERGE-SOURCE
513
514
515 def get_cached_knowledge():
516
517=== modified file 'src/provisioningserver/dns/config.py'
518=== modified file 'src/provisioningserver/dns/tests/test_config.py'
519=== modified file 'src/provisioningserver/tasks.py'
520--- src/provisioningserver/tasks.py 2012-11-07 10:39:19 +0000
521+++ src/provisioningserver/tasks.py 2012-11-08 09:19:27 +0000
522@@ -369,6 +369,7 @@
523 exc=exc, countdown=UPDATE_NODE_TAGS_RETRY_DELAY)
524 else:
525 raise
526+<<<<<<< TREE
527
528
529 # =====================================================================
530@@ -382,3 +383,18 @@
531 env['http_proxy'] = http_proxy
532 env['https_proxy'] = http_proxy
533 check_call(['sudo', '-n', 'maas-import-pxe-files'], env=env)
534+=======
535+
536+
537+# =====================================================================
538+# Image importing-related tasks
539+# =====================================================================
540+
541+@task
542+def import_pxe_files(http_proxy=None):
543+ env = dict(os.environ)
544+ if http_proxy is not None:
545+ env['http_proxy'] = http_proxy
546+ env['https_proxy'] = http_proxy
547+ check_call(['maas-import-pxe-files'], env=env)
548+>>>>>>> MERGE-SOURCE
549
550=== modified file 'src/provisioningserver/tests/test_tasks.py'
551--- src/provisioningserver/tests/test_tasks.py 2012-11-07 10:39:19 +0000
552+++ src/provisioningserver/tests/test_tasks.py 2012-11-08 09:19:27 +0000
553@@ -64,7 +64,11 @@
554 from provisioningserver.tags import MissingCredentials
555 from provisioningserver.tasks import (
556 add_new_dhcp_host_map,
557+<<<<<<< TREE
558 import_boot_images,
559+=======
560+ import_pxe_files,
561+>>>>>>> MERGE-SOURCE
562 Omshell,
563 power_off,
564 power_on,
565@@ -536,6 +540,7 @@
566 self.assertRaises(
567 MissingCredentials, update_node_tags.delay, tag,
568 '//node', retry=True)
569+<<<<<<< TREE
570
571
572 class TestImportPxeFiles(PservTestCase):
573@@ -560,3 +565,28 @@
574 expected_env = dict(os.environ, http_proxy=proxy, https_proxy=proxy)
575 recorder.assert_called_once_with(
576 ['sudo', '-n', 'maas-import-pxe-files'], env=expected_env)
577+=======
578+
579+
580+class TestImportPxeFiles(PservTestCase):
581+
582+ def test_import_pxe_files(self):
583+ recorder = self.patch(tasks, 'check_call', Mock())
584+ import_pxe_files()
585+ recorder.assert_called_once_with(['maas-import-pxe-files'], env=ANY)
586+ self.assertIsInstance(import_pxe_files, Task)
587+
588+ def test_import_pxe_files_preserves_environment(self):
589+ recorder = self.patch(tasks, 'check_call', Mock())
590+ import_pxe_files()
591+ recorder.assert_called_once_with(
592+ ['maas-import-pxe-files'], env=os.environ)
593+
594+ def test_import_pxe_files_sets_proxy(self):
595+ recorder = self.patch(tasks, 'check_call', Mock())
596+ proxy = factory.getRandomString()
597+ import_pxe_files(http_proxy=proxy)
598+ expected_env = dict(os.environ, http_proxy=proxy, https_proxy=proxy)
599+ recorder.assert_called_once_with(
600+ ['maas-import-pxe-files'], env=expected_env)
601+>>>>>>> MERGE-SOURCE