~niedbalski/charms/trusty/ceph-osd/sysctl-param

« back to all changes in this revision

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

  • Committer: James Page
  • Date: 2013-11-18 12:17:59 UTC
  • mfrom: (15.1.3 ceph-osd)
  • Revision ID: james.page@canonical.com-20131118121759-son32zoatkaqp030
[james-page] Managed ceph.conf using alternatives

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
#  Nick Moffitt <nick.moffitt@canonical.com>
6
6
#  Matthew Wedgwood <matthew.wedgwood@canonical.com>
7
7
 
8
 
import apt_pkg
9
8
import os
10
9
import pwd
11
10
import grp
 
11
import random
 
12
import string
12
13
import subprocess
13
14
import hashlib
14
15
 
15
16
from collections import OrderedDict
16
17
 
17
 
from hookenv import log, execution_environment
 
18
from hookenv import log
18
19
 
19
20
 
20
21
def service_start(service_name):
21
 
    service('start', service_name)
 
22
    """Start a system service"""
 
23
    return service('start', service_name)
22
24
 
23
25
 
24
26
def service_stop(service_name):
25
 
    service('stop', service_name)
 
27
    """Stop a system service"""
 
28
    return service('stop', service_name)
26
29
 
27
30
 
28
31
def service_restart(service_name):
29
 
    service('restart', service_name)
 
32
    """Restart a system service"""
 
33
    return service('restart', service_name)
30
34
 
31
35
 
32
36
def service_reload(service_name, restart_on_failure=False):
33
 
    if not service('reload', service_name) and restart_on_failure:
34
 
        service('restart', service_name)
 
37
    """Reload a system service, optionally falling back to restart if reload fails"""
 
38
    service_result = service('reload', service_name)
 
39
    if not service_result and restart_on_failure:
 
40
        service_result = service('restart', service_name)
 
41
    return service_result
35
42
 
36
43
 
37
44
def service(action, service_name):
 
45
    """Control a system service"""
38
46
    cmd = ['service', service_name, action]
39
47
    return subprocess.call(cmd) == 0
40
48
 
41
49
 
 
50
def service_running(service):
 
51
    """Determine whether a system service is running"""
 
52
    try:
 
53
        output = subprocess.check_output(['service', service, 'status'])
 
54
    except subprocess.CalledProcessError:
 
55
        return False
 
56
    else:
 
57
        if ("start/running" in output or "is running" in output):
 
58
            return True
 
59
        else:
 
60
            return False
 
61
 
 
62
 
42
63
def adduser(username, password=None, shell='/bin/bash', system_user=False):
43
 
    """Add a user"""
 
64
    """Add a user to the system"""
44
65
    try:
45
66
        user_info = pwd.getpwnam(username)
46
67
        log('user {0} already exists!'.format(username))
74
95
 
75
96
def rsync(from_path, to_path, flags='-r', options=None):
76
97
    """Replicate the contents of a path"""
77
 
    context = execution_environment()
78
98
    options = options or ['--delete', '--executability']
79
99
    cmd = ['/usr/bin/rsync', flags]
80
100
    cmd.extend(options)
81
 
    cmd.append(from_path.format(**context))
82
 
    cmd.append(to_path.format(**context))
 
101
    cmd.append(from_path)
 
102
    cmd.append(to_path)
83
103
    log(" ".join(cmd))
84
104
    return subprocess.check_output(cmd).strip()
85
105
 
86
106
 
87
107
def symlink(source, destination):
88
108
    """Create a symbolic link"""
89
 
    context = execution_environment()
90
109
    log("Symlinking {} as {}".format(source, destination))
91
110
    cmd = [
92
111
        'ln',
93
112
        '-sf',
94
 
        source.format(**context),
95
 
        destination.format(**context)
 
113
        source,
 
114
        destination,
96
115
    ]
97
116
    subprocess.check_call(cmd)
98
117
 
99
118
 
100
119
def mkdir(path, owner='root', group='root', perms=0555, force=False):
101
120
    """Create a directory"""
102
 
    context = execution_environment()
103
121
    log("Making dir {} {}:{} {:o}".format(path, owner, group,
104
122
                                          perms))
105
 
    uid = pwd.getpwnam(owner.format(**context)).pw_uid
106
 
    gid = grp.getgrnam(group.format(**context)).gr_gid
 
123
    uid = pwd.getpwnam(owner).pw_uid
 
124
    gid = grp.getgrnam(group).gr_gid
107
125
    realpath = os.path.abspath(path)
108
126
    if os.path.exists(realpath):
109
127
        if force and not os.path.isdir(realpath):
114
132
    os.chown(realpath, uid, gid)
115
133
 
116
134
 
117
 
def write_file(path, fmtstr, owner='root', group='root', perms=0444, **kwargs):
 
135
def write_file(path, content, owner='root', group='root', perms=0444):
118
136
    """Create or overwrite a file with the contents of a string"""
119
 
    context = execution_environment()
120
 
    context.update(kwargs)
121
 
    log("Writing file {} {}:{} {:o}".format(path, owner, group,
122
 
        perms))
123
 
    uid = pwd.getpwnam(owner.format(**context)).pw_uid
124
 
    gid = grp.getgrnam(group.format(**context)).gr_gid
125
 
    with open(path.format(**context), 'w') as target:
 
137
    log("Writing file {} {}:{} {:o}".format(path, owner, group, perms))
 
138
    uid = pwd.getpwnam(owner).pw_uid
 
139
    gid = grp.getgrnam(group).gr_gid
 
140
    with open(path, 'w') as target:
126
141
        os.fchown(target.fileno(), uid, gid)
127
142
        os.fchmod(target.fileno(), perms)
128
 
        target.write(fmtstr.format(**context))
129
 
 
130
 
 
131
 
def render_template_file(source, destination, **kwargs):
132
 
    """Create or overwrite a file using a template"""
133
 
    log("Rendering template {} for {}".format(source,
134
 
        destination))
135
 
    context = execution_environment()
136
 
    with open(source.format(**context), 'r') as template:
137
 
        write_file(destination.format(**context), template.read(),
138
 
                   **kwargs)
139
 
 
140
 
 
141
 
def filter_installed_packages(packages):
142
 
    """Returns a list of packages that require installation"""
143
 
    apt_pkg.init()
144
 
    cache = apt_pkg.Cache()
145
 
    _pkgs = []
146
 
    for package in packages:
147
 
        try:
148
 
            p = cache[package]
149
 
            p.current_ver or _pkgs.append(package)
150
 
        except KeyError:
151
 
            log('Package {} has no installation candidate.'.format(package),
152
 
                level='WARNING')
153
 
            _pkgs.append(package)
154
 
    return _pkgs
155
 
 
156
 
 
157
 
def apt_install(packages, options=None, fatal=False):
158
 
    """Install one or more packages"""
159
 
    options = options or []
160
 
    cmd = ['apt-get', '-y']
161
 
    cmd.extend(options)
162
 
    cmd.append('install')
163
 
    if isinstance(packages, basestring):
164
 
        cmd.append(packages)
165
 
    else:
166
 
        cmd.extend(packages)
167
 
    log("Installing {} with options: {}".format(packages,
168
 
                                                options))
169
 
    if fatal:
170
 
        subprocess.check_call(cmd)
171
 
    else:
172
 
        subprocess.call(cmd)
173
 
 
174
 
 
175
 
def apt_update(fatal=False):
176
 
    """Update local apt cache"""
177
 
    cmd = ['apt-get', 'update']
178
 
    if fatal:
179
 
        subprocess.check_call(cmd)
180
 
    else:
181
 
        subprocess.call(cmd)
 
143
        target.write(content)
182
144
 
183
145
 
184
146
def mount(device, mountpoint, options=None, persist=False):
185
 
    '''Mount a filesystem'''
 
147
    """Mount a filesystem at a particular mountpoint"""
186
148
    cmd_args = ['mount']
187
149
    if options is not None:
188
150
        cmd_args.extend(['-o', options])
199
161
 
200
162
 
201
163
def umount(mountpoint, persist=False):
202
 
    '''Unmount a filesystem'''
 
164
    """Unmount a filesystem"""
203
165
    cmd_args = ['umount', mountpoint]
204
166
    try:
205
167
        subprocess.check_output(cmd_args)
213
175
 
214
176
 
215
177
def mounts():
216
 
    '''List of all mounted volumes as [[mountpoint,device],[...]]'''
 
178
    """Get a list of all mounted volumes as [[mountpoint,device],[...]]"""
217
179
    with open('/proc/mounts') as f:
218
180
        # [['/mount/point','/dev/path'],[...]]
219
181
        system_mounts = [m[1::-1] for m in [l.strip().split()
222
184
 
223
185
 
224
186
def file_hash(path):
225
 
    ''' 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 """
226
188
    if os.path.exists(path):
227
189
        h = hashlib.md5()
228
190
        with open(path, 'r') as source:
233
195
 
234
196
 
235
197
def restart_on_change(restart_map):
236
 
    ''' Restart services based on configuration files changing
 
198
    """Restart services based on configuration files changing
237
199
 
238
200
    This function is used a decorator, for example
239
201
 
246
208
    In this example, the cinder-api and cinder-volume services
247
209
    would be restarted if /etc/ceph/ceph.conf is changed by the
248
210
    ceph_client_changed function.
249
 
    '''
 
211
    """
250
212
    def wrap(f):
251
213
        def wrapped_f(*args):
252
214
            checksums = {}
264
226
 
265
227
 
266
228
def lsb_release():
267
 
    '''Return /etc/lsb-release in a dict'''
 
229
    """Return /etc/lsb-release in a dict"""
268
230
    d = {}
269
231
    with open('/etc/lsb-release', 'r') as lsb:
270
232
        for l in lsb:
271
233
            k, v = l.split('=')
272
234
            d[k.strip()] = v.strip()
273
235
    return d
 
236
 
 
237
 
 
238
def pwgen(length=None):
 
239
    """Generate a random pasword."""
 
240
    if length is None:
 
241
        length = random.choice(range(35, 45))
 
242
    alphanumeric_chars = [
 
243
        l for l in (string.letters + string.digits)
 
244
        if l not in 'l0QD1vAEIOUaeiou']
 
245
    random_chars = [
 
246
        random.choice(alphanumeric_chars) for _ in range(length)]
 
247
    return(''.join(random_chars))