Adding authors and correcting licence information
[nepi.git] / test / execution / resource.py
1 #!/usr/bin/env python
2 #
3 #    NEPI, a framework to manage network experiments
4 #    Copyright (C) 2013 INRIA
5 #
6 #    This program is free software: you can redistribute it and/or modify
7 #    it under the terms of the GNU General Public License as published by
8 #    the Free Software Foundation, either version 3 of the License, or
9 #    (at your option) any later version.
10 #
11 #    This program is distributed in the hope that it will be useful,
12 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #    GNU General Public License for more details.
15 #
16 #    You should have received a copy of the GNU General Public License
17 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
20
21
22 from nepi.execution.attribute import Attribute
23 from nepi.execution.ec import ExperimentController 
24 from nepi.execution.resource import ResourceManager, ResourceState, clsinit
25
26 import time
27 import unittest
28
29 @clsinit
30 class MyResource(ResourceManager):
31     _rtype = "MyResource"
32
33     @classmethod
34     def _register_attributes(cls):
35         cool_attr = Attribute("my_attr", "is a really nice attribute!")
36         cls._register_attribute(cool_attr)
37
38     def __init__(self, ec, guid):
39         super(MyResource, self).__init__(ec, guid)
40
41 @clsinit
42 class AnotherResource(ResourceManager):
43     _rtype = "AnotherResource"
44
45     def __init__(self, ec, guid):
46         super(AnotherResource, self).__init__(ec, guid)
47      
48 class ResourceFactoryTestCase(unittest.TestCase):
49     def test_add_resource_factory(self):
50         from nepi.execution.resource import ResourceFactory
51
52         ResourceFactory.register_type(MyResource)
53         ResourceFactory.register_type(AnotherResource)
54
55         self.assertEquals(MyResource.rtype(), "MyResource")
56         self.assertEquals(len(MyResource._attributes), 1)
57
58         self.assertEquals(ResourceManager.rtype(), "Resource")
59         self.assertEquals(len(ResourceManager._attributes), 0)
60
61         self.assertEquals(AnotherResource.rtype(), "AnotherResource")
62         self.assertEquals(len(AnotherResource._attributes), 0)
63
64         self.assertEquals(len(ResourceFactory.resource_types()), 2)
65
66 class Channel(ResourceManager):
67     _rtype = "Channel"
68
69     def __init__(self, ec, guid):
70         super(Channel, self).__init__(ec, guid)
71
72     def deploy(self):
73         time.sleep(1)
74         super(Channel, self).deploy()
75         self.logger.debug(" -------- DEPLOYED ------- ")
76        
77 class Interface(ResourceManager):
78     _rtype = "Interface"
79
80     def __init__(self, ec, guid):
81         super(Interface, self).__init__(ec, guid)
82
83     def deploy(self):
84         node = self.get_connected(Node.rtype())[0]
85         chan = self.get_connected(Channel.rtype())[0]
86
87         if node.state < ResourceState.PROVISIONED:
88             self.ec.schedule("0.5s", self.deploy)
89         elif chan.state < ResourceState.READY:
90             self.ec.schedule("0.5s", self.deploy)
91         else:
92             time.sleep(2)
93             super(Interface, self).deploy()
94             self.logger.debug(" -------- DEPLOYED ------- ")
95
96 class Node(ResourceManager):
97     _rtype = "Node"
98
99     def __init__(self, ec, guid):
100         super(Node, self).__init__(ec, guid)
101
102     def deploy(self):
103         if self.state == ResourceState.NEW:
104             self.discover()
105             self.provision()
106             self.logger.debug(" -------- PROVISIONED ------- ")
107             self.ec.schedule("3s", self.deploy)
108         elif self.state == ResourceState.PROVISIONED:
109             ifaces = self.get_connected(Interface.rtype())
110             for rm in ifaces:
111                 if rm.state < ResourceState.READY:
112                     self.ec.schedule("0.5s", self.deploy)
113                     return 
114
115             super(Node, self).deploy()
116             self.logger.debug(" -------- DEPLOYED ------- ")
117
118 class Application(ResourceManager):
119     _rtype = "Application"
120
121     def __init__(self, ec, guid):
122         super(Application, self).__init__(ec, guid)
123
124     def deploy(self):
125         node = self.get_connected(Node.rtype())[0]
126         if node.state < ResourceState.READY:
127             self.ec.schedule("0.5s", self.deploy)
128         else:
129             super(Application, self).deploy()
130             self.logger.debug(" -------- DEPLOYED ------- ")
131
132 class ResourceManagerTestCase(unittest.TestCase):
133     def test_deploy_in_order(self):
134         """
135         Test scenario: 2 applications running one on 1 node each. 
136         Nodes are connected to Interfaces which are connected
137         through a channel between them.
138
139          - Application needs to wait until Node is ready to be ready
140          - Node needs to wait until Interface is ready to be ready
141          - Interface needs to wait until Node is provisioned to be ready
142          - Interface needs to wait until Channel is ready to be ready
143          - The channel doesn't wait for any other resource to be ready
144
145         """
146         from nepi.execution.resource import ResourceFactory
147         
148         ResourceFactory.register_type(Application)
149         ResourceFactory.register_type(Node)
150         ResourceFactory.register_type(Interface)
151         ResourceFactory.register_type(Channel)
152
153         ec = ExperimentController()
154
155         app1 = ec.register_resource("Application")
156         app2 = ec.register_resource("Application")
157         node1 = ec.register_resource("Node")
158         node2 = ec.register_resource("Node")
159         iface1 = ec.register_resource("Interface")
160         iface2 = ec.register_resource("Interface")
161         chan = ec.register_resource("Channel")
162
163         ec.register_connection(app1, node1)
164         ec.register_connection(app2, node2)
165         ec.register_connection(iface1, node1)
166         ec.register_connection(iface2, node2)
167         ec.register_connection(iface1, chan)
168         ec.register_connection(iface2, chan)
169
170         ec.deploy()
171
172         while not all([ ec.state(guid) == ResourceState.STARTED \
173                 for guid in [app1, app2, node1, node2, iface1, iface2, chan]]) \
174                 and not ec.finished:
175             time.sleep(0.5)
176
177         ec.shutdown()
178
179         rmapp1 = ec.get_resource(app1)
180         rmapp2 = ec.get_resource(app2)
181         rmnode1 = ec.get_resource(node1)
182         rmnode2 = ec.get_resource(node2)
183         rmiface1 = ec.get_resource(iface1)
184         rmiface2 = ec.get_resource(iface2)
185         rmchan = ec.get_resource(chan)
186
187         ## Validate deploy order
188         # - Application needs to wait until Node is ready to be ready
189         self.assertTrue(rmnode1.ready_time < rmapp1.ready_time)
190         self.assertTrue(rmnode2.ready_time < rmapp2.ready_time)
191
192          # - Node needs to wait until Interface is ready to be ready
193         self.assertTrue(rmnode1.ready_time > rmiface1.ready_time)
194         self.assertTrue(rmnode2.ready_time > rmiface2.ready_time)
195
196          # - Interface needs to wait until Node is provisioned to be ready
197         self.assertTrue(rmnode1.provision_time < rmiface1.ready_time)
198         self.assertTrue(rmnode2.provision_time < rmiface2.ready_time)
199
200          # - Interface needs to wait until Channel is ready to be ready
201         self.assertTrue(rmchan.ready_time < rmiface1.ready_time)
202         self.assertTrue(rmchan.ready_time < rmiface2.ready_time)
203
204     def test_start_with_condition(self):
205         # TODO!!!
206         pass
207     
208     def test_stop_with_condition(self):
209         # TODO!!!
210         pass
211
212     def test_set_with_condition(self):
213         # TODO!!!
214         pass
215
216
217 if __name__ == '__main__':
218     unittest.main()
219