Beispiel #1
0
 def test_unable_to_read_configuration(self, tmpdir, capsys):
     ceph_conf = os.path.join(str(tmpdir), 'ceph.conf')
     with open(ceph_conf, 'w') as config:
         config.write(']broken] config\n[[')
     with pytest.raises(RuntimeError):
         configuration.load(ceph_conf)
     stdout, stderr = capsys.readouterr()
     assert 'File contains no section headers' in stdout
 def test_unable_to_read_configuration(self, tmpdir, capsys):
     ceph_conf = os.path.join(str(tmpdir), 'ceph.conf')
     with open(ceph_conf, 'w') as config:
         config.write(']broken] config\n[[')
     with pytest.raises(RuntimeError):
         configuration.load(ceph_conf)
     stdout, stderr = capsys.readouterr()
     assert 'File contains no section headers' in stdout
Beispiel #3
0
 def main(self, argv):
     # these need to be available for the help, which gets parsed super
     # early
     self.load_ceph_conf_path()
     self.load_log_path()
     self.enable_plugins()
     main_args, subcommand_args = self._get_split_args()
     # no flags where passed in, return the help menu instead of waiting for
     # argparse which will end up complaning that there are no args
     if len(argv) <= 1:
         print(self.help(warning=True))
         return
     parser = argparse.ArgumentParser(
         prog='ceph-volume',
         formatter_class=argparse.RawDescriptionHelpFormatter,
         description=self.help(),
     )
     parser.add_argument(
         '--cluster',
         default='ceph',
         help='Cluster name (defaults to "ceph")',
     )
     parser.add_argument(
         '--log-level',
         default='debug',
         help='Change the file log level (defaults to debug)',
     )
     parser.add_argument(
         '--log-path',
         default='/var/log/ceph/',
         help='Change the log path (defaults to /var/log/ceph)',
     )
     args = parser.parse_args(main_args)
     conf.log_path = args.log_path
     if os.path.isdir(conf.log_path):
         conf.log_path = os.path.join(args.log_path, 'ceph-volume.log')
     log.setup()
     logger = logging.getLogger(__name__)
     logger.info("Running command: ceph-volume %s %s", " ".join(main_args), " ".join(subcommand_args))
     # set all variables from args and load everything needed according to
     # them
     self.load_ceph_conf_path(cluster_name=args.cluster)
     try:
         conf.ceph = configuration.load(conf.path)
     except exceptions.ConfigurationError as error:
         is_help = "-h" in subcommand_args or "--help" in subcommand_args
         if " ".join(subcommand_args[:2]) in IGNORE_CEPH_CONFIG_COMMANDS or is_help:
             # we warn only here, because it is possible that the configuration
             # file is not needed, or that it will be loaded by some other means
             # (like reading from lvm tags)
             logger.exception('ignoring inability to load ceph.conf')
             terminal.red(error)
         else:
             terminal.red(error)
             raise
     # dispatch to sub-commands
     terminal.dispatch(self.mapper, subcommand_args)
Beispiel #4
0
 def main(self, argv):
     self.load_ceph_conf_path()
     # these need to be available for the help, which gets parsed super
     # early
     self.load_ceph_conf_path()
     self.load_log_path()
     main_args, subcommand_args = self._get_split_args()
     # no flags where passed in, return the help menu instead of waiting for
     # argparse which will end up complaning that there are no args
     if len(argv) <= 1:
         print(self.help(warning=True))
         return
     parser = argparse.ArgumentParser(
         prog='ceph-volume-zfs',
         formatter_class=argparse.RawDescriptionHelpFormatter,
         description=self.help(),
     )
     parser.add_argument(
         '--cluster',
         default='ceph',
         help='Cluster name (defaults to "ceph")',
     )
     parser.add_argument(
         '--log-level',
         default='debug',
         help='Change the file log level (defaults to debug)',
     )
     parser.add_argument(
         '--log-path',
         default='/var/log/ceph/',
         help='Change the log path (defaults to /var/log/ceph)',
     )
     args = parser.parse_args(main_args)
     conf.log_path = args.log_path
     if os.path.isdir(conf.log_path):
         conf.log_path = os.path.join(args.log_path, 'ceph-volume-zfs.log')
     log.setup()
     logger = logging.getLogger(__name__)
     logger.info("Running command: ceph-volume-zfs %s %s",
                 " ".join(main_args), " ".join(subcommand_args))
     # set all variables from args and load everything needed according to
     # them
     self.load_ceph_conf_path(cluster_name=args.cluster)
     try:
         conf.ceph = configuration.load(conf.path)
     except exceptions.ConfigurationError as error:
         # we warn only here, because it is possible that the configuration
         # file is not needed, or that it will be loaded by some other means
         # (like reading from zfs tags)
         logger.exception('ignoring inability to load ceph.conf')
         terminal.red(error)
     # dispatch to sub-commands
     terminal.dispatch(self.mapper, subcommand_args)
Beispiel #5
0
 def main(self, argv):
     # these need to be available for the help, which gets parsed super
     # early
     self.load_ceph_conf_path()
     self.load_log_path()
     self.enable_plugins()
     main_args, subcommand_args = self._get_split_args()
     # no flags where passed in, return the help menu instead of waiting for
     # argparse which will end up complaning that there are no args
     if len(argv) <= 1:
         print(self.help(warning=True))
         return
     parser = argparse.ArgumentParser(
         prog='ceph-volume',
         formatter_class=argparse.RawDescriptionHelpFormatter,
         description=self.help(),
     )
     parser.add_argument(
         '--cluster',
         default='ceph',
         help='Cluster name (defaults to "ceph")',
     )
     parser.add_argument(
         '--log-level',
         default='debug',
         help='Change the file log level (defaults to debug)',
     )
     parser.add_argument(
         '--log-path',
         default='/var/log/ceph/',
         help='Change the log path (defaults to /var/log/ceph)',
     )
     args = parser.parse_args(main_args)
     conf.log_path = args.log_path
     if os.path.isdir(conf.log_path):
         conf.log_path = os.path.join(args.log_path, 'ceph-volume.log')
     log.setup()
     # set all variables from args and load everything needed according to
     # them
     self.load_ceph_conf_path(cluster_name=args.cluster)
     conf.ceph = configuration.load(conf.path)
     # dispatch to sub-commands
     terminal.dispatch(self.mapper, subcommand_args)
Beispiel #6
0
 def main(self, argv):
     # these need to be available for the help, which gets parsed super
     # early
     self.load_ceph_conf_path()
     self.load_log_path()
     self.enable_plugins()
     main_args, subcommand_args = self._get_split_args()
     # no flags where passed in, return the help menu instead of waiting for
     # argparse which will end up complaning that there are no args
     if len(argv) <= 1:
         print(self.help(warning=True))
         return
     parser = argparse.ArgumentParser(
         prog='ceph-volume',
         formatter_class=argparse.RawDescriptionHelpFormatter,
         description=self.help(),
     )
     parser.add_argument(
         '--cluster',
         default='ceph',
         help='Cluster name (defaults to "ceph")',
     )
     parser.add_argument(
         '--log-level',
         default='debug',
         help='Change the file log level (defaults to debug)',
     )
     parser.add_argument(
         '--log-path',
         default='/var/log/ceph/',
         help='Change the log path (defaults to /var/log/ceph)',
     )
     args = parser.parse_args(main_args)
     conf.log_path = args.log_path
     if os.path.isdir(conf.log_path):
         conf.log_path = os.path.join(args.log_path, 'ceph-volume.log')
     log.setup()
     # set all variables from args and load everything needed according to
     # them
     self.load_ceph_conf_path(cluster_name=args.cluster)
     conf.ceph = configuration.load(conf.path)
     # dispatch to sub-commands
     terminal.dispatch(self.mapper, subcommand_args)
Beispiel #7
0
def activate_filestore(lvs, no_systemd=False):
    # find the osd
    osd_lv = lvs.get(lv_tags={'ceph.type': 'data'})
    if not osd_lv:
        raise RuntimeError('Unable to find a data LV for filestore activation')
    is_encrypted = osd_lv.tags.get('ceph.encrypted', '0') == '1'
    is_vdo = osd_lv.tags.get('ceph.vdo', '0')

    osd_id = osd_lv.tags['ceph.osd_id']
    configuration.load_ceph_conf_path(osd_lv.tags['ceph.cluster_name'])
    configuration.load()
    # it may have a volume with a journal
    osd_journal_lv = lvs.get(lv_tags={'ceph.type': 'journal'})
    # TODO: add sensible error reporting if this is ever the case
    # blow up with a KeyError if this doesn't exist
    osd_fsid = osd_lv.tags['ceph.osd_fsid']
    if not osd_journal_lv:
        # must be a disk partition, by querying blkid by the uuid we are ensuring that the
        # device path is always correct
        journal_uuid = osd_lv.tags['ceph.journal_uuid']
        osd_journal = disk.get_device_from_partuuid(journal_uuid)
    else:
        journal_uuid = osd_journal_lv.lv_uuid
        osd_journal = osd_lv.tags['ceph.journal_device']

    if not osd_journal:
        raise RuntimeError('unable to detect an lv or device journal for OSD %s' % osd_id)

    # this is done here, so that previous checks that ensure path availability
    # and correctness can still be enforced, and report if any issues are found
    if is_encrypted:
        lockbox_secret = osd_lv.tags['ceph.cephx_lockbox_secret']
        # this keyring writing is idempotent
        encryption_utils.write_lockbox_keyring(osd_id, osd_fsid, lockbox_secret)
        dmcrypt_secret = encryption_utils.get_dmcrypt_key(osd_id, osd_fsid)
        encryption_utils.luks_open(dmcrypt_secret, osd_lv.lv_path, osd_lv.lv_uuid)
        encryption_utils.luks_open(dmcrypt_secret, osd_journal, journal_uuid)

        osd_journal = '/dev/mapper/%s' % journal_uuid
        source = '/dev/mapper/%s' % osd_lv.lv_uuid
    else:
        source = osd_lv.lv_path

    # mount the osd
    destination = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)
    if not system.device_is_mounted(source, destination=destination):
        prepare_utils.mount_osd(source, osd_id, is_vdo=is_vdo)

    # always re-do the symlink regardless if it exists, so that the journal
    # device path that may have changed can be mapped correctly every time
    destination = '/var/lib/ceph/osd/%s-%s/journal' % (conf.cluster, osd_id)
    process.run(['ln', '-snf', osd_journal, destination])

    # make sure that the journal has proper permissions
    system.chown(osd_journal)

    if no_systemd is False:
        # enable the ceph-volume unit for this OSD
        systemctl.enable_volume(osd_id, osd_fsid, 'lvm')

        # enable the OSD
        systemctl.enable_osd(osd_id)

        # start the OSD
        systemctl.start_osd(osd_id)
    terminal.success("ceph-volume lvm activate successful for osd ID: %s" % osd_id)
Beispiel #8
0
 def test_path_does_not_exist(self):
     with pytest.raises(exceptions.ConfigurationError):
         conf = configuration.load('/path/does/not/exist/ceph.con')
         conf.is_valid()
Beispiel #9
0
 def test_load_from_path(self, tmpdir):
     conf_path = os.path.join(str(tmpdir), 'ceph.conf')
     with open(conf_path, 'w') as conf:
         conf.write(tabbed_conf)
     result = configuration.load(conf_path)
     assert result.get('global', 'default') == '0'
 def test_coment_as_a_value(self, tmpdir, commented):
     conf_path = os.path.join(str(tmpdir), 'ceph.conf')
     with open(conf_path, 'w') as conf:
         conf.write(tabbed_conf)
     result = configuration.load(conf_path)
     assert result.get('global', commented) == ''
Beispiel #11
0
 def apply(contents):
     conf_path = tmpfile(contents=contents)
     parser = configuration.load(conf_path)
     monkeypatch.setattr(conf, 'ceph', parser)
     return parser
Beispiel #12
0
def activate_bluestore(osd_lvs, no_systemd=False, no_tmpfs=False):
    for lv in osd_lvs:
        if lv.tags.get('ceph.type') == 'block':
            osd_block_lv = lv
            break
    else:
        raise RuntimeError('could not find a bluestore OSD to activate')

    is_encrypted = osd_block_lv.tags.get('ceph.encrypted', '0') == '1'
    dmcrypt_secret = None
    osd_id = osd_block_lv.tags['ceph.osd_id']
    conf.cluster = osd_block_lv.tags['ceph.cluster_name']
    osd_fsid = osd_block_lv.tags['ceph.osd_fsid']
    configuration.load_ceph_conf_path(osd_block_lv.tags['ceph.cluster_name'])
    configuration.load()

    # mount on tmpfs the osd directory
    osd_path = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)
    if not system.path_is_mounted(osd_path):
        # mkdir -p and mount as tmpfs
        prepare_utils.create_osd_path(osd_id, tmpfs=not no_tmpfs)
    # XXX This needs to be removed once ceph-bluestore-tool can deal with
    # symlinks that exist in the osd dir
    for link_name in ['block', 'block.db', 'block.wal']:
        link_path = os.path.join(osd_path, link_name)
        if os.path.exists(link_path):
            os.unlink(os.path.join(osd_path, link_name))
    # encryption is handled here, before priming the OSD dir
    if is_encrypted:
        osd_lv_path = '/dev/mapper/%s' % osd_block_lv.lv_uuid
        lockbox_secret = osd_block_lv.tags['ceph.cephx_lockbox_secret']
        encryption_utils.write_lockbox_keyring(osd_id, osd_fsid,
                                               lockbox_secret)
        dmcrypt_secret = encryption_utils.get_dmcrypt_key(osd_id, osd_fsid)
        encryption_utils.luks_open(dmcrypt_secret, osd_block_lv.lv_path,
                                   osd_block_lv.lv_uuid)
    else:
        osd_lv_path = osd_block_lv.lv_path

    db_device_path = get_osd_device_path(osd_lvs,
                                         'db',
                                         dmcrypt_secret=dmcrypt_secret)
    wal_device_path = get_osd_device_path(osd_lvs,
                                          'wal',
                                          dmcrypt_secret=dmcrypt_secret)

    # Once symlinks are removed, the osd dir can be 'primed again. chown first,
    # regardless of what currently exists so that ``prime-osd-dir`` can succeed
    # even if permissions are somehow messed up
    system.chown(osd_path)
    prime_command = [
        'ceph-bluestore-tool',
        '--cluster=%s' % conf.cluster, 'prime-osd-dir', '--dev', osd_lv_path,
        '--path', osd_path, '--no-mon-config'
    ]

    process.run(prime_command)
    # always re-do the symlink regardless if it exists, so that the block,
    # block.wal, and block.db devices that may have changed can be mapped
    # correctly every time
    process.run(['ln', '-snf', osd_lv_path, os.path.join(osd_path, 'block')])
    system.chown(os.path.join(osd_path, 'block'))
    system.chown(osd_path)
    if db_device_path:
        destination = os.path.join(osd_path, 'block.db')
        process.run(['ln', '-snf', db_device_path, destination])
        system.chown(db_device_path)
        system.chown(destination)
    if wal_device_path:
        destination = os.path.join(osd_path, 'block.wal')
        process.run(['ln', '-snf', wal_device_path, destination])
        system.chown(wal_device_path)
        system.chown(destination)

    if no_systemd is False:
        # enable the ceph-volume unit for this OSD
        systemctl.enable_volume(osd_id, osd_fsid, 'lvm')

        # enable the OSD
        systemctl.enable_osd(osd_id)

        # start the OSD
        systemctl.start_osd(osd_id)
    terminal.success("ceph-volume lvm activate successful for osd ID: %s" %
                     osd_id)
 def test_path_does_not_exist(self):
     with pytest.raises(exceptions.ConfigurationError):
         conf = configuration.load('/path/does/not/exist/ceph.con')
         conf.is_valid()
 def test_load_with_hash_comments(self, tmpdir):
     conf_path = os.path.join(str(tmpdir), 'ceph.conf')
     with open(conf_path, 'w') as conf:
         conf.write(tabbed_conf)
     result = configuration.load(conf_path)
     assert result.get('global', 'other_h') == '1'
 def test_load_from_path(self, tmpdir):
     conf_path = os.path.join(str(tmpdir), 'ceph.conf')
     with open(conf_path, 'w') as conf:
         conf.write(tabbed_conf)
     result = configuration.load(conf_path)
     assert result.get('global', 'default') == '0'
Beispiel #16
0
 def stat_ceph_conf(self):
     try:
         configuration.load(conf.path)
         return terminal.green(conf.path)
     except exceptions.ConfigurationError as error:
         return terminal.red(error)
Beispiel #17
0
 def apply(contents):
     conf_path = tmpfile(contents=contents)
     parser = configuration.load(conf_path)
     monkeypatch.setattr(conf, 'ceph', parser)
     return parser
def activate_filestore(lvs, no_systemd=False):
    # find the osd
    osd_lv = lvs.get(lv_tags={'ceph.type': 'data'})
    if not osd_lv:
        raise RuntimeError('Unable to find a data LV for filestore activation')
    is_encrypted = osd_lv.tags.get('ceph.encrypted', '0') == '1'
    is_vdo = osd_lv.tags.get('ceph.vdo', '0')

    osd_id = osd_lv.tags['ceph.osd_id']
    configuration.load_ceph_conf_path(osd_lv.tags['ceph.cluster_name'])
    configuration.load()
    # it may have a volume with a journal
    osd_journal_lv = lvs.get(lv_tags={'ceph.type': 'journal'})
    # TODO: add sensible error reporting if this is ever the case
    # blow up with a KeyError if this doesn't exist
    osd_fsid = osd_lv.tags['ceph.osd_fsid']
    if not osd_journal_lv:
        # must be a disk partition, by quering blkid by the uuid we are ensuring that the
        # device path is always correct
        journal_uuid = osd_lv.tags['ceph.journal_uuid']
        osd_journal = disk.get_device_from_partuuid(journal_uuid)
    else:
        journal_uuid = osd_journal_lv.lv_uuid
        osd_journal = osd_lv.tags['ceph.journal_device']

    if not osd_journal:
        raise RuntimeError('unable to detect an lv or device journal for OSD %s' % osd_id)

    # this is done here, so that previous checks that ensure path availability
    # and correctness can still be enforced, and report if any issues are found
    if is_encrypted:
        lockbox_secret = osd_lv.tags['ceph.cephx_lockbox_secret']
        # this keyring writing is idempotent
        encryption_utils.write_lockbox_keyring(osd_id, osd_fsid, lockbox_secret)
        dmcrypt_secret = encryption_utils.get_dmcrypt_key(osd_id, osd_fsid)
        encryption_utils.luks_open(dmcrypt_secret, osd_lv.lv_path, osd_lv.lv_uuid)
        encryption_utils.luks_open(dmcrypt_secret, osd_journal, journal_uuid)

        osd_journal = '/dev/mapper/%s' % journal_uuid
        source = '/dev/mapper/%s' % osd_lv.lv_uuid
    else:
        source = osd_lv.lv_path

    # mount the osd
    destination = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)
    if not system.device_is_mounted(source, destination=destination):
        prepare_utils.mount_osd(source, osd_id, is_vdo=is_vdo)

    # always re-do the symlink regardless if it exists, so that the journal
    # device path that may have changed can be mapped correctly every time
    destination = '/var/lib/ceph/osd/%s-%s/journal' % (conf.cluster, osd_id)
    process.run(['ln', '-snf', osd_journal, destination])

    # make sure that the journal has proper permissions
    system.chown(osd_journal)

    if no_systemd is False:
        # enable the ceph-volume unit for this OSD
        systemctl.enable_volume(osd_id, osd_fsid, 'lvm')

        # enable the OSD
        systemctl.enable_osd(osd_id)

        # start the OSD
        systemctl.start_osd(osd_id)
    terminal.success("ceph-volume lvm activate successful for osd ID: %s" % osd_id)
 def test_coment_as_a_value(self, tmpdir, commented):
     conf_path = os.path.join(str(tmpdir), 'ceph.conf')
     with open(conf_path, 'w') as conf:
         conf.write(tabbed_conf)
     result = configuration.load(conf_path)
     assert result.get('global', commented) == ''
Beispiel #20
0
 def stat_ceph_conf(self):
     try:
         configuration.load(conf.path)
         return terminal.green(conf.path)
     except exceptions.ConfigurationError as error:
         return terminal.red(error)
 def test_load_with_hash_comments(self, tmpdir):
     conf_path = os.path.join(str(tmpdir), 'ceph.conf')
     with open(conf_path, 'w') as conf:
         conf.write(tabbed_conf)
     result = configuration.load(conf_path)
     assert result.get('global', 'other_h') == '1'