示例#1
0
    def main(self, argv):
        options = [
            '--cluster',
            '--ssh-config',
            '--inventory',
            '--config',
        ]
        parser = Transport(argv,
                           options=options,
                           check_help=False,
                           check_version=False)
        parser.parse_args()

        self.config_path = parser.get('--config', configuration.location())

        # load medic configuration
        loaded_config = configuration.load(
            path=parser.get('--config', self.config_path))

        # this is the earliest we can have enough config to setup logging
        log.setup(loaded_config)
        # update the module-wide configuration object
        ceph_medic.config.update(configuration.get_overrides(loaded_config))

        # SSH config
        ceph_medic.config['ssh_config'] = parser.get('--ssh-config')
        if ceph_medic.config['ssh_config']:
            ssh_config_path = ceph_medic.config['ssh_config']
            if not os.path.exists(ssh_config_path):
                terminal.error("the given ssh config path does not exist: %s" %
                               ssh_config_path)
                sys.exit()

        ceph_medic.config['cluster_name'] = parser.get('--cluster')
        ceph_medic.metadata['cluster_name'] = 'ceph'

        # Hosts file
        self.hosts_file = parser.get('--inventory',
                                     configuration.get_host_file())

        # find the hosts files, by the CLI first, fallback to the configuration
        # file, and lastly if none of those are found or defined, try to load
        # from well known locations (cwd, and /etc/ansible/)
        loaded_hosts = configuration.load_hosts(
            parser.get('--inventory',
                       ceph_medic.config.get('--inventory', self.hosts_file)))
        ceph_medic.config['nodes'] = loaded_hosts.nodes
        ceph_medic.config['hosts_file'] = loaded_hosts.filename
        self.hosts_file = loaded_hosts.filename

        parser.catch_version = ceph_medic.__version__
        parser.mapper = self.mapper
        parser.catch_help = self.help(parser.subhelp())
        if len(argv) <= 1:
            return parser.print_help()
        ceph_medic.config['config_path'] = self.config_path
        parser.dispatch()
        parser.catches_help()
        parser.catches_version()
示例#2
0
def basic_containers(deployment_type):
    base_inventory = {
        'rgws': [],
        'mgrs': [],
        'mdss': [],
        'clients': [],
        'osds': [],
        'mons': []
    }
    label_map = {
        'OSD': 'osds',
        'OSD_CEPH_VOLUME_ACTIVATE': 'osds',
        'MON': 'mons',
        'MGR': 'mgrs',
        'MDS': 'mdss',
        'RGW': 'rgws',
    }
    metal_hosts = set()
    for nodes in config.nodes.values():
        for node in nodes:
            metal_hosts.add(node['host'])
    for host in metal_hosts:
        logger.debug("listing containers for host %s", host)
        cmd = [
            deployment_type, 'container', 'ls', '--format', 'json',
            '--no-trunc'
        ]
        conn = ceph_medic.connection.get_connection(host,
                                                    deployment_type='ssh')
        out, err, code = process.check(conn, cmd)
        if code:
            terminal.error("Unable to list containers on host %s" % host)
            continue
        container_list = json.loads(''.join(out))
        if not container_list:
            terminal.warning("Host %s had no containers" % host)
            continue
        for container in container_list:
            cmd = [deployment_type, 'container', 'inspect', container['Names']]
            out, err, code = process.check(conn, cmd)
            if code:
                terminal.error("Unable to inspect container %s on host %s" %
                               (container['Names'], host))
                continue
            detail = json.loads(''.join(out))[0]
            env = dict([s.split('=', 1) for s in detail['Config']['Env']])
            if 'CEPH_DAEMON' not in env:
                continue
            if env.get('CLUSTER') != config.cluster_name:
                continue
            role = env['CEPH_DAEMON']
            if role not in label_map:
                continue
            base_inventory[label_map[role]].append({
                'host': host,
                'container': detail['Name'],
                'group': None
            })
    return base_inventory
示例#3
0
def load_hosts(_path=None):
    """
    Very similar to a plain configuration load, but do not fail if a hosts file
    is not loaded. Try the hardest to load one, and return an empty dictionary
    if nothing is found.
    """
    if _path and not os.path.exists(_path):
        terminal.error("the given inventory path does not exist: %s" % _path)
        sys.exit()
    _path = _path or get_host_file()
    return AnsibleInventoryParser(_path)
示例#4
0
def load(path=None, file=None):
    parser = Conf()
    try:
        if file:
            parser._read_file(file)
        elif path and os.path.exists(path):
            parser.read(path)
        else:
            parser.read(location())
        return parser
    except configparser.ParsingError as error:
        terminal.error('Unable to read configuration file')
        terminal.error(str(error))
        logger.exception('Unable to parse INI-style file')
示例#5
0
def get_mon_report(conn):
    command = [
        'ceph',
        '--cluster=%s' % ceph_medic.metadata['cluster_name'], 'report'
    ]
    out, err, code = remoto.process.check(conn, command)

    if code > 0:
        terminal.error(
            'failed to connect to the cluster to fetch a report from the monitor'
        )
        terminal.error('command: %s' % ' '.join(command))
        for line in err:
            terminal.error(line)
        raise RuntimeError()

    try:
        return json.loads(b''.join(out).decode('utf-8'))
    except ValueError:
        return {}
示例#6
0
    def main(self, argv):
        options = [
            '--cluster',
            '--ssh-config',
            '--inventory',
            '--config',
            '--verbosity',
        ]
        parser = Transport(argv,
                           options=options,
                           check_help=False,
                           check_version=False)
        parser.parse_args()

        self.config_path = parser.get('--config', configuration.location())

        # load medic configuration
        loaded_config = configuration.load(
            path=parser.get('--config', self.config_path))

        # this is the earliest we can have enough config to setup logging
        log.setup(loaded_config)
        ceph_medic.config.file = loaded_config
        global_options = dict(ceph_medic.config.file._sections['global'])

        # SSH config
        ceph_medic.config.ssh_config = parser.get(
            '--ssh-config', global_options.get('--ssh-config'))
        if ceph_medic.config.ssh_config:
            ssh_config_path = ceph_medic.config.ssh_config
            if not os.path.exists(ssh_config_path):
                terminal.error("the given ssh config path does not exist: %s" %
                               ssh_config_path)
                sys.exit()

        ceph_medic.config.cluster_name = parser.get('--cluster', 'ceph')
        ceph_medic.metadata['cluster_name'] = 'ceph'

        # Deployment Type
        deployment_type = ceph_medic.config.file.get_safe(
            'global', 'deployment_type', 'baremetal')
        if deployment_type in ['kubernetes', 'openshift', 'k8s', 'oc']:
            pod_hosts = hosts.container_platform(deployment_type)
            ceph_medic.config.nodes = pod_hosts
            ceph_medic.config.hosts_file = ':memory:'
            self.hosts_file = ':memory:'
        else:
            # Hosts file
            self.hosts_file = parser.get('--inventory',
                                         configuration.get_host_file())

            # find the hosts files, by the CLI first, fallback to the configuration
            # file, and lastly if none of those are found or defined, try to load
            # from well known locations (cwd, and /etc/ansible/)
            loaded_hosts = configuration.load_hosts(
                parser.get('--inventory',
                           global_options.get('--inventory', self.hosts_file)))
            ceph_medic.config.nodes = loaded_hosts.nodes
            ceph_medic.config.hosts_file = loaded_hosts.filename
            self.hosts_file = loaded_hosts.filename

        parser.catch_version = ceph_medic.__version__
        parser.mapper = self.mapper
        parser.catch_help = self.help(parser.subhelp())
        if len(argv) <= 1:
            return parser.print_help()
        ceph_medic.config.config_path = self.config_path
        parser.dispatch()
        parser.catches_help()
        parser.catches_version()

        # Verbosity
        verbosity = parser.get('--verbosity', 'debug')
        ceph_medic.config.verbosity = verbosity.lowercase()
示例#7
0
def container_platform(platform='openshift'):
    """
    Connect to a container platform (kubernetes or openshift), retrieve all the
    available pods that match the namespace (defaults to 'rook-ceph'), and
    return a dictionary including them, regardless of state.
    """
    local_conn = connection.get('local')()
    options = _platform_options(platform)
    context = options.get('context')
    namespace = options.get('namespace')
    executable = 'oc' if platform == 'openshift' else 'kubectl'

    if context:
        cmd = [executable, '--context', context]
    else:
        cmd = [executable]

    cmd.extend(['--request-timeout=5', 'get', '-n', namespace, 'pods', '-o', 'json'])

    try:
        out, err, code = process.check(local_conn, cmd)
    except RuntimeError:
        out = "{}"
        terminal.error('Unable to retrieve the pods using command: %s' % ' '.join(cmd))
    else:
        if code:
            output = out + err
            for line in output:
                terminal.error(line)

    try:
        pods = json.loads(''.join(out))
    except Exception:
        # Python3 has JSONDecodeError which doesn't exist in Python2
        # Python2 just raises ValueError
        stdout = ''.join(out)
        stderr = ''.join(err)
        logger.exception('Invalid JSON from stdout')
        terminal.error('Unable to load JSON from stdout')
        if stdout:
            logger.error('stdout: %s', stdout)
            terminal.error('stdout: %s' % stdout)
        if stderr:
            logger.error('stderr: %s', stderr)
            terminal.error('stderr: %s' % stderr)
        raise SystemExit(1)

    base_inventory = {
        'rgws': [], 'mgrs': [], 'mdss': [], 'clients': [], 'osds': [], 'mons': []
    }
    label_map = {
        'rook-ceph-mgr': 'mgrs',
        'rook-ceph-mon': 'mons',
        'rook-ceph-osd': 'osds',
        'rook-ceph-mds': 'mdss',
        'rook-ceph-rgw': 'rgws',
        'rook-ceph-client': 'clients',
    }

    for item in pods.get('items', {}):
        label_name = item['metadata'].get('labels', {}).get('app')
        if not label_name:
            continue
        if label_name in label_map:
            inventory_key = label_map[label_name]
            base_inventory[inventory_key].append(
                {'host': item['metadata']['name'], 'group': None}
            )
    for key, value in dict(base_inventory).items():
        if not value:
            base_inventory.pop(key)
    return base_inventory