Merge lp:~1chb1n/charms/trusty/cinder/amulet-fix-vol-from-img-lp1440948 into lp:~openstack-charmers-archive/charms/trusty/cinder/next

Proposed by Ryan Beisner
Status: Merged
Merged at revision: 83
Proposed branch: lp:~1chb1n/charms/trusty/cinder/amulet-fix-vol-from-img-lp1440948
Merge into: lp:~openstack-charmers-archive/charms/trusty/cinder/next
Diff against target: 681 lines (+375/-95)
11 files modified
hooks/charmhelpers/contrib/openstack/amulet/deployment.py (+25/-2)
hooks/charmhelpers/contrib/openstack/context.py (+149/-5)
hooks/charmhelpers/contrib/openstack/templates/git.upstart (+13/-0)
hooks/charmhelpers/contrib/openstack/templates/section-zeromq (+14/-0)
hooks/charmhelpers/contrib/openstack/templates/zeromq (+0/-14)
hooks/charmhelpers/contrib/openstack/utils.py (+132/-69)
hooks/charmhelpers/core/hookenv.py (+14/-1)
hooks/charmhelpers/core/unitdata.py (+1/-1)
hooks/cinder_utils.py (+1/-0)
tests/basic_deployment.py (+1/-1)
tests/charmhelpers/contrib/openstack/amulet/deployment.py (+25/-2)
To merge this branch: bzr merge lp:~1chb1n/charms/trusty/cinder/amulet-fix-vol-from-img-lp1440948
Reviewer Review Type Date Requested Status
James Page Approve
Review via email: mp+255705@code.launchpad.net

Description of the change

 - Addresses bug 1440948 by explictly installing librbd1.
 - Enables amulet debug logging.
 - Sync charmhelpers.

Reveals a separate issue (bug 1442268), which is not related to the changes of this MP. http://paste.ubuntu.com/10783843/

To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3193 cinder-next for 1chb1n mp255705
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/3193/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #2981 cinder-next for 1chb1n mp255705
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/2981/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #3003 cinder-next for 1chb1n mp255705
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
make: *** [test] Error 1
ERROR:root:Make target returned non-zero.

Full amulet test output: http://paste.ubuntu.com/10784058/
Build: http://10.245.162.77:8080/job/charm_amulet_test/3003/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3194 cinder-next for 1chb1n mp255705
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/3194/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #2982 cinder-next for 1chb1n mp255705
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/2982/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #3004 cinder-next for 1chb1n mp255705
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
make: *** [test] Error 1
ERROR:root:Make target returned non-zero.

Full amulet test output: http://paste.ubuntu.com/10784240/
Build: http://10.245.162.77:8080/job/charm_amulet_test/3004/

Revision history for this message
Ryan Beisner (1chb1n) wrote :

^ FYI amulet fail is expected due to a separate issue. See MP initial description.

Revision history for this message
James Page (james-page) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'hooks/charmhelpers/contrib/openstack/amulet/deployment.py'
--- hooks/charmhelpers/contrib/openstack/amulet/deployment.py 2015-03-13 13:00:03 +0000
+++ hooks/charmhelpers/contrib/openstack/amulet/deployment.py 2015-04-09 16:27:05 +0000
@@ -15,6 +15,7 @@
15# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.15# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
1616
17import six17import six
18from collections import OrderedDict
18from charmhelpers.contrib.amulet.deployment import (19from charmhelpers.contrib.amulet.deployment import (
19 AmuletDeployment20 AmuletDeployment
20)21)
@@ -100,12 +101,34 @@
100 """101 """
101 (self.precise_essex, self.precise_folsom, self.precise_grizzly,102 (self.precise_essex, self.precise_folsom, self.precise_grizzly,
102 self.precise_havana, self.precise_icehouse,103 self.precise_havana, self.precise_icehouse,
103 self.trusty_icehouse) = range(6)104 self.trusty_icehouse, self.trusty_juno, self.trusty_kilo) = range(8)
104 releases = {105 releases = {
105 ('precise', None): self.precise_essex,106 ('precise', None): self.precise_essex,
106 ('precise', 'cloud:precise-folsom'): self.precise_folsom,107 ('precise', 'cloud:precise-folsom'): self.precise_folsom,
107 ('precise', 'cloud:precise-grizzly'): self.precise_grizzly,108 ('precise', 'cloud:precise-grizzly'): self.precise_grizzly,
108 ('precise', 'cloud:precise-havana'): self.precise_havana,109 ('precise', 'cloud:precise-havana'): self.precise_havana,
109 ('precise', 'cloud:precise-icehouse'): self.precise_icehouse,110 ('precise', 'cloud:precise-icehouse'): self.precise_icehouse,
110 ('trusty', None): self.trusty_icehouse}111 ('trusty', None): self.trusty_icehouse,
112 ('trusty', 'cloud:trusty-juno'): self.trusty_juno,
113 ('trusty', 'cloud:trusty-kilo'): self.trusty_kilo}
111 return releases[(self.series, self.openstack)]114 return releases[(self.series, self.openstack)]
115
116 def _get_openstack_release_string(self):
117 """Get openstack release string.
118
119 Return a string representing the openstack release.
120 """
121 releases = OrderedDict([
122 ('precise', 'essex'),
123 ('quantal', 'folsom'),
124 ('raring', 'grizzly'),
125 ('saucy', 'havana'),
126 ('trusty', 'icehouse'),
127 ('utopic', 'juno'),
128 ('vivid', 'kilo'),
129 ])
130 if self.openstack:
131 os_origin = self.openstack.split(':')[1]
132 return os_origin.split('%s-' % self.series)[1].split('/')[0]
133 else:
134 return releases[self.series]
112135
=== modified file 'hooks/charmhelpers/contrib/openstack/context.py'
--- hooks/charmhelpers/contrib/openstack/context.py 2015-03-18 12:08:38 +0000
+++ hooks/charmhelpers/contrib/openstack/context.py 2015-04-09 16:27:05 +0000
@@ -47,6 +47,7 @@
47)47)
4848
49from charmhelpers.core.sysctl import create as sysctl_create49from charmhelpers.core.sysctl import create as sysctl_create
50from charmhelpers.core.strutils import bool_from_string
5051
51from charmhelpers.core.host import (52from charmhelpers.core.host import (
52 list_nics,53 list_nics,
@@ -67,6 +68,7 @@
67)68)
68from charmhelpers.contrib.openstack.neutron import (69from charmhelpers.contrib.openstack.neutron import (
69 neutron_plugin_attribute,70 neutron_plugin_attribute,
71 parse_data_port_mappings,
70)72)
71from charmhelpers.contrib.openstack.ip import (73from charmhelpers.contrib.openstack.ip import (
72 resolve_address,74 resolve_address,
@@ -82,7 +84,6 @@
82 is_bridge_member,84 is_bridge_member,
83)85)
84from charmhelpers.contrib.openstack.utils import get_host_ip86from charmhelpers.contrib.openstack.utils import get_host_ip
85
86CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'87CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
87ADDRESS_TYPES = ['admin', 'internal', 'public']88ADDRESS_TYPES = ['admin', 'internal', 'public']
8889
@@ -319,14 +320,15 @@
319320
320321
321class IdentityServiceContext(OSContextGenerator):322class IdentityServiceContext(OSContextGenerator):
322 interfaces = ['identity-service']
323323
324 def __init__(self, service=None, service_user=None):324 def __init__(self, service=None, service_user=None, rel_name='identity-service'):
325 self.service = service325 self.service = service
326 self.service_user = service_user326 self.service_user = service_user
327 self.rel_name = rel_name
328 self.interfaces = [self.rel_name]
327329
328 def __call__(self):330 def __call__(self):
329 log('Generating template context for identity-service', level=DEBUG)331 log('Generating template context for ' + self.rel_name, level=DEBUG)
330 ctxt = {}332 ctxt = {}
331333
332 if self.service and self.service_user:334 if self.service and self.service_user:
@@ -340,7 +342,7 @@
340342
341 ctxt['signing_dir'] = cachedir343 ctxt['signing_dir'] = cachedir
342344
343 for rid in relation_ids('identity-service'):345 for rid in relation_ids(self.rel_name):
344 for unit in related_units(rid):346 for unit in related_units(rid):
345 rdata = relation_get(rid=rid, unit=unit)347 rdata = relation_get(rid=rid, unit=unit)
346 serv_host = rdata.get('service_host')348 serv_host = rdata.get('service_host')
@@ -1162,3 +1164,145 @@
1162 sysctl_create(sysctl_dict,1164 sysctl_create(sysctl_dict,
1163 '/etc/sysctl.d/50-{0}.conf'.format(charm_name()))1165 '/etc/sysctl.d/50-{0}.conf'.format(charm_name()))
1164 return {'sysctl': sysctl_dict}1166 return {'sysctl': sysctl_dict}
1167
1168
1169class NeutronAPIContext(OSContextGenerator):
1170 '''
1171 Inspects current neutron-plugin-api relation for neutron settings. Return
1172 defaults if it is not present.
1173 '''
1174 interfaces = ['neutron-plugin-api']
1175
1176 def __call__(self):
1177 self.neutron_defaults = {
1178 'l2_population': {
1179 'rel_key': 'l2-population',
1180 'default': False,
1181 },
1182 'overlay_network_type': {
1183 'rel_key': 'overlay-network-type',
1184 'default': 'gre',
1185 },
1186 'neutron_security_groups': {
1187 'rel_key': 'neutron-security-groups',
1188 'default': False,
1189 },
1190 'network_device_mtu': {
1191 'rel_key': 'network-device-mtu',
1192 'default': None,
1193 },
1194 'enable_dvr': {
1195 'rel_key': 'enable-dvr',
1196 'default': False,
1197 },
1198 'enable_l3ha': {
1199 'rel_key': 'enable-l3ha',
1200 'default': False,
1201 },
1202 }
1203 ctxt = self.get_neutron_options({})
1204 for rid in relation_ids('neutron-plugin-api'):
1205 for unit in related_units(rid):
1206 rdata = relation_get(rid=rid, unit=unit)
1207 if 'l2-population' in rdata:
1208 ctxt.update(self.get_neutron_options(rdata))
1209
1210 return ctxt
1211
1212 def get_neutron_options(self, rdata):
1213 settings = {}
1214 for nkey in self.neutron_defaults.keys():
1215 defv = self.neutron_defaults[nkey]['default']
1216 rkey = self.neutron_defaults[nkey]['rel_key']
1217 if rkey in rdata.keys():
1218 if type(defv) is bool:
1219 settings[nkey] = bool_from_string(rdata[rkey])
1220 else:
1221 settings[nkey] = rdata[rkey]
1222 else:
1223 settings[nkey] = defv
1224 return settings
1225
1226
1227class ExternalPortContext(NeutronPortContext):
1228
1229 def __call__(self):
1230 ctxt = {}
1231 ports = config('ext-port')
1232 if ports:
1233 ports = [p.strip() for p in ports.split()]
1234 ports = self.resolve_ports(ports)
1235 if ports:
1236 ctxt = {"ext_port": ports[0]}
1237 napi_settings = NeutronAPIContext()()
1238 mtu = napi_settings.get('network_device_mtu')
1239 if mtu:
1240 ctxt['ext_port_mtu'] = mtu
1241
1242 return ctxt
1243
1244
1245class DataPortContext(NeutronPortContext):
1246
1247 def __call__(self):
1248 ports = config('data-port')
1249 if ports:
1250 portmap = parse_data_port_mappings(ports)
1251 ports = portmap.values()
1252 resolved = self.resolve_ports(ports)
1253 normalized = {get_nic_hwaddr(port): port for port in resolved
1254 if port not in ports}
1255 normalized.update({port: port for port in resolved
1256 if port in ports})
1257 if resolved:
1258 return {bridge: normalized[port] for bridge, port in
1259 six.iteritems(portmap) if port in normalized.keys()}
1260
1261 return None
1262
1263
1264class PhyNICMTUContext(DataPortContext):
1265
1266 def __call__(self):
1267 ctxt = {}
1268 mappings = super(PhyNICMTUContext, self).__call__()
1269 if mappings and mappings.values():
1270 ports = mappings.values()
1271 napi_settings = NeutronAPIContext()()
1272 mtu = napi_settings.get('network_device_mtu')
1273 if mtu:
1274 ctxt["devs"] = '\\n'.join(ports)
1275 ctxt['mtu'] = mtu
1276
1277 return ctxt
1278
1279
1280class NetworkServiceContext(OSContextGenerator):
1281
1282 def __init__(self, rel_name='quantum-network-service'):
1283 self.rel_name = rel_name
1284 self.interfaces = [rel_name]
1285
1286 def __call__(self):
1287 for rid in relation_ids(self.rel_name):
1288 for unit in related_units(rid):
1289 rdata = relation_get(rid=rid, unit=unit)
1290 ctxt = {
1291 'keystone_host': rdata.get('keystone_host'),
1292 'service_port': rdata.get('service_port'),
1293 'auth_port': rdata.get('auth_port'),
1294 'service_tenant': rdata.get('service_tenant'),
1295 'service_username': rdata.get('service_username'),
1296 'service_password': rdata.get('service_password'),
1297 'quantum_host': rdata.get('quantum_host'),
1298 'quantum_port': rdata.get('quantum_port'),
1299 'quantum_url': rdata.get('quantum_url'),
1300 'region': rdata.get('region'),
1301 'service_protocol':
1302 rdata.get('service_protocol') or 'http',
1303 'auth_protocol':
1304 rdata.get('auth_protocol') or 'http',
1305 }
1306 if context_complete(ctxt):
1307 return ctxt
1308 return {}
11651309
=== added file 'hooks/charmhelpers/contrib/openstack/templates/git.upstart'
--- hooks/charmhelpers/contrib/openstack/templates/git.upstart 1970-01-01 00:00:00 +0000
+++ hooks/charmhelpers/contrib/openstack/templates/git.upstart 2015-04-09 16:27:05 +0000
@@ -0,0 +1,13 @@
1description "{{ service_description }}"
2author "Juju {{ service_name }} Charm <juju@localhost>"
3
4start on runlevel [2345]
5stop on runlevel [!2345]
6
7respawn
8
9exec start-stop-daemon --start --chuid {{ user_name }} \
10 --chdir {{ start_dir }} --name {{ process_name }} \
11 --exec {{ executable_name }} -- \
12 --config-file={{ config_file }} \
13 --log-file={{ log_file }}
014
=== added file 'hooks/charmhelpers/contrib/openstack/templates/section-zeromq'
--- hooks/charmhelpers/contrib/openstack/templates/section-zeromq 1970-01-01 00:00:00 +0000
+++ hooks/charmhelpers/contrib/openstack/templates/section-zeromq 2015-04-09 16:27:05 +0000
@@ -0,0 +1,14 @@
1{% if zmq_host -%}
2# ZeroMQ configuration (restart-nonce: {{ zmq_nonce }})
3rpc_backend = zmq
4rpc_zmq_host = {{ zmq_host }}
5{% if zmq_redis_address -%}
6rpc_zmq_matchmaker = redis
7matchmaker_heartbeat_freq = 15
8matchmaker_heartbeat_ttl = 30
9[matchmaker_redis]
10host = {{ zmq_redis_address }}
11{% else -%}
12rpc_zmq_matchmaker = ring
13{% endif -%}
14{% endif -%}
015
=== removed file 'hooks/charmhelpers/contrib/openstack/templates/zeromq'
--- hooks/charmhelpers/contrib/openstack/templates/zeromq 2015-02-24 12:37:30 +0000
+++ hooks/charmhelpers/contrib/openstack/templates/zeromq 1970-01-01 00:00:00 +0000
@@ -1,14 +0,0 @@
1{% if zmq_host -%}
2# ZeroMQ configuration (restart-nonce: {{ zmq_nonce }})
3rpc_backend = zmq
4rpc_zmq_host = {{ zmq_host }}
5{% if zmq_redis_address -%}
6rpc_zmq_matchmaker = oslo.messaging._drivers.matchmaker_redis.MatchMakerRedis
7matchmaker_heartbeat_freq = 15
8matchmaker_heartbeat_ttl = 30
9[matchmaker_redis]
10host = {{ zmq_redis_address }}
11{% else -%}
12rpc_zmq_matchmaker = oslo.messaging._drivers.matchmaker_ring.MatchMakerRing
13{% endif -%}
14{% endif -%}
150
=== modified file 'hooks/charmhelpers/contrib/openstack/utils.py'
--- hooks/charmhelpers/contrib/openstack/utils.py 2015-03-13 13:00:03 +0000
+++ hooks/charmhelpers/contrib/openstack/utils.py 2015-04-09 16:27:05 +0000
@@ -30,6 +30,10 @@
3030
31from charmhelpers.contrib.network import ip31from charmhelpers.contrib.network import ip
3232
33from charmhelpers.core import (
34 unitdata,
35)
36
33from charmhelpers.core.hookenv import (37from charmhelpers.core.hookenv import (
34 config,38 config,
35 log as juju_log,39 log as juju_log,
@@ -330,6 +334,21 @@
330 error_out("Invalid openstack-release specified: %s" % rel)334 error_out("Invalid openstack-release specified: %s" % rel)
331335
332336
337def config_value_changed(option):
338 """
339 Determine if config value changed since last call to this function.
340 """
341 hook_data = unitdata.HookData()
342 with hook_data():
343 db = unitdata.kv()
344 current = config(option)
345 saved = db.get(option)
346 db.set(option, current)
347 if saved is None:
348 return False
349 return current != saved
350
351
333def save_script_rc(script_path="scripts/scriptrc", **env_vars):352def save_script_rc(script_path="scripts/scriptrc", **env_vars):
334 """353 """
335 Write an rc file in the charm-delivered directory containing354 Write an rc file in the charm-delivered directory containing
@@ -469,82 +488,103 @@
469488
470489
471def git_install_requested():490def git_install_requested():
472 """Returns true if openstack-origin-git is specified."""491 """
473 return config('openstack-origin-git') != "None"492 Returns true if openstack-origin-git is specified.
493 """
494 return config('openstack-origin-git') is not None
474495
475496
476requirements_dir = None497requirements_dir = None
477498
478499
479def git_clone_and_install(file_name, core_project):500def git_clone_and_install(projects_yaml, core_project):
480 """Clone/install all OpenStack repos specified in yaml config file."""501 """
502 Clone/install all specified OpenStack repositories.
503
504 The expected format of projects_yaml is:
505 repositories:
506 - {name: keystone,
507 repository: 'git://git.openstack.org/openstack/keystone.git',
508 branch: 'stable/icehouse'}
509 - {name: requirements,
510 repository: 'git://git.openstack.org/openstack/requirements.git',
511 branch: 'stable/icehouse'}
512 directory: /mnt/openstack-git
513 http_proxy: http://squid.internal:3128
514 https_proxy: https://squid.internal:3128
515
516 The directory, http_proxy, and https_proxy keys are optional.
517 """
481 global requirements_dir518 global requirements_dir
519 parent_dir = '/mnt/openstack-git'
482520
483 if file_name == "None":521 if not projects_yaml:
484 return522 return
485523
486 yaml_file = os.path.join(charm_dir(), file_name)524 projects = yaml.load(projects_yaml)
487525 _git_validate_projects_yaml(projects, core_project)
488 # clone/install the requirements project first526
489 installed = _git_clone_and_install_subset(yaml_file,527 if 'http_proxy' in projects.keys():
490 whitelist=['requirements'])528 os.environ['http_proxy'] = projects['http_proxy']
491 if 'requirements' not in installed:529
492 error_out('requirements git repository must be specified')530 if 'https_proxy' in projects.keys():
493531 os.environ['https_proxy'] = projects['https_proxy']
494 # clone/install all other projects except requirements and the core project532
495 blacklist = ['requirements', core_project]533 if 'directory' in projects.keys():
496 _git_clone_and_install_subset(yaml_file, blacklist=blacklist,534 parent_dir = projects['directory']
497 update_requirements=True)535
498536 for p in projects['repositories']:
499 # clone/install the core project537 repo = p['repository']
500 whitelist = [core_project]538 branch = p['branch']
501 installed = _git_clone_and_install_subset(yaml_file, whitelist=whitelist,539 if p['name'] == 'requirements':
502 update_requirements=True)540 repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
503 if core_project not in installed:541 update_requirements=False)
504 error_out('{} git repository must be specified'.format(core_project))542 requirements_dir = repo_dir
505543 else:
506544 repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
507def _git_clone_and_install_subset(yaml_file, whitelist=[], blacklist=[],545 update_requirements=True)
508 update_requirements=False):546
509 """Clone/install subset of OpenStack repos specified in yaml config file."""547
510 global requirements_dir548def _git_validate_projects_yaml(projects, core_project):
511 installed = []549 """
512550 Validate the projects yaml.
513 with open(yaml_file, 'r') as fd:551 """
514 projects = yaml.load(fd)552 _git_ensure_key_exists('repositories', projects)
515 for proj, val in projects.items():553
516 # The project subset is chosen based on the following 3 rules:554 for project in projects['repositories']:
517 # 1) If project is in blacklist, we don't clone/install it, period.555 _git_ensure_key_exists('name', project.keys())
518 # 2) If whitelist is empty, we clone/install everything else.556 _git_ensure_key_exists('repository', project.keys())
519 # 3) If whitelist is not empty, we clone/install everything in the557 _git_ensure_key_exists('branch', project.keys())
520 # whitelist.558
521 if proj in blacklist:559 if projects['repositories'][0]['name'] != 'requirements':
522 continue560 error_out('{} git repo must be specified first'.format('requirements'))
523 if whitelist and proj not in whitelist:561
524 continue562 if projects['repositories'][-1]['name'] != core_project:
525 repo = val['repository']563 error_out('{} git repo must be specified last'.format(core_project))
526 branch = val['branch']564
527 repo_dir = _git_clone_and_install_single(repo, branch,565
528 update_requirements)566def _git_ensure_key_exists(key, keys):
529 if proj == 'requirements':567 """
530 requirements_dir = repo_dir568 Ensure that key exists in keys.
531 installed.append(proj)569 """
532 return installed570 if key not in keys:
533571 error_out('openstack-origin-git key \'{}\' is missing'.format(key))
534572
535def _git_clone_and_install_single(repo, branch, update_requirements=False):573
536 """Clone and install a single git repository."""574def _git_clone_and_install_single(repo, branch, parent_dir, update_requirements):
537 dest_parent_dir = "/mnt/openstack-git/"575 """
538 dest_dir = os.path.join(dest_parent_dir, os.path.basename(repo))576 Clone and install a single git repository.
539577 """
540 if not os.path.exists(dest_parent_dir):578 dest_dir = os.path.join(parent_dir, os.path.basename(repo))
541 juju_log('Host dir not mounted at {}. '579
542 'Creating directory there instead.'.format(dest_parent_dir))580 if not os.path.exists(parent_dir):
543 os.mkdir(dest_parent_dir)581 juju_log('Directory already exists at {}. '
582 'No need to create directory.'.format(parent_dir))
583 os.mkdir(parent_dir)
544584
545 if not os.path.exists(dest_dir):585 if not os.path.exists(dest_dir):
546 juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch))586 juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch))
547 repo_dir = install_remote(repo, dest=dest_parent_dir, branch=branch)587 repo_dir = install_remote(repo, dest=parent_dir, branch=branch)
548 else:588 else:
549 repo_dir = dest_dir589 repo_dir = dest_dir
550590
@@ -561,16 +601,39 @@
561601
562602
563def _git_update_requirements(package_dir, reqs_dir):603def _git_update_requirements(package_dir, reqs_dir):
564 """Update from global requirements.604 """
605 Update from global requirements.
565606
566 Update an OpenStack git directory's requirements.txt and607 Update an OpenStack git directory's requirements.txt and
567 test-requirements.txt from global-requirements.txt."""608 test-requirements.txt from global-requirements.txt.
609 """
568 orig_dir = os.getcwd()610 orig_dir = os.getcwd()
569 os.chdir(reqs_dir)611 os.chdir(reqs_dir)
570 cmd = "python update.py {}".format(package_dir)612 cmd = ['python', 'update.py', package_dir]
571 try:613 try:
572 subprocess.check_call(cmd.split(' '))614 subprocess.check_call(cmd)
573 except subprocess.CalledProcessError:615 except subprocess.CalledProcessError:
574 package = os.path.basename(package_dir)616 package = os.path.basename(package_dir)
575 error_out("Error updating {} from global-requirements.txt".format(package))617 error_out("Error updating {} from global-requirements.txt".format(package))
576 os.chdir(orig_dir)618 os.chdir(orig_dir)
619
620
621def git_src_dir(projects_yaml, project):
622 """
623 Return the directory where the specified project's source is located.
624 """
625 parent_dir = '/mnt/openstack-git'
626
627 if not projects_yaml:
628 return
629
630 projects = yaml.load(projects_yaml)
631
632 if 'directory' in projects.keys():
633 parent_dir = projects['directory']
634
635 for p in projects['repositories']:
636 if p['name'] == project:
637 return os.path.join(parent_dir, os.path.basename(p['repository']))
638
639 return None
577640
=== modified file 'hooks/charmhelpers/core/hookenv.py'
--- hooks/charmhelpers/core/hookenv.py 2015-03-18 10:19:15 +0000
+++ hooks/charmhelpers/core/hookenv.py 2015-04-09 16:27:05 +0000
@@ -20,11 +20,13 @@
20# Authors:20# Authors:
21# Charm Helpers Developers <juju@lists.ubuntu.com>21# Charm Helpers Developers <juju@lists.ubuntu.com>
2222
23from __future__ import print_function
23import os24import os
24import json25import json
25import yaml26import yaml
26import subprocess27import subprocess
27import sys28import sys
29import errno
28from subprocess import CalledProcessError30from subprocess import CalledProcessError
2931
30import six32import six
@@ -87,7 +89,18 @@
87 if not isinstance(message, six.string_types):89 if not isinstance(message, six.string_types):
88 message = repr(message)90 message = repr(message)
89 command += [message]91 command += [message]
90 subprocess.call(command)92 # Missing juju-log should not cause failures in unit tests
93 # Send log output to stderr
94 try:
95 subprocess.call(command)
96 except OSError as e:
97 if e.errno == errno.ENOENT:
98 if level:
99 message = "{}: {}".format(level, message)
100 message = "juju-log: {}".format(message)
101 print(message, file=sys.stderr)
102 else:
103 raise
91104
92105
93class Serializable(UserDict):106class Serializable(UserDict):
94107
=== modified file 'hooks/charmhelpers/core/unitdata.py'
--- hooks/charmhelpers/core/unitdata.py 2015-02-19 03:38:40 +0000
+++ hooks/charmhelpers/core/unitdata.py 2015-04-09 16:27:05 +0000
@@ -443,7 +443,7 @@
443 data = hookenv.execution_environment()443 data = hookenv.execution_environment()
444 self.conf = conf_delta = self.kv.delta(data['conf'], 'config')444 self.conf = conf_delta = self.kv.delta(data['conf'], 'config')
445 self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')445 self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')
446 self.kv.set('env', data['env'])446 self.kv.set('env', dict(data['env']))
447 self.kv.set('unit', data['unit'])447 self.kv.set('unit', data['unit'])
448 self.kv.set('relid', data.get('relid'))448 self.kv.set('relid', data.get('relid'))
449 return conf_delta, rels_delta449 return conf_delta, rels_delta
450450
=== modified file 'hooks/cinder_utils.py'
--- hooks/cinder_utils.py 2015-02-19 19:42:21 +0000
+++ hooks/cinder_utils.py 2015-04-09 16:27:05 +0000
@@ -69,6 +69,7 @@
69 'cinder-common',69 'cinder-common',
70 'gdisk',70 'gdisk',
71 'haproxy',71 'haproxy',
72 'librbd1', # bug 1440948 vol-from-img
72 'python-jinja2',73 'python-jinja2',
73 'python-keystoneclient',74 'python-keystoneclient',
74 'python-mysqldb',75 'python-mysqldb',
7576
=== modified file 'tests/basic_deployment.py'
--- tests/basic_deployment.py 2015-03-26 16:24:22 +0000
+++ tests/basic_deployment.py 2015-04-09 16:27:05 +0000
@@ -16,7 +16,7 @@
16)16)
1717
18# Use DEBUG to turn on debug logging18# Use DEBUG to turn on debug logging
19u = OpenStackAmuletUtils(ERROR)19u = OpenStackAmuletUtils(DEBUG)
2020
2121
22class CinderBasicDeployment(OpenStackAmuletDeployment):22class CinderBasicDeployment(OpenStackAmuletDeployment):
2323
=== modified file 'tests/charmhelpers/contrib/openstack/amulet/deployment.py'
--- tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-03-13 13:00:03 +0000
+++ tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-04-09 16:27:05 +0000
@@ -15,6 +15,7 @@
15# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.15# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
1616
17import six17import six
18from collections import OrderedDict
18from charmhelpers.contrib.amulet.deployment import (19from charmhelpers.contrib.amulet.deployment import (
19 AmuletDeployment20 AmuletDeployment
20)21)
@@ -100,12 +101,34 @@
100 """101 """
101 (self.precise_essex, self.precise_folsom, self.precise_grizzly,102 (self.precise_essex, self.precise_folsom, self.precise_grizzly,
102 self.precise_havana, self.precise_icehouse,103 self.precise_havana, self.precise_icehouse,
103 self.trusty_icehouse) = range(6)104 self.trusty_icehouse, self.trusty_juno, self.trusty_kilo) = range(8)
104 releases = {105 releases = {
105 ('precise', None): self.precise_essex,106 ('precise', None): self.precise_essex,
106 ('precise', 'cloud:precise-folsom'): self.precise_folsom,107 ('precise', 'cloud:precise-folsom'): self.precise_folsom,
107 ('precise', 'cloud:precise-grizzly'): self.precise_grizzly,108 ('precise', 'cloud:precise-grizzly'): self.precise_grizzly,
108 ('precise', 'cloud:precise-havana'): self.precise_havana,109 ('precise', 'cloud:precise-havana'): self.precise_havana,
109 ('precise', 'cloud:precise-icehouse'): self.precise_icehouse,110 ('precise', 'cloud:precise-icehouse'): self.precise_icehouse,
110 ('trusty', None): self.trusty_icehouse}111 ('trusty', None): self.trusty_icehouse,
112 ('trusty', 'cloud:trusty-juno'): self.trusty_juno,
113 ('trusty', 'cloud:trusty-kilo'): self.trusty_kilo}
111 return releases[(self.series, self.openstack)]114 return releases[(self.series, self.openstack)]
115
116 def _get_openstack_release_string(self):
117 """Get openstack release string.
118
119 Return a string representing the openstack release.
120 """
121 releases = OrderedDict([
122 ('precise', 'essex'),
123 ('quantal', 'folsom'),
124 ('raring', 'grizzly'),
125 ('saucy', 'havana'),
126 ('trusty', 'icehouse'),
127 ('utopic', 'juno'),
128 ('vivid', 'kilo'),
129 ])
130 if self.openstack:
131 os_origin = self.openstack.split(':')[1]
132 return os_origin.split('%s-' % self.series)[1].split('/')[0]
133 else:
134 return releases[self.series]

Subscribers

People subscribed via source and target branches