0e1dad9d66fcbade3111ac82a9e538e862a376a9
[nepi.git] / src / nepi / resources / omf / interface.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 from nepi.execution.resource import ResourceManager, clsinit, ResourceState
22 from nepi.execution.attribute import Attribute, Flags 
23
24 from nepi.resources.omf.omf_api import OMFAPIFactory
25
26 reschedule_delay = "0.5s"
27
28 @clsinit
29 class OMFWifiInterface(ResourceManager):
30     """
31     .. class:: Class Args :
32       
33         :param ec: The Experiment controller
34         :type ec: ExperimentController
35         :param guid: guid of the RM
36         :type guid: int
37         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
38         :type creds: dict
39
40     .. note::
41
42        This class is used only by the Experiment Controller through the Resource Factory
43
44     """
45     _rtype = "OMFWifiInterface"
46     _authorized_connections = ["OMFNode" , "OMFChannel"]
47
48     #alias2name = dict({'w0':'wlan0', 'w1':'wlan1'})
49
50     @classmethod
51     def _register_attributes(cls):
52         """Register the attributes of an OMF interface 
53
54         """
55         alias = Attribute("alias","Alias of the interface", default = "w0")
56         mode = Attribute("mode","Mode of the interface")
57         type = Attribute("type","Type of the interface")
58         essid = Attribute("essid","Essid of the interface")
59         ip = Attribute("ip","IP of the interface")
60         xmppSlice = Attribute("xmppSlice","Name of the slice", flags = Flags.Credential)
61         xmppHost = Attribute("xmppHost", "Xmpp Server",flags = Flags.Credential)
62         xmppPort = Attribute("xmppPort", "Xmpp Port",flags = Flags.Credential)
63         xmppPassword = Attribute("xmppPassword", "Xmpp Port",flags = Flags.Credential)
64         cls._register_attribute(alias)
65         cls._register_attribute(xmppSlice)
66         cls._register_attribute(xmppHost)
67         cls._register_attribute(xmppPort)
68         cls._register_attribute(xmppPassword)
69         cls._register_attribute(mode)
70         cls._register_attribute(type)
71         cls._register_attribute(essid)
72         cls._register_attribute(ip)
73
74     def __init__(self, ec, guid):
75         """
76         :param ec: The Experiment controller
77         :type ec: ExperimentController
78         :param guid: guid of the RM
79         :type guid: int
80         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
81         :type creds: dict
82
83         """
84         super(OMFWifiInterface, self).__init__(ec, guid)
85
86         self._omf_api = None
87         self._alias = self.get('alias')
88
89     def valid_connection(self, guid):
90         """ Check if the connection with the guid in parameter is possible. Only meaningful connections are allowed.
91
92         :param guid: Guid of the current RM
93         :type guid: int
94         :rtype:  Boolean
95
96         """
97         rm = self.ec.get_resource(guid)
98         if rm.rtype() in self._authorized_connections:
99             msg = "Connection between %s %s and %s %s accepted" % \
100                 (self.rtype(), self._guid, rm.rtype(), guid)
101             self.debug(msg)
102             return True
103         msg = "Connection between %s %s and %s %s refused" % \
104              (self.rtype(), self._guid, rm.rtype(), guid)
105         self.debug(msg)
106         return False
107
108     def deploy(self):
109         """Deploy the RM. It means : Get the xmpp client and send messages using OMF 5.4 protocol to configure the interface
110            It becomes DEPLOYED after sending messages to configure the interface
111         """
112         if not self._omf_api :
113             self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), 
114                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'))
115
116         if self.get('mode') and self.get('type') and self.get('essid') and self.get('ip'):
117             self.debug(" " + self.rtype() + " ( Guid : " + str(self._guid) +") : " + \
118                 self.get('mode') + " : " + self.get('type') + " : " + \
119                 self.get('essid') + " : " + self.get('ip'))
120             rm_list = self.get_connected("OMFNode") 
121             for rm_node in rm_list:
122                 if rm_node.state < ResourceState.READY:
123                     self.ec.schedule(reschedule_delay, self.deploy)
124                     return 
125                 if rm_node.get('hostname') :
126                     try :
127                         for attrname in ["mode", "type", "essid", "ip"]:
128                             attrval = self.get(attrname)
129                             attrname = "net/%s/%s" % (self._alias, attrname)
130                             #print "Send the configure message"
131                             self._omf_api.configure(rm_node.get('hostname'), attrname, attrval)
132                     except AttributeError:
133                         self._state = ResourceState.FAILED
134                         msg = "Credentials are not initialzed. XMPP Connections impossible"
135                         self.debug(msg)
136                         raise
137                 else :
138                     msg = "The channel is connected with an undefined node"
139                     self.error(msg)
140         else :
141             msg = "Interface's variable are not initialized"
142             self.error(msg)
143
144         super(OMFWifiInterface, self).deploy()
145
146     def start(self):
147         """Start the RM. It means nothing special for an interface for now
148            It becomes STARTED as soon as this method starts.
149
150         """
151
152         super(OMFWifiInterface, self).start()
153
154     def stop(self):
155         """Stop the RM. It means nothing special for an interface for now
156            It becomes STOPPED as soon as this method stops
157
158         """
159         super(OMFWifiInterface, self).stop()
160
161     def release(self):
162         """Clean the RM at the end of the experiment and release the API
163
164         """
165         if self._omf_api :
166             OMFAPIFactory.release_api(self.get('xmppSlice'), 
167                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'))
168