def seen(self, driver, host, **data): if 'sockets' in data: item = find(self._seen_items, lambda s: data['sockets'] == s.process.listen_sockets) elif 'port' in data: item = find(self._seen_items, lambda s: (host, data['port']) in s.process.listen_sockets) else: client = driver.client(host) host_id = client.get_host_id() item = find(self._seen_items, lambda s: host_id == s.host_id) return item is not None
def nova_authtoken_property_assertion(self, name, values): name = subst(name) values = subst(values) if not values: return for nova in [c for c in world.openstack.components if c.name.startswith('nova')]: (authtoken_section, _) = find( nova.paste_config.items(), lambda name_values: name_values[0].startswith('filter:') and name_values[1].get('paste.filter_factory') == AUTHTOKEN_FILTER_FACTORY ) if not authtoken_section: nova.report_issue( Issue(Issue.ERROR, 'Nova has keystone "auth" strategy ' 'configured, but doesnt have authtoken ' 'paste filter')) continue authtoken_settings = nova.paste_config.section(authtoken_section) param_value = (authtoken_settings[name] or nova.config['keystone_authtoken.%s' % name]) if not (param_value and param_value in values): nova.report_issue( Issue(Issue.ERROR, 'Nova should have "%s" in %s, ' 'actual value is "%s"' % ( name, values, param_value)))
def discover(self, driver, host, path=None, withBaseDirs=True, **data): client = driver.client(host) host_id = get_host_id(client) item = find(self.items, lambda f: f.path == path and f.host_id == host_id) if item: return item self.logger.debug('Discovering directory %s' % path) if path == '/': return None item = collect_directory(driver, client, path) if not item: return None self.items.append(item) if withBaseDirs: path = os.path.dirname(path) while path != '/': self.discover(driver, host, path, withBaseDirs=False) path = os.path.dirname(path) return item
def get_parameter(self, name, section=None): # TODO: optimize this return ( find( self.parameters, lambda p: p.name == name and p.section == section) )
def inspect(self, openstack): keystone = find(openstack.components, lambda c: c.name == 'keystone') if not keystone: return for service in keystone.db['services']: if service['type'] == 'compute': endpoint = find( keystone.db['endpoints'], lambda e: e['service_id'] == service['id']) if not endpoint: keystone.report_issue( Issue( Issue.WARNING, SERVICE_WITH_NO_ENDPOINT_MSG % service['name'])) continue for url_attr in ['adminurl', 'publicurl', 'internalurl']: url = urlparse(endpoint[url_attr]) # TODO(someone): resolve endpoint url host address host = find( openstack.hosts, lambda h: url.hostname in h.network_addresses) if not host: keystone.report_issue( Issue(Issue.ERROR, UNKNOWN_HOST_ENDPOINT_MSG % (service['name'], service['id'], url_attr))) continue nova_api = None for c in host.components: if c.name != 'nova-api': continue listen_address = c.config['osapi_compute_listen'] listen_port = c.config['osapi_compute_listen_port'] if (listen_address in ['0.0.0.0', url.hostname] and listen_port == url.port): nova_api = c break if not nova_api: keystone.report_issue( Issue(Issue.ERROR, UNKNOWN_SERVICE_ENDPOINT_MSG % (service['name'], service['id'], url_attr)))
def discover(self, initial_nodes, private_key): "Takes a list of node addresses " "and returns discovered openstack installation info" driver = DiscoveryDriver(private_key) # Set connection info and queue initial nodes for info in parse_nodes_info(initial_nodes, private_key): driver.setHostConnectionInfo( host=info['host'], port=info['port'], username=info['username'], password=info['password'], privateKey=info['private_key']) driver.enqueue('host', info['host']) while len(driver.queue) > 0: task = driver.queue.popleft() driver.discover(task.type, task.host, **task.data) items = sum([agent.items for agent in driver.agents.values()], []) # Rebuild model tree openstack = model.Openstack() for host in filter(lambda i: isinstance(i, model.HostResource), items): openstack.add_host(host) for service in filter(lambda i: isinstance(i, model.Service), items): host = find(openstack.hosts, lambda h: h.id == service.host_id) if not host: self.logger.error('Got resource "%s" ' 'that belong to non-existing host' % service) continue host.add_component(service) for fs_resource in filter(lambda f: isinstance(f, model.FileSystemResource), items): host = find(openstack.hosts, lambda h: h.id == fs_resource.host_id) if not host: self.logger.error('Got resource "%s" ' 'that belong to non-existing host' % fs_resource) continue host.add_fs_resource(fs_resource) return openstack
def inspect(self, openstack): keystone = find(openstack.components, lambda c: c.name == 'keystone') if not keystone: return for service in keystone.db['services']: if service['type'] == 'compute': endpoint = find(keystone.db['endpoints'], lambda e: e['service_id'] == service['id']) if not endpoint: keystone.report_issue( Issue(Issue.WARNING, SERVICE_WITH_NO_ENDPOINT_MSG % service['name'])) continue for url_attr in ['adminurl', 'publicurl', 'internalurl']: url = urlparse(endpoint[url_attr]) # TODO: resolve endpoint url host address host = find(openstack.hosts, lambda h: url.hostname in h.network_addresses) if not host: keystone.report_issue( Issue( Issue.ERROR, UNKNOWN_HOST_ENDPOINT_MSG % (service['name'], service['id'], url_attr))) continue nova_compute = None for c in host.components: if c.name != 'nova-compute': continue listen_address = c.config['osapi_compute_listen'] listen_port = c.config['osapi_compute_listen_port'] if (listen_address in ['0.0.0.0', url.hostname] and listen_port == url.port): nova_compute = c break if not nova_compute: keystone.report_issue( Issue( Issue.ERROR, UNKNOWN_SERVICE_ENDPOINT_MSG % (service['name'], service['id'], url_attr)))
def find_process(client, pid=None, name=None, sockets=None): if pid: return find(get_processes(client), lambda p: p.pid == pid) elif sockets: current_sockets = get_listen_sockets(client) x = find(current_sockets.items(), lambda x: sockets[0] in x[1]) if not x: return None return get_process_by_pid(x[0]) elif name: processes = get_processes(client) for process in processes: args = shlex.split(process.command) if os.path.basename(args[0]) == name: return process return None
def seen(self, driver, host, path=None, **data): if not path: return True client = driver.client(host) host_id = get_host_id(client) item = find(self._seen_items, lambda f: f.path == path and f.host_id == host_id) return item is not None
def keystone_addresses(self, variable): keystone = find(world.openstack.components, lambda c: c.name == 'keystone') if keystone.config['bind_host'] == '0.0.0.0': addresses = filter( lambda ip: not ip.startswith('127.'), keystone.host.network_addresses) else: addresses = [keystone.config['bind_host']] set_variable(variable, addresses)
def controller_addresses(self, variable): controller = find(world.openstack.components, lambda c: c.name == 'nova') if controller.config['s3_host'] == '0.0.0.0': addresses = filter( lambda ip: not ip.startswith('127.'), controller.host.network_addresses) else: addresses = [controller.config['s3_host']] set_variable(variable, addresses)
def discover(self, driver, host, **data): item = find(self.items, lambda h: host in h.network_addresses) if item: return item client = driver.client(host) hostname = client.run(['hostname']).output.strip() item = model.HostResource(name=hostname) item.id = get_host_id(client) item.network_addresses = get_host_network_addresses(client) process_sockets = get_listen_sockets(client) # Service detection part process = find_python_process(client, 'keystone-all') if process: driver.enqueue( 'keystone', host=host, pid=process.pid, sockets=process_sockets.get(process.pid, [])) for service in [ 'nova-api', 'nova-volume', 'nova-scheduler', 'glance-api', 'glance-registry', 'cinder-api', 'cinder-volume', 'cinder-scheduler', 'neutron-server', 'neutron-dhcp-agent', 'neutron-l3-agent', 'neutron-metadata-agent', 'neutron-openvswitch-agent', 'swift-proxy-server', 'swift-container-server', 'swift-account-server', 'swift-object-server' ]: process = find_python_process(client, service) if not process: continue driver.enqueue( service, host=host, pid=process.pid, sockets=process_sockets.get(process.pid, [])) for service in ['mysql', 'rabbitmq']: process = find_process(client, name=service) if not process: continue driver.enqueue( service, host=host, pid=process.pid, sockets=process_sockets.get(process.pid, [])) self.items.append(item) return item
def discover(self, initial_nodes, private_key): "Takes a list of node addresses " "and returns discovered openstack installation info" agents = dict([(c.item_type, c()) for c in all_subclasses(BaseDiscovery) if hasattr(c, 'item_type')]) driver = DiscoveryDriver(private_key) # Set connection info and queue initial nodes for info in parse_nodes_info(initial_nodes, private_key): driver.setHostConnectionInfo( host=info['host'], port=info['port'], username=info['username'], password=info['password'], privateKey=info['private_key']) driver.enqueue('host', info['host']) items = [] while len(driver.queue) > 0: task = driver.queue.popleft() self.logger.info('Processing item of type %s, host = %s' % (task.type, task.host)) if task.type in agents.keys(): agent = agents[task.type] if agent.seen(driver, task.host, **task.data): continue item = agent.discover(driver, task.host, **task.data) if item: items.append(item) else: self.logger.error('Unknown item type: %s' % task.type) # Rebuild model tree openstack = Openstack() for host in filter(lambda i: isinstance(i, Host), items): openstack.add_host(host) for service in filter(lambda i: isinstance(i, Service), items): host = find(openstack.hosts, lambda h: h.id == service.host_id) if not host: continue host.add_component(service) return openstack
def discover(self, driver, host, path=None, **data): client = driver.client(host) host_id = get_host_id(client) item = find(self.items, lambda f: f.path == path and f.host_id == host_id) if item: return item item = collect_file(driver, client, path) if not item: return None self.items.append(item) driver.discover('directory', host, path=os.path.dirname(item.path)) return item
def has_section(self, section): return find(self.parameters, lambda p: p.section == section) is not None
def inspect(self, openstack): components = [] for host in openstack.hosts: components.extend(host.components) keystones = [c for c in components if c.name == 'keystone'] if len(keystones) == 0: openstack.report_issue( Issue(Issue.FATAL, 'No keystone service found')) return keystone = keystones[0] keystone_addresses = [keystone.config['bind_host']] if keystone_addresses == ['0.0.0.0']: keystone_addresses = keystone.host.network_addresses for nova in [c for c in components if c.name == 'nova-api']: if nova.config['auth_strategy'] != 'keystone': continue authtoken_section = find( nova.paste_config.items(), lambda name_values: name_values[0]. startswith('filter:') and name_values[1].get( 'paste.filter_factory') == AUTHTOKEN_FILTER_FACTORY) if not authtoken_section: continue authtoken_settings = authtoken_section[1] def get_value(name): return (authtoken_settings[name] or nova.config['keystone_authtoken.%s' % name]) auth_host = get_value('auth_host') auth_port = get_value('auth_port') auth_protocol = get_value('auth_protocol') admin_user = get_value('admin_user') # admin_password = get_value('admin_password') admin_tenant_name = get_value('admin_tenant_name') admin_token = get_value('admin_token') msg = 'Keystone authtoken config %s' def missing_param_issue(param): return Issue(Issue.ERROR, msg % (' miss "%s" setting' % param)) def incorrect_param_issue(param): return Issue(Issue.ERROR, msg % (' has incorrect "%s" setting' % param)) if not auth_host: nova.report_issue(missing_param_issue('auth_host')) elif not auth_host in keystone_addresses: nova.report_issue(incorrect_param_issue('auth_host')) if not auth_port: nova.report_issue(missing_param_issue('auth_port')) elif auth_port != keystone.config['admin_port']: nova.report_issue(incorrect_param_issue('auth_port')) if not auth_protocol: nova.report_issue(missing_param_issue('auth_protocol')) elif not auth_protocol in ['http', 'https']: nova.report_issue(incorrect_param_issue('auth_protocol')) if not admin_user: nova.report_issue(missing_param_issue('admin_user')) else: user = find(keystone.db['users'], lambda u: u['name'] == admin_user) if not user: nova.report_issue( Issue(Issue.ERROR, msg % ' has "admin_user" that is missing')) if not admin_tenant_name: nova.report_issue(missing_param_issue('admin_tenant_name')) else: tenant = find(keystone.db['tenants'], lambda t: t['name'] == admin_tenant_name) if not tenant: nova.report_issue( Issue(Issue.ERROR, msg % ' has "admin_tenant_name" that is missing')) if admin_token: nova.report_issue( Issue( Issue.WARNING, msg % ' uses insecure admin_token method' 'for authentication'))
def get_parameter(self, name, section=None): # TODO: optimize this return (find(self.parameters, lambda p: p.name == name and p.section == section))
def has_section(self, section): return (find(self.parameters, lambda p: p.section == section) is not None)
def inspect(self, openstack): components = [] for host in openstack.hosts: components.extend(host.components) keystones = [c for c in components if c.name == 'keystone'] if len(keystones) == 0: openstack.report_issue( Issue(Issue.FATAL, 'No keystone service found')) return keystone = keystones[0] keystone_addresses = [keystone.config['bind_host']] if keystone_addresses == ['0.0.0.0']: keystone_addresses = keystone.host.network_addresses for nova in [c for c in components if c.name == 'nova-api']: if nova.config['auth_strategy'] != 'keystone': continue authtoken_section = find( nova.paste_config.items(), lambda name_values: name_values[0].startswith('filter:') and name_values[1].get( 'paste.filter_factory') == AUTHTOKEN_FILTER_FACTORY) if not authtoken_section: continue authtoken_settings = authtoken_section[1] def get_value(name): return ( authtoken_settings[name] or nova.config['keystone_authtoken.%s' % name] ) auth_host = get_value('auth_host') auth_port = int(get_value('auth_port')) auth_protocol = get_value('auth_protocol') admin_user = get_value('admin_user') # admin_password = get_value('admin_password') admin_tenant_name = get_value('admin_tenant_name') admin_token = get_value('admin_token') msg = 'Keystone authtoken config %s' def missing_param_issue(param): return Issue(Issue.ERROR, msg % (' miss "%s" setting' % param)) def incorrect_param_issue(param): return Issue(Issue.ERROR, msg % (' has incorrect "%s" setting' % param)) if not auth_host: nova.report_issue(missing_param_issue('auth_host')) elif not auth_host in keystone_addresses: nova.report_issue(incorrect_param_issue('auth_host')) if not auth_port: nova.report_issue(missing_param_issue('auth_port')) elif auth_port != keystone.config['admin_port']: nova.report_issue(incorrect_param_issue('auth_port')) if not auth_protocol: nova.report_issue(missing_param_issue('auth_protocol')) elif not auth_protocol in ['http', 'https']: nova.report_issue(incorrect_param_issue('auth_protocol')) if not admin_user: nova.report_issue(missing_param_issue('admin_user')) else: user = find( keystone.db['users'], lambda u: u['name'] == admin_user) if not user: nova.report_issue( Issue(Issue.ERROR, msg % ' has "admin_user" that is missing')) if not admin_tenant_name: nova.report_issue(missing_param_issue('admin_tenant_name')) else: tenant = find(keystone.db['tenants'], lambda t: t['name'] == admin_tenant_name) if not tenant: nova.report_issue( Issue(Issue.ERROR, msg % ' has "admin_tenant_name" that is missing')) if admin_token: nova.report_issue( Issue( Issue.WARNING, msg % ' uses insecure admin_token method' 'for authentication'))
def find_param(params, name): return find(params, lambda p: p.name == name)
def seen(self, driver, host, **data): item = find(self._seen_items, lambda h: host in h.network_addresses) return item is not None
def get_process_by_pid(client, pid): return find(get_processes(client), lambda p: p.pid == pid)