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