~celebdor/charms/trusty/midonet-api/trunk

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/core/host.py

  • Committer: Antoni Segura Puimedon
  • Date: 2016-01-21 08:53:27 UTC
  • mfrom: (16.1.16 ha_origins)
  • Revision ID: toni@midokura.com-20160121085327-blkd6zkyg7vphlyy
configure with midonet-origin and openstack-origin

The old full deployment amulet tests need to be corrected in
follow-up patches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
import os
25
25
import re
26
26
import pwd
 
27
import glob
27
28
import grp
28
29
import random
29
30
import string
62
63
    return service_result
63
64
 
64
65
 
 
66
def service_pause(service_name, init_dir="/etc/init", initd_dir="/etc/init.d"):
 
67
    """Pause a system service.
 
68
 
 
69
    Stop it, and prevent it from starting again at boot."""
 
70
    stopped = service_stop(service_name)
 
71
    upstart_file = os.path.join(init_dir, "{}.conf".format(service_name))
 
72
    sysv_file = os.path.join(initd_dir, service_name)
 
73
    if os.path.exists(upstart_file):
 
74
        override_path = os.path.join(
 
75
            init_dir, '{}.override'.format(service_name))
 
76
        with open(override_path, 'w') as fh:
 
77
            fh.write("manual\n")
 
78
    elif os.path.exists(sysv_file):
 
79
        subprocess.check_call(["update-rc.d", service_name, "disable"])
 
80
    else:
 
81
        # XXX: Support SystemD too
 
82
        raise ValueError(
 
83
            "Unable to detect {0} as either Upstart {1} or SysV {2}".format(
 
84
                service_name, upstart_file, sysv_file))
 
85
    return stopped
 
86
 
 
87
 
 
88
def service_resume(service_name, init_dir="/etc/init",
 
89
                   initd_dir="/etc/init.d"):
 
90
    """Resume a system service.
 
91
 
 
92
    Reenable starting again at boot. Start the service"""
 
93
    upstart_file = os.path.join(init_dir, "{}.conf".format(service_name))
 
94
    sysv_file = os.path.join(initd_dir, service_name)
 
95
    if os.path.exists(upstart_file):
 
96
        override_path = os.path.join(
 
97
            init_dir, '{}.override'.format(service_name))
 
98
        if os.path.exists(override_path):
 
99
            os.unlink(override_path)
 
100
    elif os.path.exists(sysv_file):
 
101
        subprocess.check_call(["update-rc.d", service_name, "enable"])
 
102
    else:
 
103
        # XXX: Support SystemD too
 
104
        raise ValueError(
 
105
            "Unable to detect {0} as either Upstart {1} or SysV {2}".format(
 
106
                service_name, upstart_file, sysv_file))
 
107
 
 
108
    started = service_start(service_name)
 
109
    return started
 
110
 
 
111
 
65
112
def service(action, service_name):
66
113
    """Control a system service"""
67
114
    cmd = ['service', service_name, action]
90
137
            ['service', service_name, 'status'],
91
138
            stderr=subprocess.STDOUT).decode('UTF-8')
92
139
    except subprocess.CalledProcessError as e:
93
 
        return 'unrecognized service' not in e.output
 
140
        return b'unrecognized service' not in e.output
94
141
    else:
95
142
        return True
96
143
 
117
164
    return user_info
118
165
 
119
166
 
 
167
def user_exists(username):
 
168
    """Check if a user exists"""
 
169
    try:
 
170
        pwd.getpwnam(username)
 
171
        user_exists = True
 
172
    except KeyError:
 
173
        user_exists = False
 
174
    return user_exists
 
175
 
 
176
 
120
177
def add_group(group_name, system_group=False):
121
178
    """Add a group to the system"""
122
179
    try:
139
196
 
140
197
def add_user_to_group(username, group):
141
198
    """Add a user to a group"""
142
 
    cmd = [
143
 
        'gpasswd', '-a',
144
 
        username,
145
 
        group
146
 
    ]
 
199
    cmd = ['gpasswd', '-a', username, group]
147
200
    log("Adding user {} to group {}".format(username, group))
148
201
    subprocess.check_call(cmd)
149
202
 
253
306
    return system_mounts
254
307
 
255
308
 
 
309
def fstab_mount(mountpoint):
 
310
    """Mount filesystem using fstab"""
 
311
    cmd_args = ['mount', mountpoint]
 
312
    try:
 
313
        subprocess.check_output(cmd_args)
 
314
    except subprocess.CalledProcessError as e:
 
315
        log('Error unmounting {}\n{}'.format(mountpoint, e.output))
 
316
        return False
 
317
    return True
 
318
 
 
319
 
256
320
def file_hash(path, hash_type='md5'):
257
321
    """
258
322
    Generate a hash checksum of the contents of 'path' or None if not found.
269
333
        return None
270
334
 
271
335
 
 
336
def path_hash(path):
 
337
    """
 
338
    Generate a hash checksum of all files matching 'path'. Standard wildcards
 
339
    like '*' and '?' are supported, see documentation for the 'glob' module for
 
340
    more information.
 
341
 
 
342
    :return: dict: A { filename: hash } dictionary for all matched files.
 
343
                   Empty if none found.
 
344
    """
 
345
    return {
 
346
        filename: file_hash(filename)
 
347
        for filename in glob.iglob(path)
 
348
    }
 
349
 
 
350
 
272
351
def check_hash(path, checksum, hash_type='md5'):
273
352
    """
274
353
    Validate a file using a cryptographic checksum.
296
375
 
297
376
        @restart_on_change({
298
377
            '/etc/ceph/ceph.conf': [ 'cinder-api', 'cinder-volume' ]
 
378
            '/etc/apache/sites-enabled/*': [ 'apache2' ]
299
379
            })
300
 
        def ceph_client_changed():
 
380
        def config_changed():
301
381
            pass  # your code here
302
382
 
303
383
    In this example, the cinder-api and cinder-volume services
304
384
    would be restarted if /etc/ceph/ceph.conf is changed by the
305
 
    ceph_client_changed function.
 
385
    ceph_client_changed function. The apache2 service would be
 
386
    restarted if any file matching the pattern got changed, created
 
387
    or removed. Standard wildcards are supported, see documentation
 
388
    for the 'glob' module for more information.
306
389
    """
307
390
    def wrap(f):
308
391
        def wrapped_f(*args, **kwargs):
309
 
            checksums = {}
310
 
            for path in restart_map:
311
 
                checksums[path] = file_hash(path)
 
392
            checksums = {path: path_hash(path) for path in restart_map}
312
393
            f(*args, **kwargs)
313
394
            restarts = []
314
395
            for path in restart_map:
315
 
                if checksums[path] != file_hash(path):
 
396
                if path_hash(path) != checksums[path]:
316
397
                    restarts += restart_map[path]
317
398
            services_list = list(OrderedDict.fromkeys(restarts))
318
399
            if not stopstart:
352
433
    return(''.join(random_chars))
353
434
 
354
435
 
355
 
def list_nics(nic_type):
 
436
def is_phy_iface(interface):
 
437
    """Returns True if interface is not virtual, otherwise False."""
 
438
    if interface:
 
439
        sys_net = '/sys/class/net'
 
440
        if os.path.isdir(sys_net):
 
441
            for iface in glob.glob(os.path.join(sys_net, '*')):
 
442
                if '/virtual/' in os.path.realpath(iface):
 
443
                    continue
 
444
 
 
445
                if interface == os.path.basename(iface):
 
446
                    return True
 
447
 
 
448
    return False
 
449
 
 
450
 
 
451
def get_bond_master(interface):
 
452
    """Returns bond master if interface is bond slave otherwise None.
 
453
 
 
454
    NOTE: the provided interface is expected to be physical
 
455
    """
 
456
    if interface:
 
457
        iface_path = '/sys/class/net/%s' % (interface)
 
458
        if os.path.exists(iface_path):
 
459
            if '/virtual/' in os.path.realpath(iface_path):
 
460
                return None
 
461
 
 
462
            master = os.path.join(iface_path, 'master')
 
463
            if os.path.exists(master):
 
464
                master = os.path.realpath(master)
 
465
                # make sure it is a bond master
 
466
                if os.path.exists(os.path.join(master, 'bonding')):
 
467
                    return os.path.basename(master)
 
468
 
 
469
    return None
 
470
 
 
471
 
 
472
def list_nics(nic_type=None):
356
473
    '''Return a list of nics of given type(s)'''
357
474
    if isinstance(nic_type, six.string_types):
358
475
        int_types = [nic_type]
359
476
    else:
360
477
        int_types = nic_type
 
478
 
361
479
    interfaces = []
362
 
    for int_type in int_types:
363
 
        cmd = ['ip', 'addr', 'show', 'label', int_type + '*']
 
480
    if nic_type:
 
481
        for int_type in int_types:
 
482
            cmd = ['ip', 'addr', 'show', 'label', int_type + '*']
 
483
            ip_output = subprocess.check_output(cmd).decode('UTF-8')
 
484
            ip_output = ip_output.split('\n')
 
485
            ip_output = (line for line in ip_output if line)
 
486
            for line in ip_output:
 
487
                if line.split()[1].startswith(int_type):
 
488
                    matched = re.search('.*: (' + int_type +
 
489
                                        r'[0-9]+\.[0-9]+)@.*', line)
 
490
                    if matched:
 
491
                        iface = matched.groups()[0]
 
492
                    else:
 
493
                        iface = line.split()[1].replace(":", "")
 
494
 
 
495
                    if iface not in interfaces:
 
496
                        interfaces.append(iface)
 
497
    else:
 
498
        cmd = ['ip', 'a']
364
499
        ip_output = subprocess.check_output(cmd).decode('UTF-8').split('\n')
365
 
        ip_output = (line for line in ip_output if line)
 
500
        ip_output = (line.strip() for line in ip_output if line)
 
501
 
 
502
        key = re.compile('^[0-9]+:\s+(.+):')
366
503
        for line in ip_output:
367
 
            if line.split()[1].startswith(int_type):
368
 
                matched = re.search('.*: (' + int_type + r'[0-9]+\.[0-9]+)@.*', line)
369
 
                if matched:
370
 
                    interface = matched.groups()[0]
371
 
                else:
372
 
                    interface = line.split()[1].replace(":", "")
373
 
                interfaces.append(interface)
 
504
            matched = re.search(key, line)
 
505
            if matched:
 
506
                iface = matched.group(1)
 
507
                iface = iface.partition("@")[0]
 
508
                if iface not in interfaces:
 
509
                    interfaces.append(iface)
374
510
 
375
511
    return interfaces
376
512
 
430
566
        os.chdir(cur)
431
567
 
432
568
 
433
 
def chownr(path, owner, group, follow_links=True):
 
569
def chownr(path, owner, group, follow_links=True, chowntopdir=False):
 
570
    """
 
571
    Recursively change user and group ownership of files and directories
 
572
    in given path. Doesn't chown path itself by default, only its children.
 
573
 
 
574
    :param bool follow_links: Also Chown links if True
 
575
    :param bool chowntopdir: Also chown path itself if True
 
576
    """
434
577
    uid = pwd.getpwnam(owner).pw_uid
435
578
    gid = grp.getgrnam(group).gr_gid
436
579
    if follow_links:
438
581
    else:
439
582
        chown = os.lchown
440
583
 
 
584
    if chowntopdir:
 
585
        broken_symlink = os.path.lexists(path) and not os.path.exists(path)
 
586
        if not broken_symlink:
 
587
            chown(path, uid, gid)
441
588
    for root, dirs, files in os.walk(path):
442
589
        for name in dirs + files:
443
590
            full = os.path.join(root, name)