Adding authors and correcting licence information
[nepi.git] / src / nepi / resources / omf / node.py
1 #
2 #    NEPI, a framework to manage network experiments
3 #    Copyright (C) 2013 INRIA
4 #
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.
9 #
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.
14 #
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/>.
17 #
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19 #         Julien Tribino <julien.tribino@inria.fr>
20
21
22 from nepi.execution.resource import ResourceManager, clsinit, ResourceState
23 from nepi.execution.attribute import Attribute, Flags 
24
25 from nepi.resources.omf.omf_api import OMFAPIFactory
26
27 import time
28
29 reschedule_delay = "0.5s"
30
31 @clsinit
32 class OMFNode(ResourceManager):
33     """
34     .. class:: Class Args :
35       
36         :param ec: The Experiment controller
37         :type ec: ExperimentController
38         :param guid: guid of the RM
39         :type guid: int
40         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
41         :type creds: dict
42
43     .. note::
44
45        This class is used only by the Experiment Controller through the Resource Factory
46
47     """
48     _rtype = "OMFNode"
49     _authorized_connections = ["OMFApplication" , "OMFWifiInterface"]
50
51     @classmethod
52     def _register_attributes(cls):
53         """Register the attributes of an OMF Node
54
55         """
56         hostname = Attribute("hostname", "Hostname of the machine")
57         cpu = Attribute("cpu", "CPU of the node")
58         ram = Attribute("ram", "RAM of the node")
59         xmppSlice = Attribute("xmppSlice","Name of the slice",
60                 flags = Flags.Credential)
61         xmppHost = Attribute("xmppHost", "Xmpp Server",
62                 flags = Flags.Credential)
63         xmppPort = Attribute("xmppPort", "Xmpp Port",
64                 flags = Flags.Credential)
65         xmppPassword = Attribute("xmppPassword", "Xmpp Port",
66                 flags = Flags.Credential)
67
68         host = Attribute("host", "Hostname of the machine",
69                 flags = Flags.Filter)
70         gateway = Attribute("gateway", "Gateway",
71                 flags = Flags.Filter)
72         granularity = Attribute("granularity", "Granularity of the reservation time",
73                 flags = Flags.Filter)
74         hardware_type = Attribute("hardware_type", "Hardware type of the machine",
75                 flags = Flags.Filter)
76
77         cls._register_attribute(hostname)
78         cls._register_attribute(ram)
79         cls._register_attribute(cpu)
80         cls._register_attribute(xmppSlice)
81         cls._register_attribute(xmppHost)
82         cls._register_attribute(xmppPort)
83         cls._register_attribute(xmppPassword)
84
85         cls._register_attribute(host)
86         cls._register_attribute(gateway)
87         cls._register_attribute(granularity)
88         cls._register_attribute(hardware_type)
89
90     # XXX: We don't necessary need to have the credentials at the 
91     # moment we create the RM
92     def __init__(self, ec, guid):
93         """
94         :param ec: The Experiment controller
95         :type ec: ExperimentController
96         :param guid: guid of the RM
97         :type guid: int
98         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
99         :type creds: dict
100
101         """
102         super(OMFNode, self).__init__(ec, guid)
103
104         self._omf_api = None 
105
106         # XXX: TO DISCUSS
107
108     def _validate_connection(self, guid):
109         """Check if the connection is available.
110
111         :param guid: Guid of the current RM
112         :type guid: int
113         :rtype:  Boolean
114
115         """
116         rm = self.ec.get_resource(guid)
117         if rm.rtype() in self._authorized_connections:
118             msg = "Connection between %s %s and %s %s accepted" % (self.rtype(), self._guid, rm.rtype(), guid)
119             self.debug(msg)
120             return True
121         msg = "Connection between %s %s and %s %s refused" % (self.rtype(), self._guid, rm.rtype(), guid)
122         self.debug(msg)
123         return False
124
125     def deploy(self):
126         """Deploy the RM
127
128         """ 
129         if not self._omf_api :
130             self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), 
131                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'))
132         self._omf_api.enroll_host(self.get('hostname'))
133
134         super(OMFNode, self).deploy()
135
136     def discover(self):
137         """ Discover the availables nodes
138
139         """
140         pass
141      
142     def provision(self):
143         """ Provision some availables nodes
144
145         """
146         pass
147
148     def start(self):
149         """Send Xmpp Message Using OMF protocol to enroll the node into the experiment
150
151         """
152         super(OMFNode, self).start()
153
154
155     def stop(self):
156         """Send Xmpp Message Using OMF protocol to disconnect the node
157
158         """
159         super(OMFNode, self).stop()
160
161     def release(self):
162         """Clean the RM at the end of the experiment
163
164         """
165         self._omf_api.release(self.get('hostname'))
166         OMFAPIFactory.release_api(self.get('xmppSlice'), 
167             self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'))
168
169
170     def configure(self):
171         #routes = self.tc._add_route.get(self.guid, [])
172         #iface_guids = self.tc.get_connected(self.guid, "devs", "node")
173        
174         for route in routes:
175             (destination, netprefix, nexthop, metric, device) = route
176             netmask = ipaddr2.ipv4_mask2dot(netprefix)
177
178             # Validate that the interface is associated to the node
179             for iface_guid in iface_guids:
180                 iface = self.tc.elements.get(iface_guid)
181                 if iface.devname == device:
182                     self._omf_api.execute(self.get('hostname'), 
183                         "Id#%s" % str(random.getrandbits(128)), 
184                         "add -net %s netmask %s dev %s" % (destination, netmask, iface.devname), 
185                         "/sbin/route", # path
186                         None, # env
187                      )
188                     break