2 # NEPI, a framework to manage network experiments
3 # Copyright (C) 2013 INRIA
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
20 from nepi.execution.attribute import Attribute, Flags, Types
21 from nepi.execution.resource import ResourceManager, clsinit_copy, ResourceState, \
23 from nepi.resources.linux.node import LinuxNode
24 from nepi.resources.planetlab.plcapi import PLCAPIFactory
28 class PlanetlabNode(LinuxNode):
29 _rtype = "PlanetlabNode"
32 def _register_attributes(cls):
33 ip = Attribute("ip", "PlanetLab host public IP address",
34 flags = Flags.ReadOnly)
36 pl_url = Attribute("plcApiUrl", "URL of PlanetLab PLCAPI host (e.g. www.planet-lab.eu or www.planet-lab.org) ",
37 default = "www.planet-lab.eu",
38 flags = Flags.Credential)
40 pl_ptn = Attribute("plcApiPattern", "PLC API service regexp pattern (e.g. https://%(hostname)s:443/PLCAPI/ ) ",
41 default = "https://%(hostname)s:443/PLCAPI/",
42 flags = Flags.ExecReadOnly)
44 pl_user = Attribute("pluser", "PlanetLab account user, as the one to authenticate in the website) ",
45 flags = Flags.Credential)
47 pl_password = Attribute("password", "PlanetLab account password, as the one to authenticate in the website) ",
48 flags = Flags.Credential)
50 city = Attribute("city",
51 "Constrain location (city) during resource discovery. May use wildcards.",
54 country = Attribute("country",
55 "Constrain location (country) during resource discovery. May use wildcards.",
58 region = Attribute("region",
59 "Constrain location (region) during resource discovery. May use wildcards.",
62 architecture = Attribute("architecture",
63 "Constrain architecture during resource discovery.",
64 type = Types.Enumerate,
69 operating_system = Attribute("operatingSystem",
70 "Constrain operating system during resource discovery.",
71 type = Types.Enumerate,
79 site = Attribute("site",
80 "Constrain the PlanetLab site this node should reside on.",
81 type = Types.Enumerate,
87 min_reliability = Attribute("minReliability",
88 "Constrain reliability while picking PlanetLab nodes. Specifies a lower acceptable bound.",
93 max_reliability = Attribute("maxReliability",
94 "Constrain reliability while picking PlanetLab nodes. Specifies an upper acceptable bound.",
99 min_bandwidth = Attribute("minBandwidth",
100 "Constrain available bandwidth while picking PlanetLab nodes. Specifies a lower acceptable bound.",
103 flags = Flags.Filter)
105 max_bandwidth = Attribute("maxBandwidth",
106 "Constrain available bandwidth while picking PlanetLab nodes. Specifies an upper acceptable bound.",
109 flags = Flags.Filter)
111 min_load = Attribute("minLoad",
112 "Constrain node load average while picking PlanetLab nodes. Specifies a lower acceptable bound.",
115 flags = Flags.Filter)
117 max_load = Attribute("maxLoad",
118 "Constrain node load average while picking PlanetLab nodes. Specifies an upper acceptable bound.",
121 flags = Flags.Filter)
123 min_cpu = Attribute("minCpu",
124 "Constrain available cpu time while picking PlanetLab nodes. Specifies a lower acceptable bound.",
127 flags = Flags.Filter)
129 max_cpu = Attribute("maxCpu",
130 "Constrain available cpu time while picking PlanetLab nodes. Specifies an upper acceptable bound.",
133 flags = Flags.Filter)
135 timeframe = Attribute("timeframe",
136 "Past time period in which to check information about the node. Values are year,month, week, latest",
138 type = Types.Enumerate,
143 flags = Flags.Filter)
145 cls._register_attribute(ip)
146 cls._register_attribute(pl_url)
147 cls._register_attribute(pl_ptn)
148 cls._register_attribute(pl_user)
149 cls._register_attribute(pl_password)
150 cls._register_attribute(site)
151 cls._register_attribute(city)
152 cls._register_attribute(country)
153 cls._register_attribute(region)
154 cls._register_attribute(architecture)
155 cls._register_attribute(operating_system)
156 cls._register_attribute(min_reliability)
157 cls._register_attribute(max_reliability)
158 cls._register_attribute(min_bandwidth)
159 cls._register_attribute(max_bandwidth)
160 cls._register_attribute(min_load)
161 cls._register_attribute(max_load)
162 cls._register_attribute(min_cpu)
163 cls._register_attribute(max_cpu)
164 cls._register_attribute(timeframe)
166 def __init__(self, ec, guid):
167 super(PlanetlabNode, self).__init__(ec, guid)
174 pl_user = self.get("pluser")
175 pl_pass = self.get("password")
176 pl_url = self.get("plcApiUrl")
177 pl_ptn = self.get("plcApiPattern")
179 self._plapi = PLCAPIFactory.get_api(pl_user, pl_pass, pl_url,
185 #if self.get("hostname") or self.get("ip"):
187 #return node_id de hostname para que provision haga add_node_slice, check que ip coincide con hostname
189 def filter_based_on_attributes(self):
190 # Map attributes with tagnames of PL
191 timeframe = self.get("timeframe")[0]
194 'country' : 'country',
196 'architecture' : 'arch',
197 'operatingSystem' : 'fcdistro',
198 #'site' : 'pldistro',
199 'minReliability' : 'reliability%s' % timeframe,
200 'maxReliability' : 'reliability%s' % timeframe,
201 'minBandwidth' : 'bw%s' % timeframe,
202 'maxBandwidth' : 'bw%s' % timeframe,
203 'minLoad' : 'load%s' % timeframe,
204 'maxLoad' : 'load%s' % timeframe,
205 'minCpu' : 'cpu%s' % timeframe,
206 'maxCpu' : 'cpu%s' % timeframe,
211 for attr_name, attr_obj in self._attrs.iteritems():
212 attr_value = self.get(attr_name)
214 if attr_value is not None and attr_obj.flags == 8 and not 'min' in attr_name \
215 and not 'max'in attr_name and attr_name != 'timeframe':
216 attr_tag = attr_to_tags[attr_name]
217 filters['tagname'] = attr_tag
218 filters['value'] = attr_value
219 node_tags = self.plapi.get_node_tags(filters)
220 if node_tags is not None:
221 if len(nodes_id) == 0:
222 for node_tag in node_tags:
223 nodes_id.append(node_tag['node_id'])
226 for node_tag in node_tags:
227 if node_tag['node_id'] in nodes_id:
228 nodes_id_tmp.append(node_tag['node_id'])
229 if len(nodes_id_tmp):
230 nodes_id = set(nodes_id) & set(nodes_id_tmp)
232 return "No node matching your filters 1"
234 return "No node matching your filters 2"
235 elif attr_value is not None and attr_obj.flags == 8 and ('min' or 'max') in attr_name:
236 attr_tag = attr_to_tags[attr_name]
237 filters['tagname'] = attr_tag
238 node_tags = self.plapi.get_node_tags(filters)
239 if node_tags is not None:
240 if len(nodes_id) == 0:
241 for node_tag in node_tags:
242 if 'min' in attr_name and node_tag['value'] != 'n/a' and \
243 float(node_tag['value']) > attr_value:
244 nodes_id.append(node_tag['node_id'])
245 elif 'max' in attr_name and node_tag['value'] != 'n/a' and \
246 float(node_tag['value']) < attr_value:
247 nodes_id.append(node_tag['node_id'])
250 for node_tag in node_tags:
251 if 'min' in attr_name and node_tag['value'] != 'n/a' and \
252 float(node_tag['value']) > attr_value and \
253 node_tag['node_id'] in nodes_id:
254 nodes_id_tmp.append(node_tag['node_id'])
255 elif 'max' in attr_name and node_tag['value'] != 'n/a' and \
256 float(node_tag['value']) < attr_value and \
257 node_tag['node_id'] in nodes_id:
258 nodes_id_tmp.append(node_tag['node_id'])
259 if len(nodes_id_tmp):
260 nodes_id = set(nodes_id) & set(nodes_id_tmp)
262 return "No node matching your filters 3"
266 #def check_alive_and_active(self, nodes_id):
272 def valid_connection(self, guid):
276 # def blacklist(self):
278 # self.warn(" Blacklisting malfunctioning node ")
280 # #util.appendBlacklist(self.hostname)