def prepare_device(self, arg, device_type, cluster_fsid, osd_fsid): """ Check if ``arg`` is a device or partition to create an LV out of it with a distinct volume group name, assigning LV tags on it and ultimately, returning the logical volume object. Failing to detect a device or partition will result in error. :param arg: The value of ``--data`` when parsing args :param device_type: Usually, either ``data`` or ``block`` (filestore vs. bluestore) :param cluster_fsid: The cluster fsid/uuid :param osd_fsid: The OSD fsid/uuid """ if disk.is_partition(arg) or disk.is_device(arg): # we must create a vg, and then a single lv vg_name = "ceph-%s" % cluster_fsid if api.get_vg(vg_name=vg_name): # means we already have a group for this, make a different one # XXX this could end up being annoying for an operator, maybe? vg_name = "ceph-%s" % str(uuid.uuid4()) api.create_vg(vg_name, arg) lv_name = "osd-%s-%s" % (device_type, osd_fsid) return api.create_lv( lv_name, vg_name, # the volume group tags={'ceph.type': device_type}) else: error = [ 'Cannot use device (%s).' % arg, 'A vg/lv path or an existing device is needed' ] raise RuntimeError(' '.join(error)) raise RuntimeError('no data logical volume found with: %s' % arg)
def prepare_device(self, arg, device_type, cluster_fsid, osd_fsid): """ Check if ``arg`` is a device or partition to create an LV out of it with a distinct volume group name, assigning LV tags on it and ultimately, returning the logical volume object. Failing to detect a device or partition will result in error. :param arg: The value of ``--data`` when parsing args :param device_type: Usually, either ``data`` or ``block`` (filestore vs. bluestore) :param cluster_fsid: The cluster fsid/uuid :param osd_fsid: The OSD fsid/uuid """ if disk.is_partition(arg) or disk.is_device(arg): # we must create a vg, and then a single lv vg_name = "ceph-%s" % cluster_fsid if api.get_vg(vg_name=vg_name): # means we already have a group for this, make a different one # XXX this could end up being annoying for an operator, maybe? vg_name = "ceph-%s" % str(uuid.uuid4()) api.create_vg(vg_name, arg) lv_name = "osd-%s-%s" % (device_type, osd_fsid) return api.create_lv( lv_name, vg_name, # the volume group tags={'ceph.type': device_type}) else: error = [ 'Cannot use device (%s).' % arg, 'A vg/lv path or an existing device is needed'] raise RuntimeError(' '.join(error)) raise RuntimeError('no data logical volume found with: %s' % arg)
def prepare_data_device(self, device_type, osd_uuid): """ Check if ``arg`` is a device or partition to create an LV out of it with a distinct volume group name, assigning LV tags on it and ultimately, returning the logical volume object. Failing to detect a device or partition will result in error. :param arg: The value of ``--data`` when parsing args :param device_type: Usually, either ``data`` or ``block`` (filestore vs. bluestore) :param osd_uuid: The OSD uuid """ device = self.args.data if disk.is_partition(device) or disk.is_device(device): # we must create a vg, and then a single lv lv_name_prefix = "osd-{}".format(device_type) kwargs = { 'device': device, 'tags': { 'ceph.type': device_type }, 'slots': self.args.data_slots, } logger.debug('data device size: {}'.format(self.args.data_size)) if self.args.data_size != 0: kwargs['size'] = self.args.data_size return api.create_lv(lv_name_prefix, osd_uuid, **kwargs) else: error = [ 'Cannot use device ({}).'.format(device), 'A vg/lv path or an existing device is needed' ] raise RuntimeError(' '.join(error)) raise RuntimeError( 'no data logical volume found with: {}'.format(device))
def __call__(self, string): if not os.path.exists(string): error = "Path does not exist: %s" % string raise argparse.ArgumentError(None, error) arg_is_partition = disk.is_partition(string) if arg_is_partition: return os.path.abspath(string) absolute_path = os.path.abspath(string) if not os.path.isdir(absolute_path): error = "Argument is not a directory or device which is required to scan" raise argparse.ArgumentError(None, error) key_files = ['ceph_fsid', 'fsid', 'keyring', 'ready', 'type', 'whoami'] dir_files = os.listdir(absolute_path) for key_file in key_files: if key_file not in dir_files: terminal.error('All following files must exist in path: %s' % ' '.join(key_files)) error = "Required file (%s) was not found in OSD dir path: %s" % ( key_file, absolute_path) raise argparse.ArgumentError(None, error) return os.path.abspath(string)
def __call__(self, string): if not os.path.exists(string): error = "Path does not exist: %s" % string raise argparse.ArgumentError(None, error) arg_is_partition = disk.is_partition(string) if arg_is_partition: return os.path.abspath(string) absolute_path = os.path.abspath(string) if not os.path.isdir(absolute_path): error = "Argument is not a directory or device which is required to scan" raise argparse.ArgumentError(None, error) key_files = ['ceph_fsid', 'fsid', 'keyring', 'ready', 'type', 'whoami'] dir_files = os.listdir(absolute_path) for key_file in key_files: if key_file not in dir_files: terminal.error('All following files must exist in path: %s' % ' '.join(key_files)) error = "Required file (%s) was not found in OSD dir path: %s" % ( key_file, absolute_path ) raise argparse.ArgumentError(None, error) return os.path.abspath(string)
def main(self): sub_command_help = dedent(""" Scan an OSD directory (or data device) for files and configurations that will allow to take over the management of the OSD. Scanned OSDs will get their configurations stored in /etc/ceph/osd/<id>-<fsid>.json For an OSD ID of 0 with fsid of ``a9d50838-e823-43d6-b01f-2f8d0a77afc2`` that could mean a scan command that looks like:: ceph-volume lvm scan /var/lib/ceph/osd/ceph-0 Which would store the metadata in a JSON file at:: /etc/ceph/osd/0-a9d50838-e823-43d6-b01f-2f8d0a77afc2.json To a scan an existing, running, OSD: ceph-volume simple scan /var/lib/ceph/osd/{cluster}-{osd id} And to scan a device (mounted or unmounted) that has OSD data in it, for example /dev/sda1 ceph-volume simple scan /dev/sda1 """) parser = argparse.ArgumentParser( prog='ceph-volume simple scan', formatter_class=argparse.RawDescriptionHelpFormatter, description=sub_command_help, ) parser.add_argument( '-f', '--force', action='store_true', help='If OSD has already been scanned, the JSON file will be overwritten' ) parser.add_argument( '--stdout', action='store_true', help='Do not save to a file, output metadata to stdout' ) parser.add_argument( 'osd_path', metavar='OSD_PATH', type=arg_validators.OSDPath(), nargs='?', help='Path to an existing OSD directory or OSD data partition' ) if len(self.argv) == 0: print(sub_command_help) return args = parser.parse_args(self.argv) if disk.is_partition(args.osd_path): label = disk.lsblk(args.osd_path)['PARTLABEL'] if 'data' not in label: raise RuntimeError('Device must be the data partition, but got: %s' % label) # Capture some environment status, so that it can be reused all over self.device_mounts = system.get_mounts(devices=True) self.path_mounts = system.get_mounts(paths=True) self.encryption_metadata = encryption.legacy_encrypted(args.osd_path) self.is_encrypted = self.encryption_metadata['encrypted'] self.scan(args)
def prepare(self, args): # FIXME we don't allow re-using a keyring, we always generate one for the # OSD, this needs to be fixed. This could either be a file (!) or a string # (!!) or some flags that we would need to compound into a dict so that we # can convert to JSON (!!!) secrets = {'cephx_secret': prepare_utils.create_key()} cluster_fsid = conf.ceph.get('global', 'fsid') osd_fsid = args.osd_fsid or system.generate_uuid() # allow re-using an id, in case a prepare failed osd_id = args.osd_id or prepare_utils.create_id( osd_fsid, json.dumps(secrets)) if args.filestore: if not args.journal: raise RuntimeError( '--journal is required when using --filestore') data_lv = self.get_lv(args.data) if not data_lv: raise RuntimeError('no data logical volume found with: %s' % args.data) tags = { 'ceph.osd_fsid': osd_fsid, 'ceph.osd_id': osd_id, 'ceph.cluster_fsid': cluster_fsid, 'ceph.cluster_name': conf.cluster, 'ceph.data_device': data_lv.lv_path, 'ceph.data_uuid': data_lv.lv_uuid, } journal_device, journal_uuid, tags = self.setup_device( 'journal', args.journal, tags) tags['ceph.type'] = 'data' data_lv.set_tags(tags) prepare_filestore( data_lv.lv_path, journal_device, secrets, id_=osd_id, fsid=osd_fsid, ) elif args.bluestore: block_lv = self.get_lv(args.data) if not block_lv: if disk.is_partition(args.data) or disk.is_device(args.data): # we must create a vg, and then a single lv vg_name = "ceph-%s" % cluster_fsid if api.get_vg(vg_name=vg_name): # means we already have a group for this, make a different one # XXX this could end up being annoying for an operator, maybe? vg_name = "ceph-%s" % str(uuid.uuid4()) api.create_vg(vg_name, args.data) block_name = "osd-block-%s" % osd_fsid block_lv = api.create_lv( block_name, vg_name, # the volume group tags={'ceph.type': 'block'}) else: error = [ 'Cannot use device (%s) for bluestore. ' % args.data, 'A vg/lv path or an existing device is needed' ] raise RuntimeError(' '.join(error)) tags = { 'ceph.osd_fsid': osd_fsid, 'ceph.osd_id': osd_id, 'ceph.cluster_fsid': cluster_fsid, 'ceph.cluster_name': conf.cluster, 'ceph.block_device': block_lv.lv_path, 'ceph.block_uuid': block_lv.lv_uuid, } wal_device, wal_uuid, tags = self.setup_device( 'wal', args.block_wal, tags) db_device, db_uuid, tags = self.setup_device( 'db', args.block_db, tags) tags['ceph.type'] = 'block' block_lv.set_tags(tags) prepare_bluestore( block_lv.lv_path, wal_device, db_device, secrets, id_=osd_id, fsid=osd_fsid, )
def main(self): sub_command_help = dedent(""" Scan an OSD directory (or data device) for files and configurations that will allow to take over the management of the OSD. Scanned OSDs will get their configurations stored in /etc/ceph/osd/<id>-<fsid>.json For an OSD ID of 0 with fsid of ``a9d50838-e823-43d6-b01f-2f8d0a77afc2`` that could mean a scan command that looks like:: ceph-volume lvm scan /var/lib/ceph/osd/ceph-0 Which would store the metadata in a JSON file at:: /etc/ceph/osd/0-a9d50838-e823-43d6-b01f-2f8d0a77afc2.json To a scan an existing, running, OSD: ceph-volume simple scan /var/lib/ceph/osd/{cluster}-{osd id} And to scan a device (mounted or unmounted) that has OSD data in it, for example /dev/sda1 ceph-volume simple scan /dev/sda1 """) parser = argparse.ArgumentParser( prog='ceph-volume simple scan', formatter_class=argparse.RawDescriptionHelpFormatter, description=sub_command_help, ) parser.add_argument( '-f', '--force', action='store_true', help= 'If OSD has already been scanned, the JSON file will be overwritten' ) parser.add_argument( '--stdout', action='store_true', help='Do not save to a file, output metadata to stdout') parser.add_argument( 'osd_path', metavar='OSD_PATH', type=arg_validators.OSDPath(), nargs='?', help='Path to an existing OSD directory or OSD data partition') if len(self.argv) == 0: print(sub_command_help) return args = parser.parse_args(self.argv) if disk.is_partition(args.osd_path): label = disk.lsblk(args.osd_path)['PARTLABEL'] if 'data' not in label: raise RuntimeError( 'Device must be the data partition, but got: %s' % label) # Capture some environment status, so that it can be reused all over self.device_mounts = system.get_mounts(devices=True) self.path_mounts = system.get_mounts(paths=True) self.encryption_metadata = encryption.legacy_encrypted(args.osd_path) self.is_encrypted = self.encryption_metadata['encrypted'] self.scan(args)