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