Added LICENSE
[nepi.git] / test / execution / resource.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 #!/usr/bin/env python
21 from nepi.execution.attribute import Attribute
22 from nepi.execution.ec import ExperimentController 
23 from nepi.execution.resource import ResourceManager, ResourceState, clsinit
24
25 import time
26 import unittest
27
28 @clsinit
29 class MyResource(ResourceManager):
30     _rtype = "MyResource"
31
32     @classmethod
33     def _register_attributes(cls):
34         cool_attr = Attribute("my_attr", "is a really nice attribute!")
35         cls._register_attribute(cool_attr)
36
37     def __init__(self, ec, guid):
38         super(MyResource, self).__init__(ec, guid)
39
40 @clsinit
41 class AnotherResource(ResourceManager):
42     _rtype = "AnotherResource"
43
44     def __init__(self, ec, guid):
45         super(AnotherResource, self).__init__(ec, guid)
46      
47 class ResourceFactoryTestCase(unittest.TestCase):
48     def test_add_resource_factory(self):
49         from nepi.execution.resource import ResourceFactory
50
51         ResourceFactory.register_type(MyResource)
52         ResourceFactory.register_type(AnotherResource)
53
54         self.assertEquals(MyResource.rtype(), "MyResource")
55         self.assertEquals(len(MyResource._attributes), 1)
56
57         self.assertEquals(ResourceManager.rtype(), "Resource")
58         self.assertEquals(len(ResourceManager._attributes), 0)
59
60         self.assertEquals(AnotherResource.rtype(), "AnotherResource")
61         self.assertEquals(len(AnotherResource._attributes), 0)
62
63         self.assertEquals(len(ResourceFactory.resource_types()), 2)
64
65 class Channel(ResourceManager):
66     _rtype = "Channel"
67
68     def __init__(self, ec, guid):
69         super(Channel, self).__init__(ec, guid)
70
71     def deploy(self):
72         time.sleep(1)
73         super(Channel, self).deploy()
74         self.logger.debug(" -------- DEPLOYED ------- ")
75        
76 class Interface(ResourceManager):
77     _rtype = "Interface"
78
79     def __init__(self, ec, guid):
80         super(Interface, self).__init__(ec, guid)
81
82     def deploy(self):
83         node = self.get_connected(Node.rtype())[0]
84         chan = self.get_connected(Channel.rtype())[0]
85
86         if node.state < ResourceState.PROVISIONED:
87             self.ec.schedule("0.5s", self.deploy)
88         elif chan.state < ResourceState.READY:
89             self.ec.schedule("0.5s", self.deploy)
90         else:
91             time.sleep(2)
92             super(Interface, self).deploy()
93             self.logger.debug(" -------- DEPLOYED ------- ")
94
95 class Node(ResourceManager):
96     _rtype = "Node"
97
98     def __init__(self, ec, guid):
99         super(Node, self).__init__(ec, guid)
100
101     def deploy(self):
102         if self.state == ResourceState.NEW:
103             self.discover()
104             self.provision()
105             self.logger.debug(" -------- PROVISIONED ------- ")
106             self.ec.schedule("3s", self.deploy)
107         elif self.state == ResourceState.PROVISIONED:
108             ifaces = self.get_connected(Interface.rtype())
109             for rm in ifaces:
110                 if rm.state < ResourceState.READY:
111                     self.ec.schedule("0.5s", self.deploy)
112                     return 
113
114             super(Node, self).deploy()
115             self.logger.debug(" -------- DEPLOYED ------- ")
116
117 class Application(ResourceManager):
118     _rtype = "Application"
119
120     def __init__(self, ec, guid):
121         super(Application, self).__init__(ec, guid)
122
123     def deploy(self):
124         node = self.get_connected(Node.rtype())[0]
125         if node.state < ResourceState.READY:
126             self.ec.schedule("0.5s", self.deploy)
127         else:
128             super(Application, self).deploy()
129             self.logger.debug(" -------- DEPLOYED ------- ")
130
131 class ResourceManagerTestCase(unittest.TestCase):
132     def test_deploy_in_order(self):
133         """
134         Test scenario: 2 applications running one on 1 node each. 
135         Nodes are connected to Interfaces which are connected
136         through a channel between them.
137
138          - Application needs to wait until Node is ready to be ready
139          - Node needs to wait until Interface is ready to be ready
140          - Interface needs to wait until Node is provisioned to be ready
141          - Interface needs to wait until Channel is ready to be ready
142          - The channel doesn't wait for any other resource to be ready
143
144         """
145         from nepi.execution.resource import ResourceFactory
146         
147         ResourceFactory.register_type(Application)
148         ResourceFactory.register_type(Node)
149         ResourceFactory.register_type(Interface)
150         ResourceFactory.register_type(Channel)
151
152         ec = ExperimentController()
153
154         app1 = ec.register_resource("Application")
155         app2 = ec.register_resource("Application")
156         node1 = ec.register_resource("Node")
157         node2 = ec.register_resource("Node")
158         iface1 = ec.register_resource("Interface")
159         iface2 = ec.register_resource("Interface")
160         chan = ec.register_resource("Channel")
161
162         ec.register_connection(app1, node1)
163         ec.register_connection(app2, node2)
164         ec.register_connection(iface1, node1)
165         ec.register_connection(iface2, node2)
166         ec.register_connection(iface1, chan)
167         ec.register_connection(iface2, chan)
168
169         ec.deploy()
170
171         while not all([ ec.state(guid) == ResourceState.STARTED \
172                 for guid in [app1, app2, node1, node2, iface1, iface2, chan]]) \
173                 and not ec.finished:
174             time.sleep(0.5)
175
176         ec.shutdown()
177
178         rmapp1 = ec.get_resource(app1)
179         rmapp2 = ec.get_resource(app2)
180         rmnode1 = ec.get_resource(node1)
181         rmnode2 = ec.get_resource(node2)
182         rmiface1 = ec.get_resource(iface1)
183         rmiface2 = ec.get_resource(iface2)
184         rmchan = ec.get_resource(chan)
185
186         ## Validate deploy order
187         # - Application needs to wait until Node is ready to be ready
188         self.assertTrue(rmnode1.ready_time < rmapp1.ready_time)
189         self.assertTrue(rmnode2.ready_time < rmapp2.ready_time)
190
191          # - Node needs to wait until Interface is ready to be ready
192         self.assertTrue(rmnode1.ready_time > rmiface1.ready_time)
193         self.assertTrue(rmnode2.ready_time > rmiface2.ready_time)
194
195          # - Interface needs to wait until Node is provisioned to be ready
196         self.assertTrue(rmnode1.provision_time < rmiface1.ready_time)
197         self.assertTrue(rmnode2.provision_time < rmiface2.ready_time)
198
199          # - Interface needs to wait until Channel is ready to be ready
200         self.assertTrue(rmchan.ready_time < rmiface1.ready_time)
201         self.assertTrue(rmchan.ready_time < rmiface2.ready_time)
202
203     def test_start_with_condition(self):
204         # TODO!!!
205         pass
206     
207     def test_stop_with_condition(self):
208         # TODO!!!
209         pass
210
211     def test_set_with_condition(self):
212         # TODO!!!
213         pass
214
215
216 if __name__ == '__main__':
217     unittest.main()
218