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()
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
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)
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')
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 {}
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()
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