Exemple #1
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
Exemple #2
0
        def wrapper(*args):
            if docstring:
                self.logger.debug(docstring)
            if len(args):
                source = self._module_source + dump_template % (name,
                                                                repr(args))
            else:
                source = self._module_source + dump_template % (name, '()')

            # check python interpreter
            if self.python_executable is None:
                self.python_executable = get_python_executable(self.conn)

            out, err, code = check(self.conn, [self.python_executable],
                                   stdin=source.encode('utf-8'))
            if not out:
                if not err:
                    err = [
                        'Traceback (most recent call last):',
                        '    File "<stdin>", in <module>',
                        'Exception: error calling "%s"' % name
                    ]
                if code:
                    raise Exception('Unexpected remote exception: \n%s\n%s' %
                                    ('\n'.join(out), '\n'.join(err)))
                # at this point, there was no stdout, and the exit code was 0,
                # we must return so that we don't fail trying to serialize back
                # the JSON
                return
            response = json.loads(out[0])
            if response['exception']:
                raise Exception(response['exception'])
            return response['return']
Exemple #3
0
        def wrapper(*args):
            if docstring:
                self.logger.debug(docstring)
            if len(args):
                source = self._module_source + dump_template % (name, repr(args))
            else:
                source = self._module_source + dump_template % (name, '()')

            # check python interpreter
            if self.python_executable is None:
                self.python_executable = get_python_executable(self.conn)

            out, err, code = check(self.conn, [self.python_executable], stdin=source.encode('utf-8'))
            if not out:
                if not err:
                    err = [
                        'Traceback (most recent call last):',
                        '    File "<stdin>", in <module>',
                        'Exception: error calling "%s"' % name
                    ]
                if code:
                    raise Exception('Unexpected remote exception: \n%s\n%s' % ('\n'.join(out), '\n'.join(err)))
                # at this point, there was no stdout, and the exit code was 0,
                # we must return so that we don't fail trying to serialize back
                # the JSON
                return
            response = json.loads(out[0])
            if response['exception']:
                raise Exception(response['exception'])
            return response['return']
Exemple #4
0
def get_python_executable(conn):
    """
    Try to determine the remote Python version so that it can be used
    when executing. Avoids the problem of different Python versions, or distros
    that do not use ``python`` but do ``python3``
    """
    # executables in order of preference:
    executables = ['python3', 'python', 'python2.7']
    for executable in executables:
        conn.logger.debug(
            'trying to determine remote python executable with %s' %
            executable)
        out, err, code = check(conn, ['which', executable])
        if code:
            conn.logger.warning('skipping %s, was not found in path' %
                                executable)
        else:
            try:
                return out[0].strip()
            except IndexError:
                conn.logger.warning('could not parse stdout: %s' % out)

    # if all fails, we just return whatever the main connection had
    conn.logger.info('Falling back to using interpreter: %s' %
                     conn.interpreter)
    return conn.interpreter
Exemple #5
0
def ceph_is_installed(conn):
    try:
        stdout, stderr, exit_code = check(conn, ['which', 'ceph'])
    except RuntimeError:
        conn.logger.exception('failed to check if ceph is available in the path')
        # XXX this might be incorrect
        return False
    if exit_code != 0:
        return False
    return True
def ceph_version(conn):
    try:
        output, _, exit_code = check(conn, ['ceph', '--version'])
        if exit_code != 0:
            conn.logger.error(
                'Non zero exit status received, unable to retrieve information'
            )
            return
        return output[0]
    except RuntimeError:
        conn.logger.exception('failed to fetch ceph version')
Exemple #7
0
def ceph_socket_version(conn, socket):
    try:
        output, _, _ = check(conn,
                             ['ceph', '--admin-daemon', socket, 'version'])
        result = dict()
        try:
            result = json.loads(output[0])
        except ValueError:
            conn.logger.exception(
                "failed to fetch ceph socket version, invalid json: %s" %
                output[0])
        return result
    except RuntimeError:
        conn.logger.exception('failed to fetch ceph socket version')
def ceph_status(conn):
    try:  # collects information using ceph -s
        stdout, stderr, exit_code = check(
            conn, ['sudo', 'ceph', '-s', '--format', 'json'])
        result = dict()
        try:
            result = json.loads(''.join(stdout))
        except ValueError:
            conn.logger.exception(
                "failed to fetch ceph status, invalid json: %s" %
                ''.join(stdout))

        if exit_code == 0:
            return result
        else:
            return {}

    except RuntimeError:
        conn.logger.exception('failed to fetch ceph status')
def daemon_socket_config(conn, socket):
    """
    Capture daemon-based config from the socket
    """
    try:
        output, _, _ = check(conn, [
            'ceph', '--admin-daemon', socket, 'config', 'show', '--format',
            'json'
        ])
        result = dict()
        try:
            result = json.loads(output[0])
        except ValueError:
            conn.logger.exception(
                "failed to fetch ceph configuration via socket, invalid json: %s"
                % output[0])
        return result
    except RuntimeError:
        conn.logger.exception('failed to fetch ceph configuration via socket')
def ceph_socket_version(conn, socket):
    try:
        result = dict()
        output, _, exit_code = check(
            conn, ['ceph', '--admin-daemon', socket, 'version'])
        if exit_code != 0:
            conn.logger.error(
                'Non zero exit status received, unable to retrieve information'
            )
            return result
        try:
            result = json.loads(output[0])
        except ValueError:
            conn.logger.exception(
                "failed to fetch ceph socket version, invalid json: %s" %
                output[0])
        return result
    except RuntimeError:
        conn.logger.exception('failed to fetch ceph socket version')
def ceph_osd_dump(conn):
    try:
        stdout, stderr, exit_code = check(
            conn, ['sudo', 'ceph', 'osd', 'dump', '--format', 'json'])
        result = dict()
        if exit_code != 0:
            conn.logger.error('could not get osd dump from ceph')
            if stderr:
                for line in stderr:
                    conn.logger.error(line)
            return result
        try:
            result = json.loads(''.join(stdout))
        except ValueError:
            conn.logger.exception(
                "failed to fetch osd dump, invalid json: %s" % ''.join(stdout))

        return result

    except RuntimeError:
        conn.logger.exception('failed to fetch ceph osd dump')
Exemple #12
0
def get_python_executable(conn):
    """
    Try to determine the remote Python version so that it can be used
    when executing. Avoids the problem of different Python versions, or distros
    that do not use ``python`` but do ``python3``
    """
    # executables in order of preference:
    executables = ['python3', 'python', 'python2.7']
    for executable in executables:
        conn.logger.debug('trying to determine remote python executable with %s' % executable)
        out, err, code = check(conn, ['which', executable])
        if code:
            conn.logger.warning('skipping %s, was not found in path' % executable)
        else:
            try:
                return out[0].strip()
            except IndexError:
                conn.logger.warning('could not parse stdout: %s' % out)

    # if all fails, we just return whatever the main connection had
    conn.logger.info('Falling back to using interpreter: %s' % conn.interpreter)
    return conn.interpreter
def daemon_socket_config(conn, socket):
    """
    Capture daemon-based config from the socket
    """
    try:
        output, _, exit_code = check(conn, [
            'ceph', '--admin-daemon', socket, 'config', 'show', '--format',
            'json'
        ])
        if exit_code != 0:
            conn.logger.error(
                'Non zero exit status received, unable to retrieve information'
            )
            return
        result = dict()
        try:
            result = json.loads(output[0])
        except ValueError:
            conn.logger.exception(
                "failed to fetch ceph configuration via socket, invalid json: %s"
                % output[0])
        return result
    except RuntimeError:
        conn.logger.exception('failed to fetch ceph configuration via socket')
Exemple #14
0
def remote_cmd_list(conn, cmd_str):
    stdout, stderr, status = check(conn, cmd_str, shell=True)
    if status != 0:
        raise FailedExecError(cmd_str, 'exit code: %d, error msg: %s' % (status, '\n'.join(stderr)))
    return stdout
Exemple #15
0
def ceph_version(conn):
    try:
        output, _, _ = check(conn, ['ceph', '--version'])
        return output[0]
    except RuntimeError:
        conn.logger.exception('failed to fetch ceph version')
Exemple #16
0
# https://pypi.org/project/remoto/

import remoto
from remoto.process import check, run

conn = remoto.Connection('localhost')

print(check(conn, ['ls', '/nonexistent/path']))

conn = remoto.connection.get('ssh')('localhost')
print(check(conn, ['sh', '-c', 'source ~/.bashrc']))
run(conn, ['whoami'])
Exemple #17
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