62
63
return service_result
66
def service_pause(service_name, init_dir="/etc/init", initd_dir="/etc/init.d"):
67
"""Pause a system service.
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:
78
elif os.path.exists(sysv_file):
79
subprocess.check_call(["update-rc.d", service_name, "disable"])
81
# XXX: Support SystemD too
83
"Unable to detect {0} as either Upstart {1} or SysV {2}".format(
84
service_name, upstart_file, sysv_file))
88
def service_resume(service_name, init_dir="/etc/init",
89
initd_dir="/etc/init.d"):
90
"""Resume a system service.
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"])
103
# XXX: Support SystemD too
105
"Unable to detect {0} as either Upstart {1} or SysV {2}".format(
106
service_name, upstart_file, sysv_file))
108
started = service_start(service_name)
65
112
def service(action, service_name):
66
113
"""Control a system service"""
67
114
cmd = ['service', service_name, action]
253
306
return system_mounts
309
def fstab_mount(mountpoint):
310
"""Mount filesystem using fstab"""
311
cmd_args = ['mount', mountpoint]
313
subprocess.check_output(cmd_args)
314
except subprocess.CalledProcessError as e:
315
log('Error unmounting {}\n{}'.format(mountpoint, e.output))
256
320
def file_hash(path, hash_type='md5'):
258
322
Generate a hash checksum of the contents of 'path' or None if not found.
338
Generate a hash checksum of all files matching 'path'. Standard wildcards
339
like '*' and '?' are supported, see documentation for the 'glob' module for
342
:return: dict: A { filename: hash } dictionary for all matched files.
346
filename: file_hash(filename)
347
for filename in glob.iglob(path)
272
351
def check_hash(path, checksum, hash_type='md5'):
274
353
Validate a file using a cryptographic checksum.
297
376
@restart_on_change({
298
377
'/etc/ceph/ceph.conf': [ 'cinder-api', 'cinder-volume' ]
378
'/etc/apache/sites-enabled/*': [ 'apache2' ]
300
def ceph_client_changed():
380
def config_changed():
301
381
pass # your code here
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.
308
391
def wrapped_f(*args, **kwargs):
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)
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))
355
def list_nics(nic_type):
436
def is_phy_iface(interface):
437
"""Returns True if interface is not virtual, otherwise False."""
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):
445
if interface == os.path.basename(iface):
451
def get_bond_master(interface):
452
"""Returns bond master if interface is bond slave otherwise None.
454
NOTE: the provided interface is expected to be physical
457
iface_path = '/sys/class/net/%s' % (interface)
458
if os.path.exists(iface_path):
459
if '/virtual/' in os.path.realpath(iface_path):
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)
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]
360
477
int_types = nic_type
362
for int_type in int_types:
363
cmd = ['ip', 'addr', 'show', 'label', int_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)
491
iface = matched.groups()[0]
493
iface = line.split()[1].replace(":", "")
495
if iface not in interfaces:
496
interfaces.append(iface)
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)
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)
370
interface = matched.groups()[0]
372
interface = line.split()[1].replace(":", "")
373
interfaces.append(interface)
504
matched = re.search(key, line)
506
iface = matched.group(1)
507
iface = iface.partition("@")[0]
508
if iface not in interfaces:
509
interfaces.append(iface)
375
511
return interfaces
433
def chownr(path, owner, group, follow_links=True):
569
def chownr(path, owner, group, follow_links=True, chowntopdir=False):
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.
574
:param bool follow_links: Also Chown links if True
575
:param bool chowntopdir: Also chown path itself if True
434
577
uid = pwd.getpwnam(owner).pw_uid
435
578
gid = grp.getgrnam(group).gr_gid