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