From 6416fae6ca121026cae58d757fc11949664a6e36 Mon Sep 17 00:00:00 2001 From: Alfredo Deza Date: Tue, 11 Jul 2017 16:30:14 -0400 Subject: [PATCH] ceph-volume: util: create the module with prepare, activate, and system utilities Signed-off-by: Alfredo Deza --- src/ceph-volume/ceph_volume/util/__init__.py | 0 src/ceph-volume/ceph_volume/util/activate.py | 28 ++++ src/ceph-volume/ceph_volume/util/constants.py | 17 +++ src/ceph-volume/ceph_volume/util/prepare.py | 143 ++++++++++++++++++ src/ceph-volume/ceph_volume/util/system.py | 48 ++++++ 5 files changed, 236 insertions(+) create mode 100644 src/ceph-volume/ceph_volume/util/__init__.py create mode 100644 src/ceph-volume/ceph_volume/util/activate.py create mode 100644 src/ceph-volume/ceph_volume/util/constants.py create mode 100644 src/ceph-volume/ceph_volume/util/prepare.py create mode 100644 src/ceph-volume/ceph_volume/util/system.py diff --git a/src/ceph-volume/ceph_volume/util/__init__.py b/src/ceph-volume/ceph_volume/util/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/ceph-volume/ceph_volume/util/activate.py b/src/ceph-volume/ceph_volume/util/activate.py new file mode 100644 index 000000000000..48a8d38da251 --- /dev/null +++ b/src/ceph-volume/ceph_volume/util/activate.py @@ -0,0 +1,28 @@ +import os +from ceph_volume import process, conf + + +def add_osd_to_mon(osd_id): + """ + Register the previously prepared OSD to the monitor. A call will look like:: + + ceph --cluster ceph --name client.bootstrap-osd + --keyring /var/lib/ceph/bootstrap-osd/ceph.keyring \ + auth add osd.0 -i /var/lib/ceph/osd/ceph-0/keyring + osd "allow *" mon "allow profile osd" + """ + path = '/var/lib/ceph/osd/%s-%s/' % (conf.cluster, osd_id) + osd_keyring = os.path.join(path, 'keyring') + bootstrap_keyring = '/var/lib/ceph/bootstrap-osd/ceph.keyring' + + process.run([ + 'sudo', + 'ceph', + '--cluster', conf.cluster, + '--name', 'client.bootstrap-osd', + '--keyring', bootstrap_keyring, + 'auth', 'add', 'osd.%s' % osd_id, + '-i', osd_keyring, + 'osd', 'allow *', + 'mon', 'allow profile osd', + ]) diff --git a/src/ceph-volume/ceph_volume/util/constants.py b/src/ceph-volume/ceph_volume/util/constants.py new file mode 100644 index 000000000000..07df5a4f3611 --- /dev/null +++ b/src/ceph-volume/ceph_volume/util/constants.py @@ -0,0 +1,17 @@ + +# mount flags +mount = dict( + xfs='noatime,inode64', +) + + +# format flags +mkfs = dict( + xfs=[ + # force overwriting previous fs + '-f', + # set the inode size to 2kb + '-i', 'size=2048', + ], +) + diff --git a/src/ceph-volume/ceph_volume/util/prepare.py b/src/ceph-volume/ceph_volume/util/prepare.py new file mode 100644 index 000000000000..ba224b89a8dd --- /dev/null +++ b/src/ceph-volume/ceph_volume/util/prepare.py @@ -0,0 +1,143 @@ +""" +These utilities for prepare provide all the pieces needed to prepare a device +but also a compounded ("single call") helper to do them in order. Some plugins +may want to change some part of the process, while others might want to consume +the single-call helper +""" +import os +import logging +from ceph_volume import process, conf, terminal +from ceph_volume.util import system, constants + +logger = logging.getLogger(__name__) + + +def create_id(fsid): + stdout, stderr, returncode = process.call( + [ + 'ceph', + '--cluster', conf.cluster, + '--name', 'client.bootstrap-osd', + '--keyring', '/var/lib/ceph/bootstrap-osd/ceph.keyring', + 'osd', 'create', fsid + ], + terminal_logging=True + ) + if returncode != 0: + for line in stdout: + terminal.write(line) + for line in stderr: + terminal.write(line) + raise RuntimeError() + return ' '.join(stdout).strip() + + +def create_path(osd_id): + system.mkdir_p('/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)) + + +def format_device(device): + # only supports xfs + command = ['sudo', 'mkfs', '-t', 'xfs'] + + # get the mkfs options if any for xfs, + # fallback to the default options defined in constants.mkfs + flags = conf.ceph.get_list( + 'osd', + 'osd_mkfs_options_xfs', + default=constants.mkfs.get('xfs'), + split=' ', + ) + + # always force + if '-f' not in flags: + flags.insert(0, '-f') + + command.extend(flags) + command.append(device) + process.run(command) + + +def mount_osd(device, osd_id): + destination = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id) + command = ['sudo', 'mount', '-t', 'xfs', '-o'] + flags = conf.ceph.get_list( + 'osd', + 'osd_mount_options_xfs', + default=constants.mount.get('xfs'), + split=' ', + ) + command.append(flags) + command.append(device) + command.append(destination) + process.run(command) + + +def link_journal(journal_device, osd_id): + journal_path = '/var/lib/ceph/osd/%s-%s/journal' % ( + conf.cluster, + osd_id + ) + command = ['sudo', 'ln', '-s', journal_device, journal_path] + process.run(command) + + +def get_monmap(osd_id): + """ + Before creating the OSD files, a monmap needs to be retrieved so that it + can be used to tell the monitor(s) about the new OSD. A call will look like:: + + ceph --cluster ceph --name client.bootstrap-osd \ + --keyring /var/lib/ceph/bootstrap-osd/ceph.keyring \ + mon getmap -o /var/lib/ceph/osd/ceph-0/activate.monmap + """ + path = '/var/lib/ceph/osd/%s-%s/' % (conf.cluster, osd_id) + bootstrap_keyring = '/var/lib/ceph/bootstrap-osd/ceph.keyring' + monmap_destination = os.path.join(path, 'activate.monmap') + + process.run([ + 'sudo', + 'ceph', + '--cluster', conf.cluster, + '--name', 'client.bootstrap-osd', + '--keyring', bootstrap_keyring, + 'mon', 'getmap', '-o', monmap_destination + ]) + + +def osd_mkfs(osd_id, fsid): + """ + Create the files for the OSD to function. A normal call will look like: + + ceph-osd --cluster ceph --mkfs --mkkey -i 0 \ + --monmap /var/lib/ceph/osd/ceph-0/activate.monmap \ + --osd-data /var/lib/ceph/osd/ceph-0 \ + --osd-journal /var/lib/ceph/osd/ceph-0/journal \ + --osd-uuid 8d208665-89ae-4733-8888-5d3bfbeeec6c \ + --keyring /var/lib/ceph/osd/ceph-0/keyring \ + --setuser ceph --setgroup ceph + + """ + path = '/var/lib/ceph/osd/%s-%s/' % (conf.cluster, osd_id) + monmap = os.path.join(path, 'activate.monmap') + journal = os.path.join(path, 'journal') + keyring = os.path.join(path, 'keyring') + + system.chown(journal) + system.chown(path) + + process.run([ + 'sudo', + 'ceph-osd', + '--cluster', conf.cluster, + '--mkfs', + '--mkkey', + '-i', osd_id, + '--monmap', monmap, + '--osd-data', path, + '--osd-journal', journal, + '--osd-uuid', fsid, + '--keyring', keyring, + '--setuser', 'ceph', + '--setgroup', 'ceph' + ]) diff --git a/src/ceph-volume/ceph_volume/util/system.py b/src/ceph-volume/ceph_volume/util/system.py new file mode 100644 index 000000000000..f64ffa3f7995 --- /dev/null +++ b/src/ceph-volume/ceph_volume/util/system.py @@ -0,0 +1,48 @@ +import errno +import os +import pwd +import uuid +from ceph_volume import process + + +def generate_uuid(): + return str(uuid.uuid4()) + + +def get_ceph_user_ids(): + """ + Return the id and gid of the ceph user + """ + try: + user = pwd.getpwnam('ceph') + except KeyError: + # is this even possible? + raise RuntimeError('"ceph" user is not available in the current system') + return user[2], user[3] + + +def mkdir_p(path, chown=True): + """ + A `mkdir -p` that defaults to chown the path to the ceph user + """ + try: + os.mkdir(path) + except OSError as e: + if e.errno == errno.EEXIST: + pass + else: + raise + else: + uid, gid = get_ceph_user_ids() + os.chown(path, uid, gid) + + +def chown(path, ceph_user=True): + """ + ``chown`` a path to the ceph user (uid and guid fetched at runtime) + """ + uid, gid = get_ceph_user_ids() + if os.path.islink(path): + path = os.path.realpath(path) + process.run(['chown', '-R', 'ceph:ceph', path]) + #os.chown(path, uid, gid) -- 2.47.3