1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
"""
This file is used only by systemd units that are passing their instance suffix
as arguments to this script so that it can parse the suffix into arguments that
``ceph-volume <sub command>`` can consume
"""
import os
import sys
import time
import logging
from ceph_volume import log, process
from ceph_volume.exceptions import SuffixParsingError
def parse_subcommand(string):
subcommand = string.split('-', 1)[0]
if not subcommand:
raise SuffixParsingError('subcommand', string)
return subcommand
def parse_extra_data(string):
# get the subcommand to split on that
sub_command = parse_subcommand(string)
# the split will leave data with a dash, so remove that
data = string.split(sub_command)[-1]
if not data:
raise SuffixParsingError('data', string)
return data.lstrip('-')
def parse_osd_id(string):
osd_id = string.split('-', 1)[0]
if not osd_id:
raise SuffixParsingError('OSD id', string)
if osd_id.isdigit():
return osd_id
raise SuffixParsingError('OSD id', string)
def parse_osd_uuid(string):
osd_id = '%s-' % parse_osd_id(string)
osd_subcommand = '-%s' % parse_subcommand(string)
# remove the id first
trimmed_suffix = string.split(osd_id)[-1]
# now remove the sub command
osd_uuid = trimmed_suffix.split(osd_subcommand)[0]
if not osd_uuid:
raise SuffixParsingError('OSD uuid', string)
return osd_uuid
def main(args=None):
"""
Main entry point for the ``ceph-volume-systemd`` executable. ``args`` are
optional for easier testing of arguments.
Expected input is similar to::
['/path/to/ceph-volume-systemd', '<type>-<extra metadata>']
For example::
[
'/usr/bin/ceph-volume-systemd',
'lvm-0-8715BEB4-15C5-49DE-BA6F-401086EC7B41'
]
The first part of the argument is the only interesting bit, which contains
the metadata needed to proxy the call to ``ceph-volume`` itself.
Reusing the example, the proxy call to ``ceph-volume`` would look like::
ceph-volume lvm trigger 0-8715BEB4-15C5-49DE-BA6F-401086EC7B41
That means that ``lvm`` is used as the subcommand and it is **expected**
that a ``trigger`` sub-commmand will be present to make sense of the extra
piece of the string.
"""
log.setup(name='ceph-volume-systemd.log', log_path='/var/log/ceph/ceph-volume-systemd.log')
logger = logging.getLogger('systemd')
args = args if args is not None else sys.argv
try:
suffix = args[-1]
except IndexError:
raise RuntimeError('no arguments supplied')
sub_command = parse_subcommand(suffix)
extra_data = parse_extra_data(suffix)
logger.info('raw systemd input received: %s', suffix)
logger.info('parsed sub-command: %s, extra data: %s', sub_command, extra_data)
command = ['ceph-volume', sub_command, 'trigger', extra_data]
tries = int(os.environ.get('CEPH_VOLUME_SYSTEMD_TRIES', 30))
interval = int(os.environ.get('CEPH_VOLUME_SYSTEMD_INTERVAL', 5))
while tries > 0:
try:
# don't log any output to the terminal, just rely on stderr/stdout
# going to logging
process.run(command, terminal_logging=False)
logger.info('successfully triggered activation for: %s', extra_data)
break
except RuntimeError as error:
logger.warning(error)
logger.warning('failed activating OSD, retries left: %s', tries)
tries -= 1
time.sleep(interval)
|