Merge lp:~openstack-charmers/charms/precise/nova-cloud-controller/ods_merge into lp:~charmers/charms/precise/nova-cloud-controller/trunk
- Precise Pangolin (12.04)
- ods_merge
- Merge into trunk
Proposed by
Adam Gandelman
Status: | Merged |
---|---|
Merged at revision: | 56 |
Proposed branch: | lp:~openstack-charmers/charms/precise/nova-cloud-controller/ods_merge |
Merge into: | lp:~charmers/charms/precise/nova-cloud-controller/trunk |
Diff against target: |
1536 lines (+596/-100) 23 files modified
charm-helpers.yaml (+0/-1) config.yaml (+29/-0) hooks/charmhelpers/contrib/openstack/alternatives.py (+17/-0) hooks/charmhelpers/contrib/openstack/context.py (+20/-1) hooks/charmhelpers/contrib/openstack/neutron.py (+20/-0) hooks/charmhelpers/contrib/openstack/utils.py (+81/-10) hooks/charmhelpers/contrib/storage/linux/ceph.py (+27/-3) hooks/charmhelpers/core/hookenv.py (+78/-23) hooks/charmhelpers/core/host.py (+15/-9) hooks/charmhelpers/fetch/__init__.py (+53/-5) hooks/charmhelpers/fetch/bzrurl.py (+1/-1) hooks/nova_cc_context.py (+10/-0) hooks/nova_cc_hooks.py (+59/-29) hooks/nova_cc_utils.py (+32/-2) metadata.yaml (+3/-0) revision (+1/-1) templates/folsom/nova.conf (+14/-0) templates/folsom/quantum-server (+6/-0) templates/havana/neutron-server (+6/-0) templates/havana/nvp.ini (+11/-0) unit_tests/test_nova_cc_hooks.py (+63/-1) unit_tests/test_nova_cc_utils.py (+47/-14) unit_tests/test_utils.py (+3/-0) |
To merge this branch: | bzr merge lp:~openstack-charmers/charms/precise/nova-cloud-controller/ods_merge |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marco Ceppi (community) | Abstain | ||
OpenStack Charmers | Pending | ||
Review via email: mp+194062@code.launchpad.net |
Commit message
Description of the change
* Adds Neutron NVP suppot
* Adds VMware subordinate interface
To post a comment you must log in.
- 61. By James Page
-
Rebase on trunk
- 62. By James Page
-
Fixup nvp- prefix in pydev files
Revision history for this message
Marco Ceppi (marcoceppi) : | # |
review:
Abstain
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'charm-helpers.yaml' | |||
2 | --- charm-helpers.yaml 2013-10-15 01:32:42 +0000 | |||
3 | +++ charm-helpers.yaml 2013-11-08 05:43:26 +0000 | |||
4 | @@ -7,5 +7,4 @@ | |||
5 | 7 | - contrib.storage | 7 | - contrib.storage |
6 | 8 | - contrib.hahelpers: | 8 | - contrib.hahelpers: |
7 | 9 | - apache | 9 | - apache |
8 | 10 | - ceph | ||
9 | 11 | - payload.execd | 10 | - payload.execd |
10 | 12 | 11 | ||
11 | === modified file 'config.yaml' | |||
12 | --- config.yaml 2013-10-17 19:18:20 +0000 | |||
13 | +++ config.yaml 2013-11-08 05:43:26 +0000 | |||
14 | @@ -69,6 +69,7 @@ | |||
15 | 69 | Quantum plugin to use for network management; supports | 69 | Quantum plugin to use for network management; supports |
16 | 70 | . | 70 | . |
17 | 71 | ovs - OpenvSwitch Plugin | 71 | ovs - OpenvSwitch Plugin |
18 | 72 | nvp - Nicira Network Virtualization Platform | ||
19 | 72 | . | 73 | . |
20 | 73 | This configuration only has context when used with | 74 | This configuration only has context when used with |
21 | 74 | network-manager Quantum. | 75 | network-manager Quantum. |
22 | @@ -125,3 +126,31 @@ | |||
23 | 125 | ssl_key: | 126 | ssl_key: |
24 | 126 | type: string | 127 | type: string |
25 | 127 | description: SSL key to use with certificate specified as ssl_cert. | 128 | description: SSL key to use with certificate specified as ssl_cert. |
26 | 129 | # Neutron NVP Plugin configuration | ||
27 | 130 | nvp-controllers: | ||
28 | 131 | type: string | ||
29 | 132 | description: Space delimited addresses of NVP controllers | ||
30 | 133 | nvp-username: | ||
31 | 134 | type: string | ||
32 | 135 | default: admin | ||
33 | 136 | description: Username to connect to NVP controllers with | ||
34 | 137 | nvp-password: | ||
35 | 138 | type: string | ||
36 | 139 | default: admin | ||
37 | 140 | description: Password to connect to NVP controllers with | ||
38 | 141 | nvp-cluster-name: | ||
39 | 142 | type: string | ||
40 | 143 | default: example | ||
41 | 144 | description: Name of the NVP cluster configuration to create (grizzly only) | ||
42 | 145 | nvp-tz-uuid: | ||
43 | 146 | type: string | ||
44 | 147 | description: | | ||
45 | 148 | This is uuid of the default NVP Transport zone that will be used for | ||
46 | 149 | creating tunneled isolated Quantum networks. It needs to be created | ||
47 | 150 | in NVP before starting Quantum with the nvp plugin. | ||
48 | 151 | nvp-l3-uuid: | ||
49 | 152 | type: string | ||
50 | 153 | description: | | ||
51 | 154 | This is uuid of the default NVP L3 Gateway Service. | ||
52 | 155 | # end of NVP configuration | ||
53 | 156 | |||
54 | 128 | 157 | ||
55 | === added file 'hooks/charmhelpers/contrib/openstack/alternatives.py' | |||
56 | --- hooks/charmhelpers/contrib/openstack/alternatives.py 1970-01-01 00:00:00 +0000 | |||
57 | +++ hooks/charmhelpers/contrib/openstack/alternatives.py 2013-11-08 05:43:26 +0000 | |||
58 | @@ -0,0 +1,17 @@ | |||
59 | 1 | ''' Helper for managing alternatives for file conflict resolution ''' | ||
60 | 2 | |||
61 | 3 | import subprocess | ||
62 | 4 | import shutil | ||
63 | 5 | import os | ||
64 | 6 | |||
65 | 7 | |||
66 | 8 | def install_alternative(name, target, source, priority=50): | ||
67 | 9 | ''' Install alternative configuration ''' | ||
68 | 10 | if (os.path.exists(target) and not os.path.islink(target)): | ||
69 | 11 | # Move existing file/directory away before installing | ||
70 | 12 | shutil.move(target, '{}.bak'.format(target)) | ||
71 | 13 | cmd = [ | ||
72 | 14 | 'update-alternatives', '--force', '--install', | ||
73 | 15 | target, name, source, str(priority) | ||
74 | 16 | ] | ||
75 | 17 | subprocess.check_call(cmd) | ||
76 | 0 | 18 | ||
77 | === modified file 'hooks/charmhelpers/contrib/openstack/context.py' | |||
78 | --- hooks/charmhelpers/contrib/openstack/context.py 2013-10-15 01:32:42 +0000 | |||
79 | +++ hooks/charmhelpers/contrib/openstack/context.py 2013-11-08 05:43:26 +0000 | |||
80 | @@ -385,16 +385,33 @@ | |||
81 | 385 | def ovs_ctxt(self): | 385 | def ovs_ctxt(self): |
82 | 386 | driver = neutron_plugin_attribute(self.plugin, 'driver', | 386 | driver = neutron_plugin_attribute(self.plugin, 'driver', |
83 | 387 | self.network_manager) | 387 | self.network_manager) |
85 | 388 | 388 | config = neutron_plugin_attribute(self.plugin, 'config', | |
86 | 389 | self.network_manager) | ||
87 | 389 | ovs_ctxt = { | 390 | ovs_ctxt = { |
88 | 390 | 'core_plugin': driver, | 391 | 'core_plugin': driver, |
89 | 391 | 'neutron_plugin': 'ovs', | 392 | 'neutron_plugin': 'ovs', |
90 | 392 | 'neutron_security_groups': self.neutron_security_groups, | 393 | 'neutron_security_groups': self.neutron_security_groups, |
91 | 393 | 'local_ip': unit_private_ip(), | 394 | 'local_ip': unit_private_ip(), |
92 | 395 | 'config': config | ||
93 | 394 | } | 396 | } |
94 | 395 | 397 | ||
95 | 396 | return ovs_ctxt | 398 | return ovs_ctxt |
96 | 397 | 399 | ||
97 | 400 | def nvp_ctxt(self): | ||
98 | 401 | driver = neutron_plugin_attribute(self.plugin, 'driver', | ||
99 | 402 | self.network_manager) | ||
100 | 403 | config = neutron_plugin_attribute(self.plugin, 'config', | ||
101 | 404 | self.network_manager) | ||
102 | 405 | nvp_ctxt = { | ||
103 | 406 | 'core_plugin': driver, | ||
104 | 407 | 'neutron_plugin': 'nvp', | ||
105 | 408 | 'neutron_security_groups': self.neutron_security_groups, | ||
106 | 409 | 'local_ip': unit_private_ip(), | ||
107 | 410 | 'config': config | ||
108 | 411 | } | ||
109 | 412 | |||
110 | 413 | return nvp_ctxt | ||
111 | 414 | |||
112 | 398 | def __call__(self): | 415 | def __call__(self): |
113 | 399 | self._ensure_packages() | 416 | self._ensure_packages() |
114 | 400 | 417 | ||
115 | @@ -408,6 +425,8 @@ | |||
116 | 408 | 425 | ||
117 | 409 | if self.plugin == 'ovs': | 426 | if self.plugin == 'ovs': |
118 | 410 | ctxt.update(self.ovs_ctxt()) | 427 | ctxt.update(self.ovs_ctxt()) |
119 | 428 | elif self.plugin == 'nvp': | ||
120 | 429 | ctxt.update(self.nvp_ctxt()) | ||
121 | 411 | 430 | ||
122 | 412 | self._save_flag_file() | 431 | self._save_flag_file() |
123 | 413 | return ctxt | 432 | return ctxt |
124 | 414 | 433 | ||
125 | === modified file 'hooks/charmhelpers/contrib/openstack/neutron.py' | |||
126 | --- hooks/charmhelpers/contrib/openstack/neutron.py 2013-10-15 01:32:42 +0000 | |||
127 | +++ hooks/charmhelpers/contrib/openstack/neutron.py 2013-11-08 05:43:26 +0000 | |||
128 | @@ -34,13 +34,23 @@ | |||
129 | 34 | 'services': ['quantum-plugin-openvswitch-agent'], | 34 | 'services': ['quantum-plugin-openvswitch-agent'], |
130 | 35 | 'packages': [[headers_package(), 'openvswitch-datapath-dkms'], | 35 | 'packages': [[headers_package(), 'openvswitch-datapath-dkms'], |
131 | 36 | ['quantum-plugin-openvswitch-agent']], | 36 | ['quantum-plugin-openvswitch-agent']], |
132 | 37 | 'server_packages': ['quantum-server', | ||
133 | 38 | 'quantum-plugin-openvswitch'], | ||
134 | 39 | 'server_services': ['quantum-server'] | ||
135 | 37 | }, | 40 | }, |
136 | 38 | 'nvp': { | 41 | 'nvp': { |
137 | 39 | 'config': '/etc/quantum/plugins/nicira/nvp.ini', | 42 | 'config': '/etc/quantum/plugins/nicira/nvp.ini', |
138 | 40 | 'driver': 'quantum.plugins.nicira.nicira_nvp_plugin.' | 43 | 'driver': 'quantum.plugins.nicira.nicira_nvp_plugin.' |
139 | 41 | 'QuantumPlugin.NvpPluginV2', | 44 | 'QuantumPlugin.NvpPluginV2', |
140 | 45 | 'contexts': [ | ||
141 | 46 | context.SharedDBContext(user=config('neutron-database-user'), | ||
142 | 47 | database=config('neutron-database'), | ||
143 | 48 | relation_prefix='neutron')], | ||
144 | 42 | 'services': [], | 49 | 'services': [], |
145 | 43 | 'packages': [], | 50 | 'packages': [], |
146 | 51 | 'server_packages': ['quantum-server', | ||
147 | 52 | 'quantum-plugin-nicira'], | ||
148 | 53 | 'server_services': ['quantum-server'] | ||
149 | 44 | } | 54 | } |
150 | 45 | } | 55 | } |
151 | 46 | 56 | ||
152 | @@ -60,13 +70,23 @@ | |||
153 | 60 | 'services': ['neutron-plugin-openvswitch-agent'], | 70 | 'services': ['neutron-plugin-openvswitch-agent'], |
154 | 61 | 'packages': [[headers_package(), 'openvswitch-datapath-dkms'], | 71 | 'packages': [[headers_package(), 'openvswitch-datapath-dkms'], |
155 | 62 | ['quantum-plugin-openvswitch-agent']], | 72 | ['quantum-plugin-openvswitch-agent']], |
156 | 73 | 'server_packages': ['neutron-server', | ||
157 | 74 | 'neutron-plugin-openvswitch'], | ||
158 | 75 | 'server_services': ['neutron-server'] | ||
159 | 63 | }, | 76 | }, |
160 | 64 | 'nvp': { | 77 | 'nvp': { |
161 | 65 | 'config': '/etc/neutron/plugins/nicira/nvp.ini', | 78 | 'config': '/etc/neutron/plugins/nicira/nvp.ini', |
162 | 66 | 'driver': 'neutron.plugins.nicira.nicira_nvp_plugin.' | 79 | 'driver': 'neutron.plugins.nicira.nicira_nvp_plugin.' |
163 | 67 | 'NeutronPlugin.NvpPluginV2', | 80 | 'NeutronPlugin.NvpPluginV2', |
164 | 81 | 'contexts': [ | ||
165 | 82 | context.SharedDBContext(user=config('neutron-database-user'), | ||
166 | 83 | database=config('neutron-database'), | ||
167 | 84 | relation_prefix='neutron')], | ||
168 | 68 | 'services': [], | 85 | 'services': [], |
169 | 69 | 'packages': [], | 86 | 'packages': [], |
170 | 87 | 'server_packages': ['neutron-server', | ||
171 | 88 | 'neutron-plugin-nicira'], | ||
172 | 89 | 'server_services': ['neutron-server'] | ||
173 | 70 | } | 90 | } |
174 | 71 | } | 91 | } |
175 | 72 | 92 | ||
176 | 73 | 93 | ||
177 | === modified file 'hooks/charmhelpers/contrib/openstack/utils.py' | |||
178 | --- hooks/charmhelpers/contrib/openstack/utils.py 2013-10-15 01:32:42 +0000 | |||
179 | +++ hooks/charmhelpers/contrib/openstack/utils.py 2013-11-08 05:43:26 +0000 | |||
180 | @@ -13,19 +13,28 @@ | |||
181 | 13 | config, | 13 | config, |
182 | 14 | log as juju_log, | 14 | log as juju_log, |
183 | 15 | charm_dir, | 15 | charm_dir, |
193 | 16 | ) | 16 | ERROR, |
194 | 17 | 17 | INFO | |
195 | 18 | from charmhelpers.core.host import ( | 18 | ) |
196 | 19 | lsb_release, | 19 | |
197 | 20 | ) | 20 | from charmhelpers.contrib.storage.linux.lvm import ( |
198 | 21 | 21 | deactivate_lvm_volume_group, | |
199 | 22 | from charmhelpers.fetch import ( | 22 | is_lvm_physical_volume, |
200 | 23 | apt_install, | 23 | remove_lvm_physical_volume, |
201 | 24 | ) | 24 | ) |
202 | 25 | |||
203 | 26 | from charmhelpers.core.host import lsb_release, mounts, umount | ||
204 | 27 | from charmhelpers.fetch import apt_install | ||
205 | 28 | from charmhelpers.contrib.storage.linux.utils import is_block_device, zap_disk | ||
206 | 29 | from charmhelpers.contrib.storage.linux.loopback import ensure_loopback_device | ||
207 | 25 | 30 | ||
208 | 26 | CLOUD_ARCHIVE_URL = "http://ubuntu-cloud.archive.canonical.com/ubuntu" | 31 | CLOUD_ARCHIVE_URL = "http://ubuntu-cloud.archive.canonical.com/ubuntu" |
209 | 27 | CLOUD_ARCHIVE_KEY_ID = '5EDB1B62EC4926EA' | 32 | CLOUD_ARCHIVE_KEY_ID = '5EDB1B62EC4926EA' |
210 | 28 | 33 | ||
211 | 34 | DISTRO_PROPOSED = ('deb http://archive.ubuntu.com/ubuntu/ %s-proposed ' | ||
212 | 35 | 'restricted main multiverse universe') | ||
213 | 36 | |||
214 | 37 | |||
215 | 29 | UBUNTU_OPENSTACK_RELEASE = OrderedDict([ | 38 | UBUNTU_OPENSTACK_RELEASE = OrderedDict([ |
216 | 30 | ('oneiric', 'diablo'), | 39 | ('oneiric', 'diablo'), |
217 | 31 | ('precise', 'essex'), | 40 | ('precise', 'essex'), |
218 | @@ -57,6 +66,8 @@ | |||
219 | 57 | ('1.9.0', 'havana'), | 66 | ('1.9.0', 'havana'), |
220 | 58 | ]) | 67 | ]) |
221 | 59 | 68 | ||
222 | 69 | DEFAULT_LOOPBACK_SIZE = '5G' | ||
223 | 70 | |||
224 | 60 | 71 | ||
225 | 61 | def error_out(msg): | 72 | def error_out(msg): |
226 | 62 | juju_log("FATAL ERROR: %s" % msg, level='ERROR') | 73 | juju_log("FATAL ERROR: %s" % msg, level='ERROR') |
227 | @@ -67,7 +78,7 @@ | |||
228 | 67 | '''Derive OpenStack release codename from a given installation source.''' | 78 | '''Derive OpenStack release codename from a given installation source.''' |
229 | 68 | ubuntu_rel = lsb_release()['DISTRIB_CODENAME'] | 79 | ubuntu_rel = lsb_release()['DISTRIB_CODENAME'] |
230 | 69 | rel = '' | 80 | rel = '' |
232 | 70 | if src == 'distro': | 81 | if src in ['distro', 'distro-proposed']: |
233 | 71 | try: | 82 | try: |
234 | 72 | rel = UBUNTU_OPENSTACK_RELEASE[ubuntu_rel] | 83 | rel = UBUNTU_OPENSTACK_RELEASE[ubuntu_rel] |
235 | 73 | except KeyError: | 84 | except KeyError: |
236 | @@ -202,6 +213,10 @@ | |||
237 | 202 | '''Configure apt installation source.''' | 213 | '''Configure apt installation source.''' |
238 | 203 | if rel == 'distro': | 214 | if rel == 'distro': |
239 | 204 | return | 215 | return |
240 | 216 | elif rel == 'distro-proposed': | ||
241 | 217 | ubuntu_rel = lsb_release()['DISTRIB_CODENAME'] | ||
242 | 218 | with open('/etc/apt/sources.list.d/juju_deb.list', 'w') as f: | ||
243 | 219 | f.write(DISTRO_PROPOSED % ubuntu_rel) | ||
244 | 205 | elif rel[:4] == "ppa:": | 220 | elif rel[:4] == "ppa:": |
245 | 206 | src = rel | 221 | src = rel |
246 | 207 | subprocess.check_call(["add-apt-repository", "-y", src]) | 222 | subprocess.check_call(["add-apt-repository", "-y", src]) |
247 | @@ -299,6 +314,62 @@ | |||
248 | 299 | return apt.version_compare(available_vers, cur_vers) == 1 | 314 | return apt.version_compare(available_vers, cur_vers) == 1 |
249 | 300 | 315 | ||
250 | 301 | 316 | ||
251 | 317 | def ensure_block_device(block_device): | ||
252 | 318 | ''' | ||
253 | 319 | Confirm block_device, create as loopback if necessary. | ||
254 | 320 | |||
255 | 321 | :param block_device: str: Full path of block device to ensure. | ||
256 | 322 | |||
257 | 323 | :returns: str: Full path of ensured block device. | ||
258 | 324 | ''' | ||
259 | 325 | _none = ['None', 'none', None] | ||
260 | 326 | if (block_device in _none): | ||
261 | 327 | error_out('prepare_storage(): Missing required input: ' | ||
262 | 328 | 'block_device=%s.' % block_device, level=ERROR) | ||
263 | 329 | |||
264 | 330 | if block_device.startswith('/dev/'): | ||
265 | 331 | bdev = block_device | ||
266 | 332 | elif block_device.startswith('/'): | ||
267 | 333 | _bd = block_device.split('|') | ||
268 | 334 | if len(_bd) == 2: | ||
269 | 335 | bdev, size = _bd | ||
270 | 336 | else: | ||
271 | 337 | bdev = block_device | ||
272 | 338 | size = DEFAULT_LOOPBACK_SIZE | ||
273 | 339 | bdev = ensure_loopback_device(bdev, size) | ||
274 | 340 | else: | ||
275 | 341 | bdev = '/dev/%s' % block_device | ||
276 | 342 | |||
277 | 343 | if not is_block_device(bdev): | ||
278 | 344 | error_out('Failed to locate valid block device at %s' % bdev, | ||
279 | 345 | level=ERROR) | ||
280 | 346 | |||
281 | 347 | return bdev | ||
282 | 348 | |||
283 | 349 | |||
284 | 350 | def clean_storage(block_device): | ||
285 | 351 | ''' | ||
286 | 352 | Ensures a block device is clean. That is: | ||
287 | 353 | - unmounted | ||
288 | 354 | - any lvm volume groups are deactivated | ||
289 | 355 | - any lvm physical device signatures removed | ||
290 | 356 | - partition table wiped | ||
291 | 357 | |||
292 | 358 | :param block_device: str: Full path to block device to clean. | ||
293 | 359 | ''' | ||
294 | 360 | for mp, d in mounts(): | ||
295 | 361 | if d == block_device: | ||
296 | 362 | juju_log('clean_storage(): %s is mounted @ %s, unmounting.' % | ||
297 | 363 | (d, mp), level=INFO) | ||
298 | 364 | umount(mp, persist=True) | ||
299 | 365 | |||
300 | 366 | if is_lvm_physical_volume(block_device): | ||
301 | 367 | deactivate_lvm_volume_group(block_device) | ||
302 | 368 | remove_lvm_physical_volume(block_device) | ||
303 | 369 | else: | ||
304 | 370 | zap_disk(block_device) | ||
305 | 371 | |||
306 | 372 | |||
307 | 302 | def is_ip(address): | 373 | def is_ip(address): |
308 | 303 | """ | 374 | """ |
309 | 304 | Returns True if address is a valid IP address. | 375 | Returns True if address is a valid IP address. |
310 | 305 | 376 | ||
311 | === modified file 'hooks/charmhelpers/contrib/storage/linux/ceph.py' | |||
312 | --- hooks/charmhelpers/contrib/storage/linux/ceph.py 2013-09-27 16:18:25 +0000 | |||
313 | +++ hooks/charmhelpers/contrib/storage/linux/ceph.py 2013-11-08 05:43:26 +0000 | |||
314 | @@ -102,8 +102,12 @@ | |||
315 | 102 | Return a list of all Ceph Object Storage Daemons | 102 | Return a list of all Ceph Object Storage Daemons |
316 | 103 | currently in the cluster | 103 | currently in the cluster |
317 | 104 | ''' | 104 | ''' |
320 | 105 | return json.loads(check_output(['ceph', '--id', service, | 105 | version = ceph_version() |
321 | 106 | 'osd', 'ls', '--format=json'])) | 106 | if version and version >= '0.56': |
322 | 107 | return json.loads(check_output(['ceph', '--id', service, | ||
323 | 108 | 'osd', 'ls', '--format=json'])) | ||
324 | 109 | else: | ||
325 | 110 | return None | ||
326 | 107 | 111 | ||
327 | 108 | 112 | ||
328 | 109 | def create_pool(service, name, replicas=2): | 113 | def create_pool(service, name, replicas=2): |
329 | @@ -114,7 +118,13 @@ | |||
330 | 114 | return | 118 | return |
331 | 115 | # Calculate the number of placement groups based | 119 | # Calculate the number of placement groups based |
332 | 116 | # on upstream recommended best practices. | 120 | # on upstream recommended best practices. |
334 | 117 | pgnum = (len(get_osds(service)) * 100 / replicas) | 121 | osds = get_osds(service) |
335 | 122 | if osds: | ||
336 | 123 | pgnum = (len(osds) * 100 / replicas) | ||
337 | 124 | else: | ||
338 | 125 | # NOTE(james-page): Default to 200 for older ceph versions | ||
339 | 126 | # which don't support OSD query from cli | ||
340 | 127 | pgnum = 200 | ||
341 | 118 | cmd = [ | 128 | cmd = [ |
342 | 119 | 'ceph', '--id', service, | 129 | 'ceph', '--id', service, |
343 | 120 | 'osd', 'pool', 'create', | 130 | 'osd', 'pool', 'create', |
344 | @@ -357,3 +367,17 @@ | |||
345 | 357 | if user and group: | 367 | if user and group: |
346 | 358 | check_call(['chown', '%s.%s' % (user, group), keyring]) | 368 | check_call(['chown', '%s.%s' % (user, group), keyring]) |
347 | 359 | return True | 369 | return True |
348 | 370 | |||
349 | 371 | |||
350 | 372 | def ceph_version(): | ||
351 | 373 | ''' Retrieve the local version of ceph ''' | ||
352 | 374 | if os.path.exists('/usr/bin/ceph'): | ||
353 | 375 | cmd = ['ceph', '-v'] | ||
354 | 376 | output = check_output(cmd) | ||
355 | 377 | output = output.split() | ||
356 | 378 | if len(output) > 3: | ||
357 | 379 | return output[2] | ||
358 | 380 | else: | ||
359 | 381 | return None | ||
360 | 382 | else: | ||
361 | 383 | return None | ||
362 | 360 | 384 | ||
363 | === modified file 'hooks/charmhelpers/core/hookenv.py' | |||
364 | --- hooks/charmhelpers/core/hookenv.py 2013-08-02 03:42:16 +0000 | |||
365 | +++ hooks/charmhelpers/core/hookenv.py 2013-11-08 05:43:26 +0000 | |||
366 | @@ -9,6 +9,7 @@ | |||
367 | 9 | import yaml | 9 | import yaml |
368 | 10 | import subprocess | 10 | import subprocess |
369 | 11 | import UserDict | 11 | import UserDict |
370 | 12 | from subprocess import CalledProcessError | ||
371 | 12 | 13 | ||
372 | 13 | CRITICAL = "CRITICAL" | 14 | CRITICAL = "CRITICAL" |
373 | 14 | ERROR = "ERROR" | 15 | ERROR = "ERROR" |
374 | @@ -21,7 +22,7 @@ | |||
375 | 21 | 22 | ||
376 | 22 | 23 | ||
377 | 23 | def cached(func): | 24 | def cached(func): |
379 | 24 | ''' Cache return values for multiple executions of func + args | 25 | """Cache return values for multiple executions of func + args |
380 | 25 | 26 | ||
381 | 26 | For example: | 27 | For example: |
382 | 27 | 28 | ||
383 | @@ -32,7 +33,7 @@ | |||
384 | 32 | unit_get('test') | 33 | unit_get('test') |
385 | 33 | 34 | ||
386 | 34 | will cache the result of unit_get + 'test' for future calls. | 35 | will cache the result of unit_get + 'test' for future calls. |
388 | 35 | ''' | 36 | """ |
389 | 36 | def wrapper(*args, **kwargs): | 37 | def wrapper(*args, **kwargs): |
390 | 37 | global cache | 38 | global cache |
391 | 38 | key = str((func, args, kwargs)) | 39 | key = str((func, args, kwargs)) |
392 | @@ -46,8 +47,8 @@ | |||
393 | 46 | 47 | ||
394 | 47 | 48 | ||
395 | 48 | def flush(key): | 49 | def flush(key): |
398 | 49 | ''' Flushes any entries from function cache where the | 50 | """Flushes any entries from function cache where the |
399 | 50 | key is found in the function+args ''' | 51 | key is found in the function+args """ |
400 | 51 | flush_list = [] | 52 | flush_list = [] |
401 | 52 | for item in cache: | 53 | for item in cache: |
402 | 53 | if key in item: | 54 | if key in item: |
403 | @@ -57,7 +58,7 @@ | |||
404 | 57 | 58 | ||
405 | 58 | 59 | ||
406 | 59 | def log(message, level=None): | 60 | def log(message, level=None): |
408 | 60 | "Write a message to the juju log" | 61 | """Write a message to the juju log""" |
409 | 61 | command = ['juju-log'] | 62 | command = ['juju-log'] |
410 | 62 | if level: | 63 | if level: |
411 | 63 | command += ['-l', level] | 64 | command += ['-l', level] |
412 | @@ -66,7 +67,7 @@ | |||
413 | 66 | 67 | ||
414 | 67 | 68 | ||
415 | 68 | class Serializable(UserDict.IterableUserDict): | 69 | class Serializable(UserDict.IterableUserDict): |
417 | 69 | "Wrapper, an object that can be serialized to yaml or json" | 70 | """Wrapper, an object that can be serialized to yaml or json""" |
418 | 70 | 71 | ||
419 | 71 | def __init__(self, obj): | 72 | def __init__(self, obj): |
420 | 72 | # wrap the object | 73 | # wrap the object |
421 | @@ -96,11 +97,11 @@ | |||
422 | 96 | self.data = state | 97 | self.data = state |
423 | 97 | 98 | ||
424 | 98 | def json(self): | 99 | def json(self): |
426 | 99 | "Serialize the object to json" | 100 | """Serialize the object to json""" |
427 | 100 | return json.dumps(self.data) | 101 | return json.dumps(self.data) |
428 | 101 | 102 | ||
429 | 102 | def yaml(self): | 103 | def yaml(self): |
431 | 103 | "Serialize the object to yaml" | 104 | """Serialize the object to yaml""" |
432 | 104 | return yaml.dump(self.data) | 105 | return yaml.dump(self.data) |
433 | 105 | 106 | ||
434 | 106 | 107 | ||
435 | @@ -119,38 +120,38 @@ | |||
436 | 119 | 120 | ||
437 | 120 | 121 | ||
438 | 121 | def in_relation_hook(): | 122 | def in_relation_hook(): |
440 | 122 | "Determine whether we're running in a relation hook" | 123 | """Determine whether we're running in a relation hook""" |
441 | 123 | return 'JUJU_RELATION' in os.environ | 124 | return 'JUJU_RELATION' in os.environ |
442 | 124 | 125 | ||
443 | 125 | 126 | ||
444 | 126 | def relation_type(): | 127 | def relation_type(): |
446 | 127 | "The scope for the current relation hook" | 128 | """The scope for the current relation hook""" |
447 | 128 | return os.environ.get('JUJU_RELATION', None) | 129 | return os.environ.get('JUJU_RELATION', None) |
448 | 129 | 130 | ||
449 | 130 | 131 | ||
450 | 131 | def relation_id(): | 132 | def relation_id(): |
452 | 132 | "The relation ID for the current relation hook" | 133 | """The relation ID for the current relation hook""" |
453 | 133 | return os.environ.get('JUJU_RELATION_ID', None) | 134 | return os.environ.get('JUJU_RELATION_ID', None) |
454 | 134 | 135 | ||
455 | 135 | 136 | ||
456 | 136 | def local_unit(): | 137 | def local_unit(): |
458 | 137 | "Local unit ID" | 138 | """Local unit ID""" |
459 | 138 | return os.environ['JUJU_UNIT_NAME'] | 139 | return os.environ['JUJU_UNIT_NAME'] |
460 | 139 | 140 | ||
461 | 140 | 141 | ||
462 | 141 | def remote_unit(): | 142 | def remote_unit(): |
464 | 142 | "The remote unit for the current relation hook" | 143 | """The remote unit for the current relation hook""" |
465 | 143 | return os.environ['JUJU_REMOTE_UNIT'] | 144 | return os.environ['JUJU_REMOTE_UNIT'] |
466 | 144 | 145 | ||
467 | 145 | 146 | ||
468 | 146 | def service_name(): | 147 | def service_name(): |
470 | 147 | "The name service group this unit belongs to" | 148 | """The name service group this unit belongs to""" |
471 | 148 | return local_unit().split('/')[0] | 149 | return local_unit().split('/')[0] |
472 | 149 | 150 | ||
473 | 150 | 151 | ||
474 | 151 | @cached | 152 | @cached |
475 | 152 | def config(scope=None): | 153 | def config(scope=None): |
477 | 153 | "Juju charm configuration" | 154 | """Juju charm configuration""" |
478 | 154 | config_cmd_line = ['config-get'] | 155 | config_cmd_line = ['config-get'] |
479 | 155 | if scope is not None: | 156 | if scope is not None: |
480 | 156 | config_cmd_line.append(scope) | 157 | config_cmd_line.append(scope) |
481 | @@ -163,6 +164,7 @@ | |||
482 | 163 | 164 | ||
483 | 164 | @cached | 165 | @cached |
484 | 165 | def relation_get(attribute=None, unit=None, rid=None): | 166 | def relation_get(attribute=None, unit=None, rid=None): |
485 | 167 | """Get relation information""" | ||
486 | 166 | _args = ['relation-get', '--format=json'] | 168 | _args = ['relation-get', '--format=json'] |
487 | 167 | if rid: | 169 | if rid: |
488 | 168 | _args.append('-r') | 170 | _args.append('-r') |
489 | @@ -174,9 +176,14 @@ | |||
490 | 174 | return json.loads(subprocess.check_output(_args)) | 176 | return json.loads(subprocess.check_output(_args)) |
491 | 175 | except ValueError: | 177 | except ValueError: |
492 | 176 | return None | 178 | return None |
493 | 179 | except CalledProcessError, e: | ||
494 | 180 | if e.returncode == 2: | ||
495 | 181 | return None | ||
496 | 182 | raise | ||
497 | 177 | 183 | ||
498 | 178 | 184 | ||
499 | 179 | def relation_set(relation_id=None, relation_settings={}, **kwargs): | 185 | def relation_set(relation_id=None, relation_settings={}, **kwargs): |
500 | 186 | """Set relation information for the current unit""" | ||
501 | 180 | relation_cmd_line = ['relation-set'] | 187 | relation_cmd_line = ['relation-set'] |
502 | 181 | if relation_id is not None: | 188 | if relation_id is not None: |
503 | 182 | relation_cmd_line.extend(('-r', relation_id)) | 189 | relation_cmd_line.extend(('-r', relation_id)) |
504 | @@ -192,7 +199,7 @@ | |||
505 | 192 | 199 | ||
506 | 193 | @cached | 200 | @cached |
507 | 194 | def relation_ids(reltype=None): | 201 | def relation_ids(reltype=None): |
509 | 195 | "A list of relation_ids" | 202 | """A list of relation_ids""" |
510 | 196 | reltype = reltype or relation_type() | 203 | reltype = reltype or relation_type() |
511 | 197 | relid_cmd_line = ['relation-ids', '--format=json'] | 204 | relid_cmd_line = ['relation-ids', '--format=json'] |
512 | 198 | if reltype is not None: | 205 | if reltype is not None: |
513 | @@ -203,7 +210,7 @@ | |||
514 | 203 | 210 | ||
515 | 204 | @cached | 211 | @cached |
516 | 205 | def related_units(relid=None): | 212 | def related_units(relid=None): |
518 | 206 | "A list of related units" | 213 | """A list of related units""" |
519 | 207 | relid = relid or relation_id() | 214 | relid = relid or relation_id() |
520 | 208 | units_cmd_line = ['relation-list', '--format=json'] | 215 | units_cmd_line = ['relation-list', '--format=json'] |
521 | 209 | if relid is not None: | 216 | if relid is not None: |
522 | @@ -213,7 +220,7 @@ | |||
523 | 213 | 220 | ||
524 | 214 | @cached | 221 | @cached |
525 | 215 | def relation_for_unit(unit=None, rid=None): | 222 | def relation_for_unit(unit=None, rid=None): |
527 | 216 | "Get the json represenation of a unit's relation" | 223 | """Get the json represenation of a unit's relation""" |
528 | 217 | unit = unit or remote_unit() | 224 | unit = unit or remote_unit() |
529 | 218 | relation = relation_get(unit=unit, rid=rid) | 225 | relation = relation_get(unit=unit, rid=rid) |
530 | 219 | for key in relation: | 226 | for key in relation: |
531 | @@ -225,7 +232,7 @@ | |||
532 | 225 | 232 | ||
533 | 226 | @cached | 233 | @cached |
534 | 227 | def relations_for_id(relid=None): | 234 | def relations_for_id(relid=None): |
536 | 228 | "Get relations of a specific relation ID" | 235 | """Get relations of a specific relation ID""" |
537 | 229 | relation_data = [] | 236 | relation_data = [] |
538 | 230 | relid = relid or relation_ids() | 237 | relid = relid or relation_ids() |
539 | 231 | for unit in related_units(relid): | 238 | for unit in related_units(relid): |
540 | @@ -237,7 +244,7 @@ | |||
541 | 237 | 244 | ||
542 | 238 | @cached | 245 | @cached |
543 | 239 | def relations_of_type(reltype=None): | 246 | def relations_of_type(reltype=None): |
545 | 240 | "Get relations of a specific type" | 247 | """Get relations of a specific type""" |
546 | 241 | relation_data = [] | 248 | relation_data = [] |
547 | 242 | reltype = reltype or relation_type() | 249 | reltype = reltype or relation_type() |
548 | 243 | for relid in relation_ids(reltype): | 250 | for relid in relation_ids(reltype): |
549 | @@ -249,7 +256,7 @@ | |||
550 | 249 | 256 | ||
551 | 250 | @cached | 257 | @cached |
552 | 251 | def relation_types(): | 258 | def relation_types(): |
554 | 252 | "Get a list of relation types supported by this charm" | 259 | """Get a list of relation types supported by this charm""" |
555 | 253 | charmdir = os.environ.get('CHARM_DIR', '') | 260 | charmdir = os.environ.get('CHARM_DIR', '') |
556 | 254 | mdf = open(os.path.join(charmdir, 'metadata.yaml')) | 261 | mdf = open(os.path.join(charmdir, 'metadata.yaml')) |
557 | 255 | md = yaml.safe_load(mdf) | 262 | md = yaml.safe_load(mdf) |
558 | @@ -264,6 +271,7 @@ | |||
559 | 264 | 271 | ||
560 | 265 | @cached | 272 | @cached |
561 | 266 | def relations(): | 273 | def relations(): |
562 | 274 | """Get a nested dictionary of relation data for all related units""" | ||
563 | 267 | rels = {} | 275 | rels = {} |
564 | 268 | for reltype in relation_types(): | 276 | for reltype in relation_types(): |
565 | 269 | relids = {} | 277 | relids = {} |
566 | @@ -277,15 +285,35 @@ | |||
567 | 277 | return rels | 285 | return rels |
568 | 278 | 286 | ||
569 | 279 | 287 | ||
570 | 288 | @cached | ||
571 | 289 | def is_relation_made(relation, keys='private-address'): | ||
572 | 290 | ''' | ||
573 | 291 | Determine whether a relation is established by checking for | ||
574 | 292 | presence of key(s). If a list of keys is provided, they | ||
575 | 293 | must all be present for the relation to be identified as made | ||
576 | 294 | ''' | ||
577 | 295 | if isinstance(keys, str): | ||
578 | 296 | keys = [keys] | ||
579 | 297 | for r_id in relation_ids(relation): | ||
580 | 298 | for unit in related_units(r_id): | ||
581 | 299 | context = {} | ||
582 | 300 | for k in keys: | ||
583 | 301 | context[k] = relation_get(k, rid=r_id, | ||
584 | 302 | unit=unit) | ||
585 | 303 | if None not in context.values(): | ||
586 | 304 | return True | ||
587 | 305 | return False | ||
588 | 306 | |||
589 | 307 | |||
590 | 280 | def open_port(port, protocol="TCP"): | 308 | def open_port(port, protocol="TCP"): |
592 | 281 | "Open a service network port" | 309 | """Open a service network port""" |
593 | 282 | _args = ['open-port'] | 310 | _args = ['open-port'] |
594 | 283 | _args.append('{}/{}'.format(port, protocol)) | 311 | _args.append('{}/{}'.format(port, protocol)) |
595 | 284 | subprocess.check_call(_args) | 312 | subprocess.check_call(_args) |
596 | 285 | 313 | ||
597 | 286 | 314 | ||
598 | 287 | def close_port(port, protocol="TCP"): | 315 | def close_port(port, protocol="TCP"): |
600 | 288 | "Close a service network port" | 316 | """Close a service network port""" |
601 | 289 | _args = ['close-port'] | 317 | _args = ['close-port'] |
602 | 290 | _args.append('{}/{}'.format(port, protocol)) | 318 | _args.append('{}/{}'.format(port, protocol)) |
603 | 291 | subprocess.check_call(_args) | 319 | subprocess.check_call(_args) |
604 | @@ -293,6 +321,7 @@ | |||
605 | 293 | 321 | ||
606 | 294 | @cached | 322 | @cached |
607 | 295 | def unit_get(attribute): | 323 | def unit_get(attribute): |
608 | 324 | """Get the unit ID for the remote unit""" | ||
609 | 296 | _args = ['unit-get', '--format=json', attribute] | 325 | _args = ['unit-get', '--format=json', attribute] |
610 | 297 | try: | 326 | try: |
611 | 298 | return json.loads(subprocess.check_output(_args)) | 327 | return json.loads(subprocess.check_output(_args)) |
612 | @@ -301,22 +330,46 @@ | |||
613 | 301 | 330 | ||
614 | 302 | 331 | ||
615 | 303 | def unit_private_ip(): | 332 | def unit_private_ip(): |
616 | 333 | """Get this unit's private IP address""" | ||
617 | 304 | return unit_get('private-address') | 334 | return unit_get('private-address') |
618 | 305 | 335 | ||
619 | 306 | 336 | ||
620 | 307 | class UnregisteredHookError(Exception): | 337 | class UnregisteredHookError(Exception): |
621 | 338 | """Raised when an undefined hook is called""" | ||
622 | 308 | pass | 339 | pass |
623 | 309 | 340 | ||
624 | 310 | 341 | ||
625 | 311 | class Hooks(object): | 342 | class Hooks(object): |
626 | 343 | """A convenient handler for hook functions. | ||
627 | 344 | |||
628 | 345 | Example: | ||
629 | 346 | hooks = Hooks() | ||
630 | 347 | |||
631 | 348 | # register a hook, taking its name from the function name | ||
632 | 349 | @hooks.hook() | ||
633 | 350 | def install(): | ||
634 | 351 | ... | ||
635 | 352 | |||
636 | 353 | # register a hook, providing a custom hook name | ||
637 | 354 | @hooks.hook("config-changed") | ||
638 | 355 | def config_changed(): | ||
639 | 356 | ... | ||
640 | 357 | |||
641 | 358 | if __name__ == "__main__": | ||
642 | 359 | # execute a hook based on the name the program is called by | ||
643 | 360 | hooks.execute(sys.argv) | ||
644 | 361 | """ | ||
645 | 362 | |||
646 | 312 | def __init__(self): | 363 | def __init__(self): |
647 | 313 | super(Hooks, self).__init__() | 364 | super(Hooks, self).__init__() |
648 | 314 | self._hooks = {} | 365 | self._hooks = {} |
649 | 315 | 366 | ||
650 | 316 | def register(self, name, function): | 367 | def register(self, name, function): |
651 | 368 | """Register a hook""" | ||
652 | 317 | self._hooks[name] = function | 369 | self._hooks[name] = function |
653 | 318 | 370 | ||
654 | 319 | def execute(self, args): | 371 | def execute(self, args): |
655 | 372 | """Execute a registered hook based on args[0]""" | ||
656 | 320 | hook_name = os.path.basename(args[0]) | 373 | hook_name = os.path.basename(args[0]) |
657 | 321 | if hook_name in self._hooks: | 374 | if hook_name in self._hooks: |
658 | 322 | self._hooks[hook_name]() | 375 | self._hooks[hook_name]() |
659 | @@ -324,6 +377,7 @@ | |||
660 | 324 | raise UnregisteredHookError(hook_name) | 377 | raise UnregisteredHookError(hook_name) |
661 | 325 | 378 | ||
662 | 326 | def hook(self, *hook_names): | 379 | def hook(self, *hook_names): |
663 | 380 | """Decorator, registering them as hooks""" | ||
664 | 327 | def wrapper(decorated): | 381 | def wrapper(decorated): |
665 | 328 | for hook_name in hook_names: | 382 | for hook_name in hook_names: |
666 | 329 | self.register(hook_name, decorated) | 383 | self.register(hook_name, decorated) |
667 | @@ -337,4 +391,5 @@ | |||
668 | 337 | 391 | ||
669 | 338 | 392 | ||
670 | 339 | def charm_dir(): | 393 | def charm_dir(): |
671 | 394 | """Return the root directory of the current charm""" | ||
672 | 340 | return os.environ.get('CHARM_DIR') | 395 | return os.environ.get('CHARM_DIR') |
673 | 341 | 396 | ||
674 | === modified file 'hooks/charmhelpers/core/host.py' | |||
675 | --- hooks/charmhelpers/core/host.py 2013-09-20 16:29:50 +0000 | |||
676 | +++ hooks/charmhelpers/core/host.py 2013-11-08 05:43:26 +0000 | |||
677 | @@ -19,18 +19,22 @@ | |||
678 | 19 | 19 | ||
679 | 20 | 20 | ||
680 | 21 | def service_start(service_name): | 21 | def service_start(service_name): |
681 | 22 | """Start a system service""" | ||
682 | 22 | return service('start', service_name) | 23 | return service('start', service_name) |
683 | 23 | 24 | ||
684 | 24 | 25 | ||
685 | 25 | def service_stop(service_name): | 26 | def service_stop(service_name): |
686 | 27 | """Stop a system service""" | ||
687 | 26 | return service('stop', service_name) | 28 | return service('stop', service_name) |
688 | 27 | 29 | ||
689 | 28 | 30 | ||
690 | 29 | def service_restart(service_name): | 31 | def service_restart(service_name): |
691 | 32 | """Restart a system service""" | ||
692 | 30 | return service('restart', service_name) | 33 | return service('restart', service_name) |
693 | 31 | 34 | ||
694 | 32 | 35 | ||
695 | 33 | def service_reload(service_name, restart_on_failure=False): | 36 | def service_reload(service_name, restart_on_failure=False): |
696 | 37 | """Reload a system service, optionally falling back to restart if reload fails""" | ||
697 | 34 | service_result = service('reload', service_name) | 38 | service_result = service('reload', service_name) |
698 | 35 | if not service_result and restart_on_failure: | 39 | if not service_result and restart_on_failure: |
699 | 36 | service_result = service('restart', service_name) | 40 | service_result = service('restart', service_name) |
700 | @@ -38,11 +42,13 @@ | |||
701 | 38 | 42 | ||
702 | 39 | 43 | ||
703 | 40 | def service(action, service_name): | 44 | def service(action, service_name): |
704 | 45 | """Control a system service""" | ||
705 | 41 | cmd = ['service', service_name, action] | 46 | cmd = ['service', service_name, action] |
706 | 42 | return subprocess.call(cmd) == 0 | 47 | return subprocess.call(cmd) == 0 |
707 | 43 | 48 | ||
708 | 44 | 49 | ||
709 | 45 | def service_running(service): | 50 | def service_running(service): |
710 | 51 | """Determine whether a system service is running""" | ||
711 | 46 | try: | 52 | try: |
712 | 47 | output = subprocess.check_output(['service', service, 'status']) | 53 | output = subprocess.check_output(['service', service, 'status']) |
713 | 48 | except subprocess.CalledProcessError: | 54 | except subprocess.CalledProcessError: |
714 | @@ -55,7 +61,7 @@ | |||
715 | 55 | 61 | ||
716 | 56 | 62 | ||
717 | 57 | def adduser(username, password=None, shell='/bin/bash', system_user=False): | 63 | def adduser(username, password=None, shell='/bin/bash', system_user=False): |
719 | 58 | """Add a user""" | 64 | """Add a user to the system""" |
720 | 59 | try: | 65 | try: |
721 | 60 | user_info = pwd.getpwnam(username) | 66 | user_info = pwd.getpwnam(username) |
722 | 61 | log('user {0} already exists!'.format(username)) | 67 | log('user {0} already exists!'.format(username)) |
723 | @@ -138,7 +144,7 @@ | |||
724 | 138 | 144 | ||
725 | 139 | 145 | ||
726 | 140 | def mount(device, mountpoint, options=None, persist=False): | 146 | def mount(device, mountpoint, options=None, persist=False): |
728 | 141 | '''Mount a filesystem''' | 147 | """Mount a filesystem at a particular mountpoint""" |
729 | 142 | cmd_args = ['mount'] | 148 | cmd_args = ['mount'] |
730 | 143 | if options is not None: | 149 | if options is not None: |
731 | 144 | cmd_args.extend(['-o', options]) | 150 | cmd_args.extend(['-o', options]) |
732 | @@ -155,7 +161,7 @@ | |||
733 | 155 | 161 | ||
734 | 156 | 162 | ||
735 | 157 | def umount(mountpoint, persist=False): | 163 | def umount(mountpoint, persist=False): |
737 | 158 | '''Unmount a filesystem''' | 164 | """Unmount a filesystem""" |
738 | 159 | cmd_args = ['umount', mountpoint] | 165 | cmd_args = ['umount', mountpoint] |
739 | 160 | try: | 166 | try: |
740 | 161 | subprocess.check_output(cmd_args) | 167 | subprocess.check_output(cmd_args) |
741 | @@ -169,7 +175,7 @@ | |||
742 | 169 | 175 | ||
743 | 170 | 176 | ||
744 | 171 | def mounts(): | 177 | def mounts(): |
746 | 172 | '''List of all mounted volumes as [[mountpoint,device],[...]]''' | 178 | """Get a list of all mounted volumes as [[mountpoint,device],[...]]""" |
747 | 173 | with open('/proc/mounts') as f: | 179 | with open('/proc/mounts') as f: |
748 | 174 | # [['/mount/point','/dev/path'],[...]] | 180 | # [['/mount/point','/dev/path'],[...]] |
749 | 175 | system_mounts = [m[1::-1] for m in [l.strip().split() | 181 | system_mounts = [m[1::-1] for m in [l.strip().split() |
750 | @@ -178,7 +184,7 @@ | |||
751 | 178 | 184 | ||
752 | 179 | 185 | ||
753 | 180 | def file_hash(path): | 186 | def file_hash(path): |
755 | 181 | ''' Generate a md5 hash of the contents of 'path' or None if not found ''' | 187 | """Generate a md5 hash of the contents of 'path' or None if not found """ |
756 | 182 | if os.path.exists(path): | 188 | if os.path.exists(path): |
757 | 183 | h = hashlib.md5() | 189 | h = hashlib.md5() |
758 | 184 | with open(path, 'r') as source: | 190 | with open(path, 'r') as source: |
759 | @@ -189,7 +195,7 @@ | |||
760 | 189 | 195 | ||
761 | 190 | 196 | ||
762 | 191 | def restart_on_change(restart_map): | 197 | def restart_on_change(restart_map): |
764 | 192 | ''' Restart services based on configuration files changing | 198 | """Restart services based on configuration files changing |
765 | 193 | 199 | ||
766 | 194 | This function is used a decorator, for example | 200 | This function is used a decorator, for example |
767 | 195 | 201 | ||
768 | @@ -202,7 +208,7 @@ | |||
769 | 202 | In this example, the cinder-api and cinder-volume services | 208 | In this example, the cinder-api and cinder-volume services |
770 | 203 | would be restarted if /etc/ceph/ceph.conf is changed by the | 209 | would be restarted if /etc/ceph/ceph.conf is changed by the |
771 | 204 | ceph_client_changed function. | 210 | ceph_client_changed function. |
773 | 205 | ''' | 211 | """ |
774 | 206 | def wrap(f): | 212 | def wrap(f): |
775 | 207 | def wrapped_f(*args): | 213 | def wrapped_f(*args): |
776 | 208 | checksums = {} | 214 | checksums = {} |
777 | @@ -220,7 +226,7 @@ | |||
778 | 220 | 226 | ||
779 | 221 | 227 | ||
780 | 222 | def lsb_release(): | 228 | def lsb_release(): |
782 | 223 | '''Return /etc/lsb-release in a dict''' | 229 | """Return /etc/lsb-release in a dict""" |
783 | 224 | d = {} | 230 | d = {} |
784 | 225 | with open('/etc/lsb-release', 'r') as lsb: | 231 | with open('/etc/lsb-release', 'r') as lsb: |
785 | 226 | for l in lsb: | 232 | for l in lsb: |
786 | @@ -230,7 +236,7 @@ | |||
787 | 230 | 236 | ||
788 | 231 | 237 | ||
789 | 232 | def pwgen(length=None): | 238 | def pwgen(length=None): |
791 | 233 | '''Generate a random pasword.''' | 239 | """Generate a random pasword.""" |
792 | 234 | if length is None: | 240 | if length is None: |
793 | 235 | length = random.choice(range(35, 45)) | 241 | length = random.choice(range(35, 45)) |
794 | 236 | alphanumeric_chars = [ | 242 | alphanumeric_chars = [ |
795 | 237 | 243 | ||
796 | === modified file 'hooks/charmhelpers/fetch/__init__.py' | |||
797 | --- hooks/charmhelpers/fetch/__init__.py 2013-09-23 13:26:04 +0000 | |||
798 | +++ hooks/charmhelpers/fetch/__init__.py 2013-11-08 05:43:26 +0000 | |||
799 | @@ -20,6 +20,32 @@ | |||
800 | 20 | PROPOSED_POCKET = """# Proposed | 20 | PROPOSED_POCKET = """# Proposed |
801 | 21 | deb http://archive.ubuntu.com/ubuntu {}-proposed main universe multiverse restricted | 21 | deb http://archive.ubuntu.com/ubuntu {}-proposed main universe multiverse restricted |
802 | 22 | """ | 22 | """ |
803 | 23 | CLOUD_ARCHIVE_POCKETS = { | ||
804 | 24 | # Folsom | ||
805 | 25 | 'folsom': 'precise-updates/folsom', | ||
806 | 26 | 'precise-folsom': 'precise-updates/folsom', | ||
807 | 27 | 'precise-folsom/updates': 'precise-updates/folsom', | ||
808 | 28 | 'precise-updates/folsom': 'precise-updates/folsom', | ||
809 | 29 | 'folsom/proposed': 'precise-proposed/folsom', | ||
810 | 30 | 'precise-folsom/proposed': 'precise-proposed/folsom', | ||
811 | 31 | 'precise-proposed/folsom': 'precise-proposed/folsom', | ||
812 | 32 | # Grizzly | ||
813 | 33 | 'grizzly': 'precise-updates/grizzly', | ||
814 | 34 | 'precise-grizzly': 'precise-updates/grizzly', | ||
815 | 35 | 'precise-grizzly/updates': 'precise-updates/grizzly', | ||
816 | 36 | 'precise-updates/grizzly': 'precise-updates/grizzly', | ||
817 | 37 | 'grizzly/proposed': 'precise-proposed/grizzly', | ||
818 | 38 | 'precise-grizzly/proposed': 'precise-proposed/grizzly', | ||
819 | 39 | 'precise-proposed/grizzly': 'precise-proposed/grizzly', | ||
820 | 40 | # Havana | ||
821 | 41 | 'havana': 'precise-updates/havana', | ||
822 | 42 | 'precise-havana': 'precise-updates/havana', | ||
823 | 43 | 'precise-havana/updates': 'precise-updates/havana', | ||
824 | 44 | 'precise-updates/havana': 'precise-updates/havana', | ||
825 | 45 | 'havana/proposed': 'precise-proposed/havana', | ||
826 | 46 | 'precies-havana/proposed': 'precise-proposed/havana', | ||
827 | 47 | 'precise-proposed/havana': 'precise-proposed/havana', | ||
828 | 48 | } | ||
829 | 23 | 49 | ||
830 | 24 | 50 | ||
831 | 25 | def filter_installed_packages(packages): | 51 | def filter_installed_packages(packages): |
832 | @@ -79,16 +105,35 @@ | |||
833 | 79 | subprocess.call(cmd) | 105 | subprocess.call(cmd) |
834 | 80 | 106 | ||
835 | 81 | 107 | ||
836 | 108 | def apt_hold(packages, fatal=False): | ||
837 | 109 | """Hold one or more packages""" | ||
838 | 110 | cmd = ['apt-mark', 'hold'] | ||
839 | 111 | if isinstance(packages, basestring): | ||
840 | 112 | cmd.append(packages) | ||
841 | 113 | else: | ||
842 | 114 | cmd.extend(packages) | ||
843 | 115 | log("Holding {}".format(packages)) | ||
844 | 116 | if fatal: | ||
845 | 117 | subprocess.check_call(cmd) | ||
846 | 118 | else: | ||
847 | 119 | subprocess.call(cmd) | ||
848 | 120 | |||
849 | 121 | |||
850 | 82 | def add_source(source, key=None): | 122 | def add_source(source, key=None): |
853 | 83 | if ((source.startswith('ppa:') or | 123 | if (source.startswith('ppa:') or |
854 | 84 | source.startswith('http:'))): | 124 | source.startswith('http:') or |
855 | 125 | source.startswith('deb ') or | ||
856 | 126 | source.startswith('cloud-archive:')): | ||
857 | 85 | subprocess.check_call(['add-apt-repository', '--yes', source]) | 127 | subprocess.check_call(['add-apt-repository', '--yes', source]) |
858 | 86 | elif source.startswith('cloud:'): | 128 | elif source.startswith('cloud:'): |
859 | 87 | apt_install(filter_installed_packages(['ubuntu-cloud-keyring']), | 129 | apt_install(filter_installed_packages(['ubuntu-cloud-keyring']), |
860 | 88 | fatal=True) | 130 | fatal=True) |
861 | 89 | pocket = source.split(':')[-1] | 131 | pocket = source.split(':')[-1] |
862 | 132 | if pocket not in CLOUD_ARCHIVE_POCKETS: | ||
863 | 133 | raise SourceConfigError('Unsupported cloud: source option %s' % pocket) | ||
864 | 134 | actual_pocket = CLOUD_ARCHIVE_POCKETS[pocket] | ||
865 | 90 | with open('/etc/apt/sources.list.d/cloud-archive.list', 'w') as apt: | 135 | with open('/etc/apt/sources.list.d/cloud-archive.list', 'w') as apt: |
867 | 91 | apt.write(CLOUD_ARCHIVE.format(pocket)) | 136 | apt.write(CLOUD_ARCHIVE.format(actual_pocket)) |
868 | 92 | elif source == 'proposed': | 137 | elif source == 'proposed': |
869 | 93 | release = lsb_release()['DISTRIB_CODENAME'] | 138 | release = lsb_release()['DISTRIB_CODENAME'] |
870 | 94 | with open('/etc/apt/sources.list.d/proposed.list', 'w') as apt: | 139 | with open('/etc/apt/sources.list.d/proposed.list', 'w') as apt: |
871 | @@ -118,8 +163,11 @@ | |||
872 | 118 | Note that 'null' (a.k.a. None) should not be quoted. | 163 | Note that 'null' (a.k.a. None) should not be quoted. |
873 | 119 | """ | 164 | """ |
874 | 120 | sources = safe_load(config(sources_var)) | 165 | sources = safe_load(config(sources_var)) |
877 | 121 | keys = safe_load(config(keys_var)) | 166 | keys = config(keys_var) |
878 | 122 | if isinstance(sources, basestring) and isinstance(keys, basestring): | 167 | if keys is not None: |
879 | 168 | keys = safe_load(keys) | ||
880 | 169 | if isinstance(sources, basestring) and ( | ||
881 | 170 | keys is None or isinstance(keys, basestring)): | ||
882 | 123 | add_source(sources, keys) | 171 | add_source(sources, keys) |
883 | 124 | else: | 172 | else: |
884 | 125 | if not len(sources) == len(keys): | 173 | if not len(sources) == len(keys): |
885 | 126 | 174 | ||
886 | === modified file 'hooks/charmhelpers/fetch/bzrurl.py' | |||
887 | --- hooks/charmhelpers/fetch/bzrurl.py 2013-09-23 13:26:04 +0000 | |||
888 | +++ hooks/charmhelpers/fetch/bzrurl.py 2013-11-08 05:43:26 +0000 | |||
889 | @@ -12,6 +12,7 @@ | |||
890 | 12 | apt_install("python-bzrlib") | 12 | apt_install("python-bzrlib") |
891 | 13 | from bzrlib.branch import Branch | 13 | from bzrlib.branch import Branch |
892 | 14 | 14 | ||
893 | 15 | |||
894 | 15 | class BzrUrlFetchHandler(BaseFetchHandler): | 16 | class BzrUrlFetchHandler(BaseFetchHandler): |
895 | 16 | """Handler for bazaar branches via generic and lp URLs""" | 17 | """Handler for bazaar branches via generic and lp URLs""" |
896 | 17 | def can_handle(self, source): | 18 | def can_handle(self, source): |
897 | @@ -46,4 +47,3 @@ | |||
898 | 46 | except OSError as e: | 47 | except OSError as e: |
899 | 47 | raise UnhandledSource(e.strerror) | 48 | raise UnhandledSource(e.strerror) |
900 | 48 | return dest_dir | 49 | return dest_dir |
901 | 49 | |||
902 | 50 | 50 | ||
903 | === added symlink 'hooks/nova-vmware-relation-changed' | |||
904 | === target is u'nova_cc_hooks.py' | |||
905 | === added symlink 'hooks/nova-vmware-relation-joined' | |||
906 | === target is u'nova_cc_hooks.py' | |||
907 | === modified file 'hooks/nova_cc_context.py' | |||
908 | --- hooks/nova_cc_context.py 2013-09-30 20:46:50 +0000 | |||
909 | +++ hooks/nova_cc_context.py 2013-11-08 05:43:26 +0000 | |||
910 | @@ -139,6 +139,16 @@ | |||
911 | 139 | def __call__(self): | 139 | def __call__(self): |
912 | 140 | ctxt = super(NeutronCCContext, self).__call__() | 140 | ctxt = super(NeutronCCContext, self).__call__() |
913 | 141 | ctxt['external_network'] = config('neutron-external-network') | 141 | ctxt['external_network'] = config('neutron-external-network') |
914 | 142 | if 'nvp' in [config('quantum-plugin'), config('neutron-plugin')]: | ||
915 | 143 | _config = config() | ||
916 | 144 | for k, v in _config.iteritems(): | ||
917 | 145 | if k.startswith('nvp'): | ||
918 | 146 | ctxt[k.replace('-', '_')] = v | ||
919 | 147 | if 'nvp-controllers' in _config: | ||
920 | 148 | ctxt['nvp_controllers'] = \ | ||
921 | 149 | ','.join(_config['nvp-controllers'].split()) | ||
922 | 150 | ctxt['nvp_controllers_list'] = \ | ||
923 | 151 | _config['nvp-controllers'].split() | ||
924 | 142 | return ctxt | 152 | return ctxt |
925 | 143 | 153 | ||
926 | 144 | 154 | ||
927 | 145 | 155 | ||
928 | === modified file 'hooks/nova_cc_hooks.py' | |||
929 | --- hooks/nova_cc_hooks.py 2013-11-06 00:49:41 +0000 | |||
930 | +++ hooks/nova_cc_hooks.py 2013-11-08 05:43:26 +0000 | |||
931 | @@ -3,6 +3,7 @@ | |||
932 | 3 | import os | 3 | import os |
933 | 4 | import shutil | 4 | import shutil |
934 | 5 | import sys | 5 | import sys |
935 | 6 | import uuid | ||
936 | 6 | 7 | ||
937 | 7 | from subprocess import check_call | 8 | from subprocess import check_call |
938 | 8 | from urlparse import urlparse | 9 | from urlparse import urlparse |
939 | @@ -25,7 +26,7 @@ | |||
940 | 25 | ) | 26 | ) |
941 | 26 | 27 | ||
942 | 27 | from charmhelpers.fetch import ( | 28 | from charmhelpers.fetch import ( |
944 | 28 | apt_install, apt_update, filter_installed_packages | 29 | apt_install, apt_update |
945 | 29 | ) | 30 | ) |
946 | 30 | 31 | ||
947 | 31 | from charmhelpers.contrib.openstack.utils import ( | 32 | from charmhelpers.contrib.openstack.utils import ( |
948 | @@ -148,6 +149,9 @@ | |||
949 | 148 | 149 | ||
950 | 149 | if eligible_leader(CLUSTER_RES): | 150 | if eligible_leader(CLUSTER_RES): |
951 | 150 | migrate_database() | 151 | migrate_database() |
952 | 152 | log('Triggering remote cloud-compute restarts.') | ||
953 | 153 | [compute_joined(rid=rid, remote_restart=True) | ||
954 | 154 | for rid in relation_ids('cloud-compute')] | ||
955 | 151 | 155 | ||
956 | 152 | 156 | ||
957 | 153 | @hooks.hook('image-service-relation-changed') | 157 | @hooks.hook('image-service-relation-changed') |
958 | @@ -184,6 +188,7 @@ | |||
959 | 184 | CONFIGS.write(NEUTRON_CONF) | 188 | CONFIGS.write(NEUTRON_CONF) |
960 | 185 | [compute_joined(rid) for rid in relation_ids('cloud-compute')] | 189 | [compute_joined(rid) for rid in relation_ids('cloud-compute')] |
961 | 186 | [quantum_joined(rid) for rid in relation_ids('quantum-network-service')] | 190 | [quantum_joined(rid) for rid in relation_ids('quantum-network-service')] |
962 | 191 | [nova_vmware_relation_joined(rid) for rid in relation_ids('nova-vmware')] | ||
963 | 187 | configure_https() | 192 | configure_https() |
964 | 188 | 193 | ||
965 | 189 | 194 | ||
966 | @@ -230,8 +235,32 @@ | |||
967 | 230 | out.write('export OS_REGION_NAME=%s\n' % config('region')) | 235 | out.write('export OS_REGION_NAME=%s\n' % config('region')) |
968 | 231 | 236 | ||
969 | 232 | 237 | ||
970 | 238 | def keystone_compute_settings(): | ||
971 | 239 | ks_auth_config = _auth_config() | ||
972 | 240 | rel_settings = {} | ||
973 | 241 | |||
974 | 242 | if network_manager() in ['quantum', 'neutron']: | ||
975 | 243 | if ks_auth_config: | ||
976 | 244 | rel_settings.update(ks_auth_config) | ||
977 | 245 | |||
978 | 246 | rel_settings.update({ | ||
979 | 247 | # XXX: Rename these relations settings? | ||
980 | 248 | 'quantum_plugin': neutron_plugin(), | ||
981 | 249 | 'region': config('region'), | ||
982 | 250 | 'quantum_security_groups': config('quantum-security-groups'), | ||
983 | 251 | 'quantum_url': (canonical_url(CONFIGS) + ':' + | ||
984 | 252 | str(api_port('neutron-server'))), | ||
985 | 253 | }) | ||
986 | 254 | |||
987 | 255 | ks_ca = keystone_ca_cert_b64() | ||
988 | 256 | if ks_auth_config and ks_ca: | ||
989 | 257 | rel_settings['ca_cert'] = ks_ca | ||
990 | 258 | |||
991 | 259 | return rel_settings | ||
992 | 260 | |||
993 | 261 | |||
994 | 233 | @hooks.hook('cloud-compute-relation-joined') | 262 | @hooks.hook('cloud-compute-relation-joined') |
996 | 234 | def compute_joined(rid=None): | 263 | def compute_joined(rid=None, remote_restart=False): |
997 | 235 | if not eligible_leader(CLUSTER_RES): | 264 | if not eligible_leader(CLUSTER_RES): |
998 | 236 | return | 265 | return |
999 | 237 | rel_settings = { | 266 | rel_settings = { |
1000 | @@ -242,24 +271,12 @@ | |||
1001 | 242 | 'ec2_host': unit_get('private-address'), | 271 | 'ec2_host': unit_get('private-address'), |
1002 | 243 | } | 272 | } |
1003 | 244 | 273 | ||
1022 | 245 | ks_auth_config = _auth_config() | 274 | # update relation setting if we're attempting to restart remote |
1023 | 246 | 275 | # services | |
1024 | 247 | if network_manager() in ['quantum', 'neutron']: | 276 | if remote_restart: |
1025 | 248 | if ks_auth_config: | 277 | rel_settings['restart_trigger'] = str(uuid.uuid4()) |
1026 | 249 | rel_settings.update(ks_auth_config) | 278 | |
1027 | 250 | 279 | rel_settings.update(keystone_compute_settings()) | |
1010 | 251 | rel_settings.update({ | ||
1011 | 252 | # XXX: Rename these relations settings? | ||
1012 | 253 | 'quantum_plugin': neutron_plugin(), | ||
1013 | 254 | 'region': config('region'), | ||
1014 | 255 | 'quantum_security_groups': config('quantum-security-groups'), | ||
1015 | 256 | 'quantum_url': (canonical_url(CONFIGS) + ':' + | ||
1016 | 257 | str(api_port('neutron-server'))), | ||
1017 | 258 | }) | ||
1018 | 259 | |||
1019 | 260 | ks_ca = keystone_ca_cert_b64() | ||
1020 | 261 | if ks_auth_config and ks_ca: | ||
1021 | 262 | rel_settings['ca_cert'] = ks_ca | ||
1028 | 263 | relation_set(relation_id=rid, **rel_settings) | 280 | relation_set(relation_id=rid, **rel_settings) |
1029 | 264 | 281 | ||
1030 | 265 | 282 | ||
1031 | @@ -287,15 +304,6 @@ | |||
1032 | 287 | if not eligible_leader(CLUSTER_RES): | 304 | if not eligible_leader(CLUSTER_RES): |
1033 | 288 | return | 305 | return |
1034 | 289 | 306 | ||
1035 | 290 | if network_manager() == 'quantum': | ||
1036 | 291 | pkg = 'quantum-server' | ||
1037 | 292 | else: | ||
1038 | 293 | pkg = 'neutron-server' | ||
1039 | 294 | |||
1040 | 295 | required_pkg = filter_installed_packages([pkg]) | ||
1041 | 296 | if required_pkg: | ||
1042 | 297 | apt_install(required_pkg) | ||
1043 | 298 | |||
1044 | 299 | url = canonical_url(CONFIGS) + ':9696' | 307 | url = canonical_url(CONFIGS) + ':9696' |
1045 | 300 | # XXX: Can we rename to neutron_*? | 308 | # XXX: Can we rename to neutron_*? |
1046 | 301 | rel_settings = { | 309 | rel_settings = { |
1047 | @@ -397,6 +405,28 @@ | |||
1048 | 397 | identity_joined(rid=rid) | 405 | identity_joined(rid=rid) |
1049 | 398 | 406 | ||
1050 | 399 | 407 | ||
1051 | 408 | @hooks.hook() | ||
1052 | 409 | def nova_vmware_relation_joined(rid=None): | ||
1053 | 410 | rel_settings = {'network_manager': network_manager()} | ||
1054 | 411 | |||
1055 | 412 | ks_auth = _auth_config() | ||
1056 | 413 | if ks_auth: | ||
1057 | 414 | rel_settings.update(ks_auth) | ||
1058 | 415 | rel_settings.update({ | ||
1059 | 416 | 'quantum_plugin': neutron_plugin(), | ||
1060 | 417 | 'quantum_security_groups': config('quantum-security-groups'), | ||
1061 | 418 | 'quantum_url': (canonical_url(CONFIGS) + ':' + | ||
1062 | 419 | str(api_port('neutron-server')))}) | ||
1063 | 420 | |||
1064 | 421 | relation_set(relation_id=rid, **rel_settings) | ||
1065 | 422 | |||
1066 | 423 | |||
1067 | 424 | @hooks.hook('nova-vmware-relation-changed') | ||
1068 | 425 | @restart_on_change(restart_map()) | ||
1069 | 426 | def nova_vmware_relation_changed(): | ||
1070 | 427 | CONFIGS.write('/etc/nova/nova.conf') | ||
1071 | 428 | |||
1072 | 429 | |||
1073 | 400 | @hooks.hook('upgrade-charm') | 430 | @hooks.hook('upgrade-charm') |
1074 | 401 | def upgrade_charm(): | 431 | def upgrade_charm(): |
1075 | 402 | for r_id in relation_ids('amqp'): | 432 | for r_id in relation_ids('amqp'): |
1076 | 403 | 433 | ||
1077 | === modified file 'hooks/nova_cc_utils.py' | |||
1078 | --- hooks/nova_cc_utils.py 2013-09-25 16:24:36 +0000 | |||
1079 | +++ hooks/nova_cc_utils.py 2013-11-08 05:43:26 +0000 | |||
1080 | @@ -76,6 +76,8 @@ | |||
1081 | 76 | HAPROXY_CONF = '/etc/haproxy/haproxy.cfg' | 76 | HAPROXY_CONF = '/etc/haproxy/haproxy.cfg' |
1082 | 77 | APACHE_CONF = '/etc/apache2/sites-available/openstack_https_frontend' | 77 | APACHE_CONF = '/etc/apache2/sites-available/openstack_https_frontend' |
1083 | 78 | APACHE_24_CONF = '/etc/apache2/sites-available/openstack_https_frontend.conf' | 78 | APACHE_24_CONF = '/etc/apache2/sites-available/openstack_https_frontend.conf' |
1084 | 79 | NEUTRON_DEFAULT = '/etc/default/neutron-server' | ||
1085 | 80 | QUANTUM_DEFAULT = '/etc/default/quantum-server' | ||
1086 | 79 | 81 | ||
1087 | 80 | BASE_RESOURCE_MAP = OrderedDict([ | 82 | BASE_RESOURCE_MAP = OrderedDict([ |
1088 | 81 | (NOVA_CONF, { | 83 | (NOVA_CONF, { |
1089 | @@ -84,6 +86,11 @@ | |||
1090 | 84 | context.SharedDBContext(relation_prefix='nova'), | 86 | context.SharedDBContext(relation_prefix='nova'), |
1091 | 85 | context.ImageServiceContext(), | 87 | context.ImageServiceContext(), |
1092 | 86 | context.OSConfigFlagContext(), | 88 | context.OSConfigFlagContext(), |
1093 | 89 | context.SubordinateConfigContext( | ||
1094 | 90 | interface='nova-vmware', | ||
1095 | 91 | service='nova', | ||
1096 | 92 | config_file=NOVA_CONF, | ||
1097 | 93 | ), | ||
1098 | 87 | nova_cc_context.HAProxyContext(), | 94 | nova_cc_context.HAProxyContext(), |
1099 | 88 | nova_cc_context.IdentityServiceContext(), | 95 | nova_cc_context.IdentityServiceContext(), |
1100 | 89 | nova_cc_context.VolumeServiceContext(), | 96 | nova_cc_context.VolumeServiceContext(), |
1101 | @@ -100,6 +107,10 @@ | |||
1102 | 100 | nova_cc_context.IdentityServiceContext(), | 107 | nova_cc_context.IdentityServiceContext(), |
1103 | 101 | nova_cc_context.NeutronCCContext()], | 108 | nova_cc_context.NeutronCCContext()], |
1104 | 102 | }), | 109 | }), |
1105 | 110 | (QUANTUM_DEFAULT, { | ||
1106 | 111 | 'services': ['quantum-server'], | ||
1107 | 112 | 'contexts': [nova_cc_context.NeutronCCContext()], | ||
1108 | 113 | }), | ||
1109 | 103 | (QUANTUM_API_PASTE, { | 114 | (QUANTUM_API_PASTE, { |
1110 | 104 | 'services': ['quantum-server'], | 115 | 'services': ['quantum-server'], |
1111 | 105 | 'contexts': [nova_cc_context.IdentityServiceContext()], | 116 | 'contexts': [nova_cc_context.IdentityServiceContext()], |
1112 | @@ -111,6 +122,10 @@ | |||
1113 | 111 | nova_cc_context.NeutronCCContext(), | 122 | nova_cc_context.NeutronCCContext(), |
1114 | 112 | nova_cc_context.HAProxyContext()], | 123 | nova_cc_context.HAProxyContext()], |
1115 | 113 | }), | 124 | }), |
1116 | 125 | (NEUTRON_DEFAULT, { | ||
1117 | 126 | 'services': ['neutron-server'], | ||
1118 | 127 | 'contexts': [nova_cc_context.NeutronCCContext()], | ||
1119 | 128 | }), | ||
1120 | 114 | (HAPROXY_CONF, { | 129 | (HAPROXY_CONF, { |
1121 | 115 | 'contexts': [context.HAProxyContext(), | 130 | 'contexts': [context.HAProxyContext(), |
1122 | 116 | nova_cc_context.HAProxyContext()], | 131 | nova_cc_context.HAProxyContext()], |
1123 | @@ -166,11 +181,12 @@ | |||
1124 | 166 | plugin = neutron_plugin() | 181 | plugin = neutron_plugin() |
1125 | 167 | if plugin: | 182 | if plugin: |
1126 | 168 | conf = neutron_plugin_attribute(plugin, 'config', net_manager) | 183 | conf = neutron_plugin_attribute(plugin, 'config', net_manager) |
1127 | 169 | service = '%s-server' % net_manager | ||
1128 | 170 | ctxts = (neutron_plugin_attribute(plugin, 'contexts', net_manager) | 184 | ctxts = (neutron_plugin_attribute(plugin, 'contexts', net_manager) |
1129 | 171 | or []) | 185 | or []) |
1130 | 186 | services = neutron_plugin_attribute(plugin, 'server_services', | ||
1131 | 187 | net_manager) | ||
1132 | 172 | resource_map[conf] = {} | 188 | resource_map[conf] = {} |
1134 | 173 | resource_map[conf]['services'] = [service] | 189 | resource_map[conf]['services'] = services |
1135 | 174 | resource_map[conf]['contexts'] = ctxts | 190 | resource_map[conf]['contexts'] = ctxts |
1136 | 175 | resource_map[conf]['contexts'].append( | 191 | resource_map[conf]['contexts'].append( |
1137 | 176 | nova_cc_context.NeutronCCContext()) | 192 | nova_cc_context.NeutronCCContext()) |
1138 | @@ -178,6 +194,16 @@ | |||
1139 | 178 | # nova-conductor for releases >= G. | 194 | # nova-conductor for releases >= G. |
1140 | 179 | if os_release('nova-common') not in ['essex', 'folsom']: | 195 | if os_release('nova-common') not in ['essex', 'folsom']: |
1141 | 180 | resource_map['/etc/nova/nova.conf']['services'] += ['nova-conductor'] | 196 | resource_map['/etc/nova/nova.conf']['services'] += ['nova-conductor'] |
1142 | 197 | |||
1143 | 198 | # also manage any configs that are being updated by subordinates. | ||
1144 | 199 | vmware_ctxt = context.SubordinateConfigContext(interface='nova-vmware', | ||
1145 | 200 | service='nova', | ||
1146 | 201 | config_file=NOVA_CONF) | ||
1147 | 202 | vmware_ctxt = vmware_ctxt() | ||
1148 | 203 | if vmware_ctxt and 'services' in vmware_ctxt: | ||
1149 | 204 | for s in vmware_ctxt['services']: | ||
1150 | 205 | if s not in resource_map[NOVA_CONF]['services']: | ||
1151 | 206 | resource_map[NOVA_CONF]['services'].append(s) | ||
1152 | 181 | return resource_map | 207 | return resource_map |
1153 | 182 | 208 | ||
1154 | 183 | 209 | ||
1155 | @@ -217,6 +243,10 @@ | |||
1156 | 217 | packages = [] + BASE_PACKAGES | 243 | packages = [] + BASE_PACKAGES |
1157 | 218 | for k, v in resource_map().iteritems(): | 244 | for k, v in resource_map().iteritems(): |
1158 | 219 | packages.extend(v['services']) | 245 | packages.extend(v['services']) |
1159 | 246 | if network_manager() in ['neutron', 'quantum']: | ||
1160 | 247 | pkgs = neutron_plugin_attribute(neutron_plugin(), 'server_packages', | ||
1161 | 248 | network_manager()) | ||
1162 | 249 | packages.extend(pkgs) | ||
1163 | 220 | return list(set(packages)) | 250 | return list(set(packages)) |
1164 | 221 | 251 | ||
1165 | 222 | 252 | ||
1166 | 223 | 253 | ||
1167 | === modified file 'metadata.yaml' | |||
1168 | --- metadata.yaml 2013-10-15 13:04:00 +0000 | |||
1169 | +++ metadata.yaml 2013-11-08 05:43:26 +0000 | |||
1170 | @@ -29,6 +29,9 @@ | |||
1171 | 29 | ha: | 29 | ha: |
1172 | 30 | interface: hacluster | 30 | interface: hacluster |
1173 | 31 | scope: container | 31 | scope: container |
1174 | 32 | nova-vmware: | ||
1175 | 33 | interface: nova-vmware | ||
1176 | 34 | scope: container | ||
1177 | 32 | peers: | 35 | peers: |
1178 | 33 | cluster: | 36 | cluster: |
1179 | 34 | interface: nova-ha | 37 | interface: nova-ha |
1180 | 35 | 38 | ||
1181 | === modified file 'revision' | |||
1182 | --- revision 2013-11-06 04:34:51 +0000 | |||
1183 | +++ revision 2013-11-08 05:43:26 +0000 | |||
1184 | @@ -1,1 +1,1 @@ | |||
1186 | 1 | 307 | 1 | 311 |
1187 | 2 | 2 | ||
1188 | === modified file 'templates/folsom/nova.conf' | |||
1189 | --- templates/folsom/nova.conf 2013-09-30 20:46:50 +0000 | |||
1190 | +++ templates/folsom/nova.conf 2013-11-08 05:43:26 +0000 | |||
1191 | @@ -57,6 +57,14 @@ | |||
1192 | 57 | {% endif -%} | 57 | {% endif -%} |
1193 | 58 | {% endif -%} | 58 | {% endif -%} |
1194 | 59 | 59 | ||
1195 | 60 | {% if neutron_plugin and neutron_plugin == 'nvp' -%} | ||
1196 | 61 | security_group_api = neutron | ||
1197 | 62 | nova_firewall_driver = nova.virt.firewall.NoopFirewallDriver | ||
1198 | 63 | {% if external_network -%} | ||
1199 | 64 | default_floating_pool = {{ external_network }} | ||
1200 | 65 | {% endif -%} | ||
1201 | 66 | {% endif -%} | ||
1202 | 67 | |||
1203 | 60 | {% if network_manager_config -%} | 68 | {% if network_manager_config -%} |
1204 | 61 | {% for key, value in network_manager_config.iteritems() -%} | 69 | {% for key, value in network_manager_config.iteritems() -%} |
1205 | 62 | {{ key }} = {{ value }} | 70 | {{ key }} = {{ value }} |
1206 | @@ -90,3 +98,9 @@ | |||
1207 | 90 | {{ key }} = {{ value }} | 98 | {{ key }} = {{ value }} |
1208 | 91 | {% endfor -%} | 99 | {% endfor -%} |
1209 | 92 | {% endif -%} | 100 | {% endif -%} |
1210 | 101 | |||
1211 | 102 | {% if sections and 'DEFAULT' in sections -%} | ||
1212 | 103 | {% for key, value in sections['DEFAULT'] -%} | ||
1213 | 104 | {{ key }} = {{ value }} | ||
1214 | 105 | {% endfor -%} | ||
1215 | 106 | {% endif -%} | ||
1216 | 93 | 107 | ||
1217 | === added file 'templates/folsom/quantum-server' | |||
1218 | --- templates/folsom/quantum-server 1970-01-01 00:00:00 +0000 | |||
1219 | +++ templates/folsom/quantum-server 2013-11-08 05:43:26 +0000 | |||
1220 | @@ -0,0 +1,6 @@ | |||
1221 | 1 | # quantum | ||
1222 | 2 | ############################################################################### | ||
1223 | 3 | # [ WARNING ] | ||
1224 | 4 | # Configuration file maintained by Juju. Local changes may be overwritten. | ||
1225 | 5 | ############################################################################### | ||
1226 | 6 | QUANTUM_PLUGIN_CONFIG="{{ config }}" | ||
1227 | 0 | \ No newline at end of file | 7 | \ No newline at end of file |
1228 | 1 | 8 | ||
1229 | === added file 'templates/havana/neutron-server' | |||
1230 | --- templates/havana/neutron-server 1970-01-01 00:00:00 +0000 | |||
1231 | +++ templates/havana/neutron-server 2013-11-08 05:43:26 +0000 | |||
1232 | @@ -0,0 +1,6 @@ | |||
1233 | 1 | # havana | ||
1234 | 2 | ############################################################################### | ||
1235 | 3 | # [ WARNING ] | ||
1236 | 4 | # Configuration file maintained by Juju. Local changes may be overwritten. | ||
1237 | 5 | ############################################################################### | ||
1238 | 6 | NEUTRON_PLUGIN_CONFIG="{{ config }}" | ||
1239 | 0 | \ No newline at end of file | 7 | \ No newline at end of file |
1240 | 1 | 8 | ||
1241 | === added file 'templates/havana/nvp.ini' | |||
1242 | --- templates/havana/nvp.ini 1970-01-01 00:00:00 +0000 | |||
1243 | +++ templates/havana/nvp.ini 2013-11-08 05:43:26 +0000 | |||
1244 | @@ -0,0 +1,11 @@ | |||
1245 | 1 | # havana | ||
1246 | 2 | ############################################################################### | ||
1247 | 3 | # [ WARNING ] | ||
1248 | 4 | # Configuration file maintained by Juju. Local changes may be overwritten. | ||
1249 | 5 | ############################################################################### | ||
1250 | 6 | [DEFAULT] | ||
1251 | 7 | nvp_user = {{ nvp_username }} | ||
1252 | 8 | nvp_password = {{ nvp_password }} | ||
1253 | 9 | nvp_controllers = {{ nvp_controllers }} | ||
1254 | 10 | default_tz_uuid = {{ nvp_tz_uuid }} | ||
1255 | 11 | default_l3_gw_service_uuid = {{ nvp_l3_uuid }} | ||
1256 | 0 | 12 | ||
1257 | === modified file 'unit_tests/test_nova_cc_hooks.py' | |||
1258 | --- unit_tests/test_nova_cc_hooks.py 2013-09-27 16:18:25 +0000 | |||
1259 | +++ unit_tests/test_nova_cc_hooks.py 2013-11-08 05:43:26 +0000 | |||
1260 | @@ -17,8 +17,10 @@ | |||
1261 | 17 | 17 | ||
1262 | 18 | 18 | ||
1263 | 19 | TO_PATCH = [ | 19 | TO_PATCH = [ |
1264 | 20 | 'api_port', | ||
1265 | 20 | 'apt_update', | 21 | 'apt_update', |
1266 | 21 | 'apt_install', | 22 | 'apt_install', |
1267 | 23 | 'canonical_url', | ||
1268 | 22 | 'configure_installation_source', | 24 | 'configure_installation_source', |
1269 | 23 | 'charm_dir', | 25 | 'charm_dir', |
1270 | 24 | 'do_openstack_upgrade', | 26 | 'do_openstack_upgrade', |
1271 | @@ -33,11 +35,32 @@ | |||
1272 | 33 | 'ssh_known_hosts_b64', | 35 | 'ssh_known_hosts_b64', |
1273 | 34 | 'ssh_authorized_keys_b64', | 36 | 'ssh_authorized_keys_b64', |
1274 | 35 | 'save_script_rc', | 37 | 'save_script_rc', |
1276 | 36 | 'execd_preinstall' | 38 | 'execd_preinstall', |
1277 | 39 | 'network_manager', | ||
1278 | 40 | 'volume_service', | ||
1279 | 41 | 'unit_get', | ||
1280 | 42 | 'eligible_leader', | ||
1281 | 43 | 'keystone_ca_cert_b64', | ||
1282 | 44 | 'neutron_plugin', | ||
1283 | 37 | ] | 45 | ] |
1284 | 38 | 46 | ||
1285 | 39 | 47 | ||
1286 | 48 | FAKE_KS_AUTH_CFG = { | ||
1287 | 49 | 'auth_host': 'kshost', | ||
1288 | 50 | 'auth_port': '5000', | ||
1289 | 51 | 'service_port': 'token', | ||
1290 | 52 | 'service_username': 'admin_user', | ||
1291 | 53 | 'service_password': 'admin_passwd', | ||
1292 | 54 | 'service_tenant_name': 'admin_tenant', | ||
1293 | 55 | 'auth_uri': 'http://kshost:5000/v2', | ||
1294 | 56 | # quantum-gateway interface deviates a bit. | ||
1295 | 57 | 'keystone_host': 'kshost', | ||
1296 | 58 | 'service_tenant': 'service_tenant', | ||
1297 | 59 | } | ||
1298 | 60 | |||
1299 | 61 | |||
1300 | 40 | class NovaCCHooksTests(CharmTestCase): | 62 | class NovaCCHooksTests(CharmTestCase): |
1301 | 63 | |||
1302 | 41 | def setUp(self): | 64 | def setUp(self): |
1303 | 42 | super(NovaCCHooksTests, self).setUp(hooks, TO_PATCH) | 65 | super(NovaCCHooksTests, self).setUp(hooks, TO_PATCH) |
1304 | 43 | self.config.side_effect = self.test_config.get | 66 | self.config.side_effect = self.test_config.get |
1305 | @@ -76,3 +99,42 @@ | |||
1306 | 76 | self.ssh_compute_add.assert_called_with('fookey') | 99 | self.ssh_compute_add.assert_called_with('fookey') |
1307 | 77 | self.relation_set.assert_called_with(known_hosts='hosts', | 100 | self.relation_set.assert_called_with(known_hosts='hosts', |
1308 | 78 | authorized_keys='keys') | 101 | authorized_keys='keys') |
1309 | 102 | |||
1310 | 103 | @patch.object(hooks, '_auth_config') | ||
1311 | 104 | def test_compute_joined_neutron(self, auth_config): | ||
1312 | 105 | self.network_manager.return_value = 'neutron' | ||
1313 | 106 | self.eligible_leader = True | ||
1314 | 107 | self.keystone_ca_cert_b64.return_value = 'foocert64' | ||
1315 | 108 | self.volume_service.return_value = 'cinder' | ||
1316 | 109 | self.unit_get.return_value = 'nova-cc-host1' | ||
1317 | 110 | self.canonical_url.return_value = 'http://nova-cc-host1' | ||
1318 | 111 | self.api_port.return_value = '9696' | ||
1319 | 112 | self.neutron_plugin.return_value = 'nvp' | ||
1320 | 113 | auth_config.return_value = FAKE_KS_AUTH_CFG | ||
1321 | 114 | hooks.compute_joined() | ||
1322 | 115 | |||
1323 | 116 | self.relation_set.assert_called_with( | ||
1324 | 117 | relation_id=None, | ||
1325 | 118 | quantum_url='http://nova-cc-host1:9696', | ||
1326 | 119 | ca_cert='foocert64', | ||
1327 | 120 | quantum_security_groups='no', | ||
1328 | 121 | region='RegionOne', | ||
1329 | 122 | volume_service='cinder', | ||
1330 | 123 | ec2_host='nova-cc-host1', | ||
1331 | 124 | quantum_plugin='nvp', | ||
1332 | 125 | network_manager='neutron', **FAKE_KS_AUTH_CFG) | ||
1333 | 126 | |||
1334 | 127 | @patch.object(hooks, '_auth_config') | ||
1335 | 128 | def test_nova_vmware_joined(self, auth_config): | ||
1336 | 129 | auth_config.return_value = FAKE_KS_AUTH_CFG | ||
1337 | 130 | # quantum-security-groups, plugin | ||
1338 | 131 | self.neutron_plugin.return_value = 'nvp' | ||
1339 | 132 | self.network_manager.return_value = 'neutron' | ||
1340 | 133 | self.canonical_url.return_value = 'http://nova-cc-host1' | ||
1341 | 134 | self.api_port.return_value = '9696' | ||
1342 | 135 | hooks.nova_vmware_relation_joined() | ||
1343 | 136 | self.relation_set.assert_called_with( | ||
1344 | 137 | network_manager='neutron', quantum_security_groups='no', | ||
1345 | 138 | quantum_url='http://nova-cc-host1:9696', quantum_plugin='nvp', | ||
1346 | 139 | relation_id=None, | ||
1347 | 140 | **FAKE_KS_AUTH_CFG) | ||
1348 | 79 | 141 | ||
1349 | === modified file 'unit_tests/test_nova_cc_utils.py' | |||
1350 | --- unit_tests/test_nova_cc_utils.py 2013-10-15 13:01:37 +0000 | |||
1351 | +++ unit_tests/test_nova_cc_utils.py 2013-11-08 05:43:26 +0000 | |||
1352 | @@ -70,10 +70,11 @@ | |||
1353 | 70 | 'nova-api-ec2', 'nova-api-os-compute' | 70 | 'nova-api-ec2', 'nova-api-os-compute' |
1354 | 71 | ]), | 71 | ]), |
1355 | 72 | ('/etc/neutron/neutron.conf', ['neutron-server']), | 72 | ('/etc/neutron/neutron.conf', ['neutron-server']), |
1356 | 73 | ('/etc/default/neutron-server', ['neutron-server']), | ||
1357 | 73 | ('/etc/haproxy/haproxy.cfg', ['haproxy']), | 74 | ('/etc/haproxy/haproxy.cfg', ['haproxy']), |
1358 | 74 | ('/etc/apache2/sites-available/openstack_https_frontend', ['apache2']), | 75 | ('/etc/apache2/sites-available/openstack_https_frontend', ['apache2']), |
1359 | 75 | ('/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini', | 76 | ('/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini', |
1361 | 76 | ['neutron-server']) | 77 | ['quantum-server']) |
1362 | 77 | ]) | 78 | ]) |
1363 | 78 | 79 | ||
1364 | 79 | 80 | ||
1365 | @@ -87,13 +88,17 @@ | |||
1366 | 87 | 'services': ['quantum-plugin-openvswitch-agent'], | 88 | 'services': ['quantum-plugin-openvswitch-agent'], |
1367 | 88 | 'packages': ['quantum-plugin-openvswitch-agent', | 89 | 'packages': ['quantum-plugin-openvswitch-agent', |
1368 | 89 | 'openvswitch-datapath-dkms'], | 90 | 'openvswitch-datapath-dkms'], |
1369 | 91 | 'server_packages': ['quantum-server', 'quantum-plugin-openvswitch'], | ||
1370 | 92 | 'server_services': ['quantum-server'], | ||
1371 | 90 | }, | 93 | }, |
1372 | 91 | 'nvp': { | 94 | 'nvp': { |
1373 | 92 | 'config': '/etc/quantum/plugins/nicira/nvp.ini', | 95 | 'config': '/etc/quantum/plugins/nicira/nvp.ini', |
1374 | 93 | 'driver': 'quantum.plugins.nicira.nicira_nvp_plugin.' | 96 | 'driver': 'quantum.plugins.nicira.nicira_nvp_plugin.' |
1375 | 94 | 'QuantumPlugin.NvpPluginV2', | 97 | 'QuantumPlugin.NvpPluginV2', |
1376 | 95 | 'services': [], | 98 | 'services': [], |
1378 | 96 | 'packages': ['quantum-plugin-nicira'], | 99 | 'packages': [], |
1379 | 100 | 'server_packages': ['quantum-server', 'quantum-plugin-nicria'], | ||
1380 | 101 | 'server_services': ['quantum-server'], | ||
1381 | 97 | } | 102 | } |
1382 | 98 | } | 103 | } |
1383 | 99 | 104 | ||
1384 | @@ -107,6 +112,7 @@ | |||
1385 | 107 | 112 | ||
1386 | 108 | 113 | ||
1387 | 109 | class NovaCCUtilsTests(CharmTestCase): | 114 | class NovaCCUtilsTests(CharmTestCase): |
1388 | 115 | |||
1389 | 110 | def setUp(self): | 116 | def setUp(self): |
1390 | 111 | super(NovaCCUtilsTests, self).setUp(utils, TO_PATCH) | 117 | super(NovaCCUtilsTests, self).setUp(utils, TO_PATCH) |
1391 | 112 | self.config.side_effect = self.test_config.get | 118 | self.config.side_effect = self.test_config.get |
1392 | @@ -119,9 +125,13 @@ | |||
1393 | 119 | self.neutron_plugin_attribute.side_effect = fake_plugin_attribute | 125 | self.neutron_plugin_attribute.side_effect = fake_plugin_attribute |
1394 | 120 | if volume_manager == 'nova-volume': | 126 | if volume_manager == 'nova-volume': |
1395 | 121 | self.relation_ids.return_value = 'nova-volume-service:0' | 127 | self.relation_ids.return_value = 'nova-volume-service:0' |
1397 | 122 | return utils.resource_map() | 128 | with patch('charmhelpers.contrib.openstack.context.' |
1398 | 129 | 'SubordinateConfigContext'): | ||
1399 | 130 | _map = utils.resource_map() | ||
1400 | 131 | return _map | ||
1401 | 123 | 132 | ||
1403 | 124 | def test_resource_map_quantum(self): | 133 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') |
1404 | 134 | def test_resource_map_quantum(self, subcontext): | ||
1405 | 125 | self._resource_map(network_manager='quantum') | 135 | self._resource_map(network_manager='quantum') |
1406 | 126 | _map = utils.resource_map() | 136 | _map = utils.resource_map() |
1407 | 127 | confs = [ | 137 | confs = [ |
1408 | @@ -131,7 +141,8 @@ | |||
1409 | 131 | ] | 141 | ] |
1410 | 132 | [self.assertIn(q_conf, _map.keys()) for q_conf in confs] | 142 | [self.assertIn(q_conf, _map.keys()) for q_conf in confs] |
1411 | 133 | 143 | ||
1413 | 134 | def test_resource_map_neutron(self): | 144 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') |
1414 | 145 | def test_resource_map_neutron(self, subcontext): | ||
1415 | 135 | self._resource_map(network_manager='neutron') | 146 | self._resource_map(network_manager='neutron') |
1416 | 136 | _map = utils.resource_map() | 147 | _map = utils.resource_map() |
1417 | 137 | confs = [ | 148 | confs = [ |
1418 | @@ -139,7 +150,21 @@ | |||
1419 | 139 | ] | 150 | ] |
1420 | 140 | [self.assertIn(q_conf, _map.keys()) for q_conf in confs] | 151 | [self.assertIn(q_conf, _map.keys()) for q_conf in confs] |
1421 | 141 | 152 | ||
1423 | 142 | def test_resource_map_neutron_no_agent_installed(self): | 153 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') |
1424 | 154 | def test_resource_map_vmware(self, subcontext): | ||
1425 | 155 | fake_context = MagicMock() | ||
1426 | 156 | fake_context.return_value = { | ||
1427 | 157 | 'sections': [], | ||
1428 | 158 | 'services': ['nova-compute', 'nova-network'], | ||
1429 | 159 | |||
1430 | 160 | } | ||
1431 | 161 | subcontext.return_value = fake_context | ||
1432 | 162 | _map = utils.resource_map() | ||
1433 | 163 | for s in ['nova-compute', 'nova-network']: | ||
1434 | 164 | self.assertIn(s, _map['/etc/nova/nova.conf']['services']) | ||
1435 | 165 | |||
1436 | 166 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') | ||
1437 | 167 | def test_resource_map_neutron_no_agent_installed(self, subcontext): | ||
1438 | 143 | self._resource_map(network_manager='neutron') | 168 | self._resource_map(network_manager='neutron') |
1439 | 144 | _map = utils.resource_map() | 169 | _map = utils.resource_map() |
1440 | 145 | services = [] | 170 | services = [] |
1441 | @@ -147,22 +172,25 @@ | |||
1442 | 147 | for svc in services: | 172 | for svc in services: |
1443 | 148 | self.assertNotIn('agent', svc) | 173 | self.assertNotIn('agent', svc) |
1444 | 149 | 174 | ||
1446 | 150 | def test_resource_map_nova_volume(self): | 175 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') |
1447 | 176 | def test_resource_map_nova_volume(self, subcontext): | ||
1448 | 151 | self.relation_ids.return_value = ['nova-volume-service:0'] | 177 | self.relation_ids.return_value = ['nova-volume-service:0'] |
1449 | 152 | _map = utils.resource_map() | 178 | _map = utils.resource_map() |
1450 | 153 | self.assertIn('nova-api-os-volume', | 179 | self.assertIn('nova-api-os-volume', |
1451 | 154 | _map['/etc/nova/nova.conf']['services']) | 180 | _map['/etc/nova/nova.conf']['services']) |
1452 | 155 | 181 | ||
1453 | 156 | @patch('os.path.exists') | 182 | @patch('os.path.exists') |
1455 | 157 | def test_restart_map_api_before_frontends(self, _exists): | 183 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') |
1456 | 184 | def test_restart_map_api_before_frontends(self, subcontext, _exists): | ||
1457 | 158 | _exists.return_value = False | 185 | _exists.return_value = False |
1458 | 159 | self._resource_map(network_manager='neutron') | 186 | self._resource_map(network_manager='neutron') |
1459 | 160 | _map = utils.restart_map() | 187 | _map = utils.restart_map() |
1460 | 161 | self.assertTrue(isinstance(_map, OrderedDict)) | 188 | self.assertTrue(isinstance(_map, OrderedDict)) |
1461 | 162 | self.assertEquals(_map, RESTART_MAP) | 189 | self.assertEquals(_map, RESTART_MAP) |
1462 | 163 | 190 | ||
1463 | 191 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') | ||
1464 | 164 | @patch('os.path.exists') | 192 | @patch('os.path.exists') |
1466 | 165 | def test_restart_map_apache24(self, _exists): | 193 | def test_restart_map_apache24(self, _exists, subcontext): |
1467 | 166 | _exists.return_Value = True | 194 | _exists.return_Value = True |
1468 | 167 | self._resource_map(network_manager='neutron') | 195 | self._resource_map(network_manager='neutron') |
1469 | 168 | _map = utils.restart_map() | 196 | _map = utils.restart_map() |
1470 | @@ -171,29 +199,34 @@ | |||
1471 | 171 | self.assertTrue('/etc/apache2/sites-available/' | 199 | self.assertTrue('/etc/apache2/sites-available/' |
1472 | 172 | 'openstack_https_frontend' not in _map) | 200 | 'openstack_https_frontend' not in _map) |
1473 | 173 | 201 | ||
1475 | 174 | def test_determine_packages_quantum(self): | 202 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') |
1476 | 203 | def test_determine_packages_quantum(self, subcontext): | ||
1477 | 175 | self._resource_map(network_manager='quantum') | 204 | self._resource_map(network_manager='quantum') |
1478 | 176 | pkgs = utils.determine_packages() | 205 | pkgs = utils.determine_packages() |
1479 | 177 | self.assertIn('quantum-server', pkgs) | 206 | self.assertIn('quantum-server', pkgs) |
1480 | 178 | 207 | ||
1482 | 179 | def test_determine_packages_neutron(self): | 208 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') |
1483 | 209 | def test_determine_packages_neutron(self, subcontext): | ||
1484 | 180 | self._resource_map(network_manager='neutron') | 210 | self._resource_map(network_manager='neutron') |
1485 | 181 | pkgs = utils.determine_packages() | 211 | pkgs = utils.determine_packages() |
1486 | 182 | self.assertIn('neutron-server', pkgs) | 212 | self.assertIn('neutron-server', pkgs) |
1487 | 183 | 213 | ||
1489 | 184 | def test_determine_packages_nova_volume(self): | 214 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') |
1490 | 215 | def test_determine_packages_nova_volume(self, subcontext): | ||
1491 | 185 | self.relation_ids.return_value = ['nova-volume-service:0'] | 216 | self.relation_ids.return_value = ['nova-volume-service:0'] |
1492 | 186 | pkgs = utils.determine_packages() | 217 | pkgs = utils.determine_packages() |
1493 | 187 | self.assertIn('nova-api-os-volume', pkgs) | 218 | self.assertIn('nova-api-os-volume', pkgs) |
1494 | 188 | 219 | ||
1496 | 189 | def test_determine_packages_base(self): | 220 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') |
1497 | 221 | def test_determine_packages_base(self, subcontext): | ||
1498 | 190 | self.relation_ids.return_value = [] | 222 | self.relation_ids.return_value = [] |
1499 | 191 | self.os_release.return_value = 'folsom' | 223 | self.os_release.return_value = 'folsom' |
1500 | 192 | pkgs = utils.determine_packages() | 224 | pkgs = utils.determine_packages() |
1501 | 193 | ex = list(set(utils.BASE_PACKAGES + utils.BASE_SERVICES)) | 225 | ex = list(set(utils.BASE_PACKAGES + utils.BASE_SERVICES)) |
1502 | 194 | self.assertEquals(ex, pkgs) | 226 | self.assertEquals(ex, pkgs) |
1503 | 195 | 227 | ||
1505 | 196 | def test_determine_packages_base_grizzly_beyond(self): | 228 | @patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext') |
1506 | 229 | def test_determine_packages_base_grizzly_beyond(self, subcontext): | ||
1507 | 197 | self.relation_ids.return_value = [] | 230 | self.relation_ids.return_value = [] |
1508 | 198 | self.os_release.return_value = 'grizzly' | 231 | self.os_release.return_value = 'grizzly' |
1509 | 199 | pkgs = utils.determine_packages() | 232 | pkgs = utils.determine_packages() |
1510 | 200 | 233 | ||
1511 | === modified file 'unit_tests/test_utils.py' | |||
1512 | --- unit_tests/test_utils.py 2013-08-02 03:42:16 +0000 | |||
1513 | +++ unit_tests/test_utils.py 2013-11-08 05:43:26 +0000 | |||
1514 | @@ -45,6 +45,7 @@ | |||
1515 | 45 | 45 | ||
1516 | 46 | 46 | ||
1517 | 47 | class CharmTestCase(unittest.TestCase): | 47 | class CharmTestCase(unittest.TestCase): |
1518 | 48 | |||
1519 | 48 | def setUp(self, obj, patches): | 49 | def setUp(self, obj, patches): |
1520 | 49 | super(CharmTestCase, self).setUp() | 50 | super(CharmTestCase, self).setUp() |
1521 | 50 | self.patches = patches | 51 | self.patches = patches |
1522 | @@ -65,6 +66,7 @@ | |||
1523 | 65 | 66 | ||
1524 | 66 | 67 | ||
1525 | 67 | class TestConfig(object): | 68 | class TestConfig(object): |
1526 | 69 | |||
1527 | 68 | def __init__(self): | 70 | def __init__(self): |
1528 | 69 | self.config = get_default_config() | 71 | self.config = get_default_config() |
1529 | 70 | 72 | ||
1530 | @@ -86,6 +88,7 @@ | |||
1531 | 86 | 88 | ||
1532 | 87 | 89 | ||
1533 | 88 | class TestRelation(object): | 90 | class TestRelation(object): |
1534 | 91 | |||
1535 | 89 | def __init__(self, relation_data={}): | 92 | def __init__(self, relation_data={}): |
1536 | 90 | self.relation_data = relation_data | 93 | self.relation_data = relation_data |
1537 | 91 | 94 |