~hopem/charms/trusty/cinder/ensure-apache-restart

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/contrib/openstack/utils.py

  • Committer: Liam Young
  • Date: 2015-01-09 16:02:39 UTC
  • mfrom: (65 cinder.next)
  • mto: This revision was merged to the branch mainline in revision 67.
  • Revision ID: liam.young@canonical.com-20150109160239-qldk423wxfno2ao3
Merged next in and resolved conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
# Common python helper functions used for OpenStack charms.
4
4
from collections import OrderedDict
 
5
from functools import wraps
5
6
 
6
7
import subprocess
7
8
import json
9
10
import socket
10
11
import sys
11
12
 
 
13
import six
 
14
import yaml
 
15
 
12
16
from charmhelpers.core.hookenv import (
13
17
    config,
14
18
    log as juju_log,
15
19
    charm_dir,
16
 
    ERROR,
17
20
    INFO,
18
21
    relation_ids,
19
22
    relation_set
30
33
)
31
34
 
32
35
from charmhelpers.core.host import lsb_release, mounts, umount
33
 
from charmhelpers.fetch import apt_install, apt_cache
 
36
from charmhelpers.fetch import apt_install, apt_cache, install_remote
 
37
from charmhelpers.contrib.python.packages import pip_install
34
38
from charmhelpers.contrib.storage.linux.utils import is_block_device, zap_disk
35
39
from charmhelpers.contrib.storage.linux.loopback import ensure_loopback_device
36
40
 
112
116
 
113
117
    # Best guess match based on deb string provided
114
118
    if src.startswith('deb') or src.startswith('ppa'):
115
 
        for k, v in OPENSTACK_CODENAMES.iteritems():
 
119
        for k, v in six.iteritems(OPENSTACK_CODENAMES):
116
120
            if v in src:
117
121
                return v
118
122
 
133
137
 
134
138
def get_os_version_codename(codename):
135
139
    '''Determine OpenStack version number from codename.'''
136
 
    for k, v in OPENSTACK_CODENAMES.iteritems():
 
140
    for k, v in six.iteritems(OPENSTACK_CODENAMES):
137
141
        if v == codename:
138
142
            return k
139
143
    e = 'Could not derive OpenStack version for '\
193
197
    else:
194
198
        vers_map = OPENSTACK_CODENAMES
195
199
 
196
 
    for version, cname in vers_map.iteritems():
 
200
    for version, cname in six.iteritems(vers_map):
197
201
        if cname == codename:
198
202
            return version
199
203
    # e = "Could not determine OpenStack version for package: %s" % pkg
317
321
        rc_script.write(
318
322
            "#!/bin/bash\n")
319
323
        [rc_script.write('export %s=%s\n' % (u, p))
320
 
         for u, p in env_vars.iteritems() if u != "script_path"]
 
324
         for u, p in six.iteritems(env_vars) if u != "script_path"]
321
325
 
322
326
 
323
327
def openstack_upgrade_available(package):
350
354
    '''
351
355
    _none = ['None', 'none', None]
352
356
    if (block_device in _none):
353
 
        error_out('prepare_storage(): Missing required input: '
354
 
                  'block_device=%s.' % block_device, level=ERROR)
 
357
        error_out('prepare_storage(): Missing required input: block_device=%s.'
 
358
                  % block_device)
355
359
 
356
360
    if block_device.startswith('/dev/'):
357
361
        bdev = block_device
367
371
        bdev = '/dev/%s' % block_device
368
372
 
369
373
    if not is_block_device(bdev):
370
 
        error_out('Failed to locate valid block device at %s' % bdev,
371
 
                  level=ERROR)
 
374
        error_out('Failed to locate valid block device at %s' % bdev)
372
375
 
373
376
    return bdev
374
377
 
417
420
 
418
421
    if isinstance(address, dns.name.Name):
419
422
        rtype = 'PTR'
420
 
    elif isinstance(address, basestring):
 
423
    elif isinstance(address, six.string_types):
421
424
        rtype = 'A'
422
425
    else:
423
426
        return None
468
471
        return result.split('.')[0]
469
472
 
470
473
 
 
474
def get_matchmaker_map(mm_file='/etc/oslo/matchmaker_ring.json'):
 
475
    mm_map = {}
 
476
    if os.path.isfile(mm_file):
 
477
        with open(mm_file, 'r') as f:
 
478
            mm_map = json.load(f)
 
479
    return mm_map
 
480
 
 
481
 
471
482
def sync_db_with_multi_ipv6_addresses(database, database_user,
472
483
                                      relation_prefix=None):
473
484
    hosts = get_ipv6_addr(dynamic_only=False)
477
488
              'hostname': json.dumps(hosts)}
478
489
 
479
490
    if relation_prefix:
480
 
        keys = kwargs.keys()
481
 
        for key in keys:
 
491
        for key in list(kwargs.keys()):
482
492
            kwargs["%s_%s" % (relation_prefix, key)] = kwargs[key]
483
493
            del kwargs[key]
484
494
 
485
495
    for rid in relation_ids('shared-db'):
486
496
        relation_set(relation_id=rid, **kwargs)
 
497
 
 
498
 
 
499
def os_requires_version(ostack_release, pkg):
 
500
    """
 
501
    Decorator for hook to specify minimum supported release
 
502
    """
 
503
    def wrap(f):
 
504
        @wraps(f)
 
505
        def wrapped_f(*args):
 
506
            if os_release(pkg) < ostack_release:
 
507
                raise Exception("This hook is not supported on releases"
 
508
                                " before %s" % ostack_release)
 
509
            f(*args)
 
510
        return wrapped_f
 
511
    return wrap
 
512
 
 
513
 
 
514
def git_install_requested():
 
515
    """Returns true if openstack-origin-git is specified."""
 
516
    return config('openstack-origin-git') != "None"
 
517
 
 
518
 
 
519
requirements_dir = None
 
520
 
 
521
 
 
522
def git_clone_and_install(file_name, core_project):
 
523
    """Clone/install all OpenStack repos specified in yaml config file."""
 
524
    global requirements_dir
 
525
 
 
526
    if file_name == "None":
 
527
        return
 
528
 
 
529
    yaml_file = os.path.join(charm_dir(), file_name)
 
530
 
 
531
    # clone/install the requirements project first
 
532
    installed = _git_clone_and_install_subset(yaml_file,
 
533
                                              whitelist=['requirements'])
 
534
    if 'requirements' not in installed:
 
535
        error_out('requirements git repository must be specified')
 
536
 
 
537
    # clone/install all other projects except requirements and the core project
 
538
    blacklist = ['requirements', core_project]
 
539
    _git_clone_and_install_subset(yaml_file, blacklist=blacklist,
 
540
                                  update_requirements=True)
 
541
 
 
542
    # clone/install the core project
 
543
    whitelist = [core_project]
 
544
    installed = _git_clone_and_install_subset(yaml_file, whitelist=whitelist,
 
545
                                              update_requirements=True)
 
546
    if core_project not in installed:
 
547
        error_out('{} git repository must be specified'.format(core_project))
 
548
 
 
549
 
 
550
def _git_clone_and_install_subset(yaml_file, whitelist=[], blacklist=[],
 
551
                                  update_requirements=False):
 
552
    """Clone/install subset of OpenStack repos specified in yaml config file."""
 
553
    global requirements_dir
 
554
    installed = []
 
555
 
 
556
    with open(yaml_file, 'r') as fd:
 
557
        projects = yaml.load(fd)
 
558
        for proj, val in projects.items():
 
559
            # The project subset is chosen based on the following 3 rules:
 
560
            # 1) If project is in blacklist, we don't clone/install it, period.
 
561
            # 2) If whitelist is empty, we clone/install everything else.
 
562
            # 3) If whitelist is not empty, we clone/install everything in the
 
563
            #    whitelist.
 
564
            if proj in blacklist:
 
565
                continue
 
566
            if whitelist and proj not in whitelist:
 
567
                continue
 
568
            repo = val['repository']
 
569
            branch = val['branch']
 
570
            repo_dir = _git_clone_and_install_single(repo, branch,
 
571
                                                     update_requirements)
 
572
            if proj == 'requirements':
 
573
                requirements_dir = repo_dir
 
574
            installed.append(proj)
 
575
    return installed
 
576
 
 
577
 
 
578
def _git_clone_and_install_single(repo, branch, update_requirements=False):
 
579
    """Clone and install a single git repository."""
 
580
    dest_parent_dir = "/mnt/openstack-git/"
 
581
    dest_dir = os.path.join(dest_parent_dir, os.path.basename(repo))
 
582
 
 
583
    if not os.path.exists(dest_parent_dir):
 
584
        juju_log('Host dir not mounted at {}. '
 
585
                 'Creating directory there instead.'.format(dest_parent_dir))
 
586
        os.mkdir(dest_parent_dir)
 
587
 
 
588
    if not os.path.exists(dest_dir):
 
589
        juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch))
 
590
        repo_dir = install_remote(repo, dest=dest_parent_dir, branch=branch)
 
591
    else:
 
592
        repo_dir = dest_dir
 
593
 
 
594
    if update_requirements:
 
595
        if not requirements_dir:
 
596
            error_out('requirements repo must be cloned before '
 
597
                      'updating from global requirements.')
 
598
        _git_update_requirements(repo_dir, requirements_dir)
 
599
 
 
600
    juju_log('Installing git repo from dir: {}'.format(repo_dir))
 
601
    pip_install(repo_dir)
 
602
 
 
603
    return repo_dir
 
604
 
 
605
 
 
606
def _git_update_requirements(package_dir, reqs_dir):
 
607
    """Update from global requirements.
 
608
 
 
609
       Update an OpenStack git directory's requirements.txt and
 
610
       test-requirements.txt from global-requirements.txt."""
 
611
    orig_dir = os.getcwd()
 
612
    os.chdir(reqs_dir)
 
613
    cmd = "python update.py {}".format(package_dir)
 
614
    try:
 
615
        subprocess.check_call(cmd.split(' '))
 
616
    except subprocess.CalledProcessError:
 
617
        package = os.path.basename(package_dir)
 
618
        error_out("Error updating {} from global-requirements.txt".format(package))
 
619
    os.chdir(orig_dir)