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