1 # Copyright 2013 GRNET S.A. All rights reserved.
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
7 # 1. Redistributions of source code must retain the above
8 # copyright notice, this list of conditions and the following
11 # 2. Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following
13 # disclaimer in the documentation and/or other materials
14 # provided with the distribution.
16 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
29 # The views and conclusions contained in the software and
30 # documentation are those of the authors and should not be
31 # interpreted as representing official policies, either expressed
32 # or implied, of GRNET S.A.
33 from mock import patch, call
34 from unittest import TestCase
35 from json import loads
37 from kamaki.clients import ClientError
38 from kamaki.clients.cyclades import CycladesClient
39 from kamaki.clients.cyclades_rest_api import CycladesClientApi
41 img_ref = "1m4g3-r3f3r3nc3"
44 vm_recv = dict(server=dict(
46 updated="2013-03-01T10:04:00.637152+00:00",
50 created="2013-03-01T10:04:00.087324+00:00",
52 adminPass="n0n3sh@11p@55",
56 metadata=dict(values=dict(os="debian", users="root"))))
57 vm_list = dict(servers=dict(values=[
58 dict(name='n1', id=1),
59 dict(name='n2', id=2)]))
60 net_send = dict(network=dict(dhcp=False, name='someNet'))
61 net_recv = dict(network=dict(
63 updated="2013-03-05T15:04:51.758780+00:00",
65 created="2013-03-05T15:04:51.758728+00:00",
71 cidr="192.168.1.0/24",
74 attachments=dict(values=[dict(name='att1'), dict(name='att2')])))
75 net_list = dict(networks=dict(values=[
76 dict(id=1, name='n1'),
77 dict(id=2, name='n2'),
78 dict(id=3, name='n3')]))
82 """FR stands for Fake Response"""
92 khttp = 'kamaki.clients.connection.kamakicon.KamakiHTTPConnection'
93 cyclades_pkg = 'kamaki.clients.cyclades.CycladesClient'
96 class Cyclades(TestCase):
98 def assert_dicts_are_equal(self, d1, d2):
99 for k, v in d1.items():
100 self.assertTrue(k in d2)
101 if isinstance(v, dict):
102 self.assert_dicts_are_equal(v, d2[k])
104 self.assertEqual(unicode(v), unicode(d2[k]))
106 """Set up a Cyclades thorough test"""
108 self.url = 'http://cyclades.example.com'
109 self.token = 'cyc14d3s70k3n'
110 self.client = CycladesClient(self.url, self.token)
111 from kamaki.clients.connection.kamakicon import KamakiHTTPConnection
112 self.C = KamakiHTTPConnection
118 @patch('%s.servers_get' % cyclades_pkg, return_value=FR())
119 def test_list_servers(self, SG):
121 for detail, since in ((0, 0), (True, 0), (0, 'd473'), (True, 'd473')):
122 r = self.client.list_servers(detail=detail, changes_since=since)
123 self.assertEqual(SG.mock_calls[-1], call(
124 command='detail' if detail else '',
125 changes_since=since))
126 expected = vm_list['servers']['values']
127 for i, vm in enumerate(r):
128 self.assert_dicts_are_equal(vm, expected[i])
129 self.assertEqual(i + 1, len(expected))
131 @patch('%s.servers_post' % cyclades_pkg, return_value=FR())
132 def test_shutdown_server(self, SP):
133 vm_id = vm_recv['server']['id']
134 self.client.shutdown_server(vm_id)
135 self.assertEqual(SP.mock_calls[-1], call(
137 json_data=dict(shutdown=dict()), success=202))
139 @patch('%s.perform_request' % khttp, return_value=FR())
140 def test_start_server(self, PR):
141 vm_id = vm_recv['server']['id']
143 self.client.start_server(vm_id)
144 self.assertEqual(self.client.http_client.url, self.url)
146 self.client.http_client.path,
147 '/servers/%s/action' % vm_id)
148 self.assertEqual(PR.call_args[0], ('post', '{"start": {}}', {}, {}))
150 @patch('%s.perform_request' % khttp, return_value=FR())
151 def test_get_server_console(self, PR):
152 cnsl = dict(console=dict(info1='i1', info2='i2', info3='i3'))
154 vm_id = vm_recv['server']['id']
155 r = self.client.get_server_console(vm_id)
156 self.assertEqual(self.client.http_client.url, self.url)
158 self.client.http_client.path,
159 '/servers/%s/action' % vm_id)
160 self.assert_dicts_are_equal(cnsl['console'], r)
163 ('post', '{"console": {"type": "vnc"}}', {}, {}))
165 def test_get_firewall_profile(self):
166 vm_id = vm_recv['server']['id']
168 ret = {'attachments': {'values': [{'firewallProfile': v, 1:1}]}}
171 'get_server_details',
172 return_value=ret) as GSD:
173 r = self.client.get_firewall_profile(vm_id)
174 self.assertEqual(r, v)
175 self.assertEqual(GSD.call_args[0], (vm_id,))
176 ret['attachments']['values'][0].pop('firewallProfile')
179 self.client.get_firewall_profile,
182 @patch('%s.perform_request' % khttp, return_value=FR())
183 def test_set_firewall_profile(self, PR):
184 vm_id = vm_recv['server']['id']
187 self.client.set_firewall_profile(vm_id, v)
188 self.assertEqual(self.client.http_client.url, self.url)
190 self.client.http_client.path,
191 '/servers/%s/action' % vm_id)
192 self.assertEqual(PR.call_args[0], (
194 '{"firewallProfile": {"profile": "%s"}}' % v,
198 @patch('%s.perform_request' % khttp, return_value=FR())
199 def test_get_server_stats(self, PR):
200 vm_id = vm_recv['server']['id']
201 stats = dict(stat1='v1', stat2='v2', stat3='v3', stat4='v4')
202 FR.json = dict(stats=stats)
203 r = self.client.get_server_stats(vm_id)
204 self.assertEqual(self.client.http_client.url, self.url)
206 self.client.http_client.path,
207 '/servers/%s/stats' % vm_id)
208 self.assert_dicts_are_equal(stats, r)
210 @patch('%s.perform_request' % khttp, return_value=FR())
211 def test_create_network(self, PR):
212 net_name = net_send['network']['name']
216 cidr='192.168.0.0/24',
217 gateway='192.168.0.1',
220 test_args = dict(full_args)
221 test_args.update(dict(empty=None, full=None))
222 for arg, val in test_args.items():
223 kwargs = {} if arg == 'empty' else full_args if (
224 arg == 'full') else {arg: val}
225 r = self.client.create_network(net_name, **kwargs)
226 self.assertEqual(self.client.http_client.url, self.url)
228 self.client.http_client.path,
230 self.assert_dicts_are_equal(r, net_recv['network'])
231 data = PR.call_args[0][1]
232 expected = dict(network=dict(net_send['network']))
233 expected['network'].update(kwargs)
234 self.assert_dicts_are_equal(loads(data), expected)
236 @patch('%s.perform_request' % khttp, return_value=FR())
237 def test_connect_server(self, PR):
238 vm_id = vm_recv['server']['id']
239 net_id = net_recv['network']['id']
241 self.client.connect_server(vm_id, net_id)
242 self.assertEqual(self.client.http_client.url, self.url)
244 self.client.http_client.path,
245 '/networks/%s/action' % net_id)
248 ('post', '{"add": {"serverRef": %s}}' % vm_id, {}, {}))
250 @patch('%s.networks_post' % cyclades_pkg, return_value=FR())
251 def test_disconnect_server(self, NP):
252 vm_id = vm_recv['server']['id']
253 net_id = net_recv['network']['id']
254 nic_id = 'nic-%s-%s' % (net_id, vm_id)
256 dict(id=nic_id, network_id=net_id),
257 dict(id='another-nic-id', network_id='another-net-id'),
258 dict(id=nic_id * 2, network_id=net_id * 2)]
262 return_value=vm_nics) as LSN:
263 r = self.client.disconnect_server(vm_id, nic_id)
264 self.assertEqual(r, 1)
265 self.assertEqual(LSN.call_args[0], (vm_id,))
266 self.assertEqual(NP.call_args[0], (net_id, 'action'))
269 dict(json_data=dict(remove=dict(attachment=nic_id))))
271 @patch('%s.perform_request' % khttp, return_value=FR())
272 def test_list_server_nics(self, PR):
273 vm_id = vm_recv['server']['id']
274 nics = dict(addresses=dict(values=[dict(id='nic1'), dict(id='nic2')]))
276 r = self.client.list_server_nics(vm_id)
277 self.assertEqual(self.client.http_client.url, self.url)
279 self.client.http_client.path,
280 '/servers/%s/ips' % vm_id)
281 expected = nics['addresses']['values']
282 for i in range(len(r)):
283 self.assert_dicts_are_equal(r[i], expected[i])
285 @patch('%s.perform_request' % khttp, return_value=FR())
286 def test_list_networks(self, PR):
288 r = self.client.list_networks()
289 self.assertEqual(self.client.http_client.url, self.url)
290 self.assertEqual(self.client.http_client.path, '/networks')
291 expected = net_list['networks']['values']
292 for i in range(len(r)):
293 self.assert_dicts_are_equal(expected[i], r[i])
294 self.client.list_networks(detail=True)
295 self.assertEqual(self.client.http_client.url, self.url)
296 self.assertEqual(self.client.http_client.path, '/networks/detail')
298 @patch('%s.perform_request' % khttp, return_value=FR())
299 def test_list_network_nics(self, PR):
300 net_id = net_recv['network']['id']
302 r = self.client.list_network_nics(net_id)
303 self.assertEqual(self.client.http_client.url, self.url)
305 self.client.http_client.path,
306 '/networks/%s' % net_id)
307 expected = net_recv['network']['attachments']['values']
308 for i in range(len(r)):
309 self.assert_dicts_are_equal(r[i], expected[i])
311 @patch('%s.networks_post' % cyclades_pkg, return_value=FR())
312 def test_disconnect_network_nics(self, NP):
313 net_id = net_recv['network']['id']
314 nics = ['nic1', 'nic2', 'nic3']
318 return_value=nics) as lnn:
319 self.client.disconnect_network_nics(net_id)
320 lnn.assert_called_once_with(net_id)
321 for i in range(len(nics)):
322 expected = call(net_id, 'action', json_data=dict(
323 remove=dict(attachment=nics[i])))
324 self.assertEqual(expected, NP.mock_calls[i])
326 @patch('%s.perform_request' % khttp, return_value=FR())
327 def test_get_network_details(self, PR):
329 net_id = net_recv['network']['id']
330 r = self.client.get_network_details(net_id)
331 self.assertEqual(self.client.http_client.url, self.url)
333 self.client.http_client.path,
334 '/networks/%s' % net_id)
335 self.assert_dicts_are_equal(r, net_recv['network'])
337 @patch('%s.perform_request' % khttp, return_value=FR())
338 def test_update_network_name(self, PR):
339 net_id = net_recv['network']['id']
340 new_name = '%s_new' % net_id
342 self.client.update_network_name(net_id, new_name)
343 self.assertEqual(self.client.http_client.url, self.url)
344 self.assertEqual(self.client.http_client.path, '/networks/%s' % net_id)
345 (method, data, a_headers, a_params) = PR.call_args[0]
346 self.assert_dicts_are_equal(
347 dict(network=dict(name=new_name)),
350 @patch('%s.perform_request' % khttp, return_value=FR())
351 def test_delete_network(self, PR):
352 net_id = net_recv['network']['id']
354 self.client.delete_network(net_id)
355 self.assertEqual(self.client.http_client.url, self.url)
356 self.assertEqual(self.client.http_client.path, '/networks/%s' % net_id)
358 if __name__ == '__main__':
360 from kamaki.clients.test import runTestCase
361 runTestCase(Cyclades, 'Cyclades (multi) Client', argv[1:])