def get_nodes(gs): """Gets the list of all nodes in the current cluster. Args: gs: global state. Returns: list of wrapped node objects. Each element in the list is the result of utilities.wrap_object(node, 'Node', ...) Raises: CollectorError: in case of failure to fetch data from Kubernetes. Other exceptions may be raised due to exectution errors. """ nodes, timestamp_secs = gs.get_nodes_cache().lookup('') if timestamp_secs is not None: gs.logger_info('get_nodes() cache hit returns %d nodes', len(nodes)) return nodes nodes = [] url = '{kubernetes}/nodes'.format(kubernetes=KUBERNETES_API) try: result = fetch_data(gs, url) except: msg = 'fetching %s failed with exception %s' % (url, sys.exc_info()[0]) gs.logger_exception(msg) raise collector_error.CollectorError(msg) now = time.time() if not (isinstance(result, types.DictType) and 'items' in result): msg = 'invalid result when fetching %s' % url gs.logger_exception(msg) raise collector_error.CollectorError(msg) for node in result['items']: name = utilities.get_attribute(node, ['metadata', 'name']) if not utilities.valid_string(name): # an invalid node without a valid node ID value. continue wrapped_node = utilities.wrap_object( node, 'Node', name, now, label=utilities.node_id_to_host_name(name)) nodes.append(wrapped_node) ret_value = gs.get_nodes_cache().update('', nodes, now) gs.logger_info('get_nodes() returns %d nodes', len(nodes)) return ret_value
def test_node_id_to_host_name(self): """Tests node_id_to_host_name().""" self.assertEqual( 'k8s-guestbook-node-1', utilities.node_id_to_host_name( 'k8s-guestbook-node-1.c.rising-apricot-840.internal')) self.assertEqual( 'k8s-guestbook-node-1', utilities.node_id_to_host_name('k8s-guestbook-node-1')) self.assertEqual( 'kubernetes-minion-dlc9', utilities.node_id_to_host_name( 'kubernetes-minion-dlc9.c.spartan-alcove-89517.google.com.' 'internal')) self.assertEqual( 'k8s-guestbook-node-1', utilities.node_id_to_host_name('Node:k8s-guestbook-node-1')) with self.assertRaises(ValueError): utilities.node_id_to_host_name('x.y.z.w') with self.assertRaises(ValueError): utilities.node_id_to_host_name('') with self.assertRaises(ValueError): utilities.node_id_to_host_name('Node:x.y.z.w') with self.assertRaises(ValueError): utilities.node_id_to_host_name('Node:')
def _do_compute_master_pods(gs, cluster_guid, nodes_list, oldest_timestamp, g): """Adds pods running on the master node to the graph. These pods do not have a valid parent node, because the nodes list does not include the master node. This routine adds a dummy master node, and then adds the pods running on the master node to the graph. It does not add information about containers, processes, or images of these nodes, because there is no minion collector running on the master node. Note that in some configurations (for example, GKE), there is no master node. Args: gs: the global state. cluster_guid: the cluster's ID. nodes_list: a list of wrapped Node objects. oldest_timestamp: the timestamp of the oldest Node object. g: the context graph under construction. """ assert isinstance(gs, global_state.GlobalState) assert utilities.valid_string(cluster_guid) assert isinstance(nodes_list, types.ListType) assert utilities.valid_string(oldest_timestamp) assert isinstance(g, ContextGraph) # Compute the set of known Node names. known_node_ids = set() project_id = '_unknown_' for node in nodes_list: assert utilities.is_wrapped_object(node, 'Node') known_node_ids.add(node['id']) project_id = utilities.node_id_to_project_id(node['id']) # Compute the set of Nodes referenced by pods but not in the known set. # The set of unknown node names may be empty. assert utilities.valid_string(project_id) missing_node_ids = set() for pod in kubernetes.get_pods(gs): assert utilities.is_wrapped_object(pod, 'Pod') # pod.properties.spec.nodeName may be missing if the pod is waiting. parent_node_id = utilities.get_attribute( pod, ['properties', 'spec', 'nodeName']) if not utilities.valid_string(parent_node_id): continue if parent_node_id in known_node_ids: continue # Found a pod that does not belong to any of the known nodes. missing_node_ids.add(parent_node_id) # Process the pods in each of the missing nodes. for node_id in missing_node_ids: # Create a dummy node object just as a placeholder for metric # annotations. node = utilities.wrap_object( {}, 'Node', node_id, time.time(), label=utilities.node_id_to_host_name(node_id)) # The project_id may be '_unknown_'. This is not a big # deal, since the aggregator knows the project ID. metrics.annotate_node(project_id, node) node_guid = 'Node:' + node_id g.add_resource(node_guid, node['annotations'], 'Node', oldest_timestamp, {}) g.add_relation(cluster_guid, node_guid, 'contains') # Cluster contains Node for pod in kubernetes.get_pods(gs, node_id): _do_compute_pod(gs, cluster_guid, node_guid, pod, g)