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.perform_request' % khttp, return_value=FR())
132 def test_shutdown_server(self, PR):
133 vm_id = vm_recv['server']['id']
135 self.client.shutdown_server(vm_id)
136 self.assertEqual(self.client.http_client.url, self.url)
138 self.client.http_client.path,
139 '/servers/%s/action' % vm_id)
142 ('post', '{"shutdown": {}}', {}, {}))
144 @patch('%s.perform_request' % khttp, return_value=FR())
145 def test_start_server(self, PR):
146 vm_id = vm_recv['server']['id']
148 self.client.start_server(vm_id)
149 self.assertEqual(self.client.http_client.url, self.url)
151 self.client.http_client.path,
152 '/servers/%s/action' % vm_id)
153 self.assertEqual(PR.call_args[0], ('post', '{"start": {}}', {}, {}))
155 @patch('%s.perform_request' % khttp, return_value=FR())
156 def test_get_server_console(self, PR):
157 cnsl = dict(console=dict(info1='i1', info2='i2', info3='i3'))
159 vm_id = vm_recv['server']['id']
160 r = self.client.get_server_console(vm_id)
161 self.assertEqual(self.client.http_client.url, self.url)
163 self.client.http_client.path,
164 '/servers/%s/action' % vm_id)
165 self.assert_dicts_are_equal(cnsl['console'], r)
168 ('post', '{"console": {"type": "vnc"}}', {}, {}))
170 def test_get_firewall_profile(self):
171 vm_id = vm_recv['server']['id']
173 ret = {'attachments': {'values': [{'firewallProfile': v, 1:1}]}}
176 'get_server_details',
177 return_value=ret) as GSD:
178 r = self.client.get_firewall_profile(vm_id)
179 self.assertEqual(r, v)
180 self.assertEqual(GSD.call_args[0], (vm_id,))
181 ret['attachments']['values'][0].pop('firewallProfile')
184 self.client.get_firewall_profile,
187 @patch('%s.perform_request' % khttp, return_value=FR())
188 def test_set_firewall_profile(self, PR):
189 vm_id = vm_recv['server']['id']
192 self.client.set_firewall_profile(vm_id, v)
193 self.assertEqual(self.client.http_client.url, self.url)
195 self.client.http_client.path,
196 '/servers/%s/action' % vm_id)
197 self.assertEqual(PR.call_args[0], (
199 '{"firewallProfile": {"profile": "%s"}}' % v,
203 @patch('%s.perform_request' % khttp, return_value=FR())
204 def test_get_server_stats(self, PR):
205 vm_id = vm_recv['server']['id']
206 stats = dict(stat1='v1', stat2='v2', stat3='v3', stat4='v4')
207 FR.json = dict(stats=stats)
208 r = self.client.get_server_stats(vm_id)
209 self.assertEqual(self.client.http_client.url, self.url)
211 self.client.http_client.path,
212 '/servers/%s/stats' % vm_id)
213 self.assert_dicts_are_equal(stats, r)
215 @patch('%s.perform_request' % khttp, return_value=FR())
216 def test_create_network(self, PR):
217 net_name = net_send['network']['name']
221 cidr='192.168.0.0/24',
222 gateway='192.168.0.1',
225 test_args = dict(full_args)
226 test_args.update(dict(empty=None, full=None))
227 for arg, val in test_args.items():
228 kwargs = {} if arg == 'empty' else full_args if (
229 arg == 'full') else {arg: val}
230 r = self.client.create_network(net_name, **kwargs)
231 self.assertEqual(self.client.http_client.url, self.url)
233 self.client.http_client.path,
235 self.assert_dicts_are_equal(r, net_recv['network'])
236 data = PR.call_args[0][1]
237 expected = dict(network=dict(net_send['network']))
238 expected['network'].update(kwargs)
239 self.assert_dicts_are_equal(loads(data), expected)
241 @patch('%s.perform_request' % khttp, return_value=FR())
242 def test_connect_server(self, PR):
243 vm_id = vm_recv['server']['id']
244 net_id = net_recv['network']['id']
246 self.client.connect_server(vm_id, net_id)
247 self.assertEqual(self.client.http_client.url, self.url)
249 self.client.http_client.path,
250 '/networks/%s/action' % net_id)
253 ('post', '{"add": {"serverRef": %s}}' % vm_id, {}, {}))
255 @patch('%s.networks_post' % cyclades_pkg, return_value=FR())
256 def test_disconnect_server(self, NP):
257 vm_id = vm_recv['server']['id']
258 net_id = net_recv['network']['id']
259 nic_id = 'nic-%s-%s' % (net_id, vm_id)
261 dict(id=nic_id, network_id=net_id),
262 dict(id='another-nic-id', network_id='another-net-id'),
263 dict(id=nic_id * 2, network_id=net_id * 2)]
267 return_value=vm_nics) as LSN:
268 r = self.client.disconnect_server(vm_id, nic_id)
269 self.assertEqual(r, 1)
270 self.assertEqual(LSN.call_args[0], (vm_id,))
271 self.assertEqual(NP.call_args[0], (net_id, 'action'))
274 dict(json_data=dict(remove=dict(attachment=nic_id))))
276 @patch('%s.perform_request' % khttp, return_value=FR())
277 def test_list_server_nics(self, PR):
278 vm_id = vm_recv['server']['id']
279 nics = dict(addresses=dict(values=[dict(id='nic1'), dict(id='nic2')]))
281 r = self.client.list_server_nics(vm_id)
282 self.assertEqual(self.client.http_client.url, self.url)
284 self.client.http_client.path,
285 '/servers/%s/ips' % vm_id)
286 expected = nics['addresses']['values']
287 for i in range(len(r)):
288 self.assert_dicts_are_equal(r[i], expected[i])
290 @patch('%s.perform_request' % khttp, return_value=FR())
291 def test_list_networks(self, PR):
293 r = self.client.list_networks()
294 self.assertEqual(self.client.http_client.url, self.url)
295 self.assertEqual(self.client.http_client.path, '/networks')
296 expected = net_list['networks']['values']
297 for i in range(len(r)):
298 self.assert_dicts_are_equal(expected[i], r[i])
299 self.client.list_networks(detail=True)
300 self.assertEqual(self.client.http_client.url, self.url)
301 self.assertEqual(self.client.http_client.path, '/networks/detail')
303 @patch('%s.perform_request' % khttp, return_value=FR())
304 def test_list_network_nics(self, PR):
305 net_id = net_recv['network']['id']
307 r = self.client.list_network_nics(net_id)
308 self.assertEqual(self.client.http_client.url, self.url)
310 self.client.http_client.path,
311 '/networks/%s' % net_id)
312 expected = net_recv['network']['attachments']['values']
313 for i in range(len(r)):
314 self.assert_dicts_are_equal(r[i], expected[i])
316 @patch('%s.networks_post' % cyclades_pkg, return_value=FR())
317 def test_disconnect_network_nics(self, NP):
318 net_id = net_recv['network']['id']
319 nics = ['nic1', 'nic2', 'nic3']
323 return_value=nics) as lnn:
324 self.client.disconnect_network_nics(net_id)
325 lnn.assert_called_once_with(net_id)
326 for i in range(len(nics)):
327 expected = call(net_id, 'action', json_data=dict(
328 remove=dict(attachment=nics[i])))
329 self.assertEqual(expected, NP.mock_calls[i])
331 @patch('%s.perform_request' % khttp, return_value=FR())
332 def test_get_network_details(self, PR):
334 net_id = net_recv['network']['id']
335 r = self.client.get_network_details(net_id)
336 self.assertEqual(self.client.http_client.url, self.url)
338 self.client.http_client.path,
339 '/networks/%s' % net_id)
340 self.assert_dicts_are_equal(r, net_recv['network'])
342 @patch('%s.perform_request' % khttp, return_value=FR())
343 def test_update_network_name(self, PR):
344 net_id = net_recv['network']['id']
345 new_name = '%s_new' % net_id
347 self.client.update_network_name(net_id, new_name)
348 self.assertEqual(self.client.http_client.url, self.url)
349 self.assertEqual(self.client.http_client.path, '/networks/%s' % net_id)
350 (method, data, a_headers, a_params) = PR.call_args[0]
351 self.assert_dicts_are_equal(
352 dict(network=dict(name=new_name)),
355 @patch('%s.perform_request' % khttp, return_value=FR())
356 def test_delete_network(self, PR):
357 net_id = net_recv['network']['id']
359 self.client.delete_network(net_id)
360 self.assertEqual(self.client.http_client.url, self.url)
361 self.assertEqual(self.client.http_client.path, '/networks/%s' % net_id)
363 if __name__ == '__main__':
365 from kamaki.clients.test import runTestCase
366 runTestCase(Cyclades, 'Cyclades (multi) Client', argv[1:])