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