Modify the OMT test and add the exp_id in the xmpp Api
[nepi.git] / src / nepi / resources / omf / channel.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         reschedule_delay
22 from nepi.execution.attribute import Attribute, Flags 
23
24 from nepi.resources.omf.omf_api import OMFAPIFactory
25
26
27 @clsinit
28 class OMFChannel(ResourceManager):
29     """
30     .. class:: Class Args :
31       
32         :param ec: The Experiment controller
33         :type ec: ExperimentController
34         :param guid: guid of the RM
35         :type guid: int
36         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
37         :type creds: dict
38
39     .. note::
40
41        This class is used only by the Experiment Controller through the Resource Factory
42
43     """
44     _rtype = "OMFChannel"
45     _authorized_connections = ["OMFWifiInterface", "OMFNode"]
46
47
48     @classmethod
49     def _register_attributes(cls):
50         """Register the attributes of an OMF channel
51         """
52         channel = Attribute("channel", "Name of the application")
53         xmppSlice = Attribute("xmppSlice","Name of the slice", flags = Flags.Credential)
54         xmppHost = Attribute("xmppHost", "Xmpp Server",flags = Flags.Credential)
55         xmppPort = Attribute("xmppPort", "Xmpp Port",flags = Flags.Credential)
56         xmppPassword = Attribute("xmppPassword", "Xmpp Port",flags = Flags.Credential)
57         cls._register_attribute(channel)
58         cls._register_attribute(xmppSlice)
59         cls._register_attribute(xmppHost)
60         cls._register_attribute(xmppPort)
61         cls._register_attribute(xmppPassword)
62
63     def __init__(self, ec, guid):
64         """
65         :param ec: The Experiment controller
66         :type ec: ExperimentController
67         :param guid: guid of the RM
68         :type guid: int
69         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
70         :type creds: dict
71
72         """
73         super(OMFChannel, self).__init__(ec, guid)
74
75         self._nodes_guid = list()
76
77         self._omf_api = None
78
79     @property
80     def exp_id(self):
81         if self.ec.exp_id.startswith('exp-'):
82             return None
83         return self.ec.exp_id
84
85     def valid_connection(self, guid):
86         """Check if the connection with the guid in parameter is possible. Only meaningful connections are allowed.
87
88         :param guid: Guid of the current RM
89         :type guid: int
90         :rtype:  Boolean
91
92         """
93         rm = self.ec.get_resource(guid)
94         if rm.rtype() in self._authorized_connections:
95             msg = "Connection between %s %s and %s %s accepted" % (self.rtype(), self._guid, rm.rtype(), guid)
96             self.debug(msg)
97             return True
98         msg = "Connection between %s %s and %s %s refused" % (self.rtype(), self._guid, rm.rtype(), guid)
99         self.debug(msg)
100         return False
101
102     def _get_target(self, conn_set):
103         """
104         Get the couples (host, interface) that uses this channel
105
106         :param conn_set: Connections of the current Guid
107         :type conn_set: set
108         :rtype: list
109         :return: self._nodes_guid
110
111         """
112         res = []
113         for elt in conn_set:
114             rm_iface = self.ec.get_resource(elt)
115             for conn in rm_iface.connections:
116                 rm_node = self.ec.get_resource(conn)
117                 if rm_node.rtype() == "OMFNode" and rm_node.get('hostname'):
118                     if rm_iface.state < ResourceState.READY or rm_node.state < ResourceState.READY:
119                         return "reschedule"
120                     couple = [rm_node.get('hostname'), rm_iface.get('alias')]
121                     #print couple
122                     res.append(couple)
123         return res
124
125     def discover(self):
126         """ Discover the availables channels
127
128         """
129         pass
130      
131     def provision(self):
132         """ Provision some availables channels
133
134         """
135         pass
136
137     def deploy(self):
138         """Deploy the RM. It means : Get the xmpp client and send messages using OMF 5.4 protocol to configure the channel
139            It becomes DEPLOYED after sending messages to configure the channel
140
141         """
142         if not self._omf_api :
143             self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), 
144                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'), exp_id = self.exp_id)
145
146         if not self._omf_api :
147             self._state = ResourceState.FAILED
148             msg = "Credentials are not initialzed. XMPP Connections impossible"
149             self.error(msg)
150             return
151
152         if not self.get('channel'):
153             self._state = ResourceState.FAILED
154             msg = "Channel's value is not initialized"
155             self.error(msg)
156             raise
157
158         self._nodes_guid = self._get_target(self._connections) 
159         if self._nodes_guid == "reschedule" :
160             self.ec.schedule("2s", self.deploy)
161             return False
162
163         try:
164             for couple in self._nodes_guid:
165                 #print "Couple node/alias : " + couple[0] + "  ,  " + couple[1]
166                 attrval = self.get('channel')
167                 attrname = "net/%s/%s" % (couple[1], 'channel')
168                 self._omf_api.configure(couple[0], attrname, attrval)
169         except AttributeError:
170             self._state = ResourceState.FAILED
171             msg = "Credentials are not initialzed. XMPP Connections impossible"
172             self.error(msg)
173             raise
174
175         super(OMFChannel, self).deploy()
176
177     def start(self):
178         """Start the RM. It means nothing special for a channel for now
179            It becomes STARTED as soon as this method starts.
180
181         """
182
183         super(OMFChannel, self).start()
184
185     def stop(self):
186         """Stop the RM. It means nothing special for a channel for now
187            It becomes STOPPED as soon as this method is called
188
189         """
190         super(OMFChannel, self).stop()
191
192     def release(self):
193         """Clean the RM at the end of the experiment and release the API
194
195         """
196         if self._omf_api :
197             OMFAPIFactory.release_api(self.get('xmppSlice'), 
198                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'), exp_id = self.exp_id)
199
200         super(OMFChannel, self).release()
201