+ def _filter_based_on_attributes(self):
+ """
+ Retrive the list of nodes ids that match user's constraints
+ """
+ # Map user's defined attributes with tagnames of PlanetLab
+ timeframe = self.get("timeframe")[0]
+ attr_to_tags = {
+ 'city' : 'city',
+ 'country' : 'country',
+ 'region' : 'region',
+ 'architecture' : 'arch',
+ 'operatingSystem' : 'fcdistro',
+ #'site' : 'pldistro',
+ 'minReliability' : 'reliability%s' % timeframe,
+ 'maxReliability' : 'reliability%s' % timeframe,
+ 'minBandwidth' : 'bw%s' % timeframe,
+ 'maxBandwidth' : 'bw%s' % timeframe,
+ 'minLoad' : 'load%s' % timeframe,
+ 'maxLoad' : 'load%s' % timeframe,
+ 'minCpu' : 'cpu%s' % timeframe,
+ 'maxCpu' : 'cpu%s' % timeframe,
+ }
+
+ nodes_id = []
+ filters = {}
+
+ for attr_name, attr_obj in self._attrs.iteritems():
+ attr_value = self.get(attr_name)
+
+ if attr_value is not None and attr_obj.flags == 8 and \
+ attr_name != 'timeframe':
+
+ attr_tag = attr_to_tags[attr_name]
+ filters['tagname'] = attr_tag
+
+ # filter nodes by fixed constraints e.g. operating system
+ if not 'min' in attr_name and not 'max' in attr_name:
+ filters['value'] = attr_value
+ nodes_id = self._filter_by_fixed_attr(filters, nodes_id)
+
+ # filter nodes by range constraints e.g. max bandwidth
+ elif ('min' or 'max') in attr_name:
+ nodes_id = self._filter_by_range_attr(attr_name, attr_value, filters, nodes_id)
+
+ return nodes_id
+
+
+ def _filter_by_fixed_attr(self, filters, nodes_id):
+ """
+ Query PLCAPI for nodes ids matching fixed attributes defined by the
+ user
+ """
+ node_tags = self.plapi.get_node_tags(filters)
+ if node_tags is not None:
+
+ if len(nodes_id) == 0:
+ # first attribute being matched
+ for node_tag in node_tags:
+ nodes_id.append(node_tag['node_id'])
+ else:
+ # remove the nodes ids that don't match the new attribute
+ # that is being match
+
+ nodes_id_tmp = []
+ for node_tag in node_tags:
+ if node_tag['node_id'] in nodes_id:
+ nodes_id_tmp.append(node_tag['node_id'])
+
+ if len(nodes_id_tmp):
+ nodes_id = set(nodes_id) & set(nodes_id_tmp)
+ else:
+ # no node from before match the new constraint
+ self.fail_discovery()
+ else:
+ # no nodes match the filter applied
+ self.fail_discovery()
+
+ return nodes_id
+
+ def _filter_by_range_attr(self, attr_name, attr_value, filters, nodes_id):
+ """
+ Query PLCAPI for nodes ids matching attributes defined in a certain
+ range, by the user
+ """
+ node_tags = self.plapi.get_node_tags(filters)
+ if node_tags is not None:
+
+ if len(nodes_id) == 0:
+ # first attribute being matched
+ for node_tag in node_tags:
+
+ # check that matches the min or max restriction
+ if 'min' in attr_name and node_tag['value'] != 'n/a' and \
+ float(node_tag['value']) > attr_value:
+ nodes_id.append(node_tag['node_id'])
+
+ elif 'max' in attr_name and node_tag['value'] != 'n/a' and \
+ float(node_tag['value']) < attr_value:
+ nodes_id.append(node_tag['node_id'])
+ else:
+
+ # remove the nodes ids that don't match the new attribute
+ # that is being match
+ nodes_id_tmp = []
+ for node_tag in node_tags:
+
+ # check that matches the min or max restriction and was a
+ # matching previous filters
+ if 'min' in attr_name and node_tag['value'] != 'n/a' and \
+ float(node_tag['value']) > attr_value and \
+ node_tag['node_id'] in nodes_id:
+ nodes_id_tmp.append(node_tag['node_id'])
+
+ elif 'max' in attr_name and node_tag['value'] != 'n/a' and \
+ float(node_tag['value']) < attr_value and \
+ node_tag['node_id'] in nodes_id:
+ nodes_id_tmp.append(node_tag['node_id'])
+
+ if len(nodes_id_tmp):
+ nodes_id = set(nodes_id) & set(nodes_id_tmp)
+ else:
+ # no node from before match the new constraint
+ self.fail_discovery()
+
+ else: #TODO CHECK
+ # no nodes match the filter applied
+ self.fail_discovery()
+
+ return nodes_id
+
+ def _query_if_alive(self, nodes_id=None, hostname=None):
+ """
+ Query PLCAPI for nodes that register activity recently, using filters
+ related to the state of the node, e.g. last time it was contacted
+ """
+ if nodes_id is None and hostname is None:
+ msg = "Specify nodes_id or hostname"