Merge lp:~ubuntudotcom1/maas/kill-all-the-configs-cluster into lp:~maas-committers/maas/trunk
- kill-all-the-configs-cluster
- Merge into trunk
Proposed by
ubuntudotcom1
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 4066 | ||||||||||||
Proposed branch: | lp:~ubuntudotcom1/maas/kill-all-the-configs-cluster | ||||||||||||
Merge into: | lp:~maas-committers/maas/trunk | ||||||||||||
Prerequisite: | lp:~ubuntudotcom1/maas/kill-all-the-configs-region | ||||||||||||
Diff against target: |
3136 lines (+512/-861) 37 files modified
.gitignore (+2/-0) etc/demo_maas_cluster.conf (+0/-8) etc/maas/pserv.yaml (+0/-24) etc/maas_cluster.conf (+0/-5) services/clusterd/run (+0/-5) setup.py (+1/-3) src/maasserver/clusterrpc/tests/test_boot_images.py (+19/-5) src/provisioningserver/__main__.py (+3/-0) src/provisioningserver/boot/install_grub.py (+8/-5) src/provisioningserver/boot/tests/test_install_grub.py (+11/-4) src/provisioningserver/boot/tests/test_tftppath.py (+16/-9) src/provisioningserver/boot/tftppath.py (+11/-6) src/provisioningserver/cluster_config.py (+7/-41) src/provisioningserver/config.py (+0/-31) src/provisioningserver/diskless.py (+16/-8) src/provisioningserver/drivers/osystem/custom.py (+8/-5) src/provisioningserver/drivers/osystem/tests/test_custom.py (+14/-6) src/provisioningserver/import_images/boot_resources.py (+20/-6) src/provisioningserver/import_images/tests/test_boot_resources.py (+26/-16) src/provisioningserver/plugin.py (+26/-24) src/provisioningserver/pserv_services/tests/test_tftp.py (+11/-7) src/provisioningserver/pserv_services/tftp.py (+8/-4) src/provisioningserver/rpc/boot_images.py (+11/-7) src/provisioningserver/rpc/clusterservice.py (+12/-11) src/provisioningserver/rpc/tags.py (+20/-5) src/provisioningserver/rpc/tests/test_boot_images.py (+17/-6) src/provisioningserver/rpc/tests/test_clusterservice.py (+46/-33) src/provisioningserver/rpc/tests/test_tags.py (+16/-7) src/provisioningserver/tests/test_cluster_config.py (+72/-31) src/provisioningserver/tests/test_config.py (+0/-453) src/provisioningserver/tests/test_diskless.py (+26/-13) src/provisioningserver/tests/test_plugin.py (+19/-34) src/provisioningserver/tests/test_upgrade_cluster.py (+25/-10) src/provisioningserver/upgrade_cluster.py (+15/-9) src/provisioningserver/utils/__init__.py (+3/-2) src/provisioningserver/utils/script.py (+6/-7) src/provisioningserver/utils/tests/test_utils.py (+17/-11) |
||||||||||||
To merge this branch: | bzr merge lp:~ubuntudotcom1/maas/kill-all-the-configs-cluster | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gavin Panella (community) | Approve | ||
Review via email: mp+254970@code.launchpad.net |
Commit message
Config changes applied according to new config backend in -cluster-admin. branch.
Description of the change
Config changes applied according to new config backend in -cluster-admin. branch.
To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote : | # |
Revision history for this message
Gavin Panella (allenap) wrote : | # |
Looks good. I have a few comments, but they're not blockers.
I am interested in what your plan is for upgrading from pserv.yaml. Is that entirely happening in packaging?
review:
Approve
Revision history for this message
Gavin Panella (allenap) wrote : | # |
This has been superseded by lp:~allenap/maas/kill-all-the-configs-cluster (which builds on this).
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.gitignore' | |||
2 | --- .gitignore 2015-04-10 09:45:46 +0000 | |||
3 | +++ .gitignore 2015-05-04 14:27:25 +0000 | |||
4 | @@ -22,6 +22,8 @@ | |||
5 | 22 | /docs/_autosummary | 22 | /docs/_autosummary |
6 | 23 | /docs/_build | 23 | /docs/_build |
7 | 24 | /docs/api.rst | 24 | /docs/api.rst |
8 | 25 | /etc/maas/regiond.conf | ||
9 | 26 | /etc/maas/clusterd.conf | ||
10 | 25 | /eggs | 27 | /eggs |
11 | 26 | /include | 28 | /include |
12 | 27 | /lib | 29 | /lib |
13 | 28 | 30 | ||
14 | === removed file 'etc/demo_maas_cluster.conf' | |||
15 | --- etc/demo_maas_cluster.conf 2015-03-12 18:13:14 +0000 | |||
16 | +++ etc/demo_maas_cluster.conf 1970-01-01 00:00:00 +0000 | |||
17 | @@ -1,8 +0,0 @@ | |||
18 | 1 | # This is the version of maas_cluster.conf that's used when running from a | ||
19 | 2 | # branch. The region controller will serve HTTP on a different port from a | ||
20 | 3 | # packaged MAAS, and the master cluster controller (running on the same | ||
21 | 4 | # development machine) has a fixed UUID. | ||
22 | 5 | # It is also carefully crafted so it works as both a bash script and a | ||
23 | 6 | # Python script. | ||
24 | 7 | MAAS_URL="http://0.0.0.0:5240/MAAS/" | ||
25 | 8 | CLUSTER_UUID="adfd3977-f251-4f2c-8d61-745dbd690bf2" | ||
26 | 9 | 0 | ||
27 | === removed file 'etc/maas/pserv.yaml' | |||
28 | --- etc/maas/pserv.yaml 2015-04-24 13:27:39 +0000 | |||
29 | +++ etc/maas/pserv.yaml 1970-01-01 00:00:00 +0000 | |||
30 | @@ -1,24 +0,0 @@ | |||
31 | 1 | ## | ||
32 | 2 | ## Provisioning Server (pserv) configuration. | ||
33 | 3 | ## | ||
34 | 4 | |||
35 | 5 | ## Where to log. This log can be rotated by sending SIGUSR1 to the | ||
36 | 6 | ## running server. | ||
37 | 7 | # | ||
38 | 8 | # logfile: "pserv.log" | ||
39 | 9 | logfile: "/dev/null" | ||
40 | 10 | |||
41 | 11 | ## TFTP configuration. | ||
42 | 12 | # | ||
43 | 13 | tftp: | ||
44 | 14 | # The "root" setting has been replaced by "resource_root". The old setting | ||
45 | 15 | # is used one final time when upgrading a pre-14.04 cluster controller to a | ||
46 | 16 | # 14.04 version. After that upgrade, it can be removed. | ||
47 | 17 | # | ||
48 | 18 | # resource_root: /var/lib/maas/boot-resources/current/ | ||
49 | 19 | |||
50 | 20 | # port: 69 | ||
51 | 21 | port: 5244 | ||
52 | 22 | ## The URL to be contacted to generate PXE configurations. | ||
53 | 23 | # generator: http://localhost/MAAS/api/1.0/pxeconfig/ | ||
54 | 24 | generator: http://localhost:5240/MAAS/api/1.0/pxeconfig/ | ||
55 | 25 | 0 | ||
56 | === removed file 'etc/maas_cluster.conf' | |||
57 | --- etc/maas_cluster.conf 2015-03-12 18:13:14 +0000 | |||
58 | +++ etc/maas_cluster.conf 1970-01-01 00:00:00 +0000 | |||
59 | @@ -1,5 +0,0 @@ | |||
60 | 1 | # This file is used by the cluster controller startup script: | ||
61 | 2 | # `maas-provision start-cluster-controller` | ||
62 | 3 | # to get the URL to the MAAS region controller's API. Normally, packaging | ||
63 | 4 | # will update this file automatically but it may also be configured manually. | ||
64 | 5 | MAAS_URL=http://localhost/MAAS | ||
65 | 6 | 0 | ||
66 | === modified file 'services/clusterd/run' | |||
67 | --- services/clusterd/run 2015-04-10 09:45:46 +0000 | |||
68 | +++ services/clusterd/run 2015-05-04 14:27:25 +0000 | |||
69 | @@ -21,11 +21,6 @@ | |||
70 | 21 | script="$(readlink -f bin/twistd.cluster)" | 21 | script="$(readlink -f bin/twistd.cluster)" |
71 | 22 | config="$(readlink -f etc/maas/pserv.yaml)" | 22 | config="$(readlink -f etc/maas/pserv.yaml)" |
72 | 23 | 23 | ||
73 | 24 | # Obtain the development setting for CLUSTER_UUID. | ||
74 | 25 | . etc/demo_maas_cluster.conf | ||
75 | 26 | export CLUSTER_UUID | ||
76 | 27 | export MAAS_URL | ||
77 | 28 | |||
78 | 29 | exec $(command -v authbind && echo --deep) \ | 24 | exec $(command -v authbind && echo --deep) \ |
79 | 30 | "${script}" --nodaemon --pidfile="" maas-clusterd \ | 25 | "${script}" --nodaemon --pidfile="" maas-clusterd \ |
80 | 31 | --introspect="unix:${here}/introspect:lockfile=0" \ | 26 | --introspect="unix:${here}/introspect:lockfile=0" \ |
81 | 32 | 27 | ||
82 | === modified file 'setup.py' | |||
83 | --- setup.py 2015-05-04 14:27:25 +0000 | |||
84 | +++ setup.py 2015-05-04 14:27:25 +0000 | |||
85 | @@ -64,9 +64,7 @@ | |||
86 | 64 | 64 | ||
87 | 65 | data_files=[ | 65 | data_files=[ |
88 | 66 | ('/etc/maas', | 66 | ('/etc/maas', |
92 | 67 | ['etc/maas/pserv.yaml', | 67 | ['etc/maas/drivers.yaml', |
90 | 68 | 'etc/maas/drivers.yaml', | ||
91 | 69 | 'etc/maas_cluster.conf', | ||
93 | 70 | 'contrib/maas-http.conf']), | 68 | 'contrib/maas-http.conf']), |
94 | 71 | ('/etc/maas/templates/uefi', | 69 | ('/etc/maas/templates/uefi', |
95 | 72 | glob('etc/maas/templates/uefi/*.template')), | 70 | glob('etc/maas/templates/uefi/*.template')), |
96 | 73 | 71 | ||
97 | === modified file 'src/maasserver/clusterrpc/tests/test_boot_images.py' | |||
98 | --- src/maasserver/clusterrpc/tests/test_boot_images.py 2015-03-25 15:33:23 +0000 | |||
99 | +++ src/maasserver/clusterrpc/tests/test_boot_images.py 2015-05-04 14:27:25 +0000 | |||
100 | @@ -7,7 +7,7 @@ | |||
101 | 7 | absolute_import, | 7 | absolute_import, |
102 | 8 | print_function, | 8 | print_function, |
103 | 9 | unicode_literals, | 9 | unicode_literals, |
105 | 10 | ) | 10 | ) |
106 | 11 | 11 | ||
107 | 12 | str = None | 12 | str = None |
108 | 13 | 13 | ||
109 | @@ -37,6 +37,10 @@ | |||
110 | 37 | compose_image_path, | 37 | compose_image_path, |
111 | 38 | locate_tftp_path, | 38 | locate_tftp_path, |
112 | 39 | ) | 39 | ) |
113 | 40 | from provisioningserver.cluster_config import ( | ||
114 | 41 | CLUSTER_CONFIG, | ||
115 | 42 | set_config_cluster_variable, | ||
116 | 43 | ) | ||
117 | 40 | from provisioningserver.rpc import ( | 44 | from provisioningserver.rpc import ( |
118 | 41 | boot_images, | 45 | boot_images, |
119 | 42 | clusterservice, | 46 | clusterservice, |
120 | @@ -45,6 +49,7 @@ | |||
121 | 45 | make_boot_image_storage_params, | 49 | make_boot_image_storage_params, |
122 | 46 | make_image, | 50 | make_image, |
123 | 47 | ) | 51 | ) |
124 | 52 | from provisioningserver.testing.config import ClusterConfigurationFixture | ||
125 | 48 | from twisted.internet.defer import succeed | 53 | from twisted.internet.defer import succeed |
126 | 49 | 54 | ||
127 | 50 | 55 | ||
128 | @@ -141,11 +146,14 @@ | |||
129 | 141 | 146 | ||
130 | 142 | def setUp(self): | 147 | def setUp(self): |
131 | 143 | super(TestGetBootImages, self).setUp() | 148 | super(TestGetBootImages, self).setUp() |
132 | 149 | self.useFixture(ClusterConfigurationFixture()) | ||
133 | 144 | resource_dir = self.make_dir() | 150 | resource_dir = self.make_dir() |
134 | 145 | self.tftproot = os.path.join(resource_dir, 'current') | 151 | self.tftproot = os.path.join(resource_dir, 'current') |
135 | 146 | os.mkdir(self.tftproot) | 152 | os.mkdir(self.tftproot) |
136 | 147 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) | 153 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) |
138 | 148 | self.patch(boot_images, 'BOOT_RESOURCES_STORAGE', resource_dir) | 154 | set_config_cluster_variable( |
139 | 155 | CLUSTER_CONFIG.DB_boot_resources_storage, | ||
140 | 156 | self.tftproot) | ||
141 | 149 | 157 | ||
142 | 150 | def test_returns_boot_images(self): | 158 | def test_returns_boot_images(self): |
143 | 151 | nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ACCEPTED) | 159 | nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ACCEPTED) |
144 | @@ -170,11 +178,14 @@ | |||
145 | 170 | 178 | ||
146 | 171 | def setUp(self): | 179 | def setUp(self): |
147 | 172 | super(TestGetAvailableBootImages, self).setUp() | 180 | super(TestGetAvailableBootImages, self).setUp() |
148 | 181 | self.useFixture(ClusterConfigurationFixture()) | ||
149 | 173 | resource_dir = self.make_dir() | 182 | resource_dir = self.make_dir() |
150 | 174 | self.tftproot = os.path.join(resource_dir, 'current') | 183 | self.tftproot = os.path.join(resource_dir, 'current') |
151 | 175 | os.mkdir(self.tftproot) | 184 | os.mkdir(self.tftproot) |
152 | 176 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) | 185 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) |
154 | 177 | self.patch(boot_images, 'BOOT_RESOURCES_STORAGE', resource_dir) | 186 | set_config_cluster_variable( |
155 | 187 | CLUSTER_CONFIG.DB_boot_resources_storage, | ||
156 | 188 | self.tftproot) | ||
157 | 178 | 189 | ||
158 | 179 | def test_returns_boot_images_for_one_cluster(self): | 190 | def test_returns_boot_images_for_one_cluster(self): |
159 | 180 | factory.make_NodeGroup().accept() | 191 | factory.make_NodeGroup().accept() |
160 | @@ -260,11 +271,14 @@ | |||
161 | 260 | 271 | ||
162 | 261 | def setUp(self): | 272 | def setUp(self): |
163 | 262 | super(TestGetBootImagesFor, self).setUp() | 273 | super(TestGetBootImagesFor, self).setUp() |
164 | 274 | self.useFixture(ClusterConfigurationFixture()) | ||
165 | 263 | resource_dir = self.make_dir() | 275 | resource_dir = self.make_dir() |
166 | 264 | self.tftproot = os.path.join(resource_dir, 'current') | 276 | self.tftproot = os.path.join(resource_dir, 'current') |
167 | 265 | os.mkdir(self.tftproot) | 277 | os.mkdir(self.tftproot) |
168 | 266 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) | 278 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) |
170 | 267 | self.patch(boot_images, 'BOOT_RESOURCES_STORAGE', resource_dir) | 279 | set_config_cluster_variable( |
171 | 280 | CLUSTER_CONFIG.DB_boot_resources_storage, | ||
172 | 281 | self.tftproot) | ||
173 | 268 | 282 | ||
174 | 269 | def make_boot_images(self): | 283 | def make_boot_images(self): |
175 | 270 | purposes = ['install', 'commissioning', 'xinstall'] | 284 | purposes = ['install', 'commissioning', 'xinstall'] |
176 | @@ -279,7 +293,7 @@ | |||
177 | 279 | return [ | 293 | return [ |
178 | 280 | make_image(param, purpose) | 294 | make_image(param, purpose) |
179 | 281 | for purpose in purposes | 295 | for purpose in purposes |
181 | 282 | ] | 296 | ] |
182 | 283 | 297 | ||
183 | 284 | def test_returns_boot_images_matching_subarchitecture(self): | 298 | def test_returns_boot_images_matching_subarchitecture(self): |
184 | 285 | nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ACCEPTED) | 299 | nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ACCEPTED) |
185 | 286 | 300 | ||
186 | === modified file 'src/provisioningserver/__main__.py' | |||
187 | --- src/provisioningserver/__main__.py 2015-03-30 18:05:57 +0000 | |||
188 | +++ src/provisioningserver/__main__.py 2015-05-04 14:27:25 +0000 | |||
189 | @@ -14,6 +14,7 @@ | |||
190 | 14 | 14 | ||
191 | 15 | __metaclass__ = type | 15 | __metaclass__ = type |
192 | 16 | 16 | ||
193 | 17 | |||
194 | 17 | from provisioningserver import security | 18 | from provisioningserver import security |
195 | 18 | import provisioningserver.boot.install_bootloader | 19 | import provisioningserver.boot.install_bootloader |
196 | 19 | import provisioningserver.boot.install_grub | 20 | import provisioningserver.boot.install_grub |
197 | @@ -42,6 +43,8 @@ | |||
198 | 42 | 43 | ||
199 | 43 | 44 | ||
200 | 44 | main = MainScript(__doc__) | 45 | main = MainScript(__doc__) |
201 | 46 | |||
202 | 47 | |||
203 | 45 | for name, command in sorted(script_commands.items()): | 48 | for name, command in sorted(script_commands.items()): |
204 | 46 | main.register(name, command) | 49 | main.register(name, command) |
205 | 47 | main() | 50 | main() |
206 | 48 | 51 | ||
207 | === modified file 'src/provisioningserver/boot/install_grub.py' | |||
208 | --- src/provisioningserver/boot/install_grub.py 2015-02-24 20:11:09 +0000 | |||
209 | +++ src/provisioningserver/boot/install_grub.py 2015-05-04 14:27:25 +0000 | |||
210 | @@ -7,7 +7,7 @@ | |||
211 | 7 | absolute_import, | 7 | absolute_import, |
212 | 8 | print_function, | 8 | print_function, |
213 | 9 | unicode_literals, | 9 | unicode_literals, |
215 | 10 | ) | 10 | ) |
216 | 11 | 11 | ||
217 | 12 | str = None | 12 | str = None |
218 | 13 | 13 | ||
219 | @@ -15,12 +15,15 @@ | |||
220 | 15 | __all__ = [ | 15 | __all__ = [ |
221 | 16 | "add_arguments", | 16 | "add_arguments", |
222 | 17 | "run", | 17 | "run", |
224 | 18 | ] | 18 | ] |
225 | 19 | 19 | ||
226 | 20 | import os.path | 20 | import os.path |
227 | 21 | 21 | ||
228 | 22 | from provisioningserver.boot.install_bootloader import make_destination | 22 | from provisioningserver.boot.install_bootloader import make_destination |
230 | 23 | from provisioningserver.config import Config | 23 | from provisioningserver.cluster_config import ( |
231 | 24 | CLUSTER_CONFIG, | ||
232 | 25 | get_config_cluster_variable, | ||
233 | 26 | ) | ||
234 | 24 | from provisioningserver.utils.fs import write_text_file | 27 | from provisioningserver.utils.fs import write_text_file |
235 | 25 | 28 | ||
236 | 26 | 29 | ||
237 | @@ -44,7 +47,7 @@ | |||
238 | 44 | """Install a GRUB2 pre-boot loader config into the TFTP | 47 | """Install a GRUB2 pre-boot loader config into the TFTP |
239 | 45 | directory structure. | 48 | directory structure. |
240 | 46 | """ | 49 | """ |
243 | 47 | config = Config.load(args.config_file) | 50 | grubroot = os.path.join(get_config_cluster_variable( |
244 | 48 | grubroot = os.path.join(config["tftp"]["resource_root"], 'grub') | 51 | CLUSTER_CONFIG.DB_tftp_resource_root), 'grub') |
245 | 49 | destination_path = make_destination(grubroot) | 52 | destination_path = make_destination(grubroot) |
246 | 50 | write_text_file(os.path.join(destination_path, 'grub.cfg'), CONFIG_FILE) | 53 | write_text_file(os.path.join(destination_path, 'grub.cfg'), CONFIG_FILE) |
247 | 51 | 54 | ||
248 | === modified file 'src/provisioningserver/boot/tests/test_install_grub.py' | |||
249 | --- src/provisioningserver/boot/tests/test_install_grub.py 2014-08-13 21:49:35 +0000 | |||
250 | +++ src/provisioningserver/boot/tests/test_install_grub.py 2015-05-04 14:27:25 +0000 | |||
251 | @@ -7,7 +7,7 @@ | |||
252 | 7 | absolute_import, | 7 | absolute_import, |
253 | 8 | print_function, | 8 | print_function, |
254 | 9 | unicode_literals, | 9 | unicode_literals, |
256 | 10 | ) | 10 | ) |
257 | 11 | 11 | ||
258 | 12 | str = None | 12 | str = None |
259 | 13 | 13 | ||
260 | @@ -20,7 +20,11 @@ | |||
261 | 20 | from maastesting.testcase import MAASTestCase | 20 | from maastesting.testcase import MAASTestCase |
262 | 21 | import provisioningserver.boot.install_grub | 21 | import provisioningserver.boot.install_grub |
263 | 22 | from provisioningserver.boot.tftppath import locate_tftp_path | 22 | from provisioningserver.boot.tftppath import locate_tftp_path |
265 | 23 | from provisioningserver.testing.config import set_tftp_root | 23 | from provisioningserver.cluster_config import ( |
266 | 24 | CLUSTER_CONFIG, | ||
267 | 25 | set_config_cluster_variable, | ||
268 | 26 | ) | ||
269 | 27 | from provisioningserver.testing.config import ClusterConfigurationFixture | ||
270 | 24 | from provisioningserver.utils.script import MainScript | 28 | from provisioningserver.utils.script import MainScript |
271 | 25 | from testtools.matchers import FileExists | 29 | from testtools.matchers import FileExists |
272 | 26 | 30 | ||
273 | @@ -28,14 +32,17 @@ | |||
274 | 28 | class TestInstallGrub(MAASTestCase): | 32 | class TestInstallGrub(MAASTestCase): |
275 | 29 | 33 | ||
276 | 30 | def test_integration(self): | 34 | def test_integration(self): |
277 | 35 | self.useFixture(ClusterConfigurationFixture()) | ||
278 | 31 | tftproot = self.make_dir() | 36 | tftproot = self.make_dir() |
280 | 32 | config_fixture = self.useFixture(set_tftp_root(tftproot)) | 37 | set_config_cluster_variable( |
281 | 38 | CLUSTER_CONFIG.DB_tftp_resource_root, | ||
282 | 39 | tftproot) | ||
283 | 33 | 40 | ||
284 | 34 | action = factory.make_name("action") | 41 | action = factory.make_name("action") |
285 | 35 | script = MainScript(action) | 42 | script = MainScript(action) |
286 | 36 | script.register(action, provisioningserver.boot.install_grub) | 43 | script.register(action, provisioningserver.boot.install_grub) |
287 | 37 | script.execute( | 44 | script.execute( |
289 | 38 | ("--config-file", config_fixture.filename, action)) | 45 | ("--config-file", "clusterd.conf", action)) |
290 | 39 | 46 | ||
291 | 40 | config_filename = os.path.join('grub', 'grub.cfg') | 47 | config_filename = os.path.join('grub', 'grub.cfg') |
292 | 41 | self.assertThat( | 48 | self.assertThat( |
293 | 42 | 49 | ||
294 | === modified file 'src/provisioningserver/boot/tests/test_tftppath.py' | |||
295 | --- src/provisioningserver/boot/tests/test_tftppath.py 2015-03-25 15:33:23 +0000 | |||
296 | +++ src/provisioningserver/boot/tests/test_tftppath.py 2015-05-04 14:27:25 +0000 | |||
297 | @@ -7,7 +7,7 @@ | |||
298 | 7 | absolute_import, | 7 | absolute_import, |
299 | 8 | print_function, | 8 | print_function, |
300 | 9 | unicode_literals, | 9 | unicode_literals, |
302 | 10 | ) | 10 | ) |
303 | 11 | 11 | ||
304 | 12 | str = None | 12 | str = None |
305 | 13 | 13 | ||
306 | @@ -21,7 +21,6 @@ | |||
307 | 21 | from maastesting.matchers import MockCalledOnceWith | 21 | from maastesting.matchers import MockCalledOnceWith |
308 | 22 | from maastesting.testcase import MAASTestCase | 22 | from maastesting.testcase import MAASTestCase |
309 | 23 | from mock import Mock | 23 | from mock import Mock |
310 | 24 | from provisioningserver import config | ||
311 | 25 | from provisioningserver.boot import tftppath | 24 | from provisioningserver.boot import tftppath |
312 | 26 | from provisioningserver.boot.tftppath import ( | 25 | from provisioningserver.boot.tftppath import ( |
313 | 27 | compose_image_path, | 26 | compose_image_path, |
314 | @@ -35,6 +34,10 @@ | |||
315 | 35 | locate_tftp_path, | 34 | locate_tftp_path, |
316 | 36 | maas_meta_last_modified, | 35 | maas_meta_last_modified, |
317 | 37 | ) | 36 | ) |
318 | 37 | from provisioningserver.cluster_config import ( | ||
319 | 38 | CLUSTER_CONFIG, | ||
320 | 39 | get_config_cluster_variable, | ||
321 | 40 | ) | ||
322 | 38 | from provisioningserver.drivers.osystem import OperatingSystemRegistry | 41 | from provisioningserver.drivers.osystem import OperatingSystemRegistry |
323 | 39 | from provisioningserver.import_images.boot_image_mapping import ( | 42 | from provisioningserver.import_images.boot_image_mapping import ( |
324 | 40 | BootImageMapping, | 43 | BootImageMapping, |
325 | @@ -48,7 +51,10 @@ | |||
326 | 48 | make_boot_image_storage_params, | 51 | make_boot_image_storage_params, |
327 | 49 | make_image, | 52 | make_image, |
328 | 50 | ) | 53 | ) |
330 | 51 | from provisioningserver.testing.config import set_tftp_root | 54 | from provisioningserver.testing.config import ( |
331 | 55 | ClusterConfigurationFixture, | ||
332 | 56 | set_tftp_root, | ||
333 | 57 | ) | ||
334 | 52 | from provisioningserver.testing.os import make_osystem | 58 | from provisioningserver.testing.os import make_osystem |
335 | 53 | from testtools.matchers import ( | 59 | from testtools.matchers import ( |
336 | 54 | Not, | 60 | Not, |
337 | @@ -102,12 +108,13 @@ | |||
338 | 102 | self.assertIsNone(observed) | 108 | self.assertIsNone(observed) |
339 | 103 | 109 | ||
340 | 104 | def test_maas_meta_last_modified_defaults_tftproot(self): | 110 | def test_maas_meta_last_modified_defaults_tftproot(self): |
341 | 111 | self.useFixture(ClusterConfigurationFixture()) | ||
342 | 105 | path = factory.make_file(self.tftproot, name="maas.meta") | 112 | path = factory.make_file(self.tftproot, name="maas.meta") |
343 | 106 | maas_meta_file_path = self.patch(tftppath, 'maas_meta_file_path') | 113 | maas_meta_file_path = self.patch(tftppath, 'maas_meta_file_path') |
344 | 107 | maas_meta_file_path.return_value = path | 114 | maas_meta_file_path.return_value = path |
345 | 108 | maas_meta_last_modified() | 115 | maas_meta_last_modified() |
348 | 109 | expected_path = os.path.join( | 116 | expected_path = get_config_cluster_variable( |
349 | 110 | config.BOOT_RESOURCES_STORAGE, 'current') | 117 | CLUSTER_CONFIG.DB_tftp_resource_root) |
350 | 111 | self.assertThat(maas_meta_file_path, MockCalledOnceWith(expected_path)) | 118 | self.assertThat(maas_meta_file_path, MockCalledOnceWith(expected_path)) |
351 | 112 | 119 | ||
352 | 113 | def test_maas_meta_last_modified_reraises_non_ENOENT(self): | 120 | def test_maas_meta_last_modified_reraises_non_ENOENT(self): |
353 | @@ -299,7 +306,7 @@ | |||
354 | 299 | resource = dict( | 306 | resource = dict( |
355 | 300 | subarches=factory.make_name("subarch"), | 307 | subarches=factory.make_name("subarch"), |
356 | 301 | other_item=factory.make_name("other"), | 308 | other_item=factory.make_name("other"), |
358 | 302 | ) | 309 | ) |
359 | 303 | image = make_image_spec() | 310 | image = make_image_spec() |
360 | 304 | mapping = set_resource(image_spec=image, resource=resource) | 311 | mapping = set_resource(image_spec=image, resource=resource) |
361 | 305 | metadata = mapping.dump_json() | 312 | metadata = mapping.dump_json() |
362 | @@ -313,7 +320,7 @@ | |||
363 | 313 | "subarchitecture": image.subarch, | 320 | "subarchitecture": image.subarch, |
364 | 314 | "release": image.release, | 321 | "release": image.release, |
365 | 315 | "label": image.label, | 322 | "label": image.label, |
367 | 316 | } | 323 | } |
368 | 317 | extracted_data = extract_metadata(metadata, params) | 324 | extracted_data = extract_metadata(metadata, params) |
369 | 318 | 325 | ||
370 | 319 | # We only expect the supported_subarches key from the resource data. | 326 | # We only expect the supported_subarches key from the resource data. |
371 | @@ -323,7 +330,7 @@ | |||
372 | 323 | def test_extract_metadata_handles_missing_subarch(self): | 330 | def test_extract_metadata_handles_missing_subarch(self): |
373 | 324 | resource = dict( | 331 | resource = dict( |
374 | 325 | other_item=factory.make_name("other"), | 332 | other_item=factory.make_name("other"), |
376 | 326 | ) | 333 | ) |
377 | 327 | image = make_image_spec() | 334 | image = make_image_spec() |
378 | 328 | mapping = set_resource(image_spec=image, resource=resource) | 335 | mapping = set_resource(image_spec=image, resource=resource) |
379 | 329 | metadata = mapping.dump_json() | 336 | metadata = mapping.dump_json() |
380 | @@ -337,7 +344,7 @@ | |||
381 | 337 | "subarchitecture": image.subarch, | 344 | "subarchitecture": image.subarch, |
382 | 338 | "release": image.release, | 345 | "release": image.release, |
383 | 339 | "label": image.label, | 346 | "label": image.label, |
385 | 340 | } | 347 | } |
386 | 341 | self.assertEqual({}, extract_metadata(metadata, params)) | 348 | self.assertEqual({}, extract_metadata(metadata, params)) |
387 | 342 | 349 | ||
388 | 343 | def _make_path(self): | 350 | def _make_path(self): |
389 | 344 | 351 | ||
390 | === modified file 'src/provisioningserver/boot/tftppath.py' | |||
391 | --- src/provisioningserver/boot/tftppath.py 2015-03-25 15:33:23 +0000 | |||
392 | +++ src/provisioningserver/boot/tftppath.py 2015-05-04 14:27:25 +0000 | |||
393 | @@ -7,7 +7,7 @@ | |||
394 | 7 | absolute_import, | 7 | absolute_import, |
395 | 8 | print_function, | 8 | print_function, |
396 | 9 | unicode_literals, | 9 | unicode_literals, |
398 | 10 | ) | 10 | ) |
399 | 11 | 11 | ||
400 | 12 | str = None | 12 | str = None |
401 | 13 | 13 | ||
402 | @@ -17,13 +17,16 @@ | |||
403 | 17 | 'list_boot_images', | 17 | 'list_boot_images', |
404 | 18 | 'list_subdirs', | 18 | 'list_subdirs', |
405 | 19 | 'locate_tftp_path', | 19 | 'locate_tftp_path', |
407 | 20 | ] | 20 | ] |
408 | 21 | 21 | ||
409 | 22 | import errno | 22 | import errno |
410 | 23 | from itertools import chain | 23 | from itertools import chain |
411 | 24 | import os.path | 24 | import os.path |
412 | 25 | 25 | ||
414 | 26 | from provisioningserver import config | 26 | from provisioningserver.cluster_config import ( |
415 | 27 | CLUSTER_CONFIG, | ||
416 | 28 | get_config_cluster_variable, | ||
417 | 29 | ) | ||
418 | 27 | from provisioningserver.drivers.osystem import ( | 30 | from provisioningserver.drivers.osystem import ( |
419 | 28 | BOOT_IMAGE_PURPOSE, | 31 | BOOT_IMAGE_PURPOSE, |
420 | 29 | OperatingSystemRegistry, | 32 | OperatingSystemRegistry, |
421 | @@ -137,7 +140,7 @@ | |||
422 | 137 | subarch=params["subarchitecture"], | 140 | subarch=params["subarchitecture"], |
423 | 138 | release=params["release"], | 141 | release=params["release"], |
424 | 139 | label=params["label"], | 142 | label=params["label"], |
426 | 140 | ) | 143 | ) |
427 | 141 | try: | 144 | try: |
428 | 142 | # On upgrade from 1.5 to 1.6, the subarches does not exist in the | 145 | # On upgrade from 1.5 to 1.6, the subarches does not exist in the |
429 | 143 | # maas.meta file . Without this catch boot images will fail to | 146 | # maas.meta file . Without this catch boot images will fail to |
430 | @@ -206,10 +209,12 @@ | |||
431 | 206 | or None if the file doesn't exist. | 209 | or None if the file doesn't exist. |
432 | 207 | 210 | ||
433 | 208 | :param tftproot: Optional tftp root dir, defaults to | 211 | :param tftproot: Optional tftp root dir, defaults to |
435 | 209 | provisioningserver.config.BOOT_RESOURCES_STORAGE | 212 | 'tftp-root' in the cluster Config backend. Please refer to the |
436 | 213 | 'maas-provision config --tftp-root' command to set this directory | ||
437 | 210 | """ | 214 | """ |
438 | 211 | if tftproot is None: | 215 | if tftproot is None: |
440 | 212 | tftproot = os.path.join(config.BOOT_RESOURCES_STORAGE, 'current') | 216 | tftproot = get_config_cluster_variable( |
441 | 217 | CLUSTER_CONFIG.DB_tftp_resource_root) | ||
442 | 213 | meta_file = maas_meta_file_path(tftproot) | 218 | meta_file = maas_meta_file_path(tftproot) |
443 | 214 | try: | 219 | try: |
444 | 215 | return os.path.getmtime(meta_file) | 220 | return os.path.getmtime(meta_file) |
445 | 216 | 221 | ||
446 | === modified file 'src/provisioningserver/cluster_config.py' | |||
447 | --- src/provisioningserver/cluster_config.py 2015-04-02 18:44:12 +0000 | |||
448 | +++ src/provisioningserver/cluster_config.py 2015-05-04 14:27:25 +0000 | |||
449 | @@ -13,13 +13,10 @@ | |||
450 | 13 | 13 | ||
451 | 14 | __metaclass__ = type | 14 | __metaclass__ = type |
452 | 15 | __all__ = [ | 15 | __all__ = [ |
453 | 16 | 'get_cluster_uuid', | ||
454 | 17 | 'get_maas_url', | ||
455 | 18 | "get_cluster_variable", | ||
456 | 19 | "get_config_cluster_variable", | 16 | "get_config_cluster_variable", |
460 | 20 | "set_config_cluster_variable", ] | 17 | "get_tftp_generator", |
461 | 21 | 18 | "set_config_cluster_variable", | |
462 | 22 | from os import environ | 19 | "CLUSTER_CONFIG", ] |
463 | 23 | 20 | ||
464 | 24 | from provisioningserver.config import ClusterConfiguration | 21 | from provisioningserver.config import ClusterConfiguration |
465 | 25 | 22 | ||
466 | @@ -34,7 +31,7 @@ | |||
467 | 34 | DB_tftpport = 'tftp_port' | 31 | DB_tftpport = 'tftp_port' |
468 | 35 | 32 | ||
469 | 36 | 33 | ||
471 | 37 | # New get function for ClusterConfiguration backend | 34 | # Get function for ClusterConfiguration backend |
472 | 38 | def get_config_cluster_variable(var): | 35 | def get_config_cluster_variable(var): |
473 | 39 | """Obtain the given environment variable from clusterd config""" | 36 | """Obtain the given environment variable from clusterd config""" |
474 | 40 | with ClusterConfiguration.open() as config: | 37 | with ClusterConfiguration.open() as config: |
475 | @@ -52,37 +49,6 @@ | |||
476 | 52 | """Return the `tftp_generator` setting, which is | 49 | """Return the `tftp_generator` setting, which is |
477 | 53 | <maas url>/api/1.0/pxeconfig/ | 50 | <maas url>/api/1.0/pxeconfig/ |
478 | 54 | """ | 51 | """ |
513 | 55 | return '/'.join(get_cluster_variable(CLUSTER_CONFIG.DB_maas_url), | 52 | return '/'.join(( |
514 | 56 | 'api', '1.0', 'pxeconfig') | 53 | get_config_cluster_variable(CLUSTER_CONFIG.DB_maas_url), |
515 | 57 | 54 | 'api', '1.0', 'pxeconfig')) | |
482 | 58 | |||
483 | 59 | # Old get function for config file (via env variables) backend, | ||
484 | 60 | # to be removed in follow-up branch. This branch is a prerequisite branch for | ||
485 | 61 | # a follow-up branch, where this function will be removed. Both | ||
486 | 62 | # the new and old versions of this function have been included | ||
487 | 63 | # in this intermediate branch at the request of the package | ||
488 | 64 | # maintainers. | ||
489 | 65 | def get_cluster_variable(var): | ||
490 | 66 | """Obtain the given environment variable from maas_cluster.conf. | ||
491 | 67 | |||
492 | 68 | If the variable is not set, it probably means that whatever script | ||
493 | 69 | started the current process neglected to run maas_cluster.conf. | ||
494 | 70 | In that case, fail helpfully but utterly. | ||
495 | 71 | """ | ||
496 | 72 | value = environ.get(var) | ||
497 | 73 | if value is None: | ||
498 | 74 | raise AssertionError( | ||
499 | 75 | "%s is not set. This probably means that the script which " | ||
500 | 76 | "started this program failed to source maas_cluster.conf." | ||
501 | 77 | % var) | ||
502 | 78 | return value | ||
503 | 79 | |||
504 | 80 | |||
505 | 81 | def get_cluster_uuid(): | ||
506 | 82 | """Return the `CLUSTER_UUID` setting.""" | ||
507 | 83 | return get_cluster_variable('CLUSTER_UUID') | ||
508 | 84 | |||
509 | 85 | |||
510 | 86 | def get_maas_url(): | ||
511 | 87 | """Return the `MAAS_URL` setting.""" | ||
512 | 88 | return get_cluster_variable('MAAS_URL') | ||
516 | 89 | 55 | ||
517 | === modified file 'src/provisioningserver/config.py' | |||
518 | --- src/provisioningserver/config.py 2015-04-04 00:40:18 +0000 | |||
519 | +++ src/provisioningserver/config.py 2015-05-04 14:27:25 +0000 | |||
520 | @@ -52,7 +52,6 @@ | |||
521 | 52 | 52 | ||
522 | 53 | __metaclass__ = type | 53 | __metaclass__ = type |
523 | 54 | __all__ = [ | 54 | __all__ = [ |
524 | 55 | "BOOT_RESOURCES_STORAGE", | ||
525 | 56 | "BootSources", | 55 | "BootSources", |
526 | 57 | "Config", | 56 | "Config", |
527 | 58 | "ConfigBase", | 57 | "ConfigBase", |
528 | @@ -100,11 +99,6 @@ | |||
529 | 100 | ) | 99 | ) |
530 | 101 | import yaml | 100 | import yaml |
531 | 102 | 101 | ||
532 | 103 | # Path to the directory on the cluster controller where boot resources are | ||
533 | 104 | # stored. This used to be configurable in bootresources.yaml, and may become | ||
534 | 105 | # configurable again in the future. | ||
535 | 106 | BOOT_RESOURCES_STORAGE = '/var/lib/maas/boot-resources/' | ||
536 | 107 | |||
537 | 108 | # Default result for cluster UUID if not set | 102 | # Default result for cluster UUID if not set |
538 | 109 | UUID_NOT_SET = '** UUID NOT SET **' | 103 | UUID_NOT_SET = '** UUID NOT SET **' |
539 | 110 | 104 | ||
540 | @@ -205,30 +199,6 @@ | |||
541 | 205 | vhost = String(if_missing="/") | 199 | vhost = String(if_missing="/") |
542 | 206 | 200 | ||
543 | 207 | 201 | ||
544 | 208 | class ConfigTFTP(Schema): | ||
545 | 209 | """Configuration validator for the TFTP service.""" | ||
546 | 210 | |||
547 | 211 | if_key_missing = None | ||
548 | 212 | |||
549 | 213 | # Obsolete: old TFTP root directory. This is retained for the purpose of | ||
550 | 214 | # deriving new, Simplestreams-based import configuration from previously | ||
551 | 215 | # imported boot images. | ||
552 | 216 | # The last time this is needed is for upgrading an older cluster | ||
553 | 217 | # controller to the Ubuntu 14.04 version of MAAS. After installation of | ||
554 | 218 | # the 14.04 version, this setting is never used. | ||
555 | 219 | root = String(if_missing="/var/lib/maas/tftp") | ||
556 | 220 | |||
557 | 221 | # TFTP root directory, managed by the Simplestreams-based import script. | ||
558 | 222 | # The import script maintains "current" as a symlink pointing to the most | ||
559 | 223 | # recent images. | ||
560 | 224 | # XXX jtv 2014-05-22: Redundant with BOOT_RESOURCES_STORAGE. | ||
561 | 225 | resource_root = String( | ||
562 | 226 | if_missing=os.path.join(BOOT_RESOURCES_STORAGE, 'current/')) | ||
563 | 227 | |||
564 | 228 | port = Int(min=1, max=65535, if_missing=69) | ||
565 | 229 | generator = String(if_missing=b"http://localhost/MAAS/api/1.0/pxeconfig/") | ||
566 | 230 | |||
567 | 231 | |||
568 | 232 | class ConfigLegacyEphemeral(Schema): | 202 | class ConfigLegacyEphemeral(Schema): |
569 | 233 | """Legacy `ephemeral` section in `pserv.yaml` prior to MAAS 1.5. | 203 | """Legacy `ephemeral` section in `pserv.yaml` prior to MAAS 1.5. |
570 | 234 | 204 | ||
571 | @@ -415,7 +385,6 @@ | |||
572 | 415 | logfile = String(if_empty=b"pserv.log", if_missing=b"pserv.log") | 385 | logfile = String(if_empty=b"pserv.log", if_missing=b"pserv.log") |
573 | 416 | oops = ConfigOops | 386 | oops = ConfigOops |
574 | 417 | broker = ConfigBroker | 387 | broker = ConfigBroker |
575 | 418 | tftp = ConfigTFTP | ||
576 | 419 | rpc = ConfigRPC | 388 | rpc = ConfigRPC |
577 | 420 | boot = ConfigLegacyBoot | 389 | boot = ConfigLegacyBoot |
578 | 421 | 390 | ||
579 | 422 | 391 | ||
580 | === modified file 'src/provisioningserver/diskless.py' | |||
581 | --- src/provisioningserver/diskless.py 2015-03-25 15:33:23 +0000 | |||
582 | +++ src/provisioningserver/diskless.py 2015-05-04 14:27:25 +0000 | |||
583 | @@ -7,7 +7,7 @@ | |||
584 | 7 | absolute_import, | 7 | absolute_import, |
585 | 8 | print_function, | 8 | print_function, |
586 | 9 | unicode_literals, | 9 | unicode_literals, |
588 | 10 | ) | 10 | ) |
589 | 11 | 11 | ||
590 | 12 | str = None | 12 | str = None |
591 | 13 | 13 | ||
592 | @@ -15,17 +15,21 @@ | |||
593 | 15 | __all__ = [ | 15 | __all__ = [ |
594 | 16 | 'create_diskless_disk', | 16 | 'create_diskless_disk', |
595 | 17 | 'delete_diskless_disk', | 17 | 'delete_diskless_disk', |
597 | 18 | ] | 18 | ] |
598 | 19 | 19 | ||
599 | 20 | import os | 20 | import os |
600 | 21 | from textwrap import dedent | 21 | from textwrap import dedent |
601 | 22 | 22 | ||
603 | 23 | from provisioningserver import config | 23 | from provisioningserver.cluster_config import ( |
604 | 24 | CLUSTER_CONFIG, | ||
605 | 25 | get_config_cluster_variable, | ||
606 | 26 | ) | ||
607 | 24 | from provisioningserver.drivers.diskless import DisklessDriverRegistry | 27 | from provisioningserver.drivers.diskless import DisklessDriverRegistry |
608 | 25 | from provisioningserver.drivers.osystem import ( | 28 | from provisioningserver.drivers.osystem import ( |
609 | 26 | BOOT_IMAGE_PURPOSE, | 29 | BOOT_IMAGE_PURPOSE, |
610 | 27 | OperatingSystemRegistry, | 30 | OperatingSystemRegistry, |
611 | 28 | ) | 31 | ) |
612 | 32 | from provisioningserver.import_images.boot_resources import two_dir_levels_up | ||
613 | 29 | from provisioningserver.logger import get_maas_logger | 33 | from provisioningserver.logger import get_maas_logger |
614 | 30 | from provisioningserver.utils.fs import ( | 34 | from provisioningserver.utils.fs import ( |
615 | 31 | atomic_symlink, | 35 | atomic_symlink, |
616 | @@ -48,7 +52,8 @@ | |||
617 | 48 | currently in use disk for diskless booting. | 52 | currently in use disk for diskless booting. |
618 | 49 | """ | 53 | """ |
619 | 50 | return os.path.join( | 54 | return os.path.join( |
621 | 51 | config.BOOT_RESOURCES_STORAGE, 'diskless', 'store') | 55 | two_dir_levels_up(get_config_cluster_variable( |
622 | 56 | CLUSTER_CONFIG.DB_boot_resources_storage)), 'diskless', 'store') | ||
623 | 52 | 57 | ||
624 | 53 | 58 | ||
625 | 54 | def compose_diskless_link_path(system_id): | 59 | def compose_diskless_link_path(system_id): |
626 | @@ -100,7 +105,9 @@ | |||
627 | 100 | def get_diskless_tgt_path(): | 105 | def get_diskless_tgt_path(): |
628 | 101 | """Return path to maas-diskless.tgt.""" | 106 | """Return path to maas-diskless.tgt.""" |
629 | 102 | return os.path.join( | 107 | return os.path.join( |
631 | 103 | config.BOOT_RESOURCES_STORAGE, 'diskless', 'maas-diskless.tgt') | 108 | two_dir_levels_up(get_config_cluster_variable( |
632 | 109 | CLUSTER_CONFIG.DB_boot_resources_storage)), | ||
633 | 110 | 'diskless', 'maas-diskless.tgt') | ||
634 | 104 | 111 | ||
635 | 105 | 112 | ||
636 | 106 | def tgt_entry(system_id, image): | 113 | def tgt_entry(system_id, image): |
637 | @@ -145,7 +152,7 @@ | |||
638 | 145 | '/usr/sbin/tgt-admin', | 152 | '/usr/sbin/tgt-admin', |
639 | 146 | '--conf', get_diskless_tgt_path(), | 153 | '--conf', get_diskless_tgt_path(), |
640 | 147 | '--update', 'ALL', | 154 | '--update', 'ALL', |
642 | 148 | ]) | 155 | ]) |
643 | 149 | 156 | ||
644 | 150 | 157 | ||
645 | 151 | def update_diskless_tgt(): | 158 | def update_diskless_tgt(): |
646 | @@ -153,7 +160,7 @@ | |||
647 | 153 | symlinks in the diskless store. Reloads the tgt config.""" | 160 | symlinks in the diskless store. Reloads the tgt config.""" |
648 | 154 | tgt_path = get_diskless_tgt_path() | 161 | tgt_path = get_diskless_tgt_path() |
649 | 155 | tgt_config = compose_diskless_tgt_config() | 162 | tgt_config = compose_diskless_tgt_config() |
651 | 156 | atomic_write(tgt_config, tgt_path, mode=0644) | 163 | atomic_write(tgt_config, tgt_path, mode=0o644) |
652 | 157 | reload_diskless_tgt() | 164 | reload_diskless_tgt() |
653 | 158 | 165 | ||
654 | 159 | 166 | ||
655 | @@ -184,7 +191,8 @@ | |||
656 | 184 | "OS doesn't support diskless booting: %s" % osystem_name) | 191 | "OS doesn't support diskless booting: %s" % osystem_name) |
657 | 185 | root_path, _ = osystem.get_xinstall_parameters() | 192 | root_path, _ = osystem.get_xinstall_parameters() |
658 | 186 | return os.path.join( | 193 | return os.path.join( |
660 | 187 | config.BOOT_RESOURCES_STORAGE, 'current', | 194 | get_config_cluster_variable( |
661 | 195 | CLUSTER_CONFIG.DB_boot_resources_storage), | ||
662 | 188 | osystem_name, arch, subarch, release, label, root_path) | 196 | osystem_name, arch, subarch, release, label, root_path) |
663 | 189 | 197 | ||
664 | 190 | 198 | ||
665 | 191 | 199 | ||
666 | === modified file 'src/provisioningserver/drivers/osystem/custom.py' | |||
667 | --- src/provisioningserver/drivers/osystem/custom.py 2015-03-25 15:33:23 +0000 | |||
668 | +++ src/provisioningserver/drivers/osystem/custom.py 2015-05-04 14:27:25 +0000 | |||
669 | @@ -7,18 +7,21 @@ | |||
670 | 7 | absolute_import, | 7 | absolute_import, |
671 | 8 | print_function, | 8 | print_function, |
672 | 9 | unicode_literals, | 9 | unicode_literals, |
674 | 10 | ) | 10 | ) |
675 | 11 | 11 | ||
676 | 12 | str = None | 12 | str = None |
677 | 13 | 13 | ||
678 | 14 | __metaclass__ = type | 14 | __metaclass__ = type |
679 | 15 | __all__ = [ | 15 | __all__ = [ |
680 | 16 | "CustomOS", | 16 | "CustomOS", |
682 | 17 | ] | 17 | ] |
683 | 18 | 18 | ||
684 | 19 | import os | 19 | import os |
685 | 20 | 20 | ||
687 | 21 | from provisioningserver.config import BOOT_RESOURCES_STORAGE | 21 | from provisioningserver.cluster_config import ( |
688 | 22 | CLUSTER_CONFIG, | ||
689 | 23 | get_config_cluster_variable, | ||
690 | 24 | ) | ||
691 | 22 | from provisioningserver.drivers.osystem import ( | 25 | from provisioningserver.drivers.osystem import ( |
692 | 23 | BOOT_IMAGE_PURPOSE, | 26 | BOOT_IMAGE_PURPOSE, |
693 | 24 | OperatingSystem, | 27 | OperatingSystem, |
694 | @@ -55,8 +58,8 @@ | |||
695 | 55 | 58 | ||
696 | 56 | def get_xinstall_parameters(self, arch, subarch, release, label): | 59 | def get_xinstall_parameters(self, arch, subarch, release, label): |
697 | 57 | """Returns the xinstall image name and type for given image.""" | 60 | """Returns the xinstall image name and type for given image.""" |
700 | 58 | path = os.path.join( | 61 | path = os.path.join(get_config_cluster_variable( |
701 | 59 | BOOT_RESOURCES_STORAGE, 'current', 'custom', | 62 | CLUSTER_CONFIG.DB_boot_resources_storage), 'custom', |
702 | 60 | arch, subarch, release, label) | 63 | arch, subarch, release, label) |
703 | 61 | if os.path.exists(os.path.join(path, 'root-dd')): | 64 | if os.path.exists(os.path.join(path, 'root-dd')): |
704 | 62 | return "root-dd", "dd-tgz" | 65 | return "root-dd", "dd-tgz" |
705 | 63 | 66 | ||
706 | === modified file 'src/provisioningserver/drivers/osystem/tests/test_custom.py' | |||
707 | --- src/provisioningserver/drivers/osystem/tests/test_custom.py 2015-03-25 15:33:23 +0000 | |||
708 | +++ src/provisioningserver/drivers/osystem/tests/test_custom.py 2015-05-04 14:27:25 +0000 | |||
709 | @@ -7,7 +7,7 @@ | |||
710 | 7 | absolute_import, | 7 | absolute_import, |
711 | 8 | print_function, | 8 | print_function, |
712 | 9 | unicode_literals, | 9 | unicode_literals, |
714 | 10 | ) | 10 | ) |
715 | 11 | 11 | ||
716 | 12 | str = None | 12 | str = None |
717 | 13 | 13 | ||
718 | @@ -19,26 +19,34 @@ | |||
719 | 19 | 19 | ||
720 | 20 | from maastesting.factory import factory | 20 | from maastesting.factory import factory |
721 | 21 | from maastesting.testcase import MAASTestCase | 21 | from maastesting.testcase import MAASTestCase |
723 | 22 | from provisioningserver.drivers.osystem import custom | 22 | from provisioningserver.cluster_config import ( |
724 | 23 | CLUSTER_CONFIG, | ||
725 | 24 | set_config_cluster_variable, | ||
726 | 25 | ) | ||
727 | 23 | from provisioningserver.drivers.osystem.custom import ( | 26 | from provisioningserver.drivers.osystem.custom import ( |
728 | 24 | BOOT_IMAGE_PURPOSE, | 27 | BOOT_IMAGE_PURPOSE, |
729 | 25 | CustomOS, | 28 | CustomOS, |
730 | 26 | ) | 29 | ) |
731 | 30 | from provisioningserver.testing.config import ClusterConfigurationFixture | ||
732 | 27 | 31 | ||
733 | 28 | 32 | ||
734 | 29 | class TestCustomOS(MAASTestCase): | 33 | class TestCustomOS(MAASTestCase): |
735 | 30 | 34 | ||
736 | 31 | def make_resource_path(self, filename): | 35 | def make_resource_path(self, filename): |
737 | 36 | self.useFixture(ClusterConfigurationFixture()) | ||
738 | 32 | tmpdir = self.make_dir() | 37 | tmpdir = self.make_dir() |
739 | 33 | arch = factory.make_name('arch') | 38 | arch = factory.make_name('arch') |
740 | 34 | subarch = factory.make_name('subarch') | 39 | subarch = factory.make_name('subarch') |
741 | 35 | release = factory.make_name('release') | 40 | release = factory.make_name('release') |
742 | 36 | label = factory.make_name('label') | 41 | label = factory.make_name('label') |
743 | 42 | current_dir = os.path.join(tmpdir, 'current') + '/' | ||
744 | 37 | dirpath = os.path.join( | 43 | dirpath = os.path.join( |
746 | 38 | tmpdir, 'current', 'custom', arch, subarch, release, label) | 44 | current_dir, 'custom', arch, subarch, release, label) |
747 | 39 | os.makedirs(dirpath) | 45 | os.makedirs(dirpath) |
748 | 40 | factory.make_file(dirpath, filename) | 46 | factory.make_file(dirpath, filename) |
750 | 41 | self.patch(custom, 'BOOT_RESOURCES_STORAGE', tmpdir) | 47 | set_config_cluster_variable( |
751 | 48 | CLUSTER_CONFIG.DB_boot_resources_storage, | ||
752 | 49 | current_dir) | ||
753 | 42 | return arch, subarch, release, label | 50 | return arch, subarch, release, label |
754 | 43 | 51 | ||
755 | 44 | def test_get_boot_image_purposes(self): | 52 | def test_get_boot_image_purposes(self): |
756 | @@ -54,7 +62,7 @@ | |||
757 | 54 | self.assertIsInstance(expected, list) | 62 | self.assertIsInstance(expected, list) |
758 | 55 | self.assertEqual(expected, [ | 63 | self.assertEqual(expected, [ |
759 | 56 | BOOT_IMAGE_PURPOSE.XINSTALL, | 64 | BOOT_IMAGE_PURPOSE.XINSTALL, |
761 | 57 | ]) | 65 | ]) |
762 | 58 | 66 | ||
763 | 59 | def test_is_release_supported(self): | 67 | def test_is_release_supported(self): |
764 | 60 | osystem = CustomOS() | 68 | osystem = CustomOS() |
765 | @@ -62,7 +70,7 @@ | |||
766 | 62 | supported = [ | 70 | supported = [ |
767 | 63 | osystem.is_release_supported(release) | 71 | osystem.is_release_supported(release) |
768 | 64 | for release in releases | 72 | for release in releases |
770 | 65 | ] | 73 | ] |
771 | 66 | self.assertEqual([True, True, True], supported) | 74 | self.assertEqual([True, True, True], supported) |
772 | 67 | 75 | ||
773 | 68 | def test_get_default_release(self): | 76 | def test_get_default_release(self): |
774 | 69 | 77 | ||
775 | === modified file 'src/provisioningserver/import_images/boot_resources.py' | |||
776 | --- src/provisioningserver/import_images/boot_resources.py 2015-03-25 15:33:23 +0000 | |||
777 | +++ src/provisioningserver/import_images/boot_resources.py 2015-05-04 14:27:25 +0000 | |||
778 | @@ -5,7 +5,7 @@ | |||
779 | 5 | absolute_import, | 5 | absolute_import, |
780 | 6 | print_function, | 6 | print_function, |
781 | 7 | unicode_literals, | 7 | unicode_literals, |
783 | 8 | ) | 8 | ) |
784 | 9 | 9 | ||
785 | 10 | str = None | 10 | str = None |
786 | 11 | 11 | ||
787 | @@ -15,16 +15,19 @@ | |||
788 | 15 | 'main', | 15 | 'main', |
789 | 16 | 'main_with_services', | 16 | 'main_with_services', |
790 | 17 | 'make_arg_parser', | 17 | 'make_arg_parser', |
792 | 18 | ] | 18 | ] |
793 | 19 | 19 | ||
794 | 20 | from argparse import ArgumentParser | 20 | from argparse import ArgumentParser |
795 | 21 | import errno | 21 | import errno |
796 | 22 | import os | 22 | import os |
797 | 23 | from textwrap import dedent | 23 | from textwrap import dedent |
798 | 24 | 24 | ||
799 | 25 | import provisioningserver | ||
800 | 26 | from provisioningserver.boot import BootMethodRegistry | 25 | from provisioningserver.boot import BootMethodRegistry |
801 | 27 | from provisioningserver.boot.tftppath import list_boot_images | 26 | from provisioningserver.boot.tftppath import list_boot_images |
802 | 27 | from provisioningserver.cluster_config import ( | ||
803 | 28 | CLUSTER_CONFIG, | ||
804 | 29 | get_config_cluster_variable, | ||
805 | 30 | ) | ||
806 | 28 | from provisioningserver.config import BootSources | 31 | from provisioningserver.config import BootSources |
807 | 29 | from provisioningserver.import_images.cleanup import ( | 32 | from provisioningserver.import_images.cleanup import ( |
808 | 30 | cleanup_snapshots_and_cache, | 33 | cleanup_snapshots_and_cache, |
809 | @@ -48,6 +51,16 @@ | |||
810 | 48 | from provisioningserver.utils.shell import call_and_check | 51 | from provisioningserver.utils.shell import call_and_check |
811 | 49 | 52 | ||
812 | 50 | 53 | ||
813 | 54 | def two_dir_levels_up(path): | ||
814 | 55 | # NOTE: Syntax along the lines of: | ||
815 | 56 | # os.path.normpath(os.path.join( | ||
816 | 57 | # path, os.path.pardir, os.path.pardir)) | ||
817 | 58 | # will NOT work here, as the classes that use these file paths | ||
818 | 59 | # to NOT support paths with 'os.path.pardir' segments. Thus | ||
819 | 60 | # we must manually resolve the path here. | ||
820 | 61 | return os.path.split(os.path.split(path)[0])[0] | ||
821 | 62 | |||
822 | 63 | |||
823 | 51 | class NoConfigFile(Exception): | 64 | class NoConfigFile(Exception): |
824 | 52 | """Raised when the config file for the script doesn't exist.""" | 65 | """Raised when the config file for the script doesn't exist.""" |
825 | 53 | 66 | ||
826 | @@ -81,7 +94,7 @@ | |||
827 | 81 | subarch, | 94 | subarch, |
828 | 82 | release, | 95 | release, |
829 | 83 | label | 96 | label |
831 | 84 | ) | 97 | ) |
832 | 85 | entry = dedent("""\ | 98 | entry = dedent("""\ |
833 | 86 | <target {prefix}:{target_name}> | 99 | <target {prefix}:{target_name}> |
834 | 87 | readonly 1 | 100 | readonly 1 |
835 | @@ -191,7 +204,7 @@ | |||
836 | 191 | '/usr/sbin/tgt-admin', | 204 | '/usr/sbin/tgt-admin', |
837 | 192 | '--conf', targets_conf, | 205 | '--conf', targets_conf, |
838 | 193 | '--update', 'ALL', | 206 | '--update', 'ALL', |
840 | 194 | ]) | 207 | ]) |
841 | 195 | 208 | ||
842 | 196 | 209 | ||
843 | 197 | def read_sources(sources_yaml): | 210 | def read_sources(sources_yaml): |
844 | @@ -245,7 +258,8 @@ | |||
845 | 245 | "any boot images available.") | 258 | "any boot images available.") |
846 | 246 | return | 259 | return |
847 | 247 | 260 | ||
849 | 248 | storage = provisioningserver.config.BOOT_RESOURCES_STORAGE | 261 | storage = two_dir_levels_up(get_config_cluster_variable( |
850 | 262 | CLUSTER_CONFIG.DB_boot_resources_storage)) | ||
851 | 249 | meta_file_content = image_descriptions.dump_json() | 263 | meta_file_content = image_descriptions.dump_json() |
852 | 250 | if meta_contains(storage, meta_file_content): | 264 | if meta_contains(storage, meta_file_content): |
853 | 251 | maaslog.info( | 265 | maaslog.info( |
854 | 252 | 266 | ||
855 | === modified file 'src/provisioningserver/import_images/tests/test_boot_resources.py' | |||
856 | --- src/provisioningserver/import_images/tests/test_boot_resources.py 2015-03-25 15:33:23 +0000 | |||
857 | +++ src/provisioningserver/import_images/tests/test_boot_resources.py 2015-05-04 14:27:25 +0000 | |||
858 | @@ -7,7 +7,7 @@ | |||
859 | 7 | absolute_import, | 7 | absolute_import, |
860 | 8 | print_function, | 8 | print_function, |
861 | 9 | unicode_literals, | 9 | unicode_literals, |
863 | 10 | ) | 10 | ) |
864 | 11 | 11 | ||
865 | 12 | str = None | 12 | str = None |
866 | 13 | 13 | ||
867 | @@ -39,14 +39,20 @@ | |||
868 | 39 | import mock | 39 | import mock |
869 | 40 | from mock import call | 40 | from mock import call |
870 | 41 | from provisioningserver.boot import BootMethodRegistry | 41 | from provisioningserver.boot import BootMethodRegistry |
872 | 42 | import provisioningserver.config | 42 | from provisioningserver.cluster_config import ( |
873 | 43 | CLUSTER_CONFIG, | ||
874 | 44 | set_config_cluster_variable, | ||
875 | 45 | ) | ||
876 | 43 | from provisioningserver.config import BootSources | 46 | from provisioningserver.config import BootSources |
877 | 44 | from provisioningserver.import_images import boot_resources | 47 | from provisioningserver.import_images import boot_resources |
878 | 45 | from provisioningserver.import_images.boot_image_mapping import ( | 48 | from provisioningserver.import_images.boot_image_mapping import ( |
879 | 46 | BootImageMapping, | 49 | BootImageMapping, |
880 | 47 | ) | 50 | ) |
881 | 48 | from provisioningserver.import_images.testing.factory import make_image_spec | 51 | from provisioningserver.import_images.testing.factory import make_image_spec |
883 | 49 | from provisioningserver.testing.config import BootSourcesFixture | 52 | from provisioningserver.testing.config import ( |
884 | 53 | BootSourcesFixture, | ||
885 | 54 | ClusterConfigurationFixture, | ||
886 | 55 | ) | ||
887 | 50 | from provisioningserver.utils.fs import write_text_file | 56 | from provisioningserver.utils.fs import write_text_file |
888 | 51 | from testtools.content import Content | 57 | from testtools.content import Content |
889 | 52 | from testtools.content_type import UTF8_TEXT | 58 | from testtools.content_type import UTF8_TEXT |
890 | @@ -195,9 +201,13 @@ | |||
891 | 195 | 201 | ||
892 | 196 | def setUp(self): | 202 | def setUp(self): |
893 | 197 | super(TestMain, self).setUp() | 203 | super(TestMain, self).setUp() |
894 | 204 | self.useFixture(ClusterConfigurationFixture()) | ||
895 | 198 | self.storage = self.make_dir() | 205 | self.storage = self.make_dir() |
898 | 199 | self.patch( | 206 | current_dir = os.path.join(self.storage, 'current') + os.sep |
899 | 200 | provisioningserver.config, 'BOOT_RESOURCES_STORAGE', self.storage) | 207 | os.makedirs(current_dir) |
900 | 208 | set_config_cluster_variable(CLUSTER_CONFIG.DB_boot_resources_storage, | ||
901 | 209 | current_dir) | ||
902 | 210 | os.rmdir(current_dir) | ||
903 | 201 | # Forcing arch to amd64 causes pxelinux.0 to be installed, giving more | 211 | # Forcing arch to amd64 causes pxelinux.0 to be installed, giving more |
904 | 202 | # test coverage. | 212 | # test coverage. |
905 | 203 | self.image = make_image_spec(arch='amd64') | 213 | self.image = make_image_spec(arch='amd64') |
906 | @@ -232,9 +242,9 @@ | |||
907 | 232 | 'updated': 'Tue, 25 Mar 2014 16:19:49 +0000', | 242 | 'updated': 'Tue, 25 Mar 2014 16:19:49 +0000', |
908 | 233 | 'format': 'products:1.0', | 243 | 'format': 'products:1.0', |
909 | 234 | 'products': [product], | 244 | 'products': [product], |
910 | 235 | }, | ||
911 | 236 | }, | 245 | }, |
913 | 237 | } | 246 | }, |
914 | 247 | } | ||
915 | 238 | write_text_file(index_file, json.dumps(index)) | 248 | write_text_file(index_file, json.dumps(index)) |
916 | 239 | return index_file | 249 | return index_file |
917 | 240 | 250 | ||
918 | @@ -251,7 +261,7 @@ | |||
919 | 251 | image_spec.release, | 261 | image_spec.release, |
920 | 252 | image_spec.subarch, | 262 | image_spec.subarch, |
921 | 253 | filename, | 263 | filename, |
923 | 254 | ] | 264 | ] |
924 | 255 | native_path = os.path.join(repo, *path) | 265 | native_path = os.path.join(repo, *path) |
925 | 256 | os.makedirs(os.path.dirname(native_path)) | 266 | os.makedirs(os.path.dirname(native_path)) |
926 | 257 | contents = ("Contents: %s" % filename).encode('utf-8') | 267 | contents = ("Contents: %s" % filename).encode('utf-8') |
927 | @@ -318,7 +328,7 @@ | |||
928 | 318 | os_release = '%d.%.2s' % ( | 328 | os_release = '%d.%.2s' % ( |
929 | 319 | randint(1, 99), | 329 | randint(1, 99), |
930 | 320 | ('04' if randint(0, 1) == 0 else '10'), | 330 | ('04' if randint(0, 1) == 0 else '10'), |
932 | 321 | ) | 331 | ) |
933 | 322 | repo = self.make_dir() | 332 | repo = self.make_dir() |
934 | 323 | index_dir = os.path.join(repo, 'streams', 'v1') | 333 | index_dir = os.path.join(repo, 'streams', 'v1') |
935 | 324 | os.makedirs(index_dir) | 334 | os.makedirs(index_dir) |
936 | @@ -327,7 +337,7 @@ | |||
937 | 327 | os_release, | 337 | os_release, |
938 | 328 | image_spec.arch, | 338 | image_spec.arch, |
939 | 329 | image_spec.subarch, | 339 | image_spec.subarch, |
941 | 330 | ) | 340 | ) |
942 | 331 | version = '20140317' | 341 | version = '20140317' |
943 | 332 | download_file, sha = self.make_download_file(repo, image_spec, version) | 342 | download_file, sha = self.make_download_file(repo, image_spec, version) |
944 | 333 | self.make_simplestreams_product_index( | 343 | self.make_simplestreams_product_index( |
945 | @@ -350,9 +360,9 @@ | |||
946 | 350 | 'subarches': [self.subarch], | 360 | 'subarches': [self.subarch], |
947 | 351 | 'labels': [self.label], | 361 | 'labels': [self.label], |
948 | 352 | }, | 362 | }, |
950 | 353 | ], | 363 | ], |
951 | 354 | }, | 364 | }, |
953 | 355 | ] | 365 | ] |
954 | 356 | sources_file = self.make_file( | 366 | sources_file = self.make_file( |
955 | 357 | 'sources.yaml', contents=yaml.safe_dump(sources)) | 367 | 'sources.yaml', contents=yaml.safe_dump(sources)) |
956 | 358 | return self.make_args(sources_file=sources_file) | 368 | return self.make_args(sources_file=sources_file) |
957 | @@ -541,9 +551,9 @@ | |||
958 | 541 | 'subarches': [factory.make_name("subarch")], | 551 | 'subarches': [factory.make_name("subarch")], |
959 | 542 | 'labels': [factory.make_name("label")], | 552 | 'labels': [factory.make_name("label")], |
960 | 543 | }, | 553 | }, |
962 | 544 | ], | 554 | ], |
963 | 545 | }, | 555 | }, |
965 | 546 | ] | 556 | ] |
966 | 547 | parsed_sources = boot_resources.parse_sources(yaml.safe_dump(sources)) | 557 | parsed_sources = boot_resources.parse_sources(yaml.safe_dump(sources)) |
967 | 548 | self.assertEqual(sources, parsed_sources) | 558 | self.assertEqual(sources, parsed_sources) |
968 | 549 | 559 | ||
969 | @@ -577,9 +587,9 @@ | |||
970 | 577 | 'subarches': [factory.make_name("subarch")], | 587 | 'subarches': [factory.make_name("subarch")], |
971 | 578 | 'labels': [factory.make_name("label")], | 588 | 'labels': [factory.make_name("label")], |
972 | 579 | }, | 589 | }, |
974 | 580 | ], | 590 | ], |
975 | 581 | }, | 591 | }, |
977 | 582 | ], | 592 | ], |
978 | 583 | boot_resources.import_images(sources) | 593 | boot_resources.import_images(sources) |
979 | 584 | self.assertThat( | 594 | self.assertThat( |
980 | 585 | fake_write_all_keyrings, MockCalledWith(mock.ANY, sources)) | 595 | fake_write_all_keyrings, MockCalledWith(mock.ANY, sources)) |
981 | 586 | 596 | ||
982 | === modified file 'src/provisioningserver/plugin.py' | |||
983 | --- src/provisioningserver/plugin.py 2015-04-29 06:19:04 +0000 | |||
984 | +++ src/provisioningserver/plugin.py 2015-05-04 14:27:25 +0000 | |||
985 | @@ -7,7 +7,7 @@ | |||
986 | 7 | absolute_import, | 7 | absolute_import, |
987 | 8 | print_function, | 8 | print_function, |
988 | 9 | unicode_literals, | 9 | unicode_literals, |
990 | 10 | ) | 10 | ) |
991 | 11 | 11 | ||
992 | 12 | str = None | 12 | str = None |
993 | 13 | 13 | ||
994 | @@ -17,10 +17,14 @@ | |||
995 | 17 | ] | 17 | ] |
996 | 18 | 18 | ||
997 | 19 | from errno import ENOPROTOOPT | 19 | from errno import ENOPROTOOPT |
998 | 20 | import os | ||
999 | 21 | import socket | 20 | import socket |
1000 | 22 | from socket import error as socket_error | 21 | from socket import error as socket_error |
1001 | 23 | 22 | ||
1002 | 23 | from provisioningserver.cluster_config import ( | ||
1003 | 24 | CLUSTER_CONFIG, | ||
1004 | 25 | get_config_cluster_variable, | ||
1005 | 26 | get_tftp_generator, | ||
1006 | 27 | ) | ||
1007 | 24 | from provisioningserver.utils.debug import ( | 28 | from provisioningserver.utils.debug import ( |
1008 | 25 | register_sigusr2_thread_dump_handler, | 29 | register_sigusr2_thread_dump_handler, |
1009 | 26 | ) | 30 | ) |
1010 | @@ -93,7 +97,7 @@ | |||
1011 | 93 | """Command line options for the provisioning server.""" | 97 | """Command line options for the provisioning server.""" |
1012 | 94 | 98 | ||
1013 | 95 | optParameters = [ | 99 | optParameters = [ |
1015 | 96 | ["config-file", "c", "pserv.yaml", "Configuration file to load."], | 100 | ["config-file", "c", "clusterd.conf", "Configuration file to load."], |
1016 | 97 | ["introspect", None, None, | 101 | ["introspect", None, None, |
1017 | 98 | ("Allow introspection, allowing unhindered access to the internals " | 102 | ("Allow introspection, allowing unhindered access to the internals " |
1018 | 99 | "of MAAS. This should probably only be used for debugging. Supply " | 103 | "of MAAS. This should probably only be used for debugging. Supply " |
1019 | @@ -128,8 +132,6 @@ | |||
1020 | 128 | from provisioningserver.pserv_services.image import ( | 132 | from provisioningserver.pserv_services.image import ( |
1021 | 129 | BootImageEndpointService) | 133 | BootImageEndpointService) |
1022 | 130 | from twisted.internet.endpoints import AdoptedStreamServerEndpoint | 134 | from twisted.internet.endpoints import AdoptedStreamServerEndpoint |
1023 | 131 | from provisioningserver import config | ||
1024 | 132 | |||
1025 | 133 | port = 5248 # config["port"] | 135 | port = 5248 # config["port"] |
1026 | 134 | # Make a socket with SO_REUSEPORT set so that we can run multiple we | 136 | # Make a socket with SO_REUSEPORT set so that we can run multiple we |
1027 | 135 | # applications. This is easier to do from outside of Twisted as there's | 137 | # applications. This is easier to do from outside of Twisted as there's |
1028 | @@ -157,59 +159,58 @@ | |||
1029 | 157 | site_endpoint.socket = s # Prevent garbage collection. | 159 | site_endpoint.socket = s # Prevent garbage collection. |
1030 | 158 | 160 | ||
1031 | 159 | image_service = BootImageEndpointService( | 161 | image_service = BootImageEndpointService( |
1034 | 160 | resource_root=os.path.join( | 162 | resource_root=get_config_cluster_variable( |
1035 | 161 | config.BOOT_RESOURCES_STORAGE, "current"), | 163 | CLUSTER_CONFIG.DB_boot_resources_storage), |
1036 | 162 | endpoint=site_endpoint) | 164 | endpoint=site_endpoint) |
1037 | 163 | image_service.setName("image_service") | 165 | image_service.setName("image_service") |
1038 | 164 | return image_service | 166 | return image_service |
1039 | 165 | 167 | ||
1041 | 166 | def _makeTFTPService(self, tftp_config): | 168 | def _makeTFTPService(self, tftp_root, tftp_port, tftp_generator): |
1042 | 167 | """Create the dynamic TFTP service.""" | 169 | """Create the dynamic TFTP service.""" |
1043 | 168 | from provisioningserver.pserv_services.tftp import TFTPService | 170 | from provisioningserver.pserv_services.tftp import TFTPService |
1044 | 169 | tftp_service = TFTPService( | 171 | tftp_service = TFTPService( |
1047 | 170 | resource_root=tftp_config['resource_root'], | 172 | resource_root=tftp_root, port=tftp_port, generator=tftp_generator) |
1046 | 171 | port=tftp_config['port'], generator=tftp_config['generator']) | ||
1048 | 172 | tftp_service.setName("tftp") | 173 | tftp_service.setName("tftp") |
1049 | 173 | return tftp_service | 174 | return tftp_service |
1050 | 174 | 175 | ||
1051 | 175 | def _makeImageDownloadService(self, rpc_service): | 176 | def _makeImageDownloadService(self, rpc_service): |
1052 | 176 | from provisioningserver.cluster_config import get_cluster_uuid | ||
1053 | 177 | from provisioningserver.pserv_services.image_download_service \ | 177 | from provisioningserver.pserv_services.image_download_service \ |
1054 | 178 | import ImageDownloadService | 178 | import ImageDownloadService |
1055 | 179 | image_download_service = ImageDownloadService( | 179 | image_download_service = ImageDownloadService( |
1057 | 180 | rpc_service, reactor, get_cluster_uuid()) | 180 | rpc_service, reactor, get_config_cluster_variable( |
1058 | 181 | CLUSTER_CONFIG.DB_cluster_uuid)) | ||
1059 | 181 | image_download_service.setName("image_download") | 182 | image_download_service.setName("image_download") |
1060 | 182 | return image_download_service | 183 | return image_download_service |
1061 | 183 | 184 | ||
1062 | 184 | def _makeLeaseUploadService(self, rpc_service): | 185 | def _makeLeaseUploadService(self, rpc_service): |
1063 | 185 | from provisioningserver.cluster_config import get_cluster_uuid | ||
1064 | 186 | from provisioningserver.pserv_services.lease_upload_service \ | 186 | from provisioningserver.pserv_services.lease_upload_service \ |
1065 | 187 | import LeaseUploadService | 187 | import LeaseUploadService |
1066 | 188 | lease_upload_service = LeaseUploadService( | 188 | lease_upload_service = LeaseUploadService( |
1068 | 189 | rpc_service, reactor, get_cluster_uuid()) | 189 | rpc_service, reactor, get_config_cluster_variable( |
1069 | 190 | CLUSTER_CONFIG.DB_cluster_uuid)) | ||
1070 | 190 | lease_upload_service.setName("lease_upload") | 191 | lease_upload_service.setName("lease_upload") |
1071 | 191 | return lease_upload_service | 192 | return lease_upload_service |
1072 | 192 | 193 | ||
1073 | 193 | def _makeNodePowerMonitorService(self): | 194 | def _makeNodePowerMonitorService(self): |
1074 | 194 | from provisioningserver.cluster_config import get_cluster_uuid | ||
1075 | 195 | from provisioningserver.pserv_services.node_power_monitor_service \ | 195 | from provisioningserver.pserv_services.node_power_monitor_service \ |
1076 | 196 | import NodePowerMonitorService | 196 | import NodePowerMonitorService |
1078 | 197 | node_monitor = NodePowerMonitorService(get_cluster_uuid(), reactor) | 197 | node_monitor = NodePowerMonitorService(get_config_cluster_variable( |
1079 | 198 | CLUSTER_CONFIG.DB_cluster_uuid), reactor) | ||
1080 | 198 | node_monitor.setName("node_monitor") | 199 | node_monitor.setName("node_monitor") |
1081 | 199 | return node_monitor | 200 | return node_monitor |
1082 | 200 | 201 | ||
1084 | 201 | def _makeRPCService(self, rpc_config): | 202 | def _makeRPCService(self): |
1085 | 202 | from provisioningserver.rpc.clusterservice import ClusterClientService | 203 | from provisioningserver.rpc.clusterservice import ClusterClientService |
1086 | 203 | rpc_service = ClusterClientService(reactor) | 204 | rpc_service = ClusterClientService(reactor) |
1087 | 204 | rpc_service.setName("rpc") | 205 | rpc_service.setName("rpc") |
1088 | 205 | return rpc_service | 206 | return rpc_service |
1089 | 206 | 207 | ||
1090 | 207 | def _makeDHCPProbeService(self, rpc_service): | 208 | def _makeDHCPProbeService(self, rpc_service): |
1091 | 208 | from provisioningserver.cluster_config import get_cluster_uuid | ||
1092 | 209 | from provisioningserver.pserv_services.dhcp_probe_service \ | 209 | from provisioningserver.pserv_services.dhcp_probe_service \ |
1093 | 210 | import DHCPProbeService | 210 | import DHCPProbeService |
1094 | 211 | dhcp_probe_service = DHCPProbeService( | 211 | dhcp_probe_service = DHCPProbeService( |
1096 | 212 | rpc_service, reactor, get_cluster_uuid()) | 212 | rpc_service, reactor, |
1097 | 213 | get_config_cluster_variable(CLUSTER_CONFIG.DB_cluster_uuid)) | ||
1098 | 213 | dhcp_probe_service.setName("dhcp_probe") | 214 | dhcp_probe_service.setName("dhcp_probe") |
1099 | 214 | return dhcp_probe_service | 215 | return dhcp_probe_service |
1100 | 215 | 216 | ||
1101 | @@ -226,17 +227,18 @@ | |||
1102 | 226 | register_sigusr2_thread_dump_handler() | 227 | register_sigusr2_thread_dump_handler() |
1103 | 227 | 228 | ||
1104 | 228 | from provisioningserver import services | 229 | from provisioningserver import services |
1105 | 229 | from provisioningserver.config import Config | ||
1106 | 230 | |||
1107 | 231 | config = Config.load(options["config-file"]) | ||
1108 | 232 | 230 | ||
1109 | 233 | image_service = self._makeImageService() | 231 | image_service = self._makeImageService() |
1110 | 234 | image_service.setServiceParent(services) | 232 | image_service.setServiceParent(services) |
1111 | 235 | 233 | ||
1113 | 236 | tftp_service = self._makeTFTPService(config["tftp"]) | 234 | tftp_service = self._makeTFTPService( |
1114 | 235 | get_config_cluster_variable(CLUSTER_CONFIG.DB_tftp_resource_root), | ||
1115 | 236 | get_config_cluster_variable(CLUSTER_CONFIG.DB_tftpport), | ||
1116 | 237 | get_tftp_generator()) | ||
1117 | 238 | |||
1118 | 237 | tftp_service.setServiceParent(services) | 239 | tftp_service.setServiceParent(services) |
1119 | 238 | 240 | ||
1121 | 239 | rpc_service = self._makeRPCService(config["rpc"]) | 241 | rpc_service = self._makeRPCService() |
1122 | 240 | rpc_service.setServiceParent(services) | 242 | rpc_service.setServiceParent(services) |
1123 | 241 | 243 | ||
1124 | 242 | node_monitor = self._makeNodePowerMonitorService() | 244 | node_monitor = self._makeNodePowerMonitorService() |
1125 | 243 | 245 | ||
1126 | === modified file 'src/provisioningserver/pserv_services/tests/test_tftp.py' | |||
1127 | --- src/provisioningserver/pserv_services/tests/test_tftp.py 2015-04-24 20:41:48 +0000 | |||
1128 | +++ src/provisioningserver/pserv_services/tests/test_tftp.py 2015-05-04 14:27:25 +0000 | |||
1129 | @@ -30,7 +30,6 @@ | |||
1130 | 30 | urlparse, | 30 | urlparse, |
1131 | 31 | ) | 31 | ) |
1132 | 32 | 32 | ||
1133 | 33 | from fixtures import EnvironmentVariable | ||
1134 | 34 | from maastesting.factory import factory | 33 | from maastesting.factory import factory |
1135 | 35 | from maastesting.matchers import ( | 34 | from maastesting.matchers import ( |
1136 | 36 | MockCalledOnceWith, | 35 | MockCalledOnceWith, |
1137 | @@ -50,6 +49,7 @@ | |||
1138 | 50 | IPV4_LINK_LOCAL, | 49 | IPV4_LINK_LOCAL, |
1139 | 51 | IPV6_LINK_LOCAL, | 50 | IPV6_LINK_LOCAL, |
1140 | 52 | ) | 51 | ) |
1141 | 52 | from provisioningserver import cluster_config | ||
1142 | 53 | from provisioningserver.boot import BytesReader | 53 | from provisioningserver.boot import BytesReader |
1143 | 54 | from provisioningserver.boot.pxe import PXEBootMethod | 54 | from provisioningserver.boot.pxe import PXEBootMethod |
1144 | 55 | from provisioningserver.boot.tests.test_pxe import compose_config_path | 55 | from provisioningserver.boot.tests.test_pxe import compose_config_path |
1145 | @@ -63,6 +63,7 @@ | |||
1146 | 63 | UDPServer, | 63 | UDPServer, |
1147 | 64 | ) | 64 | ) |
1148 | 65 | from provisioningserver.rpc.testing import TwistedLoggerFixture | 65 | from provisioningserver.rpc.testing import TwistedLoggerFixture |
1149 | 66 | from provisioningserver.testing.config import ClusterConfigurationFixture | ||
1150 | 66 | from provisioningserver.tests.test_kernel_opts import make_kernel_parameters | 67 | from provisioningserver.tests.test_kernel_opts import make_kernel_parameters |
1151 | 67 | from testtools import ExpectedException | 68 | from testtools import ExpectedException |
1152 | 68 | from testtools.matchers import ( | 69 | from testtools.matchers import ( |
1153 | @@ -127,6 +128,7 @@ | |||
1154 | 127 | 128 | ||
1155 | 128 | def setUp(self): | 129 | def setUp(self): |
1156 | 129 | super(TestTFTPBackend, self).setUp() | 130 | super(TestTFTPBackend, self).setUp() |
1157 | 131 | self.useFixture(ClusterConfigurationFixture()) | ||
1158 | 130 | from provisioningserver import boot | 132 | from provisioningserver import boot |
1159 | 131 | self.patch(boot, "find_mac_via_arp") | 133 | self.patch(boot, "find_mac_via_arp") |
1160 | 132 | self.patch(tftp_module, 'log_request') | 134 | self.patch(tftp_module, 'log_request') |
1161 | @@ -219,7 +221,8 @@ | |||
1162 | 219 | 221 | ||
1163 | 220 | @inlineCallbacks | 222 | @inlineCallbacks |
1164 | 221 | def test_get_reader_converts_404s_to_tftp_error(self): | 223 | def test_get_reader_converts_404s_to_tftp_error(self): |
1166 | 222 | self.useFixture(EnvironmentVariable("CLUSTER_UUID", "foobar")) | 224 | cluster_config.set_config_cluster_variable( |
1167 | 225 | cluster_config.CLUSTER_CONFIG.DB_cluster_uuid, factory.make_UUID()) | ||
1168 | 223 | 226 | ||
1169 | 224 | backend = TFTPBackend(self.make_dir(), "http://example.com/") | 227 | backend = TFTPBackend(self.make_dir(), "http://example.com/") |
1170 | 225 | get_page = self.patch(backend, 'get_page') | 228 | get_page = self.patch(backend, 'get_page') |
1171 | @@ -230,7 +233,8 @@ | |||
1172 | 230 | 233 | ||
1173 | 231 | @inlineCallbacks | 234 | @inlineCallbacks |
1174 | 232 | def test_get_reader_converts_other_exceptions_to_tftp_error(self): | 235 | def test_get_reader_converts_other_exceptions_to_tftp_error(self): |
1176 | 233 | self.useFixture(EnvironmentVariable("CLUSTER_UUID", "foobar")) | 236 | cluster_config.set_config_cluster_variable( |
1177 | 237 | cluster_config.CLUSTER_CONFIG.DB_cluster_uuid, factory.make_UUID()) | ||
1178 | 234 | 238 | ||
1179 | 235 | exception_type = factory.make_exception_type() | 239 | exception_type = factory.make_exception_type() |
1180 | 236 | exception_message = factory.make_string() | 240 | exception_message = factory.make_string() |
1181 | @@ -257,8 +261,8 @@ | |||
1182 | 257 | # For paths matching PXEBootMethod.match_path, TFTPBackend.get_reader() | 261 | # For paths matching PXEBootMethod.match_path, TFTPBackend.get_reader() |
1183 | 258 | # returns a Deferred that will yield a BytesReader. | 262 | # returns a Deferred that will yield a BytesReader. |
1184 | 259 | cluster_uuid = factory.make_UUID() | 263 | cluster_uuid = factory.make_UUID() |
1187 | 260 | get_cluster_uuid = self.patch(tftp_module, 'get_cluster_uuid') | 264 | cluster_config.set_config_cluster_variable( |
1188 | 261 | get_cluster_uuid.return_value = cluster_uuid | 265 | cluster_config.CLUSTER_CONFIG.DB_cluster_uuid, cluster_uuid) |
1189 | 262 | mac = factory.make_mac_address("-") | 266 | mac = factory.make_mac_address("-") |
1190 | 263 | config_path = compose_config_path(mac) | 267 | config_path = compose_config_path(mac) |
1191 | 264 | backend = TFTPBackend(self.make_dir(), b"http://example.com/") | 268 | backend = TFTPBackend(self.make_dir(), b"http://example.com/") |
1192 | @@ -356,8 +360,8 @@ | |||
1193 | 356 | # arch field of the parameters (mapping from pxe to maas | 360 | # arch field of the parameters (mapping from pxe to maas |
1194 | 357 | # namespace). | 361 | # namespace). |
1195 | 358 | cluster_uuid = factory.make_UUID() | 362 | cluster_uuid = factory.make_UUID() |
1198 | 359 | get_cluster_uuid = self.patch(tftp_module, 'get_cluster_uuid') | 363 | cluster_config.set_config_cluster_variable( |
1199 | 360 | get_cluster_uuid.return_value = cluster_uuid | 364 | cluster_config.CLUSTER_CONFIG.DB_cluster_uuid, cluster_uuid) |
1200 | 361 | config_path = "pxelinux.cfg/default-arm" | 365 | config_path = "pxelinux.cfg/default-arm" |
1201 | 362 | backend = TFTPBackend(self.make_dir(), b"http://example.com/") | 366 | backend = TFTPBackend(self.make_dir(), b"http://example.com/") |
1202 | 363 | # python-tx-tftp sets up call context so that backends can discover | 367 | # python-tx-tftp sets up call context so that backends can discover |
1203 | 364 | 368 | ||
1204 | === modified file 'src/provisioningserver/pserv_services/tftp.py' | |||
1205 | --- src/provisioningserver/pserv_services/tftp.py 2015-04-24 20:39:18 +0000 | |||
1206 | +++ src/provisioningserver/pserv_services/tftp.py 2015-05-04 14:27:25 +0000 | |||
1207 | @@ -7,7 +7,7 @@ | |||
1208 | 7 | absolute_import, | 7 | absolute_import, |
1209 | 8 | print_function, | 8 | print_function, |
1210 | 9 | unicode_literals, | 9 | unicode_literals, |
1212 | 10 | ) | 10 | ) |
1213 | 11 | 11 | ||
1214 | 12 | str = None | 12 | str = None |
1215 | 13 | 13 | ||
1216 | @@ -15,7 +15,7 @@ | |||
1217 | 15 | __all__ = [ | 15 | __all__ = [ |
1218 | 16 | "TFTPBackend", | 16 | "TFTPBackend", |
1219 | 17 | "TFTPService", | 17 | "TFTPService", |
1221 | 18 | ] | 18 | ] |
1222 | 19 | 19 | ||
1223 | 20 | from functools import partial | 20 | from functools import partial |
1224 | 21 | import httplib | 21 | import httplib |
1225 | @@ -35,7 +35,10 @@ | |||
1226 | 35 | BootMethodRegistry, | 35 | BootMethodRegistry, |
1227 | 36 | get_remote_mac, | 36 | get_remote_mac, |
1228 | 37 | ) | 37 | ) |
1230 | 38 | from provisioningserver.cluster_config import get_cluster_uuid | 38 | from provisioningserver.cluster_config import ( |
1231 | 39 | CLUSTER_CONFIG, | ||
1232 | 40 | get_config_cluster_variable, | ||
1233 | 41 | ) | ||
1234 | 39 | from provisioningserver.drivers import ArchitectureRegistry | 42 | from provisioningserver.drivers import ArchitectureRegistry |
1235 | 40 | from provisioningserver.events import ( | 43 | from provisioningserver.events import ( |
1236 | 41 | EVENT_TYPES, | 44 | EVENT_TYPES, |
1237 | @@ -223,7 +226,8 @@ | |||
1238 | 223 | params["local"] = local_host | 226 | params["local"] = local_host |
1239 | 224 | remote_host, remote_port = tftp.get_remote_address() | 227 | remote_host, remote_port = tftp.get_remote_address() |
1240 | 225 | params["remote"] = remote_host | 228 | params["remote"] = remote_host |
1242 | 226 | params["cluster_uuid"] = get_cluster_uuid() | 229 | params["cluster_uuid"] = get_config_cluster_variable( |
1243 | 230 | CLUSTER_CONFIG.DB_cluster_uuid) | ||
1244 | 227 | d = self.get_boot_method_reader(boot_method, params) | 231 | d = self.get_boot_method_reader(boot_method, params) |
1245 | 228 | return d | 232 | return d |
1246 | 229 | 233 | ||
1247 | 230 | 234 | ||
1248 | === modified file 'src/provisioningserver/rpc/boot_images.py' | |||
1249 | --- src/provisioningserver/rpc/boot_images.py 2015-02-24 13:52:12 +0000 | |||
1250 | +++ src/provisioningserver/rpc/boot_images.py 2015-05-04 14:27:25 +0000 | |||
1251 | @@ -7,7 +7,7 @@ | |||
1252 | 7 | absolute_import, | 7 | absolute_import, |
1253 | 8 | print_function, | 8 | print_function, |
1254 | 9 | unicode_literals, | 9 | unicode_literals, |
1256 | 10 | ) | 10 | ) |
1257 | 11 | 11 | ||
1258 | 12 | str = None | 12 | str = None |
1259 | 13 | 13 | ||
1260 | @@ -16,15 +16,17 @@ | |||
1261 | 16 | "import_boot_images", | 16 | "import_boot_images", |
1262 | 17 | "list_boot_images", | 17 | "list_boot_images", |
1263 | 18 | "is_import_boot_images_running", | 18 | "is_import_boot_images_running", |
1265 | 19 | ] | 19 | ] |
1266 | 20 | 20 | ||
1267 | 21 | import os | ||
1268 | 22 | from urlparse import urlparse | 21 | from urlparse import urlparse |
1269 | 23 | 22 | ||
1270 | 24 | from provisioningserver import concurrency | 23 | from provisioningserver import concurrency |
1271 | 25 | from provisioningserver.auth import get_maas_user_gpghome | 24 | from provisioningserver.auth import get_maas_user_gpghome |
1272 | 26 | from provisioningserver.boot import tftppath | 25 | from provisioningserver.boot import tftppath |
1274 | 27 | from provisioningserver.config import BOOT_RESOURCES_STORAGE | 26 | from provisioningserver.cluster_config import ( |
1275 | 27 | CLUSTER_CONFIG, | ||
1276 | 28 | get_config_cluster_variable, | ||
1277 | 29 | ) | ||
1278 | 28 | from provisioningserver.import_images import boot_resources | 30 | from provisioningserver.import_images import boot_resources |
1279 | 29 | from provisioningserver.utils.env import environment_variables | 31 | from provisioningserver.utils.env import environment_variables |
1280 | 30 | from provisioningserver.utils.twisted import synchronous | 32 | from provisioningserver.utils.twisted import synchronous |
1281 | @@ -41,10 +43,12 @@ | |||
1282 | 41 | of IO, as this function is called often. To update the cache call | 43 | of IO, as this function is called often. To update the cache call |
1283 | 42 | `reload_boot_images`. | 44 | `reload_boot_images`. |
1284 | 43 | """ | 45 | """ |
1285 | 46 | |||
1286 | 44 | global CACHED_BOOT_IMAGES | 47 | global CACHED_BOOT_IMAGES |
1287 | 45 | if CACHED_BOOT_IMAGES is None: | 48 | if CACHED_BOOT_IMAGES is None: |
1288 | 46 | CACHED_BOOT_IMAGES = tftppath.list_boot_images( | 49 | CACHED_BOOT_IMAGES = tftppath.list_boot_images( |
1290 | 47 | os.path.join(BOOT_RESOURCES_STORAGE, 'current')) | 50 | get_config_cluster_variable( |
1291 | 51 | CLUSTER_CONFIG.DB_boot_resources_storage)) | ||
1292 | 48 | return CACHED_BOOT_IMAGES | 52 | return CACHED_BOOT_IMAGES |
1293 | 49 | 53 | ||
1294 | 50 | 54 | ||
1295 | @@ -53,7 +57,7 @@ | |||
1296 | 53 | most up-to-date boot images list.""" | 57 | most up-to-date boot images list.""" |
1297 | 54 | global CACHED_BOOT_IMAGES | 58 | global CACHED_BOOT_IMAGES |
1298 | 55 | CACHED_BOOT_IMAGES = tftppath.list_boot_images( | 59 | CACHED_BOOT_IMAGES = tftppath.list_boot_images( |
1300 | 56 | os.path.join(BOOT_RESOURCES_STORAGE, 'current')) | 60 | get_config_cluster_variable(CLUSTER_CONFIG.DB_boot_resources_storage)) |
1301 | 57 | 61 | ||
1302 | 58 | 62 | ||
1303 | 59 | def get_hosts_from_sources(sources): | 63 | def get_hosts_from_sources(sources): |
1304 | @@ -74,7 +78,7 @@ | |||
1305 | 74 | """ | 78 | """ |
1306 | 75 | variables = { | 79 | variables = { |
1307 | 76 | 'GNUPGHOME': get_maas_user_gpghome(), | 80 | 'GNUPGHOME': get_maas_user_gpghome(), |
1309 | 77 | } | 81 | } |
1310 | 78 | if http_proxy is not None: | 82 | if http_proxy is not None: |
1311 | 79 | variables['http_proxy'] = http_proxy | 83 | variables['http_proxy'] = http_proxy |
1312 | 80 | if https_proxy is not None: | 84 | if https_proxy is not None: |
1313 | 81 | 85 | ||
1314 | === modified file 'src/provisioningserver/rpc/clusterservice.py' | |||
1315 | --- src/provisioningserver/rpc/clusterservice.py 2015-04-22 16:51:55 +0000 | |||
1316 | +++ src/provisioningserver/rpc/clusterservice.py 2015-05-04 14:27:25 +0000 | |||
1317 | @@ -7,7 +7,7 @@ | |||
1318 | 7 | absolute_import, | 7 | absolute_import, |
1319 | 8 | print_function, | 8 | print_function, |
1320 | 9 | unicode_literals, | 9 | unicode_literals, |
1322 | 10 | ) | 10 | ) |
1323 | 11 | 11 | ||
1324 | 12 | str = None | 12 | str = None |
1325 | 13 | 13 | ||
1326 | @@ -27,8 +27,8 @@ | |||
1327 | 27 | from apiclient.utils import ascii_url | 27 | from apiclient.utils import ascii_url |
1328 | 28 | from provisioningserver import concurrency | 28 | from provisioningserver import concurrency |
1329 | 29 | from provisioningserver.cluster_config import ( | 29 | from provisioningserver.cluster_config import ( |
1332 | 30 | get_cluster_uuid, | 30 | CLUSTER_CONFIG, |
1333 | 31 | get_maas_url, | 31 | get_config_cluster_variable, |
1334 | 32 | ) | 32 | ) |
1335 | 33 | from provisioningserver.drivers import ( | 33 | from provisioningserver.drivers import ( |
1336 | 34 | ArchitectureRegistry, | 34 | ArchitectureRegistry, |
1337 | @@ -137,7 +137,8 @@ | |||
1338 | 137 | Implementation of | 137 | Implementation of |
1339 | 138 | :py:class:`~provisioningserver.rpc.cluster.Identify`. | 138 | :py:class:`~provisioningserver.rpc.cluster.Identify`. |
1340 | 139 | """ | 139 | """ |
1342 | 140 | return {b"ident": get_cluster_uuid().decode("ascii")} | 140 | return {b"ident": get_config_cluster_variable( |
1343 | 141 | CLUSTER_CONFIG.DB_cluster_uuid).decode("ascii")} | ||
1344 | 141 | 142 | ||
1345 | 142 | @cluster.Authenticate.responder | 143 | @cluster.Authenticate.responder |
1346 | 143 | def authenticate(self, message): | 144 | def authenticate(self, message): |
1347 | @@ -194,8 +195,8 @@ | |||
1348 | 194 | 'architectures': [ | 195 | 'architectures': [ |
1349 | 195 | {'name': arch.name, 'description': arch.description} | 196 | {'name': arch.name, 'description': arch.description} |
1350 | 196 | for _, arch in ArchitectureRegistry | 197 | for _, arch in ArchitectureRegistry |
1353 | 197 | ], | 198 | ], |
1354 | 198 | } | 199 | } |
1355 | 199 | 200 | ||
1356 | 200 | @cluster.ListOperatingSystems.responder | 201 | @cluster.ListOperatingSystems.responder |
1357 | 201 | def list_operating_systems(self): | 202 | def list_operating_systems(self): |
1358 | @@ -258,7 +259,7 @@ | |||
1359 | 258 | osystem, interfaces, auto_interfaces, ips_mapping=ips_mapping, | 259 | osystem, interfaces, auto_interfaces, ips_mapping=ips_mapping, |
1360 | 259 | gateways_mapping=gateways_mapping, disable_ipv4=disable_ipv4, | 260 | gateways_mapping=gateways_mapping, disable_ipv4=disable_ipv4, |
1361 | 260 | nameservers=nameservers, netmasks=netmasks), | 261 | nameservers=nameservers, netmasks=netmasks), |
1363 | 261 | } | 262 | } |
1364 | 262 | 263 | ||
1365 | 263 | @cluster.PowerOn.responder | 264 | @cluster.PowerOn.responder |
1366 | 264 | def power_on(self, system_id, hostname, power_type, context): | 265 | def power_on(self, system_id, hostname, power_type, context): |
1367 | @@ -523,9 +524,9 @@ | |||
1368 | 523 | returnValue(digest == digest_local) | 524 | returnValue(digest == digest_local) |
1369 | 524 | 525 | ||
1370 | 525 | def registerWithRegion(self): | 526 | def registerWithRegion(self): |
1372 | 526 | uuid = get_cluster_uuid() | 527 | uuid = get_config_cluster_variable(CLUSTER_CONFIG.DB_cluster_uuid) |
1373 | 527 | networks = discover_networks() | 528 | networks = discover_networks() |
1375 | 528 | url = get_maas_url() | 529 | url = get_config_cluster_variable(CLUSTER_CONFIG.DB_maas_url) |
1376 | 529 | 530 | ||
1377 | 530 | def cb_register(_): | 531 | def cb_register(_): |
1378 | 531 | log.msg( | 532 | log.msg( |
1379 | @@ -660,7 +661,7 @@ | |||
1380 | 660 | scheme_ports = { | 661 | scheme_ports = { |
1381 | 661 | 'https': 443, | 662 | 'https': 443, |
1382 | 662 | 'http': 80, | 663 | 'http': 80, |
1384 | 663 | } | 664 | } |
1385 | 664 | defaultPort = scheme_ports.get(scheme, 80) | 665 | defaultPort = scheme_ports.get(scheme, 80) |
1386 | 665 | 666 | ||
1387 | 666 | if '[' in netloc: | 667 | if '[' in netloc: |
1388 | @@ -775,7 +776,7 @@ | |||
1389 | 775 | @staticmethod | 776 | @staticmethod |
1390 | 776 | def _get_rpc_info_url(): | 777 | def _get_rpc_info_url(): |
1391 | 777 | """Return the URL to the RPC infomation page on the region.""" | 778 | """Return the URL to the RPC infomation page on the region.""" |
1393 | 778 | url = urlparse(get_maas_url()) | 779 | url = urlparse(get_config_cluster_variable(CLUSTER_CONFIG.DB_maas_url)) |
1394 | 779 | url = url._replace(path="%s/rpc/" % url.path.rstrip("/")) | 780 | url = url._replace(path="%s/rpc/" % url.path.rstrip("/")) |
1395 | 780 | url = url.geturl() | 781 | url = url.geturl() |
1396 | 781 | return ascii_url(url) | 782 | return ascii_url(url) |
1397 | 782 | 783 | ||
1398 | === modified file 'src/provisioningserver/rpc/tags.py' | |||
1399 | --- src/provisioningserver/rpc/tags.py 2015-03-25 15:33:23 +0000 | |||
1400 | +++ src/provisioningserver/rpc/tags.py 2015-05-04 14:27:25 +0000 | |||
1401 | @@ -7,7 +7,7 @@ | |||
1402 | 7 | absolute_import, | 7 | absolute_import, |
1403 | 8 | print_function, | 8 | print_function, |
1404 | 9 | unicode_literals, | 9 | unicode_literals, |
1406 | 10 | ) | 10 | ) |
1407 | 11 | 11 | ||
1408 | 12 | str = None | 12 | str = None |
1409 | 13 | 13 | ||
1410 | @@ -22,13 +22,26 @@ | |||
1411 | 22 | MAASOAuth, | 22 | MAASOAuth, |
1412 | 23 | ) | 23 | ) |
1413 | 24 | from provisioningserver.cluster_config import ( | 24 | from provisioningserver.cluster_config import ( |
1416 | 25 | get_cluster_uuid, | 25 | CLUSTER_CONFIG, |
1417 | 26 | get_maas_url, | 26 | get_config_cluster_variable, |
1418 | 27 | set_config_cluster_variable, | ||
1419 | 27 | ) | 28 | ) |
1420 | 28 | from provisioningserver.tags import process_node_tags | 29 | from provisioningserver.tags import process_node_tags |
1421 | 29 | from provisioningserver.utils.twisted import synchronous | 30 | from provisioningserver.utils.twisted import synchronous |
1422 | 30 | 31 | ||
1423 | 31 | 32 | ||
1424 | 33 | def get_maas_url(): | ||
1425 | 34 | return get_config_cluster_variable(CLUSTER_CONFIG.DB_maas_url) | ||
1426 | 35 | |||
1427 | 36 | |||
1428 | 37 | def get_cluster_uuid(): | ||
1429 | 38 | return get_config_cluster_variable(CLUSTER_CONFIG.DB_cluster_uuid) | ||
1430 | 39 | |||
1431 | 40 | |||
1432 | 41 | def set_maas_url(value): | ||
1433 | 42 | return set_config_cluster_variable(CLUSTER_CONFIG.DB_maas_url, value) | ||
1434 | 43 | |||
1435 | 44 | |||
1436 | 32 | @synchronous | 45 | @synchronous |
1437 | 33 | def evaluate_tag(tag_name, tag_definition, tag_nsmap, credentials): | 46 | def evaluate_tag(tag_name, tag_definition, tag_nsmap, credentials): |
1438 | 34 | """Evaluate `tag_definition` against this cluster's nodes' details. | 47 | """Evaluate `tag_definition` against this cluster's nodes' details. |
1439 | @@ -40,7 +53,9 @@ | |||
1440 | 40 | """ | 53 | """ |
1441 | 41 | client = MAASClient( | 54 | client = MAASClient( |
1442 | 42 | auth=MAASOAuth(*credentials), dispatcher=MAASDispatcher(), | 55 | auth=MAASOAuth(*credentials), dispatcher=MAASDispatcher(), |
1444 | 43 | base_url=get_maas_url()) | 56 | base_url=get_config_cluster_variable(CLUSTER_CONFIG.DB_maas_url)) |
1445 | 44 | process_node_tags( | 57 | process_node_tags( |
1446 | 45 | tag_name=tag_name, tag_definition=tag_definition, tag_nsmap=tag_nsmap, | 58 | tag_name=tag_name, tag_definition=tag_definition, tag_nsmap=tag_nsmap, |
1448 | 46 | client=client, nodegroup_uuid=get_cluster_uuid()) | 59 | client=client, |
1449 | 60 | nodegroup_uuid=get_config_cluster_variable( | ||
1450 | 61 | CLUSTER_CONFIG.DB_cluster_uuid)) | ||
1451 | 47 | 62 | ||
1452 | === modified file 'src/provisioningserver/rpc/tests/test_boot_images.py' | |||
1453 | --- src/provisioningserver/rpc/tests/test_boot_images.py 2015-03-25 15:33:23 +0000 | |||
1454 | +++ src/provisioningserver/rpc/tests/test_boot_images.py 2015-05-04 14:27:25 +0000 | |||
1455 | @@ -7,7 +7,7 @@ | |||
1456 | 7 | absolute_import, | 7 | absolute_import, |
1457 | 8 | print_function, | 8 | print_function, |
1458 | 9 | unicode_literals, | 9 | unicode_literals, |
1460 | 10 | ) | 10 | ) |
1461 | 11 | 11 | ||
1462 | 12 | str = None | 12 | str = None |
1463 | 13 | 13 | ||
1464 | @@ -29,7 +29,10 @@ | |||
1465 | 29 | ) | 29 | ) |
1466 | 30 | from provisioningserver import concurrency | 30 | from provisioningserver import concurrency |
1467 | 31 | from provisioningserver.boot import tftppath | 31 | from provisioningserver.boot import tftppath |
1469 | 32 | from provisioningserver.config import BOOT_RESOURCES_STORAGE | 32 | from provisioningserver.cluster_config import ( |
1470 | 33 | CLUSTER_CONFIG, | ||
1471 | 34 | get_config_cluster_variable, | ||
1472 | 35 | ) | ||
1473 | 33 | from provisioningserver.import_images import boot_resources | 36 | from provisioningserver.import_images import boot_resources |
1474 | 34 | from provisioningserver.rpc import boot_images | 37 | from provisioningserver.rpc import boot_images |
1475 | 35 | from provisioningserver.rpc.boot_images import ( | 38 | from provisioningserver.rpc.boot_images import ( |
1476 | @@ -40,7 +43,10 @@ | |||
1477 | 40 | list_boot_images, | 43 | list_boot_images, |
1478 | 41 | reload_boot_images, | 44 | reload_boot_images, |
1479 | 42 | ) | 45 | ) |
1481 | 43 | from provisioningserver.testing.config import BootSourcesFixture | 46 | from provisioningserver.testing.config import ( |
1482 | 47 | BootSourcesFixture, | ||
1483 | 48 | ClusterConfigurationFixture, | ||
1484 | 49 | ) | ||
1485 | 44 | from provisioningserver.testing.testcase import PservTestCase | 50 | from provisioningserver.testing.testcase import PservTestCase |
1486 | 45 | from provisioningserver.utils.twisted import pause | 51 | from provisioningserver.utils.twisted import pause |
1487 | 46 | from testtools.matchers import Equals | 52 | from testtools.matchers import Equals |
1488 | @@ -54,16 +60,20 @@ | |||
1489 | 54 | 'http://%s:%s/images-stream/streams/v1/index.json' % ( | 60 | 'http://%s:%s/images-stream/streams/v1/index.json' % ( |
1490 | 55 | host, randint(1, 1000)) | 61 | host, randint(1, 1000)) |
1491 | 56 | for host in hosts | 62 | for host in hosts |
1493 | 57 | ] | 63 | ] |
1494 | 58 | sources = [ | 64 | sources = [ |
1495 | 59 | {'url': url, 'selections': []} | 65 | {'url': url, 'selections': []} |
1496 | 60 | for url in urls | 66 | for url in urls |
1498 | 61 | ] | 67 | ] |
1499 | 62 | return sources, hosts | 68 | return sources, hosts |
1500 | 63 | 69 | ||
1501 | 64 | 70 | ||
1502 | 65 | class TestListBootImages(PservTestCase): | 71 | class TestListBootImages(PservTestCase): |
1503 | 66 | 72 | ||
1504 | 73 | def setUp(self): | ||
1505 | 74 | super(TestListBootImages, self).setUp() | ||
1506 | 75 | self.useFixture(ClusterConfigurationFixture()) | ||
1507 | 76 | |||
1508 | 67 | def test__calls_list_boot_images_with_boot_resource_storage(self): | 77 | def test__calls_list_boot_images_with_boot_resource_storage(self): |
1509 | 68 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) | 78 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) |
1510 | 69 | mock_list_boot_images = self.patch(tftppath, 'list_boot_images') | 79 | mock_list_boot_images = self.patch(tftppath, 'list_boot_images') |
1511 | @@ -71,7 +81,8 @@ | |||
1512 | 71 | self.assertThat( | 81 | self.assertThat( |
1513 | 72 | mock_list_boot_images, | 82 | mock_list_boot_images, |
1514 | 73 | MockCalledOnceWith( | 83 | MockCalledOnceWith( |
1516 | 74 | os.path.join(BOOT_RESOURCES_STORAGE, "current"))) | 84 | get_config_cluster_variable( |
1517 | 85 | CLUSTER_CONFIG.DB_boot_resources_storage))) | ||
1518 | 75 | 86 | ||
1519 | 76 | def test__calls_list_boot_images_when_cache_is_None(self): | 87 | def test__calls_list_boot_images_when_cache_is_None(self): |
1520 | 77 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) | 88 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) |
1521 | 78 | 89 | ||
1522 | === modified file 'src/provisioningserver/rpc/tests/test_clusterservice.py' | |||
1523 | --- src/provisioningserver/rpc/tests/test_clusterservice.py 2015-04-22 16:51:55 +0000 | |||
1524 | +++ src/provisioningserver/rpc/tests/test_clusterservice.py 2015-05-04 14:27:25 +0000 | |||
1525 | @@ -7,7 +7,7 @@ | |||
1526 | 7 | absolute_import, | 7 | absolute_import, |
1527 | 8 | print_function, | 8 | print_function, |
1528 | 9 | unicode_literals, | 9 | unicode_literals, |
1530 | 10 | ) | 10 | ) |
1531 | 11 | 11 | ||
1532 | 12 | str = None | 12 | str = None |
1533 | 13 | 13 | ||
1534 | @@ -49,13 +49,12 @@ | |||
1535 | 49 | Mock, | 49 | Mock, |
1536 | 50 | sentinel, | 50 | sentinel, |
1537 | 51 | ) | 51 | ) |
1539 | 52 | from provisioningserver import concurrency | 52 | from provisioningserver import ( |
1540 | 53 | cluster_config, | ||
1541 | 54 | concurrency, | ||
1542 | 55 | ) | ||
1543 | 53 | from provisioningserver.boot import tftppath | 56 | from provisioningserver.boot import tftppath |
1544 | 54 | from provisioningserver.boot.tests.test_tftppath import make_osystem | 57 | from provisioningserver.boot.tests.test_tftppath import make_osystem |
1545 | 55 | from provisioningserver.cluster_config import ( | ||
1546 | 56 | get_cluster_uuid, | ||
1547 | 57 | get_maas_url, | ||
1548 | 58 | ) | ||
1549 | 59 | from provisioningserver.dhcp.testing.config import make_subnet_config | 58 | from provisioningserver.dhcp.testing.config import make_subnet_config |
1550 | 60 | from provisioningserver.drivers.osystem import ( | 59 | from provisioningserver.drivers.osystem import ( |
1551 | 61 | OperatingSystem, | 60 | OperatingSystem, |
1552 | @@ -106,6 +105,7 @@ | |||
1553 | 106 | StubOS, | 105 | StubOS, |
1554 | 107 | ) | 106 | ) |
1555 | 108 | from provisioningserver.security import set_shared_secret_on_filesystem | 107 | from provisioningserver.security import set_shared_secret_on_filesystem |
1556 | 108 | from provisioningserver.testing.config import ClusterConfigurationFixture | ||
1557 | 109 | from testtools import ExpectedException | 109 | from testtools import ExpectedException |
1558 | 110 | from testtools.deferredruntest import extract_result | 110 | from testtools.deferredruntest import extract_result |
1559 | 111 | from testtools.matchers import ( | 111 | from testtools.matchers import ( |
1560 | @@ -150,10 +150,11 @@ | |||
1561 | 150 | self.assertIsNotNone(responder) | 150 | self.assertIsNotNone(responder) |
1562 | 151 | 151 | ||
1563 | 152 | def test_identify_reports_cluster_uuid(self): | 152 | def test_identify_reports_cluster_uuid(self): |
1564 | 153 | self.useFixture(ClusterConfigurationFixture()) | ||
1565 | 153 | example_uuid = factory.make_UUID() | 154 | example_uuid = factory.make_UUID() |
1566 | 154 | 155 | ||
1569 | 155 | get_cluster_uuid = self.patch(clusterservice, "get_cluster_uuid") | 156 | cluster_config.set_config_cluster_variable( |
1570 | 156 | get_cluster_uuid.return_value = example_uuid | 157 | cluster_config.CLUSTER_CONFIG.DB_cluster_uuid, example_uuid) |
1571 | 157 | 158 | ||
1572 | 158 | d = call_responder(Cluster(), cluster.Identify, {}) | 159 | d = call_responder(Cluster(), cluster.Identify, {}) |
1573 | 159 | 160 | ||
1574 | @@ -239,6 +240,7 @@ | |||
1575 | 239 | 240 | ||
1576 | 240 | @inlineCallbacks | 241 | @inlineCallbacks |
1577 | 241 | def test_list_boot_images_with_things_to_report(self): | 242 | def test_list_boot_images_with_things_to_report(self): |
1578 | 243 | self.useFixture(ClusterConfigurationFixture()) | ||
1579 | 242 | # tftppath.list_boot_images()'s return value matches the | 244 | # tftppath.list_boot_images()'s return value matches the |
1580 | 243 | # response schema that ListBootImages declares, and is | 245 | # response schema that ListBootImages declares, and is |
1581 | 244 | # serialised correctly. | 246 | # serialised correctly. |
1582 | @@ -258,7 +260,11 @@ | |||
1583 | 258 | for options in product(osystems, archs, subarchs, releases, labels): | 260 | for options in product(osystems, archs, subarchs, releases, labels): |
1584 | 259 | os.makedirs(os.path.join(current_dir, *options)) | 261 | os.makedirs(os.path.join(current_dir, *options)) |
1585 | 260 | make_osystem(self, options[0], purposes) | 262 | make_osystem(self, options[0], purposes) |
1587 | 261 | self.patch(boot_images, 'BOOT_RESOURCES_STORAGE', tftpdir) | 263 | |
1588 | 264 | cluster_config.set_config_cluster_variable( | ||
1589 | 265 | cluster_config.CLUSTER_CONFIG.DB_tftp_resource_root, | ||
1590 | 266 | os.path.join(tftpdir, 'current/')) | ||
1591 | 267 | |||
1592 | 262 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) | 268 | self.patch(boot_images, 'CACHED_BOOT_IMAGES', None) |
1593 | 263 | 269 | ||
1594 | 264 | expected_images = [ | 270 | expected_images = [ |
1595 | @@ -272,7 +278,7 @@ | |||
1596 | 272 | } | 278 | } |
1597 | 273 | for osystem, arch, subarch, release, label, purpose in product( | 279 | for osystem, arch, subarch, release, label, purpose in product( |
1598 | 274 | osystems, archs, subarchs, releases, labels, purposes) | 280 | osystems, archs, subarchs, releases, labels, purposes) |
1600 | 275 | ] | 281 | ] |
1601 | 276 | for expected_image in expected_images: | 282 | for expected_image in expected_images: |
1602 | 277 | if expected_image['purpose'] == 'xinstall': | 283 | if expected_image['purpose'] == 'xinstall': |
1603 | 278 | expected_image['xinstall_path'] = 'root-tgz' | 284 | expected_image['xinstall_path'] = 'root-tgz' |
1604 | @@ -343,7 +349,7 @@ | |||
1605 | 343 | 'sources': [], | 349 | 'sources': [], |
1606 | 344 | 'http_proxy': parsed_proxy, | 350 | 'http_proxy': parsed_proxy, |
1607 | 345 | 'https_proxy': parsed_proxy, | 351 | 'https_proxy': parsed_proxy, |
1609 | 346 | }) | 352 | }) |
1610 | 347 | 353 | ||
1611 | 348 | self.assertThat( | 354 | self.assertThat( |
1612 | 349 | import_boot_images, | 355 | import_boot_images, |
1613 | @@ -465,9 +471,13 @@ | |||
1614 | 465 | self.assertThat(service.clock, Is(sentinel.reactor)) | 471 | self.assertThat(service.clock, Is(sentinel.reactor)) |
1615 | 466 | 472 | ||
1616 | 467 | def test__get_rpc_info_url(self): | 473 | def test__get_rpc_info_url(self): |
1617 | 474 | self.useFixture(ClusterConfigurationFixture()) | ||
1618 | 475 | |||
1619 | 468 | maas_url = "http://%s/%s/" % ( | 476 | maas_url = "http://%s/%s/" % ( |
1620 | 469 | factory.make_hostname(), factory.make_name("path")) | 477 | factory.make_hostname(), factory.make_name("path")) |
1622 | 470 | self.useFixture(EnvironmentVariable("MAAS_URL", maas_url)) | 478 | cluster_config.set_config_cluster_variable( |
1623 | 479 | cluster_config.CLUSTER_CONFIG.DB_maas_url, | ||
1624 | 480 | maas_url) | ||
1625 | 471 | expected_rpc_info_url = maas_url + "rpc/" | 481 | expected_rpc_info_url = maas_url + "rpc/" |
1626 | 472 | observed_rpc_info_url = ClusterClientService._get_rpc_info_url() | 482 | observed_rpc_info_url = ClusterClientService._get_rpc_info_url() |
1627 | 473 | self.assertThat(observed_rpc_info_url, Equals(expected_rpc_info_url)) | 483 | self.assertThat(observed_rpc_info_url, Equals(expected_rpc_info_url)) |
1628 | @@ -1199,15 +1209,18 @@ | |||
1629 | 1199 | 1209 | ||
1630 | 1200 | @inlineCallbacks | 1210 | @inlineCallbacks |
1631 | 1201 | def test_registerWithRegion_end_to_end(self): | 1211 | def test_registerWithRegion_end_to_end(self): |
1632 | 1212 | self.useFixture(ClusterConfigurationFixture()) | ||
1633 | 1202 | fixture = self.useFixture(MockLiveClusterToRegionRPCFixture()) | 1213 | fixture = self.useFixture(MockLiveClusterToRegionRPCFixture()) |
1634 | 1203 | protocol, connecting = fixture.makeEventLoop() | 1214 | protocol, connecting = fixture.makeEventLoop() |
1635 | 1204 | self.addCleanup((yield connecting)) | 1215 | self.addCleanup((yield connecting)) |
1636 | 1205 | yield getRegionClient() | 1216 | yield getRegionClient() |
1637 | 1206 | self.assertThat( | 1217 | self.assertThat( |
1638 | 1207 | protocol.Register, MockCalledOnceWith( | 1218 | protocol.Register, MockCalledOnceWith( |
1640 | 1208 | protocol, uuid=get_cluster_uuid(), | 1219 | protocol, uuid=cluster_config.get_config_cluster_variable( |
1641 | 1220 | cluster_config.CLUSTER_CONFIG.DB_cluster_uuid), | ||
1642 | 1209 | networks=discover_networks(), | 1221 | networks=discover_networks(), |
1644 | 1210 | url=urlparse(get_maas_url()))) | 1222 | url=urlparse(cluster_config.get_config_cluster_variable( |
1645 | 1223 | cluster_config.CLUSTER_CONFIG.DB_maas_url)))) | ||
1646 | 1211 | 1224 | ||
1647 | 1212 | 1225 | ||
1648 | 1213 | class TestClusterProtocol_ListSupportedArchitectures(MAASTestCase): | 1226 | class TestClusterProtocol_ListSupportedArchitectures(MAASTestCase): |
1649 | @@ -1438,9 +1451,9 @@ | |||
1650 | 1438 | 'ips_mapping': {mac: [factory.make_ipv4_address()]}, | 1451 | 'ips_mapping': {mac: [factory.make_ipv4_address()]}, |
1651 | 1439 | 'gateways_mapping': {mac: [factory.make_ipv4_address()]}, | 1452 | 'gateways_mapping': {mac: [factory.make_ipv4_address()]}, |
1652 | 1440 | 'nameservers': [], | 1453 | 'nameservers': [], |
1654 | 1441 | }, | 1454 | }, |
1655 | 1442 | 'disable_ipv4': factory.pick_bool(), | 1455 | 'disable_ipv4': factory.pick_bool(), |
1657 | 1443 | } | 1456 | } |
1658 | 1444 | 1457 | ||
1659 | 1445 | def test__is_registered(self): | 1458 | def test__is_registered(self): |
1660 | 1446 | protocol = Cluster() | 1459 | protocol = Cluster() |
1661 | @@ -1654,7 +1667,7 @@ | |||
1662 | 1654 | yield call_responder(Cluster(), self.command, { | 1667 | yield call_responder(Cluster(), self.command, { |
1663 | 1655 | 'omapi_key': omapi_key, | 1668 | 'omapi_key': omapi_key, |
1664 | 1656 | 'subnet_configs': subnet_configs, | 1669 | 'subnet_configs': subnet_configs, |
1666 | 1657 | }) | 1670 | }) |
1667 | 1658 | 1671 | ||
1668 | 1659 | self.assertThat(DHCPServer, MockCalledOnceWith(omapi_key)) | 1672 | self.assertThat(DHCPServer, MockCalledOnceWith(omapi_key)) |
1669 | 1660 | self.assertThat(configure, MockCalledOnceWith( | 1673 | self.assertThat(configure, MockCalledOnceWith( |
1670 | @@ -1675,7 +1688,7 @@ | |||
1671 | 1675 | yield call_responder(Cluster(), self.command, { | 1688 | yield call_responder(Cluster(), self.command, { |
1672 | 1676 | 'omapi_key': factory.make_name('key'), | 1689 | 'omapi_key': factory.make_name('key'), |
1673 | 1677 | 'subnet_configs': [], | 1690 | 'subnet_configs': [], |
1675 | 1678 | }) | 1691 | }) |
1676 | 1679 | self.assertFalse(concurrency.dhcp.locked) | 1692 | self.assertFalse(concurrency.dhcp.locked) |
1677 | 1680 | 1693 | ||
1678 | 1681 | @inlineCallbacks | 1694 | @inlineCallbacks |
1679 | @@ -1692,7 +1705,7 @@ | |||
1680 | 1692 | yield call_responder(Cluster(), self.command, { | 1705 | yield call_responder(Cluster(), self.command, { |
1681 | 1693 | 'omapi_key': omapi_key, | 1706 | 'omapi_key': omapi_key, |
1682 | 1694 | 'subnet_configs': subnet_configs, | 1707 | 'subnet_configs': subnet_configs, |
1684 | 1695 | }) | 1708 | }) |
1685 | 1696 | 1709 | ||
1686 | 1697 | 1710 | ||
1687 | 1698 | class TestClusterProtocol_CreateHostMaps(MAASTestCase): | 1711 | class TestClusterProtocol_CreateHostMaps(MAASTestCase): |
1688 | @@ -1905,7 +1918,7 @@ | |||
1689 | 1905 | "password": password, | 1918 | "password": password, |
1690 | 1906 | "prefix_filter": prefix_filter, | 1919 | "prefix_filter": prefix_filter, |
1691 | 1907 | "accept_all": True, | 1920 | "accept_all": True, |
1693 | 1908 | }) | 1921 | }) |
1694 | 1909 | self.assertThat( | 1922 | self.assertThat( |
1695 | 1910 | mock_deferToThread, MockCalledOnceWith( | 1923 | mock_deferToThread, MockCalledOnceWith( |
1696 | 1911 | clusterservice.probe_virsh_and_enlist, | 1924 | clusterservice.probe_virsh_and_enlist, |
1697 | @@ -1923,7 +1936,7 @@ | |||
1698 | 1923 | "password": None, | 1936 | "password": None, |
1699 | 1924 | "prefix_filter": prefix_filter, | 1937 | "prefix_filter": prefix_filter, |
1700 | 1925 | "accept_all": True, | 1938 | "accept_all": True, |
1702 | 1926 | }) | 1939 | }) |
1703 | 1927 | self.assertThat( | 1940 | self.assertThat( |
1704 | 1928 | mock_deferToThread, MockCalledOnceWith( | 1941 | mock_deferToThread, MockCalledOnceWith( |
1705 | 1929 | clusterservice.probe_virsh_and_enlist, | 1942 | clusterservice.probe_virsh_and_enlist, |
1706 | @@ -1940,7 +1953,7 @@ | |||
1707 | 1940 | "poweraddr": poweraddr, | 1953 | "poweraddr": poweraddr, |
1708 | 1941 | "prefix_filter": prefix_filter, | 1954 | "prefix_filter": prefix_filter, |
1709 | 1942 | "accept_all": True, | 1955 | "accept_all": True, |
1711 | 1943 | }) | 1956 | }) |
1712 | 1944 | self.assertThat( | 1957 | self.assertThat( |
1713 | 1945 | mock_deferToThread, MockCalledOnceWith( | 1958 | mock_deferToThread, MockCalledOnceWith( |
1714 | 1946 | clusterservice.probe_virsh_and_enlist, | 1959 | clusterservice.probe_virsh_and_enlist, |
1715 | @@ -1962,7 +1975,7 @@ | |||
1716 | 1962 | "password": password, | 1975 | "password": password, |
1717 | 1963 | "prefix_filter": prefix_filter, | 1976 | "prefix_filter": prefix_filter, |
1718 | 1964 | "accept_all": True, | 1977 | "accept_all": True, |
1720 | 1965 | }) | 1978 | }) |
1721 | 1966 | self.assertThat( | 1979 | self.assertThat( |
1722 | 1967 | clusterservice.maaslog.error, | 1980 | clusterservice.maaslog.error, |
1723 | 1968 | MockAnyCall( | 1981 | MockAnyCall( |
1724 | @@ -1998,7 +2011,7 @@ | |||
1725 | 1998 | "protocol": protocol, | 2011 | "protocol": protocol, |
1726 | 1999 | "prefix_filter": prefix_filter, | 2012 | "prefix_filter": prefix_filter, |
1727 | 2000 | "accept_all": True, | 2013 | "accept_all": True, |
1729 | 2001 | }) | 2014 | }) |
1730 | 2002 | self.assertThat( | 2015 | self.assertThat( |
1731 | 2003 | mock_deferToThread, MockCalledOnceWith( | 2016 | mock_deferToThread, MockCalledOnceWith( |
1732 | 2004 | clusterservice.probe_vsphere_and_enlist, | 2017 | clusterservice.probe_vsphere_and_enlist, |
1733 | @@ -2024,7 +2037,7 @@ | |||
1734 | 2024 | "protocol": None, | 2037 | "protocol": None, |
1735 | 2025 | "prefix_filter": prefix_filter, | 2038 | "prefix_filter": prefix_filter, |
1736 | 2026 | "accept_all": True, | 2039 | "accept_all": True, |
1738 | 2027 | }) | 2040 | }) |
1739 | 2028 | self.assertThat( | 2041 | self.assertThat( |
1740 | 2029 | mock_deferToThread, MockCalledOnceWith( | 2042 | mock_deferToThread, MockCalledOnceWith( |
1741 | 2030 | clusterservice.probe_vsphere_and_enlist, | 2043 | clusterservice.probe_vsphere_and_enlist, |
1742 | @@ -2049,7 +2062,7 @@ | |||
1743 | 2049 | "password": password, | 2062 | "password": password, |
1744 | 2050 | "prefix_filter": prefix_filter, | 2063 | "prefix_filter": prefix_filter, |
1745 | 2051 | "accept_all": True, | 2064 | "accept_all": True, |
1747 | 2052 | }) | 2065 | }) |
1748 | 2053 | self.assertThat( | 2066 | self.assertThat( |
1749 | 2054 | mock_deferToThread, MockCalledOnceWith( | 2067 | mock_deferToThread, MockCalledOnceWith( |
1750 | 2055 | clusterservice.probe_vsphere_and_enlist, | 2068 | clusterservice.probe_vsphere_and_enlist, |
1751 | @@ -2076,7 +2089,7 @@ | |||
1752 | 2076 | "password": password, | 2089 | "password": password, |
1753 | 2077 | "prefix_filter": prefix_filter, | 2090 | "prefix_filter": prefix_filter, |
1754 | 2078 | "accept_all": True, | 2091 | "accept_all": True, |
1756 | 2079 | }) | 2092 | }) |
1757 | 2080 | 2093 | ||
1758 | 2081 | self.assertThat( | 2094 | self.assertThat( |
1759 | 2082 | clusterservice.maaslog.error, | 2095 | clusterservice.maaslog.error, |
1760 | @@ -2108,7 +2121,7 @@ | |||
1761 | 2108 | "password": password, | 2121 | "password": password, |
1762 | 2109 | "prefix_filter": prefix_filter, | 2122 | "prefix_filter": prefix_filter, |
1763 | 2110 | "accept_all": True, | 2123 | "accept_all": True, |
1765 | 2111 | }) | 2124 | }) |
1766 | 2112 | self.assertThat( | 2125 | self.assertThat( |
1767 | 2113 | mock_deferToThread, MockCalledOnceWith( | 2126 | mock_deferToThread, MockCalledOnceWith( |
1768 | 2114 | clusterservice.probe_esxi_and_enlist, | 2127 | clusterservice.probe_esxi_and_enlist, |
1769 | @@ -2133,7 +2146,7 @@ | |||
1770 | 2133 | "password": password, | 2146 | "password": password, |
1771 | 2134 | "prefix_filter": prefix_filter, | 2147 | "prefix_filter": prefix_filter, |
1772 | 2135 | "accept_all": True, | 2148 | "accept_all": True, |
1774 | 2136 | }) | 2149 | }) |
1775 | 2137 | self.assertThat( | 2150 | self.assertThat( |
1776 | 2138 | clusterservice.maaslog.error, | 2151 | clusterservice.maaslog.error, |
1777 | 2139 | MockAnyCall( | 2152 | MockAnyCall( |
1778 | @@ -2169,7 +2182,7 @@ | |||
1779 | 2169 | "password": password, | 2182 | "password": password, |
1780 | 2170 | "power_control": power_control, | 2183 | "power_control": power_control, |
1781 | 2171 | "accept_all": True, | 2184 | "accept_all": True, |
1783 | 2172 | }) | 2185 | }) |
1784 | 2173 | 2186 | ||
1785 | 2174 | self.assertThat( | 2187 | self.assertThat( |
1786 | 2175 | find_ip_via_arp, MockCalledOnceWith(mac)) | 2188 | find_ip_via_arp, MockCalledOnceWith(mac)) |
1787 | @@ -2195,7 +2208,7 @@ | |||
1788 | 2195 | "password": password, | 2208 | "password": password, |
1789 | 2196 | "power_control": power_control, | 2209 | "power_control": power_control, |
1790 | 2197 | "accept_all": True, | 2210 | "accept_all": True, |
1792 | 2198 | }) | 2211 | }) |
1793 | 2199 | 2212 | ||
1794 | 2200 | self.assertThat( | 2213 | self.assertThat( |
1795 | 2201 | maaslog.warning, | 2214 | maaslog.warning, |
1796 | @@ -2221,7 +2234,7 @@ | |||
1797 | 2221 | "password": password, | 2234 | "password": password, |
1798 | 2222 | "power_control": power_control, | 2235 | "power_control": power_control, |
1799 | 2223 | "accept_all": True, | 2236 | "accept_all": True, |
1801 | 2224 | }) | 2237 | }) |
1802 | 2225 | 2238 | ||
1803 | 2226 | self.assertThat( | 2239 | self.assertThat( |
1804 | 2227 | mock_deferToThread, MockCalledOnceWith( | 2240 | mock_deferToThread, MockCalledOnceWith( |
1805 | @@ -2251,7 +2264,7 @@ | |||
1806 | 2251 | "password": password, | 2264 | "password": password, |
1807 | 2252 | "power_control": power_control, | 2265 | "power_control": power_control, |
1808 | 2253 | "accept_all": True, | 2266 | "accept_all": True, |
1810 | 2254 | }) | 2267 | }) |
1811 | 2255 | self.assertThat( | 2268 | self.assertThat( |
1812 | 2256 | clusterservice.maaslog.error, | 2269 | clusterservice.maaslog.error, |
1813 | 2257 | MockAnyCall( | 2270 | MockAnyCall( |
1814 | 2258 | 2271 | ||
1815 | === modified file 'src/provisioningserver/rpc/tests/test_tags.py' | |||
1816 | --- src/provisioningserver/rpc/tests/test_tags.py 2015-03-25 15:33:23 +0000 | |||
1817 | +++ src/provisioningserver/rpc/tests/test_tags.py 2015-05-04 14:27:25 +0000 | |||
1818 | @@ -7,13 +7,14 @@ | |||
1819 | 7 | absolute_import, | 7 | absolute_import, |
1820 | 8 | print_function, | 8 | print_function, |
1821 | 9 | unicode_literals, | 9 | unicode_literals, |
1823 | 10 | ) | 10 | ) |
1824 | 11 | 11 | ||
1825 | 12 | str = None | 12 | str = None |
1826 | 13 | 13 | ||
1827 | 14 | __metaclass__ = type | 14 | __metaclass__ = type |
1828 | 15 | __all__ = [] | 15 | __all__ = [] |
1829 | 16 | 16 | ||
1830 | 17 | |||
1831 | 17 | from apiclient.maas_client import ( | 18 | from apiclient.maas_client import ( |
1832 | 18 | MAASClient, | 19 | MAASClient, |
1833 | 19 | MAASDispatcher, | 20 | MAASDispatcher, |
1834 | @@ -26,17 +27,25 @@ | |||
1835 | 26 | ANY, | 27 | ANY, |
1836 | 27 | sentinel, | 28 | sentinel, |
1837 | 28 | ) | 29 | ) |
1838 | 30 | from provisioningserver import cluster_config | ||
1839 | 29 | from provisioningserver.rpc import tags | 31 | from provisioningserver.rpc import tags |
1840 | 32 | from provisioningserver.testing.config import ClusterConfigurationFixture | ||
1841 | 30 | 33 | ||
1842 | 31 | 34 | ||
1843 | 32 | class TestEvaluateTag(MAASTestCase): | 35 | class TestEvaluateTag(MAASTestCase): |
1844 | 33 | 36 | ||
1845 | 34 | def setUp(self): | 37 | def setUp(self): |
1846 | 35 | super(TestEvaluateTag, self).setUp() | 38 | super(TestEvaluateTag, self).setUp() |
1851 | 36 | get_maas_url = self.patch_autospec(tags, "get_maas_url") | 39 | self.useFixture(ClusterConfigurationFixture()) |
1852 | 37 | get_maas_url.return_value = sentinel.maas_url | 40 | |
1853 | 38 | get_cluster_uuid = self.patch_autospec(tags, "get_cluster_uuid") | 41 | self.mock_cluster_uuid = factory.make_UUID() |
1854 | 39 | get_cluster_uuid.return_value = sentinel.cluster_uuid | 42 | self.mock_url = factory.make_simple_http_url() |
1855 | 43 | |||
1856 | 44 | cluster_config.set_config_cluster_variable( | ||
1857 | 45 | cluster_config.CLUSTER_CONFIG.DB_cluster_uuid, | ||
1858 | 46 | self.mock_cluster_uuid) | ||
1859 | 47 | cluster_config.set_config_cluster_variable( | ||
1860 | 48 | cluster_config.CLUSTER_CONFIG.DB_maas_url, self.mock_url) | ||
1861 | 40 | 49 | ||
1862 | 41 | def test__calls_process_node_tags(self): | 50 | def test__calls_process_node_tags(self): |
1863 | 42 | credentials = "aaa", "bbb", "ccc" | 51 | credentials = "aaa", "bbb", "ccc" |
1864 | @@ -49,7 +58,7 @@ | |||
1865 | 49 | tag_name=sentinel.tag_name, | 58 | tag_name=sentinel.tag_name, |
1866 | 50 | tag_definition=sentinel.tag_definition, | 59 | tag_definition=sentinel.tag_definition, |
1867 | 51 | tag_nsmap=sentinel.tag_nsmap, client=ANY, | 60 | tag_nsmap=sentinel.tag_nsmap, client=ANY, |
1869 | 52 | nodegroup_uuid=sentinel.cluster_uuid)) | 61 | nodegroup_uuid=self.mock_cluster_uuid)) |
1870 | 53 | 62 | ||
1871 | 54 | def test__constructs_client_with_credentials(self): | 63 | def test__constructs_client_with_credentials(self): |
1872 | 55 | consumer_key = factory.make_name("ckey") | 64 | consumer_key = factory.make_name("ckey") |
1873 | @@ -66,7 +75,7 @@ | |||
1874 | 66 | 75 | ||
1875 | 67 | client = tags.process_node_tags.call_args[1]["client"] | 76 | client = tags.process_node_tags.call_args[1]["client"] |
1876 | 68 | self.assertIsInstance(client, MAASClient) | 77 | self.assertIsInstance(client, MAASClient) |
1878 | 69 | self.assertEqual(sentinel.maas_url, client.url) | 78 | self.assertEqual(self.mock_url, client.url) |
1879 | 70 | self.assertIsInstance(client.dispatcher, MAASDispatcher) | 79 | self.assertIsInstance(client.dispatcher, MAASDispatcher) |
1880 | 71 | self.assertIsInstance(client.auth, MAASOAuth) | 80 | self.assertIsInstance(client.auth, MAASOAuth) |
1881 | 72 | self.assertThat(tags.MAASOAuth, MockCalledOnceWith( | 81 | self.assertThat(tags.MAASOAuth, MockCalledOnceWith( |
1882 | 73 | 82 | ||
1883 | === modified file 'src/provisioningserver/tests/test_cluster_config.py' | |||
1884 | --- src/provisioningserver/tests/test_cluster_config.py 2015-03-25 15:33:23 +0000 | |||
1885 | +++ src/provisioningserver/tests/test_cluster_config.py 2015-05-04 14:27:25 +0000 | |||
1886 | @@ -7,42 +7,83 @@ | |||
1887 | 7 | absolute_import, | 7 | absolute_import, |
1888 | 8 | print_function, | 8 | print_function, |
1889 | 9 | unicode_literals, | 9 | unicode_literals, |
1891 | 10 | ) | 10 | ) |
1892 | 11 | 11 | ||
1893 | 12 | str = None | 12 | str = None |
1894 | 13 | 13 | ||
1895 | 14 | __metaclass__ = type | 14 | __metaclass__ = type |
1896 | 15 | __all__ = [] | 15 | __all__ = [] |
1897 | 16 | 16 | ||
1899 | 17 | from fixtures import EnvironmentVariableFixture | 17 | import os |
1900 | 18 | |||
1901 | 18 | from maastesting.factory import factory | 19 | from maastesting.factory import factory |
1902 | 19 | from maastesting.testcase import MAASTestCase | 20 | from maastesting.testcase import MAASTestCase |
1932 | 20 | from provisioningserver.cluster_config import ( | 21 | from provisioningserver import cluster_config |
1933 | 21 | get_cluster_uuid, | 22 | from provisioningserver.config import UUID_NOT_SET |
1934 | 22 | get_cluster_variable, | 23 | from provisioningserver.testing.config import ClusterConfigurationFixture |
1935 | 23 | get_maas_url, | 24 | |
1936 | 24 | ) | 25 | |
1937 | 25 | 26 | class TestClusterConfigTFTPGenerator(MAASTestCase): | |
1938 | 26 | 27 | """Tests for the get_tftp_generator() function.""" | |
1939 | 27 | class TestClusterConfig(MAASTestCase): | 28 | |
1940 | 28 | 29 | def test_get_tftp_generator(self): | |
1941 | 29 | def test_get_cluster_variable_reads_env(self): | 30 | self.useFixture(ClusterConfigurationFixture()) |
1942 | 30 | var = factory.make_name('variable') | 31 | random_path = factory.make_simple_http_url() |
1943 | 31 | value = factory.make_name('value') | 32 | cluster_config.set_config_cluster_variable( |
1944 | 32 | self.useFixture(EnvironmentVariableFixture(var, value)) | 33 | cluster_config.CLUSTER_CONFIG.DB_maas_url, random_path) |
1945 | 33 | self.assertEqual(value, get_cluster_variable(var)) | 34 | |
1946 | 34 | 35 | observed = cluster_config.get_tftp_generator() | |
1947 | 35 | def test_get_cluster_variable_fails_if_not_set(self): | 36 | expected = os.path.join(random_path, 'api', '1.0', 'pxeconfig') |
1948 | 36 | self.assertRaises( | 37 | self.assertEqual(observed, expected) |
1949 | 37 | AssertionError, | 38 | |
1950 | 38 | get_cluster_variable, factory.make_name('nonexistent-variable')) | 39 | |
1951 | 39 | 40 | class TestClusterConfigDatabaseOptions(MAASTestCase): | |
1952 | 40 | def test_get_cluster_uuid_reads_CLUSTER_UUID(self): | 41 | """Tests for the database options in `cluster_config`.""" |
1953 | 41 | uuid = factory.make_name('uuid') | 42 | |
1954 | 42 | self.useFixture(EnvironmentVariableFixture('CLUSTER_UUID', uuid)) | 43 | def setUp(self): |
1955 | 43 | self.assertEqual(uuid, get_cluster_uuid()) | 44 | super(TestClusterConfigDatabaseOptions, self).setUp() |
1956 | 44 | 45 | self.useFixture(ClusterConfigurationFixture()) | |
1957 | 45 | def test_get_maas_url_reads_MAAS_URL(self): | 46 | |
1958 | 46 | maas_url = factory.make_name('maas_url') | 47 | options_and_defaults = { |
1959 | 47 | self.useFixture(EnvironmentVariableFixture('MAAS_URL', maas_url)) | 48 | cluster_config.CLUSTER_CONFIG.DB_cluster_uuid: UUID_NOT_SET, |
1960 | 48 | self.assertEqual(maas_url, get_maas_url()) | 49 | cluster_config.CLUSTER_CONFIG.DB_maas_url: |
1961 | 50 | "http://localhost:5240/MAAS", | ||
1962 | 51 | cluster_config.CLUSTER_CONFIG.DB_tftp_resource_root: | ||
1963 | 52 | "/var/lib/maas/boot-resources/current/", | ||
1964 | 53 | cluster_config.CLUSTER_CONFIG.DB_boot_resources_storage: | ||
1965 | 54 | "/var/lib/maas/boot-resources/current/", | ||
1966 | 55 | cluster_config.CLUSTER_CONFIG.DB_tftpport: 69, | ||
1967 | 56 | } | ||
1968 | 57 | |||
1969 | 58 | scenarios = tuple( | ||
1970 | 59 | (name, {"option": name, "default": default}) | ||
1971 | 60 | for name, default in options_and_defaults.viewitems() | ||
1972 | 61 | ) | ||
1973 | 62 | |||
1974 | 63 | def test__default(self): | ||
1975 | 64 | self.assertEqual( | ||
1976 | 65 | self.default, | ||
1977 | 66 | cluster_config.get_config_cluster_variable(self.option)) | ||
1978 | 67 | |||
1979 | 68 | def test__set_and_get(self): | ||
1980 | 69 | # NOTE: test_values cannot be a class attribute factory | ||
1981 | 70 | # since make_dir() requires a reference to 'self' for the | ||
1982 | 71 | # TempDirectory fixture. | ||
1983 | 72 | test_values = { | ||
1984 | 73 | cluster_config.CLUSTER_CONFIG.DB_cluster_uuid: factory.make_UUID(), | ||
1985 | 74 | cluster_config.CLUSTER_CONFIG.DB_maas_url: | ||
1986 | 75 | factory.make_simple_http_url(), | ||
1987 | 76 | cluster_config.CLUSTER_CONFIG.DB_tftp_resource_root: | ||
1988 | 77 | self.make_dir(), | ||
1989 | 78 | cluster_config.CLUSTER_CONFIG.DB_boot_resources_storage: | ||
1990 | 79 | self.make_dir(), | ||
1991 | 80 | cluster_config.CLUSTER_CONFIG.DB_tftpport: factory.pick_port(), | ||
1992 | 81 | } | ||
1993 | 82 | |||
1994 | 83 | example_value = test_values[self.option] | ||
1995 | 84 | |||
1996 | 85 | cluster_config.set_config_cluster_variable(self.option, example_value) | ||
1997 | 86 | |||
1998 | 87 | self.assertEqual(example_value, | ||
1999 | 88 | cluster_config.get_config_cluster_variable( | ||
2000 | 89 | self.option)) | ||
2001 | 49 | 90 | ||
2002 | === modified file 'src/provisioningserver/tests/test_config.py' | |||
2003 | --- src/provisioningserver/tests/test_config.py 2015-05-04 14:27:25 +0000 | |||
2004 | +++ src/provisioningserver/tests/test_config.py 2015-05-04 14:27:25 +0000 | |||
2005 | @@ -15,24 +15,17 @@ | |||
2006 | 15 | __all__ = [] | 15 | __all__ = [] |
2007 | 16 | 16 | ||
2008 | 17 | import contextlib | 17 | import contextlib |
2009 | 18 | from copy import deepcopy | ||
2010 | 19 | import errno | ||
2011 | 20 | from functools import partial | ||
2012 | 21 | from getpass import getuser | ||
2013 | 22 | from io import BytesIO | ||
2014 | 23 | from operator import methodcaller | 18 | from operator import methodcaller |
2015 | 24 | import os.path | 19 | import os.path |
2016 | 25 | import random | 20 | import random |
2017 | 26 | import re | 21 | import re |
2018 | 27 | import sqlite3 | 22 | import sqlite3 |
2019 | 28 | from textwrap import dedent | ||
2020 | 29 | from uuid import uuid4 | 23 | from uuid import uuid4 |
2021 | 30 | 24 | ||
2022 | 31 | from fixtures import EnvironmentVariableFixture | 25 | from fixtures import EnvironmentVariableFixture |
2023 | 32 | import formencode | 26 | import formencode |
2024 | 33 | import formencode.validators | 27 | import formencode.validators |
2025 | 34 | from formencode.validators import Invalid | 28 | from formencode.validators import Invalid |
2026 | 35 | from maastesting import root | ||
2027 | 36 | from maastesting.factory import factory | 29 | from maastesting.factory import factory |
2028 | 37 | from maastesting.matchers import ( | 30 | from maastesting.matchers import ( |
2029 | 38 | MockCalledOnceWith, | 31 | MockCalledOnceWith, |
2030 | @@ -41,11 +34,7 @@ | |||
2031 | 41 | from maastesting.testcase import MAASTestCase | 34 | from maastesting.testcase import MAASTestCase |
2032 | 42 | from mock import sentinel | 35 | from mock import sentinel |
2033 | 43 | from provisioningserver.config import ( | 36 | from provisioningserver.config import ( |
2034 | 44 | BootSources, | ||
2035 | 45 | ClusterConfiguration, | 37 | ClusterConfiguration, |
2036 | 46 | Config, | ||
2037 | 47 | ConfigBase, | ||
2038 | 48 | ConfigMeta, | ||
2039 | 49 | Configuration, | 38 | Configuration, |
2040 | 50 | ConfigurationDatabase, | 39 | ConfigurationDatabase, |
2041 | 51 | ConfigurationFile, | 40 | ConfigurationFile, |
2042 | @@ -56,17 +45,13 @@ | |||
2043 | 56 | UUID, | 45 | UUID, |
2044 | 57 | ) | 46 | ) |
2045 | 58 | from provisioningserver.path import get_path | 47 | from provisioningserver.path import get_path |
2046 | 59 | from provisioningserver.testing.config import ConfigFixtureBase | ||
2047 | 60 | from provisioningserver.utils.fs import FileLockProxy | 48 | from provisioningserver.utils.fs import FileLockProxy |
2048 | 61 | from testtools import ExpectedException | 49 | from testtools import ExpectedException |
2049 | 62 | from testtools.matchers import ( | 50 | from testtools.matchers import ( |
2050 | 63 | DirExists, | ||
2051 | 64 | FileContains, | 51 | FileContains, |
2052 | 65 | FileExists, | 52 | FileExists, |
2053 | 66 | Is, | 53 | Is, |
2054 | 67 | MatchesException, | ||
2055 | 68 | MatchesStructure, | 54 | MatchesStructure, |
2056 | 69 | Raises, | ||
2057 | 70 | ) | 55 | ) |
2058 | 71 | from twisted.python.filepath import FilePath | 56 | from twisted.python.filepath import FilePath |
2059 | 72 | import yaml | 57 | import yaml |
2060 | @@ -224,444 +209,6 @@ | |||
2061 | 224 | "url: %s" % url) | 209 | "url: %s" % url) |
2062 | 225 | 210 | ||
2063 | 226 | 211 | ||
2064 | 227 | class ExampleConfig(ConfigBase, formencode.Schema): | ||
2065 | 228 | """An example configuration schema. | ||
2066 | 229 | |||
2067 | 230 | It derives from :class:`ConfigBase` and has a metaclass derived from | ||
2068 | 231 | :class:`ConfigMeta`, just as a "real" schema must. | ||
2069 | 232 | """ | ||
2070 | 233 | |||
2071 | 234 | class __metaclass__(ConfigMeta): | ||
2072 | 235 | envvar = "MAAS_TESTING_SETTINGS" | ||
2073 | 236 | default = "example.yaml" | ||
2074 | 237 | |||
2075 | 238 | something = formencode.validators.String(if_missing="*missing*") | ||
2076 | 239 | |||
2077 | 240 | |||
2078 | 241 | class ExampleConfigFixture(ConfigFixtureBase): | ||
2079 | 242 | """A fixture to help with testing :class:`ExampleConfig`.""" | ||
2080 | 243 | |||
2081 | 244 | schema = ExampleConfig | ||
2082 | 245 | |||
2083 | 246 | |||
2084 | 247 | class TestConfigFixtureBase(MAASTestCase): | ||
2085 | 248 | """Tests for `ConfigFixtureBase`.""" | ||
2086 | 249 | |||
2087 | 250 | def exercise_fixture(self, fixture): | ||
2088 | 251 | # ConfigFixtureBase arranges a minimal configuration on disk, | ||
2089 | 252 | # and exports the configuration filename to the environment so | ||
2090 | 253 | # that subprocesses can find it. | ||
2091 | 254 | with fixture: | ||
2092 | 255 | self.assertThat(fixture.dir, DirExists()) | ||
2093 | 256 | self.assertThat(fixture.filename, FileExists()) | ||
2094 | 257 | self.assertEqual( | ||
2095 | 258 | {fixture.schema.envvar: fixture.filename}, | ||
2096 | 259 | fixture.environ) | ||
2097 | 260 | self.assertEqual( | ||
2098 | 261 | fixture.filename, os.environ[fixture.schema.envvar]) | ||
2099 | 262 | with open(fixture.filename, "rb") as stream: | ||
2100 | 263 | self.assertEqual(fixture.config, yaml.safe_load(stream)) | ||
2101 | 264 | |||
2102 | 265 | def test_use_minimal(self): | ||
2103 | 266 | # With no arguments, ConfigFixtureBase arranges a minimal | ||
2104 | 267 | # configuration. | ||
2105 | 268 | fixture = ExampleConfigFixture() | ||
2106 | 269 | self.exercise_fixture(fixture) | ||
2107 | 270 | |||
2108 | 271 | def test_use_with_config(self): | ||
2109 | 272 | # Given a configuration, ConfigFixtureBase can arrange a minimal | ||
2110 | 273 | # global configuration with the additional options merged in. | ||
2111 | 274 | something = self.getUniqueString("something") | ||
2112 | 275 | fixture = ExampleConfigFixture({"something": something}) | ||
2113 | 276 | self.assertEqual(something, fixture.config["something"]) | ||
2114 | 277 | self.exercise_fixture(fixture) | ||
2115 | 278 | |||
2116 | 279 | |||
2117 | 280 | class TestConfigMeta_DEFAULT_FILENAME(MAASTestCase): | ||
2118 | 281 | """Tests for `provisioningserver.config.ConfigBase.DEFAULT_FILENAME`.""" | ||
2119 | 282 | |||
2120 | 283 | def set_envvar(self, filepath=None): | ||
2121 | 284 | """Continue this test with a given environment variable.""" | ||
2122 | 285 | self.useFixture(EnvironmentVariableFixture( | ||
2123 | 286 | ExampleConfig.envvar, filepath)) | ||
2124 | 287 | |||
2125 | 288 | def set_MAAS_CONFIG_DIR(self, dirpath=None): | ||
2126 | 289 | """Continue this test with a given `MAAS_CONFIG_DIR`.""" | ||
2127 | 290 | self.useFixture(EnvironmentVariableFixture("MAAS_CONFIG_DIR", dirpath)) | ||
2128 | 291 | |||
2129 | 292 | def make_config(self): | ||
2130 | 293 | """Create a config file in a directory of its own.""" | ||
2131 | 294 | return self.make_file(name=ExampleConfig.default) | ||
2132 | 295 | |||
2133 | 296 | def test_gets_filename_from_MAAS_PROVISIONING_SETTNGS(self): | ||
2134 | 297 | dummy_filename = factory.make_name("config") | ||
2135 | 298 | self.set_MAAS_CONFIG_DIR(None) | ||
2136 | 299 | self.set_envvar(dummy_filename) | ||
2137 | 300 | self.assertEqual(dummy_filename, ExampleConfig.DEFAULT_FILENAME) | ||
2138 | 301 | |||
2139 | 302 | def test_falls_back_to_MAAS_CONFIG_DIR(self): | ||
2140 | 303 | config_file = self.make_config() | ||
2141 | 304 | self.set_MAAS_CONFIG_DIR(os.path.dirname(config_file)) | ||
2142 | 305 | self.set_envvar(None) | ||
2143 | 306 | self.assertEqual(config_file, ExampleConfig.DEFAULT_FILENAME) | ||
2144 | 307 | |||
2145 | 308 | def test_MAAS_PROVISIONING_SETTINGS_trumps_MAAS_CONFIG_DIR(self): | ||
2146 | 309 | provisioning_settings = factory.make_name("config") | ||
2147 | 310 | self.set_MAAS_CONFIG_DIR(os.path.dirname(self.make_config())) | ||
2148 | 311 | self.set_envvar(provisioning_settings) | ||
2149 | 312 | self.assertEqual( | ||
2150 | 313 | provisioning_settings, | ||
2151 | 314 | ExampleConfig.DEFAULT_FILENAME) | ||
2152 | 315 | |||
2153 | 316 | def test_defaults_to_global_config(self): | ||
2154 | 317 | self.set_MAAS_CONFIG_DIR(None) | ||
2155 | 318 | self.set_envvar(None) | ||
2156 | 319 | self.assertEqual( | ||
2157 | 320 | '/etc/maas/%s' % ExampleConfig.default, | ||
2158 | 321 | ExampleConfig.DEFAULT_FILENAME) | ||
2159 | 322 | |||
2160 | 323 | def test_set(self): | ||
2161 | 324 | dummy_filename = factory.make_name("config") | ||
2162 | 325 | ExampleConfig.DEFAULT_FILENAME = dummy_filename | ||
2163 | 326 | self.assertEqual(dummy_filename, ExampleConfig.DEFAULT_FILENAME) | ||
2164 | 327 | |||
2165 | 328 | def test_delete(self): | ||
2166 | 329 | self.set_MAAS_CONFIG_DIR(None) | ||
2167 | 330 | self.set_envvar(None) | ||
2168 | 331 | ExampleConfig.DEFAULT_FILENAME = factory.make_name("config") | ||
2169 | 332 | del ExampleConfig.DEFAULT_FILENAME | ||
2170 | 333 | # The filename reverts; see test_get_with_environment_empty. | ||
2171 | 334 | self.assertEqual( | ||
2172 | 335 | "/etc/maas/%s" % ExampleConfig.default, | ||
2173 | 336 | ExampleConfig.DEFAULT_FILENAME) | ||
2174 | 337 | # The delete does not fail when called multiple times. | ||
2175 | 338 | del ExampleConfig.DEFAULT_FILENAME | ||
2176 | 339 | |||
2177 | 340 | |||
2178 | 341 | class TestConfigBase(MAASTestCase): | ||
2179 | 342 | """Tests for `provisioningserver.config.ConfigBase`.""" | ||
2180 | 343 | |||
2181 | 344 | def make_config_data(self): | ||
2182 | 345 | """Return random config data for `ExampleConfig`.""" | ||
2183 | 346 | return {'something': factory.make_name('value')} | ||
2184 | 347 | |||
2185 | 348 | def make_config_file(self, name=None, data=None): | ||
2186 | 349 | """Write a YAML config file, and return its path.""" | ||
2187 | 350 | if name is None: | ||
2188 | 351 | name = factory.make_name('config') + '.yaml' | ||
2189 | 352 | if data is None: | ||
2190 | 353 | data = self.make_config_data() | ||
2191 | 354 | return self.make_file(name=name, contents=yaml.safe_dump(data)) | ||
2192 | 355 | |||
2193 | 356 | def test_get_defaults_returns_default_config(self): | ||
2194 | 357 | # The default configuration is production-ready. | ||
2195 | 358 | observed = ExampleConfig.get_defaults() | ||
2196 | 359 | self.assertEqual({"something": "*missing*"}, observed) | ||
2197 | 360 | |||
2198 | 361 | def test_get_defaults_ignores_settings(self): | ||
2199 | 362 | self.useFixture(ExampleConfigFixture(self.make_config_data())) | ||
2200 | 363 | observed = ExampleConfig.get_defaults() | ||
2201 | 364 | self.assertEqual({"something": "*missing*"}, observed) | ||
2202 | 365 | |||
2203 | 366 | def test_parse(self): | ||
2204 | 367 | # Configuration can be parsed from a snippet of YAML. | ||
2205 | 368 | observed = ExampleConfig.parse(b'something: "important"\n') | ||
2206 | 369 | self.assertEqual("important", observed["something"]) | ||
2207 | 370 | |||
2208 | 371 | def test_load(self): | ||
2209 | 372 | # Configuration can be loaded and parsed from a file. | ||
2210 | 373 | config = dedent(""" | ||
2211 | 374 | something: "important" | ||
2212 | 375 | """) | ||
2213 | 376 | filename = self.make_file(contents=config) | ||
2214 | 377 | observed = ExampleConfig.load(filename) | ||
2215 | 378 | self.assertEqual({"something": "important"}, observed) | ||
2216 | 379 | |||
2217 | 380 | def test_load_defaults_to_default_filename(self): | ||
2218 | 381 | data = self.make_config_data() | ||
2219 | 382 | filename = self.make_config_file(name='config.yaml', data=data) | ||
2220 | 383 | self.patch(ExampleConfig, 'DEFAULT_FILENAME', filename) | ||
2221 | 384 | self.assertEqual(data, ExampleConfig.load()) | ||
2222 | 385 | |||
2223 | 386 | def test_load_from_cache_loads_config(self): | ||
2224 | 387 | data = self.make_config_data() | ||
2225 | 388 | filename = self.make_config_file(data=data) | ||
2226 | 389 | self.assertEqual(data, ExampleConfig.load_from_cache(filename)) | ||
2227 | 390 | |||
2228 | 391 | def test_load_from_cache_uses_defaults(self): | ||
2229 | 392 | filename = self.make_file(contents='') | ||
2230 | 393 | self.assertEqual( | ||
2231 | 394 | ExampleConfig.get_defaults(), | ||
2232 | 395 | ExampleConfig.load_from_cache(filename)) | ||
2233 | 396 | |||
2234 | 397 | def test_load_from_cache_caches_each_file_separately(self): | ||
2235 | 398 | config1 = self.make_file(contents=yaml.safe_dump({'something': "1"})) | ||
2236 | 399 | config2 = self.make_file(contents=yaml.safe_dump({'something': "2"})) | ||
2237 | 400 | |||
2238 | 401 | self.assertEqual( | ||
2239 | 402 | {"something": "1"}, | ||
2240 | 403 | ExampleConfig.load_from_cache(config1)) | ||
2241 | 404 | self.assertEqual( | ||
2242 | 405 | {"something": "2"}, | ||
2243 | 406 | ExampleConfig.load_from_cache(config2)) | ||
2244 | 407 | |||
2245 | 408 | def test_load_from_cache_reloads_from_cache_not_from_file(self): | ||
2246 | 409 | # A config loaded by Config.load_from_cache() is never reloaded. | ||
2247 | 410 | filename = self.make_config_file() | ||
2248 | 411 | config_before = ExampleConfig.load_from_cache(filename) | ||
2249 | 412 | os.unlink(filename) | ||
2250 | 413 | config_after = ExampleConfig.load_from_cache(filename) | ||
2251 | 414 | self.assertEqual(config_before, config_after) | ||
2252 | 415 | |||
2253 | 416 | def test_load_from_cache_caches_immutable_copy(self): | ||
2254 | 417 | filename = self.make_config_file() | ||
2255 | 418 | |||
2256 | 419 | first_load = ExampleConfig.load_from_cache(filename) | ||
2257 | 420 | second_load = ExampleConfig.load_from_cache(filename) | ||
2258 | 421 | |||
2259 | 422 | self.assertEqual(first_load, second_load) | ||
2260 | 423 | self.assertIsNot(first_load, second_load) | ||
2261 | 424 | first_load['something'] = factory.make_name('newthing') | ||
2262 | 425 | self.assertNotEqual(first_load['something'], second_load['something']) | ||
2263 | 426 | |||
2264 | 427 | def test_flush_cache_without_filename_empties_cache(self): | ||
2265 | 428 | filename = self.make_config_file() | ||
2266 | 429 | ExampleConfig.load_from_cache(filename) | ||
2267 | 430 | os.unlink(filename) | ||
2268 | 431 | ExampleConfig.flush_cache() | ||
2269 | 432 | error = self.assertRaises( | ||
2270 | 433 | IOError, | ||
2271 | 434 | ExampleConfig.load_from_cache, filename) | ||
2272 | 435 | self.assertEqual(errno.ENOENT, error.errno) | ||
2273 | 436 | |||
2274 | 437 | def test_flush_cache_flushes_specific_file(self): | ||
2275 | 438 | filename = self.make_config_file() | ||
2276 | 439 | ExampleConfig.load_from_cache(filename) | ||
2277 | 440 | os.unlink(filename) | ||
2278 | 441 | ExampleConfig.flush_cache(filename) | ||
2279 | 442 | error = self.assertRaises( | ||
2280 | 443 | IOError, | ||
2281 | 444 | ExampleConfig.load_from_cache, filename) | ||
2282 | 445 | self.assertEqual(errno.ENOENT, error.errno) | ||
2283 | 446 | |||
2284 | 447 | def test_flush_cache_retains_other_files(self): | ||
2285 | 448 | flushed_file = self.make_config_file() | ||
2286 | 449 | cached_file = self.make_config_file() | ||
2287 | 450 | ExampleConfig.load_from_cache(flushed_file) | ||
2288 | 451 | cached_config = ExampleConfig.load_from_cache(cached_file) | ||
2289 | 452 | os.unlink(cached_file) | ||
2290 | 453 | ExampleConfig.flush_cache(flushed_file) | ||
2291 | 454 | self.assertEqual( | ||
2292 | 455 | cached_config, | ||
2293 | 456 | ExampleConfig.load_from_cache(cached_file)) | ||
2294 | 457 | |||
2295 | 458 | def test_flush_cache_ignores_uncached_files(self): | ||
2296 | 459 | data = self.make_config_data() | ||
2297 | 460 | filename = self.make_config_file(data=data) | ||
2298 | 461 | ExampleConfig.flush_cache(filename) | ||
2299 | 462 | self.assertEqual(data, ExampleConfig.load_from_cache(filename)) | ||
2300 | 463 | |||
2301 | 464 | def test_field(self): | ||
2302 | 465 | self.assertIs(ExampleConfig, ExampleConfig.field()) | ||
2303 | 466 | self.assertIs( | ||
2304 | 467 | ExampleConfig.fields["something"], | ||
2305 | 468 | ExampleConfig.field("something")) | ||
2306 | 469 | |||
2307 | 470 | def test_save_and_load_interoperate(self): | ||
2308 | 471 | something = self.getUniqueString() | ||
2309 | 472 | saved_file = self.make_file() | ||
2310 | 473 | |||
2311 | 474 | ExampleConfig.save({'something': something}, saved_file) | ||
2312 | 475 | loaded_config = ExampleConfig.load(saved_file) | ||
2313 | 476 | self.assertEqual(something, loaded_config['something']) | ||
2314 | 477 | |||
2315 | 478 | def test_save_saves_yaml_file(self): | ||
2316 | 479 | config = {'something': self.getUniqueString()} | ||
2317 | 480 | saved_file = self.make_file() | ||
2318 | 481 | |||
2319 | 482 | ExampleConfig.save(config, saved_file) | ||
2320 | 483 | |||
2321 | 484 | with open(saved_file, 'rb') as written_file: | ||
2322 | 485 | loaded_config = yaml.safe_load(written_file) | ||
2323 | 486 | self.assertEqual(config, loaded_config) | ||
2324 | 487 | |||
2325 | 488 | def test_save_defaults_to_default_filename(self): | ||
2326 | 489 | something = self.getUniqueString() | ||
2327 | 490 | filename = self.make_file(name="config.yaml") | ||
2328 | 491 | self.patch(ExampleConfig, 'DEFAULT_FILENAME', filename) | ||
2329 | 492 | |||
2330 | 493 | ExampleConfig.save({'something': something}) | ||
2331 | 494 | |||
2332 | 495 | self.assertEqual( | ||
2333 | 496 | {'something': something}, | ||
2334 | 497 | ExampleConfig.load(filename)) | ||
2335 | 498 | |||
2336 | 499 | def test_create_backup_creates_backup(self): | ||
2337 | 500 | something = self.getUniqueString() | ||
2338 | 501 | filename = self.make_file(name="config.yaml") | ||
2339 | 502 | config = {'something': something} | ||
2340 | 503 | yaml_config = yaml.safe_dump(config) | ||
2341 | 504 | self.patch(ExampleConfig, 'DEFAULT_FILENAME', filename) | ||
2342 | 505 | ExampleConfig.save(config) | ||
2343 | 506 | |||
2344 | 507 | ExampleConfig.create_backup('test') | ||
2345 | 508 | |||
2346 | 509 | backup_name = "%s.%s.bak" % (filename, 'test') | ||
2347 | 510 | self.assertThat(backup_name, FileContains(yaml_config)) | ||
2348 | 511 | |||
2349 | 512 | |||
2350 | 513 | class TestConfig(MAASTestCase): | ||
2351 | 514 | """Tests for `provisioningserver.config.Config`.""" | ||
2352 | 515 | |||
2353 | 516 | default_production_config = { | ||
2354 | 517 | 'broker': { | ||
2355 | 518 | 'host': 'localhost', | ||
2356 | 519 | 'port': 5673, | ||
2357 | 520 | 'username': getuser(), | ||
2358 | 521 | 'password': 'test', | ||
2359 | 522 | 'vhost': '/', | ||
2360 | 523 | }, | ||
2361 | 524 | 'logfile': 'pserv.log', | ||
2362 | 525 | 'oops': { | ||
2363 | 526 | 'directory': '', | ||
2364 | 527 | 'reporter': '', | ||
2365 | 528 | }, | ||
2366 | 529 | 'rpc': {}, | ||
2367 | 530 | 'tftp': { | ||
2368 | 531 | 'generator': 'http://localhost/MAAS/api/1.0/pxeconfig/', | ||
2369 | 532 | 'port': 69, | ||
2370 | 533 | # The "root" setting is obsolete; resource_root replaces it. | ||
2371 | 534 | 'root': "/var/lib/maas/tftp", | ||
2372 | 535 | 'resource_root': "/var/lib/maas/boot-resources/current/", | ||
2373 | 536 | }, | ||
2374 | 537 | # Legacy section. Became unused in MAAS 1.5. | ||
2375 | 538 | 'boot': { | ||
2376 | 539 | 'architectures': None, | ||
2377 | 540 | 'ephemeral': { | ||
2378 | 541 | 'images_directory': None, | ||
2379 | 542 | 'releases': None, | ||
2380 | 543 | }, | ||
2381 | 544 | }, | ||
2382 | 545 | } | ||
2383 | 546 | |||
2384 | 547 | default_development_config = deepcopy(default_production_config) | ||
2385 | 548 | default_development_config.update(logfile="/dev/null") | ||
2386 | 549 | default_development_config["tftp"].update( | ||
2387 | 550 | port=5244, generator="http://localhost:5240/MAAS/api/1.0/pxeconfig/") | ||
2388 | 551 | |||
2389 | 552 | def test_get_defaults_returns_default_config(self): | ||
2390 | 553 | # The default configuration is production-ready. | ||
2391 | 554 | observed = Config.get_defaults() | ||
2392 | 555 | self.assertEqual(self.default_production_config, observed) | ||
2393 | 556 | |||
2394 | 557 | def test_load_example(self): | ||
2395 | 558 | # The example configuration is designed for development. | ||
2396 | 559 | filename = os.path.join(root, "etc", "maas", "pserv.yaml") | ||
2397 | 560 | self.assertEqual( | ||
2398 | 561 | self.default_development_config, | ||
2399 | 562 | Config.load(filename)) | ||
2400 | 563 | |||
2401 | 564 | def test_oops_directory_without_reporter(self): | ||
2402 | 565 | # It is an error to omit the OOPS reporter if directory is specified. | ||
2403 | 566 | config = ( | ||
2404 | 567 | 'oops:\n' | ||
2405 | 568 | ' directory: /tmp/oops\n' | ||
2406 | 569 | ) | ||
2407 | 570 | expected = MatchesException( | ||
2408 | 571 | formencode.Invalid, "oops: You must give a value for reporter") | ||
2409 | 572 | self.assertThat( | ||
2410 | 573 | partial(Config.parse, config), | ||
2411 | 574 | Raises(expected)) | ||
2412 | 575 | |||
2413 | 576 | def test_accepts_1_4_config_file(self): | ||
2414 | 577 | # A config file that was valid with MAAS 1.4 still loads, even though | ||
2415 | 578 | # its "boot" section is no longer used. | ||
2416 | 579 | broker_password = factory.make_name('pass') | ||
2417 | 580 | config = Config.parse(dedent("""\ | ||
2418 | 581 | logfile: "/dev/null" | ||
2419 | 582 | oops: | ||
2420 | 583 | directory: "logs/oops" | ||
2421 | 584 | reporter: "maas-pserv" | ||
2422 | 585 | broker: | ||
2423 | 586 | host: "localhost" | ||
2424 | 587 | port: 5673 | ||
2425 | 588 | username: brokeruser | ||
2426 | 589 | password: "%s" | ||
2427 | 590 | vhost: "/" | ||
2428 | 591 | tftp: | ||
2429 | 592 | root: /var/lib/maas/tftp | ||
2430 | 593 | port: 5244 | ||
2431 | 594 | generator: http://localhost:5240/api/1.0/pxeconfig/ | ||
2432 | 595 | boot: | ||
2433 | 596 | architectures: ['i386', 'armhf'] | ||
2434 | 597 | ephemeral: | ||
2435 | 598 | images_directory: /var/lib/maas/ephemeral | ||
2436 | 599 | releases: ['precise', 'saucy'] | ||
2437 | 600 | """) % broker_password) | ||
2438 | 601 | # This does not fail. | ||
2439 | 602 | self.assertEqual(broker_password, config['broker']['password']) | ||
2440 | 603 | |||
2441 | 604 | |||
2442 | 605 | class TestBootSources(MAASTestCase): | ||
2443 | 606 | """Tests for `provisioningserver.config.BootSources`.""" | ||
2444 | 607 | |||
2445 | 608 | default_source = { | ||
2446 | 609 | 'url': ( | ||
2447 | 610 | 'http://maas.ubuntu.com/images/ephemeral-v2/releases/' | ||
2448 | 611 | ), | ||
2449 | 612 | 'keyring': ( | ||
2450 | 613 | '/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg'), | ||
2451 | 614 | 'keyring_data': None, | ||
2452 | 615 | 'selections': [ | ||
2453 | 616 | { | ||
2454 | 617 | 'os': '*', | ||
2455 | 618 | 'release': '*', | ||
2456 | 619 | 'labels': ['*'], | ||
2457 | 620 | 'arches': ['*'], | ||
2458 | 621 | 'subarches': ['*'], | ||
2459 | 622 | }, | ||
2460 | 623 | ], | ||
2461 | 624 | } | ||
2462 | 625 | |||
2463 | 626 | def make_source(self): | ||
2464 | 627 | """Create a dict defining an arbitrary `BootSource`.""" | ||
2465 | 628 | return { | ||
2466 | 629 | 'url': 'http://example.com/' + factory.make_name('path'), | ||
2467 | 630 | 'keyring': factory.make_name('keyring'), | ||
2468 | 631 | 'keyring_data': factory.make_string(), | ||
2469 | 632 | 'selections': [{ | ||
2470 | 633 | 'os': factory.make_name('os'), | ||
2471 | 634 | 'release': factory.make_name('release'), | ||
2472 | 635 | 'labels': [factory.make_name('label')], | ||
2473 | 636 | 'arches': [factory.make_name('arch')], | ||
2474 | 637 | 'subarches': [factory.make_name('sub') for _ in range(3)], | ||
2475 | 638 | }], | ||
2476 | 639 | } | ||
2477 | 640 | |||
2478 | 641 | def test_parse_parses_source(self): | ||
2479 | 642 | sources = [self.make_source()] | ||
2480 | 643 | self.assertEqual( | ||
2481 | 644 | sources, | ||
2482 | 645 | BootSources.parse(BytesIO(yaml.safe_dump(sources)))) | ||
2483 | 646 | |||
2484 | 647 | def test_parse_parses_multiple_sources(self): | ||
2485 | 648 | sources = [self.make_source() for _ in range(2)] | ||
2486 | 649 | self.assertEqual( | ||
2487 | 650 | sources, | ||
2488 | 651 | BootSources.parse(BytesIO(yaml.safe_dump(sources)))) | ||
2489 | 652 | |||
2490 | 653 | def test_parse_uses_defaults(self): | ||
2491 | 654 | self.assertEqual( | ||
2492 | 655 | [self.default_source], | ||
2493 | 656 | BootSources.parse(BytesIO(b'[{}]'))) | ||
2494 | 657 | |||
2495 | 658 | def test_load_parses_file(self): | ||
2496 | 659 | sources = [self.make_source()] | ||
2497 | 660 | self.assertEqual( | ||
2498 | 661 | sources, | ||
2499 | 662 | BootSources.load(self.make_file(contents=yaml.safe_dump(sources)))) | ||
2500 | 663 | |||
2501 | 664 | |||
2502 | 665 | ############################################################################### | 212 | ############################################################################### |
2503 | 666 | # New configuration API follows. | 213 | # New configuration API follows. |
2504 | 667 | ############################################################################### | 214 | ############################################################################### |
2505 | 668 | 215 | ||
2506 | === modified file 'src/provisioningserver/tests/test_diskless.py' | |||
2507 | --- src/provisioningserver/tests/test_diskless.py 2015-03-25 15:33:23 +0000 | |||
2508 | +++ src/provisioningserver/tests/test_diskless.py 2015-05-04 14:27:25 +0000 | |||
2509 | @@ -7,7 +7,7 @@ | |||
2510 | 7 | absolute_import, | 7 | absolute_import, |
2511 | 8 | print_function, | 8 | print_function, |
2512 | 9 | unicode_literals, | 9 | unicode_literals, |
2514 | 10 | ) | 10 | ) |
2515 | 11 | 11 | ||
2516 | 12 | str = None | 12 | str = None |
2517 | 13 | 13 | ||
2518 | @@ -24,9 +24,11 @@ | |||
2519 | 24 | ) | 24 | ) |
2520 | 25 | from maastesting.testcase import MAASTestCase | 25 | from maastesting.testcase import MAASTestCase |
2521 | 26 | from mock import sentinel | 26 | from mock import sentinel |
2525 | 27 | from provisioningserver import ( | 27 | from provisioningserver import diskless |
2526 | 28 | config, | 28 | from provisioningserver.cluster_config import ( |
2527 | 29 | diskless, | 29 | CLUSTER_CONFIG, |
2528 | 30 | get_config_cluster_variable, | ||
2529 | 31 | set_config_cluster_variable, | ||
2530 | 30 | ) | 32 | ) |
2531 | 31 | from provisioningserver.diskless import ( | 33 | from provisioningserver.diskless import ( |
2532 | 32 | compose_diskless_link_path, | 34 | compose_diskless_link_path, |
2533 | @@ -54,6 +56,7 @@ | |||
2534 | 54 | BOOT_IMAGE_PURPOSE, | 56 | BOOT_IMAGE_PURPOSE, |
2535 | 55 | OperatingSystemRegistry, | 57 | OperatingSystemRegistry, |
2536 | 56 | ) | 58 | ) |
2537 | 59 | from provisioningserver.testing.config import ClusterConfigurationFixture | ||
2538 | 57 | from provisioningserver.testing.os import FakeOS | 60 | from provisioningserver.testing.os import FakeOS |
2539 | 58 | from provisioningserver.utils.testing import RegistryFixture | 61 | from provisioningserver.utils.testing import RegistryFixture |
2540 | 59 | from testtools.matchers import ( | 62 | from testtools.matchers import ( |
2541 | @@ -71,13 +74,18 @@ | |||
2542 | 71 | 74 | ||
2543 | 72 | def setUp(self): | 75 | def setUp(self): |
2544 | 73 | super(DisklessTestMixin, self).setUp() | 76 | super(DisklessTestMixin, self).setUp() |
2545 | 77 | self.useFixture(ClusterConfigurationFixture()) | ||
2546 | 74 | # Ensure the global registry is empty for each test run. | 78 | # Ensure the global registry is empty for each test run. |
2547 | 75 | self.useFixture(RegistryFixture()) | 79 | self.useFixture(RegistryFixture()) |
2548 | 76 | 80 | ||
2549 | 77 | def configure_resource_storage(self): | 81 | def configure_resource_storage(self): |
2550 | 78 | resource_dir = self.make_dir() | 82 | resource_dir = self.make_dir() |
2551 | 79 | os.mkdir(os.path.join(resource_dir, 'diskless')) | 83 | os.mkdir(os.path.join(resource_dir, 'diskless')) |
2553 | 80 | self.patch(config, 'BOOT_RESOURCES_STORAGE', resource_dir) | 84 | current_dir = os.path.join(resource_dir, 'current') + '/' |
2554 | 85 | os.mkdir(current_dir) | ||
2555 | 86 | set_config_cluster_variable( | ||
2556 | 87 | CLUSTER_CONFIG.DB_boot_resources_storage, | ||
2557 | 88 | current_dir) | ||
2558 | 81 | return resource_dir | 89 | return resource_dir |
2559 | 82 | 90 | ||
2560 | 83 | def configure_diskless_storage(self): | 91 | def configure_diskless_storage(self): |
2561 | @@ -116,8 +124,12 @@ | |||
2562 | 116 | class TestHelpers(MAASTestCase, DisklessTestMixin): | 124 | class TestHelpers(MAASTestCase, DisklessTestMixin): |
2563 | 117 | 125 | ||
2564 | 118 | def test_get_diskless_store(self): | 126 | def test_get_diskless_store(self): |
2567 | 119 | storage_dir = factory.make_name('storage') | 127 | storage_dir = self.make_dir() |
2568 | 120 | self.patch(config, 'BOOT_RESOURCES_STORAGE', storage_dir) | 128 | current_dir = os.path.join(storage_dir, 'current') + '/' |
2569 | 129 | os.mkdir(current_dir) | ||
2570 | 130 | set_config_cluster_variable( | ||
2571 | 131 | CLUSTER_CONFIG.DB_boot_resources_storage, | ||
2572 | 132 | current_dir) | ||
2573 | 121 | self.assertEqual( | 133 | self.assertEqual( |
2574 | 122 | os.path.join(storage_dir, 'diskless', 'store'), | 134 | os.path.join(storage_dir, 'diskless', 'store'), |
2575 | 123 | get_diskless_store()) | 135 | get_diskless_store()) |
2576 | @@ -241,7 +253,7 @@ | |||
2577 | 241 | '%s</target>\n' % entry | 253 | '%s</target>\n' % entry |
2578 | 242 | for entry in tgt_output.split('</target>\n') | 254 | for entry in tgt_output.split('</target>\n') |
2579 | 243 | if entry != "" | 255 | if entry != "" |
2581 | 244 | ]) | 256 | ]) |
2582 | 245 | 257 | ||
2583 | 246 | def test_reload_diskless_tgt(self): | 258 | def test_reload_diskless_tgt(self): |
2584 | 247 | tgt_path = factory.make_name('tgt_path') | 259 | tgt_path = factory.make_name('tgt_path') |
2585 | @@ -255,7 +267,7 @@ | |||
2586 | 255 | '/usr/sbin/tgt-admin', | 267 | '/usr/sbin/tgt-admin', |
2587 | 256 | '--conf', tgt_path, | 268 | '--conf', tgt_path, |
2588 | 257 | '--update', 'ALL', | 269 | '--update', 'ALL', |
2590 | 258 | ])) | 270 | ])) |
2591 | 259 | 271 | ||
2592 | 260 | def test_update_diskless_tgt_calls_atomic_write(self): | 272 | def test_update_diskless_tgt_calls_atomic_write(self): |
2593 | 261 | tgt_path = factory.make_name('tgt_path') | 273 | tgt_path = factory.make_name('tgt_path') |
2594 | @@ -269,7 +281,7 @@ | |||
2595 | 269 | update_diskless_tgt() | 281 | update_diskless_tgt() |
2596 | 270 | self.assertThat( | 282 | self.assertThat( |
2597 | 271 | mock_write, | 283 | mock_write, |
2599 | 272 | MockCalledOnceWith(tgt_config, tgt_path, mode=0644)) | 284 | MockCalledOnceWith(tgt_config, tgt_path, mode=0o644)) |
2600 | 273 | 285 | ||
2601 | 274 | 286 | ||
2602 | 275 | class TestComposeSourcePath(MAASTestCase, DisklessTestMixin): | 287 | class TestComposeSourcePath(MAASTestCase, DisklessTestMixin): |
2603 | @@ -299,7 +311,8 @@ | |||
2604 | 299 | mock_xi_params.return_value = (root_path, 'tgz') | 311 | mock_xi_params.return_value = (root_path, 'tgz') |
2605 | 300 | self.assertEqual( | 312 | self.assertEqual( |
2606 | 301 | os.path.join( | 313 | os.path.join( |
2608 | 302 | config.BOOT_RESOURCES_STORAGE, 'current', os_name, | 314 | get_config_cluster_variable( |
2609 | 315 | CLUSTER_CONFIG.DB_boot_resources_storage), os_name, | ||
2610 | 303 | arch, subarch, release, label, root_path), | 316 | arch, subarch, release, label, root_path), |
2611 | 304 | compose_source_path(os_name, arch, subarch, release, label)) | 317 | compose_source_path(os_name, arch, subarch, release, label)) |
2612 | 305 | 318 | ||
2613 | @@ -337,7 +350,7 @@ | |||
2614 | 337 | driver_options = { | 350 | driver_options = { |
2615 | 338 | factory.make_name('arg'): factory.make_name('value') | 351 | factory.make_name('arg'): factory.make_name('value') |
2616 | 339 | for _ in range(3) | 352 | for _ in range(3) |
2618 | 340 | } | 353 | } |
2619 | 341 | create_diskless_disk( | 354 | create_diskless_disk( |
2620 | 342 | driver.name, driver_options, | 355 | driver.name, driver_options, |
2621 | 343 | system_id, sentinel.osystem, sentinel.arch, | 356 | system_id, sentinel.osystem, sentinel.arch, |
2622 | @@ -451,7 +464,7 @@ | |||
2623 | 451 | driver_options = { | 464 | driver_options = { |
2624 | 452 | factory.make_name('arg'): factory.make_name('value') | 465 | factory.make_name('arg'): factory.make_name('value') |
2625 | 453 | for _ in range(3) | 466 | for _ in range(3) |
2627 | 454 | } | 467 | } |
2628 | 455 | delete_diskless_disk(driver.name, driver_options, system_id) | 468 | delete_diskless_disk(driver.name, driver_options, system_id) |
2629 | 456 | self.assertThat( | 469 | self.assertThat( |
2630 | 457 | mock_delete, | 470 | mock_delete, |
2631 | 458 | 471 | ||
2632 | === modified file 'src/provisioningserver/tests/test_plugin.py' | |||
2633 | --- src/provisioningserver/tests/test_plugin.py 2015-04-29 06:19:04 +0000 | |||
2634 | +++ src/provisioningserver/tests/test_plugin.py 2015-05-04 14:27:25 +0000 | |||
2635 | @@ -7,7 +7,7 @@ | |||
2636 | 7 | absolute_import, | 7 | absolute_import, |
2637 | 8 | print_function, | 8 | print_function, |
2638 | 9 | unicode_literals, | 9 | unicode_literals, |
2640 | 10 | ) | 10 | ) |
2641 | 11 | 11 | ||
2642 | 12 | str = None | 12 | str = None |
2643 | 13 | 13 | ||
2644 | @@ -16,13 +16,16 @@ | |||
2645 | 16 | 16 | ||
2646 | 17 | import os | 17 | import os |
2647 | 18 | 18 | ||
2648 | 19 | from fixtures import EnvironmentVariableFixture | ||
2649 | 20 | from maastesting.factory import factory | ||
2650 | 21 | from maastesting.testcase import ( | 19 | from maastesting.testcase import ( |
2651 | 22 | MAASTestCase, | 20 | MAASTestCase, |
2652 | 23 | MAASTwistedRunTest, | 21 | MAASTwistedRunTest, |
2653 | 24 | ) | 22 | ) |
2654 | 25 | import provisioningserver | 23 | import provisioningserver |
2655 | 24 | from provisioningserver.cluster_config import ( | ||
2656 | 25 | CLUSTER_CONFIG, | ||
2657 | 26 | get_config_cluster_variable, | ||
2658 | 27 | get_tftp_generator, | ||
2659 | 28 | ) | ||
2660 | 26 | from provisioningserver.plugin import ( | 29 | from provisioningserver.plugin import ( |
2661 | 27 | Options, | 30 | Options, |
2662 | 28 | ProvisioningRealm, | 31 | ProvisioningRealm, |
2663 | @@ -43,6 +46,7 @@ | |||
2664 | 43 | TFTPBackend, | 46 | TFTPBackend, |
2665 | 44 | TFTPService, | 47 | TFTPService, |
2666 | 45 | ) | 48 | ) |
2667 | 49 | from provisioningserver.testing.config import ClusterConfigurationFixture | ||
2668 | 46 | from testtools.deferredruntest import assert_fails_with | 50 | from testtools.deferredruntest import assert_fails_with |
2669 | 47 | from testtools.matchers import ( | 51 | from testtools.matchers import ( |
2670 | 48 | AfterPreprocessing, | 52 | AfterPreprocessing, |
2671 | @@ -56,7 +60,6 @@ | |||
2672 | 56 | from twisted.cred.error import UnauthorizedLogin | 60 | from twisted.cred.error import UnauthorizedLogin |
2673 | 57 | from twisted.internet.defer import inlineCallbacks | 61 | from twisted.internet.defer import inlineCallbacks |
2674 | 58 | from twisted.web.resource import IResource | 62 | from twisted.web.resource import IResource |
2675 | 59 | import yaml | ||
2676 | 60 | 63 | ||
2677 | 61 | 64 | ||
2678 | 62 | class TestOptions(MAASTestCase): | 65 | class TestOptions(MAASTestCase): |
2679 | @@ -64,7 +67,7 @@ | |||
2680 | 64 | 67 | ||
2681 | 65 | def test_defaults(self): | 68 | def test_defaults(self): |
2682 | 66 | options = Options() | 69 | options = Options() |
2684 | 67 | expected = {"config-file": "pserv.yaml", "introspect": None} | 70 | expected = {"config-file": "clusterd.conf", "introspect": None} |
2685 | 68 | self.assertEqual(expected, options.defaults) | 71 | self.assertEqual(expected, options.defaults) |
2686 | 69 | 72 | ||
2687 | 70 | def test_parse_minimal_options(self): | 73 | def test_parse_minimal_options(self): |
2688 | @@ -81,17 +84,9 @@ | |||
2689 | 81 | 84 | ||
2690 | 82 | def setUp(self): | 85 | def setUp(self): |
2691 | 83 | super(TestProvisioningServiceMaker, self).setUp() | 86 | super(TestProvisioningServiceMaker, self).setUp() |
2692 | 87 | self.useFixture(ClusterConfigurationFixture()) | ||
2693 | 84 | self.patch(provisioningserver, "services", MultiService()) | 88 | self.patch(provisioningserver, "services", MultiService()) |
2694 | 85 | self.tempdir = self.make_dir() | 89 | self.tempdir = self.make_dir() |
2695 | 86 | self.useFixture( | ||
2696 | 87 | EnvironmentVariableFixture( | ||
2697 | 88 | "CLUSTER_UUID", factory.make_UUID())) | ||
2698 | 89 | |||
2699 | 90 | def write_config(self, config): | ||
2700 | 91 | config_filename = os.path.join(self.tempdir, "config.yaml") | ||
2701 | 92 | with open(config_filename, "wb") as stream: | ||
2702 | 93 | yaml.safe_dump(config, stream) | ||
2703 | 94 | return config_filename | ||
2704 | 95 | 90 | ||
2705 | 96 | def test_init(self): | 91 | def test_init(self): |
2706 | 97 | service_maker = ProvisioningServiceMaker("Harry", "Hill") | 92 | service_maker = ProvisioningServiceMaker("Harry", "Hill") |
2707 | @@ -103,14 +98,13 @@ | |||
2708 | 103 | Only the site service is created when no options are given. | 98 | Only the site service is created when no options are given. |
2709 | 104 | """ | 99 | """ |
2710 | 105 | options = Options() | 100 | options = Options() |
2711 | 106 | options["config-file"] = self.write_config({}) | ||
2712 | 107 | service_maker = ProvisioningServiceMaker("Harry", "Hill") | 101 | service_maker = ProvisioningServiceMaker("Harry", "Hill") |
2713 | 108 | service = service_maker.makeService(options) | 102 | service = service_maker.makeService(options) |
2714 | 109 | self.assertIsInstance(service, MultiService) | 103 | self.assertIsInstance(service, MultiService) |
2715 | 110 | expected_services = [ | 104 | expected_services = [ |
2716 | 111 | "dhcp_probe", "image_download", "lease_upload", | 105 | "dhcp_probe", "image_download", "lease_upload", |
2717 | 112 | "node_monitor", "rpc", "tftp", "image_service" | 106 | "node_monitor", "rpc", "tftp", "image_service" |
2719 | 113 | ] | 107 | ] |
2720 | 114 | self.assertItemsEqual(expected_services, service.namedServices) | 108 | self.assertItemsEqual(expected_services, service.namedServices) |
2721 | 115 | self.assertEqual( | 109 | self.assertEqual( |
2722 | 116 | len(service.namedServices), len(service.services), | 110 | len(service.namedServices), len(service.services), |
2723 | @@ -119,7 +113,6 @@ | |||
2724 | 119 | 113 | ||
2725 | 120 | def test_image_download_service(self): | 114 | def test_image_download_service(self): |
2726 | 121 | options = Options() | 115 | options = Options() |
2727 | 122 | options["config-file"] = self.write_config({}) | ||
2728 | 123 | service_maker = ProvisioningServiceMaker("Harry", "Hill") | 116 | service_maker = ProvisioningServiceMaker("Harry", "Hill") |
2729 | 124 | service = service_maker.makeService(options) | 117 | service = service_maker.makeService(options) |
2730 | 125 | image_service = service.getServiceNamed("image_download") | 118 | image_service = service.getServiceNamed("image_download") |
2731 | @@ -127,7 +120,6 @@ | |||
2732 | 127 | 120 | ||
2733 | 128 | def test_node_monitor_service(self): | 121 | def test_node_monitor_service(self): |
2734 | 129 | options = Options() | 122 | options = Options() |
2735 | 130 | options["config-file"] = self.write_config({}) | ||
2736 | 131 | service_maker = ProvisioningServiceMaker("Harry", "Hill") | 123 | service_maker = ProvisioningServiceMaker("Harry", "Hill") |
2737 | 132 | service = service_maker.makeService(options) | 124 | service = service_maker.makeService(options) |
2738 | 133 | node_monitor = service.getServiceNamed("node_monitor") | 125 | node_monitor = service.getServiceNamed("node_monitor") |
2739 | @@ -135,7 +127,6 @@ | |||
2740 | 135 | 127 | ||
2741 | 136 | def test_dhcp_probe_service(self): | 128 | def test_dhcp_probe_service(self): |
2742 | 137 | options = Options() | 129 | options = Options() |
2743 | 138 | options["config-file"] = self.write_config({}) | ||
2744 | 139 | service_maker = ProvisioningServiceMaker("Spike", "Milligan") | 130 | service_maker = ProvisioningServiceMaker("Spike", "Milligan") |
2745 | 140 | service = service_maker.makeService(options) | 131 | service = service_maker.makeService(options) |
2746 | 141 | dhcp_probe = service.getServiceNamed("dhcp_probe") | 132 | dhcp_probe = service.getServiceNamed("dhcp_probe") |
2747 | @@ -143,15 +134,7 @@ | |||
2748 | 143 | 134 | ||
2749 | 144 | def test_tftp_service(self): | 135 | def test_tftp_service(self): |
2750 | 145 | # A TFTP service is configured and added to the top-level service. | 136 | # A TFTP service is configured and added to the top-level service. |
2751 | 146 | config = { | ||
2752 | 147 | "tftp": { | ||
2753 | 148 | "generator": "http://candlemass/solitude", | ||
2754 | 149 | "resource_root": self.tempdir, | ||
2755 | 150 | "port": factory.pick_port(), | ||
2756 | 151 | }, | ||
2757 | 152 | } | ||
2758 | 153 | options = Options() | 137 | options = Options() |
2759 | 154 | options["config-file"] = self.write_config(config) | ||
2760 | 155 | service_maker = ProvisioningServiceMaker("Harry", "Hill") | 138 | service_maker = ProvisioningServiceMaker("Harry", "Hill") |
2761 | 156 | service = service_maker.makeService(options) | 139 | service = service_maker.makeService(options) |
2762 | 157 | tftp_service = service.getServiceNamed("tftp") | 140 | tftp_service = service.getServiceNamed("tftp") |
2763 | @@ -161,24 +144,25 @@ | |||
2764 | 161 | IsInstance(TFTPBackend), | 144 | IsInstance(TFTPBackend), |
2765 | 162 | AfterPreprocessing( | 145 | AfterPreprocessing( |
2766 | 163 | lambda backend: backend.base.path, | 146 | lambda backend: backend.base.path, |
2768 | 164 | Equals(config["tftp"]["resource_root"])), | 147 | Equals(os.path.split( |
2769 | 148 | get_config_cluster_variable( | ||
2770 | 149 | CLUSTER_CONFIG.DB_tftp_resource_root))[0])), | ||
2771 | 165 | AfterPreprocessing( | 150 | AfterPreprocessing( |
2772 | 166 | lambda backend: backend.generator_url.geturl(), | 151 | lambda backend: backend.generator_url.geturl(), |
2774 | 167 | Equals(config["tftp"]["generator"]))) | 152 | Equals(get_tftp_generator()))) |
2775 | 168 | 153 | ||
2776 | 169 | self.assertThat( | 154 | self.assertThat( |
2777 | 170 | tftp_service, MatchesStructure( | 155 | tftp_service, MatchesStructure( |
2778 | 171 | backend=expected_backend, | 156 | backend=expected_backend, |
2780 | 172 | port=Equals(config["tftp"]["port"]), | 157 | port=Equals(get_config_cluster_variable( |
2781 | 158 | CLUSTER_CONFIG.DB_tftpport)), | ||
2782 | 173 | )) | 159 | )) |
2783 | 174 | 160 | ||
2784 | 175 | def test_image_service(self): | 161 | def test_image_service(self): |
2785 | 176 | from provisioningserver import config | ||
2786 | 177 | from twisted.web.server import Site | 162 | from twisted.web.server import Site |
2787 | 178 | from twisted.python.filepath import FilePath | 163 | from twisted.python.filepath import FilePath |
2788 | 179 | 164 | ||
2789 | 180 | options = Options() | 165 | options = Options() |
2790 | 181 | options["config-file"] = self.write_config({}) | ||
2791 | 182 | service_maker = ProvisioningServiceMaker("Harry", "Hill") | 166 | service_maker = ProvisioningServiceMaker("Harry", "Hill") |
2792 | 183 | service = service_maker.makeService(options) | 167 | service = service_maker.makeService(options) |
2793 | 184 | image_service = service.getServiceNamed("image_service") | 168 | image_service = service.getServiceNamed("image_service") |
2794 | @@ -189,8 +173,9 @@ | |||
2795 | 189 | "images", request=None) | 173 | "images", request=None) |
2796 | 190 | self.assertThat(root, IsInstance(FilePath)) | 174 | self.assertThat(root, IsInstance(FilePath)) |
2797 | 191 | 175 | ||
2800 | 192 | resource_root = os.path.join( | 176 | resource_root = os.path.split( |
2801 | 193 | config.BOOT_RESOURCES_STORAGE, "current") | 177 | get_config_cluster_variable( |
2802 | 178 | CLUSTER_CONFIG.DB_tftp_resource_root))[0] | ||
2803 | 194 | 179 | ||
2804 | 195 | self.assertEqual(resource_root, root.path) | 180 | self.assertEqual(resource_root, root.path) |
2805 | 196 | 181 | ||
2806 | 197 | 182 | ||
2807 | === modified file 'src/provisioningserver/tests/test_upgrade_cluster.py' | |||
2808 | --- src/provisioningserver/tests/test_upgrade_cluster.py 2015-03-25 15:33:23 +0000 | |||
2809 | +++ src/provisioningserver/tests/test_upgrade_cluster.py 2015-05-04 14:27:25 +0000 | |||
2810 | @@ -7,7 +7,7 @@ | |||
2811 | 7 | absolute_import, | 7 | absolute_import, |
2812 | 8 | print_function, | 8 | print_function, |
2813 | 9 | unicode_literals, | 9 | unicode_literals, |
2815 | 10 | ) | 10 | ) |
2816 | 11 | 11 | ||
2817 | 12 | str = None | 12 | str = None |
2818 | 13 | 13 | ||
2819 | @@ -27,11 +27,13 @@ | |||
2820 | 27 | from maastesting.testcase import MAASTestCase | 27 | from maastesting.testcase import MAASTestCase |
2821 | 28 | from maastesting.utils import sample_binary_data | 28 | from maastesting.utils import sample_binary_data |
2822 | 29 | from mock import Mock | 29 | from mock import Mock |
2827 | 30 | from provisioningserver import ( | 30 | from provisioningserver import upgrade_cluster |
2824 | 31 | config, | ||
2825 | 32 | upgrade_cluster, | ||
2826 | 33 | ) | ||
2828 | 34 | from provisioningserver.boot.tftppath import list_subdirs | 31 | from provisioningserver.boot.tftppath import list_subdirs |
2829 | 32 | from provisioningserver.cluster_config import ( | ||
2830 | 33 | CLUSTER_CONFIG, | ||
2831 | 34 | set_config_cluster_variable, | ||
2832 | 35 | ) | ||
2833 | 36 | from provisioningserver.testing.config import ClusterConfigurationFixture | ||
2834 | 35 | from provisioningserver.utils.fs import read_text_file | 37 | from provisioningserver.utils.fs import read_text_file |
2835 | 36 | from testtools.matchers import ( | 38 | from testtools.matchers import ( |
2836 | 37 | DirExists, | 39 | DirExists, |
2837 | @@ -86,9 +88,14 @@ | |||
2838 | 86 | class TestMakeMAASOwnBootResources(MAASTestCase): | 88 | class TestMakeMAASOwnBootResources(MAASTestCase): |
2839 | 87 | """Tests for the `make_maas_own_boot_resources` upgrade.""" | 89 | """Tests for the `make_maas_own_boot_resources` upgrade.""" |
2840 | 88 | 90 | ||
2841 | 91 | def setUp(self): | ||
2842 | 92 | super(TestMakeMAASOwnBootResources, self).setUp() | ||
2843 | 93 | self.useFixture(ClusterConfigurationFixture()) | ||
2844 | 94 | |||
2845 | 89 | def configure_storage(self, storage_dir): | 95 | def configure_storage(self, storage_dir): |
2846 | 90 | """Create a storage config.""" | 96 | """Create a storage config.""" |
2848 | 91 | self.patch(config, 'BOOT_RESOURCES_STORAGE', storage_dir) | 97 | set_config_cluster_variable( |
2849 | 98 | CLUSTER_CONFIG.DB_boot_resources_storage, storage_dir) | ||
2850 | 92 | 99 | ||
2851 | 93 | def test__calls_chown_if_boot_resources_dir_exists(self): | 100 | def test__calls_chown_if_boot_resources_dir_exists(self): |
2852 | 94 | self.patch(upgrade_cluster, 'check_call') | 101 | self.patch(upgrade_cluster, 'check_call') |
2853 | @@ -102,7 +109,9 @@ | |||
2854 | 102 | def test__skips_chown_if_boot_resources_dir_does_not_exist(self): | 109 | def test__skips_chown_if_boot_resources_dir_does_not_exist(self): |
2855 | 103 | self.patch(upgrade_cluster, 'check_call') | 110 | self.patch(upgrade_cluster, 'check_call') |
2856 | 104 | storage_dir = os.path.join(self.make_dir(), factory.make_name('none')) | 111 | storage_dir = os.path.join(self.make_dir(), factory.make_name('none')) |
2857 | 112 | os.mkdir(storage_dir) | ||
2858 | 105 | self.configure_storage(storage_dir) | 113 | self.configure_storage(storage_dir) |
2859 | 114 | os.rmdir(storage_dir) | ||
2860 | 106 | upgrade_cluster.make_maas_own_boot_resources() | 115 | upgrade_cluster.make_maas_own_boot_resources() |
2861 | 107 | self.assertThat(upgrade_cluster.check_call, MockNotCalled()) | 116 | self.assertThat(upgrade_cluster.check_call, MockNotCalled()) |
2862 | 108 | 117 | ||
2863 | @@ -203,12 +212,18 @@ | |||
2864 | 203 | class TestMigrateArchitecturesIntoUbuntuDirectory(MAASTestCase): | 212 | class TestMigrateArchitecturesIntoUbuntuDirectory(MAASTestCase): |
2865 | 204 | """Tests for the `migrate_architectures_into_ubuntu_directory` upgrade.""" | 213 | """Tests for the `migrate_architectures_into_ubuntu_directory` upgrade.""" |
2866 | 205 | 214 | ||
2867 | 215 | def setUp(self): | ||
2868 | 216 | super(TestMigrateArchitecturesIntoUbuntuDirectory, self).setUp() | ||
2869 | 217 | self.useFixture(ClusterConfigurationFixture()) | ||
2870 | 218 | |||
2871 | 206 | def configure_storage(self, storage_dir, make_current_dir=True): | 219 | def configure_storage(self, storage_dir, make_current_dir=True): |
2872 | 207 | """Create a storage config.""" | 220 | """Create a storage config.""" |
2877 | 208 | if make_current_dir: | 221 | current_dir = os.path.join(storage_dir, "current") |
2878 | 209 | current_dir = os.path.join(storage_dir, "current") | 222 | os.makedirs(current_dir) |
2879 | 210 | os.mkdir(current_dir) | 223 | set_config_cluster_variable( |
2880 | 211 | self.patch(config, 'BOOT_RESOURCES_STORAGE', storage_dir) | 224 | CLUSTER_CONFIG.DB_boot_resources_storage, current_dir) |
2881 | 225 | if not make_current_dir: | ||
2882 | 226 | os.rmdir(current_dir) | ||
2883 | 212 | 227 | ||
2884 | 213 | def test__list_subdirs_under_current_directory(self): | 228 | def test__list_subdirs_under_current_directory(self): |
2885 | 214 | self.patch(upgrade_cluster, 'list_subdirs').return_value = ['ubuntu'] | 229 | self.patch(upgrade_cluster, 'list_subdirs').return_value = ['ubuntu'] |
2886 | 215 | 230 | ||
2887 | === modified file 'src/provisioningserver/upgrade_cluster.py' | |||
2888 | --- src/provisioningserver/upgrade_cluster.py 2015-03-26 00:12:12 +0000 | |||
2889 | +++ src/provisioningserver/upgrade_cluster.py 2015-05-04 14:27:25 +0000 | |||
2890 | @@ -22,7 +22,7 @@ | |||
2891 | 22 | absolute_import, | 22 | absolute_import, |
2892 | 23 | print_function, | 23 | print_function, |
2893 | 24 | unicode_literals, | 24 | unicode_literals, |
2895 | 25 | ) | 25 | ) |
2896 | 26 | 26 | ||
2897 | 27 | str = None | 27 | str = None |
2898 | 28 | 28 | ||
2899 | @@ -30,7 +30,7 @@ | |||
2900 | 30 | __all__ = [ | 30 | __all__ = [ |
2901 | 31 | 'add_arguments', | 31 | 'add_arguments', |
2902 | 32 | 'run', | 32 | 'run', |
2904 | 33 | ] | 33 | ] |
2905 | 34 | 34 | ||
2906 | 35 | import os | 35 | import os |
2907 | 36 | from os import makedirs | 36 | from os import makedirs |
2908 | @@ -38,12 +38,15 @@ | |||
2909 | 38 | from subprocess import check_call | 38 | from subprocess import check_call |
2910 | 39 | from textwrap import dedent | 39 | from textwrap import dedent |
2911 | 40 | 40 | ||
2912 | 41 | from provisioningserver import config | ||
2913 | 42 | from provisioningserver.auth import get_maas_user_gpghome | 41 | from provisioningserver.auth import get_maas_user_gpghome |
2914 | 43 | from provisioningserver.boot.tftppath import ( | 42 | from provisioningserver.boot.tftppath import ( |
2915 | 44 | drill_down, | 43 | drill_down, |
2916 | 45 | list_subdirs, | 44 | list_subdirs, |
2917 | 46 | ) | 45 | ) |
2918 | 46 | from provisioningserver.cluster_config import ( | ||
2919 | 47 | CLUSTER_CONFIG, | ||
2920 | 48 | get_config_cluster_variable, | ||
2921 | 49 | ) | ||
2922 | 47 | from provisioningserver.import_images.boot_resources import ( | 50 | from provisioningserver.import_images.boot_resources import ( |
2923 | 48 | update_targets_conf, | 51 | update_targets_conf, |
2924 | 49 | write_targets_conf, | 52 | write_targets_conf, |
2925 | @@ -57,8 +60,10 @@ | |||
2926 | 57 | def make_maas_own_boot_resources(): | 60 | def make_maas_own_boot_resources(): |
2927 | 58 | """Upgrade hook: make the `maas` user the owner of the boot resources.""" | 61 | """Upgrade hook: make the `maas` user the owner of the boot resources.""" |
2928 | 59 | # This reduces the privileges required for importing and managing images. | 62 | # This reduces the privileges required for importing and managing images. |
2931 | 60 | if os.path.isdir(config.BOOT_RESOURCES_STORAGE): | 63 | boot_resources_storage = get_config_cluster_variable( |
2932 | 61 | check_call(['chown', '-R', 'maas', config.BOOT_RESOURCES_STORAGE]) | 64 | CLUSTER_CONFIG.DB_boot_resources_storage) |
2933 | 65 | if os.path.isdir(boot_resources_storage): | ||
2934 | 66 | check_call(['chown', '-R', 'maas', boot_resources_storage]) | ||
2935 | 62 | 67 | ||
2936 | 63 | 68 | ||
2937 | 64 | def create_gnupg_home(): | 69 | def create_gnupg_home(): |
2938 | @@ -146,8 +151,8 @@ | |||
2939 | 146 | """Remove paths that contain directories with more levels. We don't want | 151 | """Remove paths that contain directories with more levels. We don't want |
2940 | 147 | to move other operating systems under the ubuntu directory.""" | 152 | to move other operating systems under the ubuntu directory.""" |
2941 | 148 | for arch, subarch, release, label in paths: | 153 | for arch, subarch, release, label in paths: |
2944 | 149 | path = os.path.join( | 154 | path = os.path.join(get_config_cluster_variable( |
2945 | 150 | config.BOOT_RESOURCES_STORAGE, 'current', | 155 | CLUSTER_CONFIG.DB_boot_resources_storage), |
2946 | 151 | arch, subarch, release, label) | 156 | arch, subarch, release, label) |
2947 | 152 | if len(list_subdirs(path)) == 0: | 157 | if len(list_subdirs(path)) == 0: |
2948 | 153 | yield (arch, subarch, release, label) | 158 | yield (arch, subarch, release, label) |
2949 | @@ -165,7 +170,8 @@ | |||
2950 | 165 | folders have structure arch/subarch/release/label and move them into | 170 | folders have structure arch/subarch/release/label and move them into |
2951 | 166 | ubuntu folder. Making the final path ubuntu/arch/subarch/release/label. | 171 | ubuntu folder. Making the final path ubuntu/arch/subarch/release/label. |
2952 | 167 | """ | 172 | """ |
2954 | 168 | current_dir = os.path.join(config.BOOT_RESOURCES_STORAGE, "current") | 173 | current_dir = get_config_cluster_variable( |
2955 | 174 | CLUSTER_CONFIG.DB_boot_resources_storage) | ||
2956 | 169 | if not os.path.isdir(current_dir): | 175 | if not os.path.isdir(current_dir): |
2957 | 170 | return | 176 | return |
2958 | 171 | # If ubuntu folder already exists, then no reason to continue | 177 | # If ubuntu folder already exists, then no reason to continue |
2959 | @@ -213,7 +219,7 @@ | |||
2960 | 213 | create_gnupg_home, | 219 | create_gnupg_home, |
2961 | 214 | retire_bootresources_yaml, | 220 | retire_bootresources_yaml, |
2962 | 215 | migrate_architectures_into_ubuntu_directory, | 221 | migrate_architectures_into_ubuntu_directory, |
2964 | 216 | ] | 222 | ] |
2965 | 217 | 223 | ||
2966 | 218 | 224 | ||
2967 | 219 | def add_arguments(parser): | 225 | def add_arguments(parser): |
2968 | 220 | 226 | ||
2969 | === modified file 'src/provisioningserver/utils/__init__.py' | |||
2970 | --- src/provisioningserver/utils/__init__.py 2015-03-30 18:05:57 +0000 | |||
2971 | +++ src/provisioningserver/utils/__init__.py 2015-05-04 14:27:25 +0000 | |||
2972 | @@ -97,7 +97,7 @@ | |||
2973 | 97 | """ | 97 | """ |
2974 | 98 | # Avoid circular dependencies. | 98 | # Avoid circular dependencies. |
2975 | 99 | from provisioningserver.rpc.region import CreateNode | 99 | from provisioningserver.rpc.region import CreateNode |
2977 | 100 | from provisioningserver.cluster_config import get_cluster_uuid | 100 | from provisioningserver import cluster_config |
2978 | 101 | 101 | ||
2979 | 102 | for elapsed, remaining, wait in retries(15, 5, reactor): | 102 | for elapsed, remaining, wait in retries(15, 5, reactor): |
2980 | 103 | try: | 103 | try: |
2981 | @@ -116,7 +116,8 @@ | |||
2982 | 116 | try: | 116 | try: |
2983 | 117 | response = yield client( | 117 | response = yield client( |
2984 | 118 | CreateNode, | 118 | CreateNode, |
2986 | 119 | cluster_uuid=get_cluster_uuid(), | 119 | cluster_uuid=cluster_config.get_config_cluster_variable( |
2987 | 120 | cluster_config.CLUSTER_CONFIG.DB_cluster_uuid), | ||
2988 | 120 | architecture=arch, | 121 | architecture=arch, |
2989 | 121 | power_type=power_type, | 122 | power_type=power_type, |
2990 | 122 | power_parameters=json.dumps(power_parameters), | 123 | power_parameters=json.dumps(power_parameters), |
2991 | 123 | 124 | ||
2992 | === modified file 'src/provisioningserver/utils/script.py' | |||
2993 | --- src/provisioningserver/utils/script.py 2015-02-24 13:52:12 +0000 | |||
2994 | +++ src/provisioningserver/utils/script.py 2015-05-04 14:27:25 +0000 | |||
2995 | @@ -7,7 +7,7 @@ | |||
2996 | 7 | absolute_import, | 7 | absolute_import, |
2997 | 8 | print_function, | 8 | print_function, |
2998 | 9 | unicode_literals, | 9 | unicode_literals, |
3000 | 10 | ) | 10 | ) |
3001 | 11 | 11 | ||
3002 | 12 | str = None | 12 | str = None |
3003 | 13 | 13 | ||
3004 | @@ -16,7 +16,7 @@ | |||
3005 | 16 | 'ActionScript', | 16 | 'ActionScript', |
3006 | 17 | 'AtomicWriteScript', | 17 | 'AtomicWriteScript', |
3007 | 18 | 'MainScript', | 18 | 'MainScript', |
3009 | 19 | ] | 19 | ] |
3010 | 20 | 20 | ||
3011 | 21 | from argparse import ArgumentParser | 21 | from argparse import ArgumentParser |
3012 | 22 | from os import fdopen | 22 | from os import fdopen |
3013 | @@ -24,6 +24,7 @@ | |||
3014 | 24 | from subprocess import CalledProcessError | 24 | from subprocess import CalledProcessError |
3015 | 25 | import sys | 25 | import sys |
3016 | 26 | 26 | ||
3017 | 27 | from provisioningserver.config import ClusterConfiguration | ||
3018 | 27 | from provisioningserver.utils.fs import atomic_write | 28 | from provisioningserver.utils.fs import atomic_write |
3019 | 28 | 29 | ||
3020 | 29 | 30 | ||
3021 | @@ -92,20 +93,18 @@ | |||
3022 | 92 | 93 | ||
3023 | 93 | The `--config-file` option defaults to the value of | 94 | The `--config-file` option defaults to the value of |
3024 | 94 | `MAAS_PROVISIONING_SETTINGS` in the process's environment, or absent | 95 | `MAAS_PROVISIONING_SETTINGS` in the process's environment, or absent |
3027 | 95 | that, `$MAAS_CONFIG_DIR/pserv.yaml` (normally /etc/maas/pserv.yaml for | 96 | that, or when running from branch, the equivalent |
3026 | 96 | packaged installations, or when running from branch, the equivalent | ||
3028 | 97 | inside that branch). | 97 | inside that branch). |
3029 | 98 | """ | 98 | """ |
3030 | 99 | 99 | ||
3031 | 100 | def __init__(self, description): | 100 | def __init__(self, description): |
3032 | 101 | # Avoid circular imports. | 101 | # Avoid circular imports. |
3033 | 102 | from provisioningserver.config import Config | ||
3034 | 103 | 102 | ||
3035 | 104 | super(MainScript, self).__init__(description) | 103 | super(MainScript, self).__init__(description) |
3036 | 105 | self.parser.add_argument( | 104 | self.parser.add_argument( |
3037 | 106 | "-c", "--config-file", metavar="FILENAME", | 105 | "-c", "--config-file", metavar="FILENAME", |
3038 | 107 | help="Configuration file to load [%(default)s].", | 106 | help="Configuration file to load [%(default)s].", |
3040 | 108 | default=Config.DEFAULT_FILENAME) | 107 | default=ClusterConfiguration.default) |
3041 | 109 | 108 | ||
3042 | 110 | 109 | ||
3043 | 111 | class AtomicWriteScript: | 110 | class AtomicWriteScript: |
3044 | @@ -141,7 +140,7 @@ | |||
3045 | 141 | if args.mode is not None: | 140 | if args.mode is not None: |
3046 | 142 | mode = int(args.mode, 8) | 141 | mode = int(args.mode, 8) |
3047 | 143 | else: | 142 | else: |
3049 | 144 | mode = 0600 | 143 | mode = 0o600 |
3050 | 145 | atomic_write( | 144 | atomic_write( |
3051 | 146 | content, args.filename, overwrite=not args.no_overwrite, | 145 | content, args.filename, overwrite=not args.no_overwrite, |
3052 | 147 | mode=mode) | 146 | mode=mode) |
3053 | 148 | 147 | ||
3054 | === modified file 'src/provisioningserver/utils/tests/test_utils.py' | |||
3055 | --- src/provisioningserver/utils/tests/test_utils.py 2015-03-30 18:05:57 +0000 | |||
3056 | +++ src/provisioningserver/utils/tests/test_utils.py 2015-05-04 14:27:25 +0000 | |||
3057 | @@ -34,12 +34,17 @@ | |||
3058 | 34 | sentinel, | 34 | sentinel, |
3059 | 35 | ) | 35 | ) |
3060 | 36 | import provisioningserver | 36 | import provisioningserver |
3061 | 37 | from provisioningserver.cluster_config import ( | ||
3062 | 38 | CLUSTER_CONFIG, | ||
3063 | 39 | set_config_cluster_variable, | ||
3064 | 40 | ) | ||
3065 | 37 | from provisioningserver.rpc import region | 41 | from provisioningserver.rpc import region |
3066 | 38 | from provisioningserver.rpc.exceptions import ( | 42 | from provisioningserver.rpc.exceptions import ( |
3067 | 39 | CommissionNodeFailed, | 43 | CommissionNodeFailed, |
3068 | 40 | NodeAlreadyExists, | 44 | NodeAlreadyExists, |
3069 | 41 | ) | 45 | ) |
3070 | 42 | from provisioningserver.rpc.testing import MockLiveClusterToRegionRPCFixture | 46 | from provisioningserver.rpc.testing import MockLiveClusterToRegionRPCFixture |
3071 | 47 | from provisioningserver.testing.config import ClusterConfigurationFixture | ||
3072 | 43 | from provisioningserver.testing.testcase import PservTestCase | 48 | from provisioningserver.testing.testcase import PservTestCase |
3073 | 44 | import provisioningserver.utils | 49 | import provisioningserver.utils |
3074 | 45 | from provisioningserver.utils import ( | 50 | from provisioningserver.utils import ( |
3075 | @@ -411,6 +416,10 @@ | |||
3076 | 411 | 416 | ||
3077 | 412 | class TestCreateNode(PservTestCase): | 417 | class TestCreateNode(PservTestCase): |
3078 | 413 | 418 | ||
3079 | 419 | def setUp(self): | ||
3080 | 420 | super(TestCreateNode, self).setUp() | ||
3081 | 421 | self.useFixture(ClusterConfigurationFixture()) | ||
3082 | 422 | |||
3083 | 414 | run_tests_with = MAASTwistedRunTest.make_factory(timeout=5) | 423 | run_tests_with = MAASTwistedRunTest.make_factory(timeout=5) |
3084 | 415 | 424 | ||
3085 | 416 | def prepare_region_rpc(self): | 425 | def prepare_region_rpc(self): |
3086 | @@ -438,14 +447,14 @@ | |||
3087 | 438 | 'power_control': None, | 447 | 'power_control': None, |
3088 | 439 | 'system_id': uuid | 448 | 'system_id': uuid |
3089 | 440 | } | 449 | } |
3093 | 441 | get_cluster_uuid = self.patch( | 450 | test_uuid = factory.make_UUID() |
3094 | 442 | provisioningserver.cluster_config, 'get_cluster_uuid') | 451 | set_config_cluster_variable(CLUSTER_CONFIG.DB_cluster_uuid, test_uuid) |
3095 | 443 | get_cluster_uuid.return_value = 'cluster-' + factory.make_UUID() | 452 | |
3096 | 444 | yield create_node( | 453 | yield create_node( |
3097 | 445 | macs, arch, power_type, power_parameters, hostname=hostname) | 454 | macs, arch, power_type, power_parameters, hostname=hostname) |
3098 | 446 | self.assertThat( | 455 | self.assertThat( |
3099 | 447 | protocol.CreateNode, MockCalledOnceWith( | 456 | protocol.CreateNode, MockCalledOnceWith( |
3101 | 448 | protocol, cluster_uuid=get_cluster_uuid.return_value, | 457 | protocol, cluster_uuid=test_uuid, |
3102 | 449 | architecture=arch, power_type=power_type, | 458 | architecture=arch, power_type=power_type, |
3103 | 450 | power_parameters=json.dumps(power_parameters), | 459 | power_parameters=json.dumps(power_parameters), |
3104 | 451 | mac_addresses=macs, hostname=hostname)) | 460 | mac_addresses=macs, hostname=hostname)) |
3105 | @@ -483,9 +492,9 @@ | |||
3106 | 483 | system_id = factory.make_name("system-id") | 492 | system_id = factory.make_name("system-id") |
3107 | 484 | protocol.CreateNode.return_value = defer.succeed( | 493 | protocol.CreateNode.return_value = defer.succeed( |
3108 | 485 | {"system_id": system_id}) | 494 | {"system_id": system_id}) |
3112 | 486 | get_cluster_uuid = self.patch( | 495 | |
3113 | 487 | provisioningserver.cluster_config, 'get_cluster_uuid') | 496 | test_uuid = factory.make_UUID() |
3114 | 488 | get_cluster_uuid.return_value = 'cluster-' + factory.make_UUID() | 497 | set_config_cluster_variable(CLUSTER_CONFIG.DB_cluster_uuid, test_uuid) |
3115 | 489 | 498 | ||
3116 | 490 | uuid = 'node-' + factory.make_UUID() | 499 | uuid = 'node-' + factory.make_UUID() |
3117 | 491 | arch = factory.make_name('architecture') | 500 | arch = factory.make_name('architecture') |
3118 | @@ -506,7 +515,7 @@ | |||
3119 | 506 | macs_with_duplicate, arch, power_type, power_parameters) | 515 | macs_with_duplicate, arch, power_type, power_parameters) |
3120 | 507 | self.assertThat( | 516 | self.assertThat( |
3121 | 508 | protocol.CreateNode, MockCalledOnceWith( | 517 | protocol.CreateNode, MockCalledOnceWith( |
3123 | 509 | protocol, cluster_uuid=get_cluster_uuid.return_value, | 518 | protocol, cluster_uuid=test_uuid, |
3124 | 510 | architecture=arch, power_type=power_type, | 519 | architecture=arch, power_type=power_type, |
3125 | 511 | power_parameters=json.dumps(power_parameters), | 520 | power_parameters=json.dumps(power_parameters), |
3126 | 512 | mac_addresses=macs, hostname=None)) | 521 | mac_addresses=macs, hostname=None)) |
3127 | @@ -517,9 +526,6 @@ | |||
3128 | 517 | self.addCleanup((yield connecting)) | 526 | self.addCleanup((yield connecting)) |
3129 | 518 | system_id = factory.make_name("system-id") | 527 | system_id = factory.make_name("system-id") |
3130 | 519 | maaslog = self.patch(provisioningserver.utils, 'maaslog') | 528 | maaslog = self.patch(provisioningserver.utils, 'maaslog') |
3131 | 520 | get_cluster_uuid = self.patch( | ||
3132 | 521 | provisioningserver.utils, 'get_cluster_uuid') | ||
3133 | 522 | get_cluster_uuid.return_value = 'cluster-' + factory.make_UUID() | ||
3134 | 523 | 529 | ||
3135 | 524 | uuid = 'node-' + factory.make_UUID() | 530 | uuid = 'node-' + factory.make_UUID() |
3136 | 525 | macs = sorted(factory.make_mac_address() for _ in range(3)) | 531 | macs = sorted(factory.make_mac_address() for _ in range(3)) |
There's a minor conflict in src/provisionin gserver/ plugin. py.