1
# Copyright 2012 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
"""Tests for the install_pxe_image command."""
6
from __future__ import (
17
from maastesting.factory import factory
18
from maastesting.testcase import TestCase
19
import provisioningserver.pxe.install_image
20
from provisioningserver.pxe.install_image import (
25
from provisioningserver.pxe.tftppath import (
29
from provisioningserver.testing.config import ConfigFixture
30
from provisioningserver.utils import MainScript
31
from testtools.matchers import (
39
def make_arch_subarch_release_purpose():
40
"""Create arbitrary architecture/subarchitecture/release names.
42
:return: A triplet of three identifiers for these respective items.
45
factory.make_name(item)
46
for item in ('arch', 'subarch', 'release', 'purpose'))
49
class TestInstallPXEImage(TestCase):
51
def test_integration(self):
52
tftproot = self.make_dir()
53
config = {"tftp": {"root": tftproot}}
54
config_fixture = ConfigFixture(config)
55
self.useFixture(config_fixture)
57
download_dir = self.make_dir()
58
image_dir = os.path.join(download_dir, 'image')
59
os.makedirs(image_dir)
60
factory.make_file(image_dir, 'kernel')
61
arch, subarch, release, purpose = make_arch_subarch_release_purpose()
63
action = factory.make_name("action")
64
script = MainScript(action)
65
script.register(action, provisioningserver.pxe.install_image)
67
("--config-file", config_fixture.filename, action, "--arch", arch,
68
"--subarch", subarch, "--release", release, "--purpose", purpose,
69
"--image", image_dir))
74
compose_image_path(arch, subarch, release, purpose),
79
def test_make_destination_follows_pxe_path_conventions(self):
80
# The directory that make_destination returns follows the PXE
81
# directory hierarchy specified for MAAS:
82
# /var/lib/tftproot/maas/<arch>/<subarch>/<release>/<purpose>
83
# (Where the /var/lib/tftproot/ part is configurable, so we
84
# can test this without overwriting system files).
85
tftproot = self.make_dir()
86
arch, subarch, release, purpose = make_arch_subarch_release_purpose()
88
os.path.join(tftproot, 'maas', arch, subarch, release, purpose),
89
make_destination(tftproot, arch, subarch, release, purpose))
91
def test_make_destination_creates_directory_if_not_present(self):
92
tftproot = self.make_dir()
93
arch, subarch, release, purpose = make_arch_subarch_release_purpose()
94
expected_destination = os.path.dirname(locate_tftp_path(
95
compose_image_path(arch, subarch, release, purpose),
97
make_destination(tftproot, arch, subarch, release, purpose)
98
self.assertThat(expected_destination, DirExists())
100
def test_make_destination_returns_existing_directory(self):
101
tftproot = self.make_dir()
102
arch, subarch, release, purpose = make_arch_subarch_release_purpose()
103
expected_dest = locate_tftp_path(
104
compose_image_path(arch, subarch, release, purpose),
106
os.makedirs(expected_dest)
107
contents = factory.getRandomString()
108
testfile = factory.make_name('testfile')
109
factory.make_file(expected_dest, contents=contents, name=testfile)
110
dest = make_destination(tftproot, arch, subarch, release, purpose)
111
self.assertThat(os.path.join(dest, testfile), FileContains(contents))
113
def test_are_identical_dirs_sees_missing_old_dir_as_different(self):
116
os.path.join(self.make_dir(), factory.getRandomString()),
117
os.path.dirname(self.make_file())))
119
def test_are_identical_dirs_returns_true_if_identical(self):
120
name = factory.getRandomString()
121
contents = factory.getRandomString()
122
self.assertTrue(are_identical_dirs(
123
os.path.dirname(self.make_file(name=name, contents=contents)),
124
os.path.dirname(self.make_file(name=name, contents=contents))))
126
def test_are_identical_dirs_returns_false_if_file_has_changed(self):
127
name = factory.getRandomString()
128
old = os.path.dirname(self.make_file(name=name))
129
new = os.path.dirname(self.make_file(name=name))
130
self.assertFalse(are_identical_dirs(old, new))
132
def test_are_identical_dirs_returns_false_if_file_was_added(self):
133
shared_file = factory.getRandomString()
134
contents = factory.getRandomString()
135
old = os.path.dirname(
136
self.make_file(name=shared_file, contents=contents))
137
new = os.path.dirname(
138
self.make_file(name=shared_file, contents=contents))
139
factory.make_file(new)
140
self.assertFalse(are_identical_dirs(old, new))
142
def test_are_identical_dirs_returns_false_if_file_was_removed(self):
143
shared_file = factory.getRandomString()
144
contents = factory.getRandomString()
145
old = os.path.dirname(
146
self.make_file(name=shared_file, contents=contents))
147
new = os.path.dirname(
148
self.make_file(name=shared_file, contents=contents))
149
factory.make_file(old)
150
self.assertFalse(are_identical_dirs(old, new))
152
def test_install_dir_moves_dir_into_place(self):
153
download_image = os.path.join(self.make_dir(), 'download-image')
154
published_image = os.path.join(self.make_dir(), 'published-image')
155
contents = factory.getRandomString()
156
os.makedirs(download_image)
157
sample_file = factory.make_file(download_image, contents=contents)
158
install_dir(download_image, published_image)
160
os.path.join(published_image, os.path.basename(sample_file)),
161
FileContains(contents))
163
def test_install_dir_replaces_existing_dir(self):
164
download_image = os.path.join(self.make_dir(), 'download-image')
165
published_image = os.path.join(self.make_dir(), 'published-image')
166
os.makedirs(download_image)
167
sample_file = factory.make_file(download_image)
168
os.makedirs(published_image)
169
obsolete_file = factory.make_file(published_image)
170
install_dir(download_image, published_image)
172
os.path.join(published_image, os.path.basename(sample_file)),
174
self.assertThat(obsolete_file, Not(FileExists()))
176
def test_install_dir_sweeps_aside_dot_new_and_dot_old_if_any(self):
177
# If directories <old>.old or <old>.new already exist, they're
178
# probably from an aborted previous run. They won't stop
179
# install_dir from doing its work.
180
download_image = os.path.join(self.make_dir(), 'download-image')
181
published_image = os.path.join(
182
self.make_dir(), factory.getRandomString())
183
contents = factory.getRandomString()
184
os.makedirs(download_image)
185
sample_file = factory.make_file(download_image, contents=contents)
186
os.makedirs('%s.old' % published_image)
187
os.makedirs('%s.new' % published_image)
188
install_dir(download_image, published_image)
190
os.path.join(published_image, os.path.basename(sample_file)),
191
FileContains(contents))
192
self.assertThat('%s.old' % published_image, Not(DirExists()))
193
self.assertThat('%s.new' % published_image, Not(DirExists()))