5
5
# Nick Moffitt <nick.moffitt@canonical.com>
6
6
# Matthew Wedgwood <matthew.wedgwood@canonical.com>
15
16
from collections import OrderedDict
17
from hookenv import log, execution_environment
18
from hookenv import log
20
21
def service_start(service_name):
21
service('start', service_name)
22
"""Start a system service"""
23
return service('start', service_name)
24
26
def service_stop(service_name):
25
service('stop', service_name)
27
"""Stop a system service"""
28
return service('stop', service_name)
28
31
def service_restart(service_name):
29
service('restart', service_name)
32
"""Restart a system service"""
33
return service('restart', service_name)
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)
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
50
def service_running(service):
51
"""Determine whether a system service is running"""
53
output = subprocess.check_output(['service', service, 'status'])
54
except subprocess.CalledProcessError:
57
if ("start/running" in output or "is running" in output):
42
63
def adduser(username, password=None, shell='/bin/bash', system_user=False):
64
"""Add a user to the system"""
45
66
user_info = pwd.getpwnam(username)
46
67
log('user {0} already exists!'.format(username))
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)
83
103
log(" ".join(cmd))
84
104
return subprocess.check_output(cmd).strip()
87
107
def symlink(source, destination):
88
108
"""Create a symbolic link"""
89
context = execution_environment()
90
109
log("Symlinking {} as {}".format(source, destination))
94
source.format(**context),
95
destination.format(**context)
97
116
subprocess.check_call(cmd)
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,
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)
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,
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))
131
def render_template_file(source, destination, **kwargs):
132
"""Create or overwrite a file using a template"""
133
log("Rendering template {} for {}".format(source,
135
context = execution_environment()
136
with open(source.format(**context), 'r') as template:
137
write_file(destination.format(**context), template.read(),
141
def filter_installed_packages(packages):
142
"""Returns a list of packages that require installation"""
144
cache = apt_pkg.Cache()
146
for package in packages:
149
p.current_ver or _pkgs.append(package)
151
log('Package {} has no installation candidate.'.format(package),
153
_pkgs.append(package)
157
def apt_install(packages, options=None, fatal=False):
158
"""Install one or more packages"""
159
options = options or []
160
cmd = ['apt-get', '-y']
162
cmd.append('install')
163
if isinstance(packages, basestring):
167
log("Installing {} with options: {}".format(packages,
170
subprocess.check_call(cmd)
175
def apt_update(fatal=False):
176
"""Update local apt cache"""
177
cmd = ['apt-get', 'update']
179
subprocess.check_call(cmd)
143
target.write(content)
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])
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()
266
228
def lsb_release():
267
'''Return /etc/lsb-release in a dict'''
229
"""Return /etc/lsb-release in a dict"""
269
231
with open('/etc/lsb-release', 'r') as lsb:
271
233
k, v = l.split('=')
272
234
d[k.strip()] = v.strip()
238
def pwgen(length=None):
239
"""Generate a random pasword."""
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']
246
random.choice(alphanumeric_chars) for _ in range(length)]
247
return(''.join(random_chars))