Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / cyclades / test.py @ 4e25b350

History | View | Annotate | Download (8.8 kB)

1
# Copyright 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
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.
15
#
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.
28
#
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

    
34
from mock import patch, call
35
from unittest import TestCase
36
from itertools import product
37
from json import dumps
38

    
39
from kamaki.clients import ClientError, cyclades
40

    
41
img_ref = "1m4g3-r3f3r3nc3"
42
vm_name = "my new VM"
43
fid = 42
44
vm_recv = dict(server=dict(
45
    status="BUILD",
46
    updated="2013-03-01T10:04:00.637152+00:00",
47
    hostId="",
48
    name=vm_name,
49
    imageRef=img_ref,
50
    created="2013-03-01T10:04:00.087324+00:00",
51
    flavorRef=fid,
52
    adminPass="n0n3sh@11p@55",
53
    suspended=False,
54
    progress=0,
55
    id=31173,
56
    metadata=dict(os="debian", users="root")))
57
vm_list = dict(servers=[
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(
62
    status="PENDING",
63
    updated="2013-03-05T15:04:51.758780+00:00",
64
    name="someNet",
65
    created="2013-03-05T15:04:51.758728+00:00",
66
    cidr6=None,
67
    id="2130",
68
    gateway6=None,
69
    public=False,
70
    dhcp=False,
71
    cidr="192.168.1.0/24",
72
    type="MAC_FILTERED",
73
    gateway=None,
74
    attachments=[dict(name='att1'), dict(name='att2')]))
75
net_list = dict(networks=[
76
    dict(id=1, name='n1'),
77
    dict(id=2, name='n2'),
78
    dict(id=3, name='n3')])
79
firewalls = dict(attachments=[
80
    dict(firewallProfile='50m3_pr0f1L3', otherStuff='57uff')])
81

    
82

    
83
class FR(object):
84
    """FR stands for Fake Response"""
85
    json = vm_recv
86
    headers = {}
87
    content = json
88
    status = None
89
    status_code = 200
90

    
91
rest_pkg = 'kamaki.clients.cyclades.CycladesRestClient'
92
cyclades_pkg = 'kamaki.clients.cyclades.CycladesClient'
93

    
94

    
95
class CycladesRestClient(TestCase):
96

    
97
    def setUp(self):
98
        self.url = 'http://cyclades.example.com'
99
        self.token = 'cyc14d3s70k3n'
100
        self.client = cyclades.CycladesRestClient(self.url, self.token)
101

    
102
    @patch('kamaki.clients.Client.get', return_value='ret')
103
    def test_servers_stats_get(self, get):
104
        server_id = 'server id'
105
        self.assertEqual(self.client.servers_stats_get(server_id), 'ret')
106
        get.assert_called_once_with(
107
            '/servers/%s/stats' % server_id, success=200)
108

    
109

    
110
class CycladesNetworkClient(TestCase):
111

    
112
    """Set up a ComputesRest thorough test"""
113
    def setUp(self):
114
        self.url = 'http://network.example.com'
115
        self.token = 'n2tw0rk70k3n'
116
        self.client = cyclades.CycladesNetworkClient(self.url, self.token)
117

    
118
    def tearDown(self):
119
        FR.json = vm_recv
120
        del self.client
121

    
122
    @patch('kamaki.clients.Client.get', return_value=FR)
123
    def test_list_networks(self, get):
124
        FR.json = dict(networks='ret val')
125
        for detail in (True, None):
126
            self.assertEqual(self.client.list_networks(detail), 'ret val')
127
            path = '/networks/detail' if detail else '/networks'
128
            self.assertEqual(get.mock_calls[-1], call(path, success=200))
129

    
130
    @patch(
131
        'kamaki.clients.network.rest_api.NetworkRestClient.networks_post',
132
        return_value=FR())
133
    def test_create_network(self, networks_post):
134
        for name, shared in product((None, 'net name'), (None, True)):
135
            FR.json = dict(network='ret val')
136
            type = 'net type'
137
            self.assertEqual(
138
                self.client.create_network(type, name=name, shared=shared),
139
                'ret val')
140
            req = dict(type=type, admin_state_up=True)
141
            if name:
142
                req['name'] = name
143
            if shared:
144
                req['shared'] = shared
145
            expargs = dict(json_data=dict(network=req), success=201)
146
            self.assertEqual(networks_post.mock_calls[-1], call(**expargs))
147

    
148
    @patch(
149
        'kamaki.clients.network.rest_api.NetworkRestClient.ports_post',
150
        return_value=FR)
151
    def test_create_port(self, ports_post):
152
        network_id, device_id, FR.json = 'netid', 'devid', dict(port='ret v')
153
        for name, sec_grp, fixed_ips in product(
154
                ('port name', None),
155
                ([1, 2, 3], None),
156
                (
157
                    [dict(subnet_id='sid', ip_address='ipa')],
158
                    [dict(subnet_id='sid')], [dict(ip_address='ipa')],
159
                    None)):
160

    
161
            if fixed_ips:
162
                diff = set(['ip_address', ]).difference(fixed_ips[0])
163
                if diff:
164
                    self.assertRaises(
165
                        ValueError, self.client.create_port,
166
                        network_id, device_id,
167
                        name=name,
168
                        security_groups=sec_grp,
169
                        fixed_ips=fixed_ips)
170
                    continue
171
            self.assertEqual(
172
                self.client.create_port(
173
                    network_id, device_id,
174
                    name=name, security_groups=sec_grp, fixed_ips=fixed_ips),
175
                'ret v')
176
            req = dict(network_id=network_id, device_id=device_id)
177
            if sec_grp:
178
                req['security_groups'] = sec_grp
179
            if name:
180
                req['name'] = name
181
            if fixed_ips:
182
                req['fixed_ips'] = fixed_ips
183
            expargs = dict(json_data=dict(port=req), success=201)
184
            self.assertEqual(ports_post.mock_calls[-1], call(**expargs))
185

    
186

    
187
class CycladesClient(TestCase):
188

    
189
    def assert_dicts_are_equal(self, d1, d2):
190
        for k, v in d1.items():
191
            self.assertTrue(k in d2)
192
            if isinstance(v, dict):
193
                self.assert_dicts_are_equal(v, d2[k])
194
            else:
195
                self.assertEqual(unicode(v), unicode(d2[k]))
196

    
197
    """Set up a Cyclades thorough test"""
198
    def setUp(self):
199
        self.url = 'http://cyclades.example.com'
200
        self.token = 'cyc14d3s70k3n'
201
        self.client = cyclades.CycladesClient(self.url, self.token)
202

    
203
    def tearDown(self):
204
        FR.status_code = 200
205
        FR.json = vm_recv
206

    
207
    @patch('%s.servers_action_post' % cyclades_pkg, return_value=FR())
208
    def test_shutdown_server(self, SP):
209
        vm_id = vm_recv['server']['id']
210
        self.client.shutdown_server(vm_id)
211
        SP.assert_called_once_with(
212
            vm_id, json_data=dict(shutdown=dict()), success=202)
213

    
214
    @patch('%s.servers_action_post' % cyclades_pkg, return_value=FR())
215
    def test_start_server(self, SP):
216
        vm_id = vm_recv['server']['id']
217
        self.client.start_server(vm_id)
218
        SP.assert_called_once_with(
219
            vm_id, json_data=dict(start=dict()), success=202)
220

    
221
    @patch('%s.servers_action_post' % cyclades_pkg, return_value=FR())
222
    def test_get_server_console(self, SP):
223
        cnsl = dict(console=dict(info1='i1', info2='i2', info3='i3'))
224
        FR.json = cnsl
225
        vm_id = vm_recv['server']['id']
226
        r = self.client.get_server_console(vm_id)
227
        SP.assert_called_once_with(
228
            vm_id, json_data=dict(console=dict(type='vnc')), success=200)
229
        self.assert_dicts_are_equal(r, cnsl['console'])
230

    
231

    
232
if __name__ == '__main__':
233
    from sys import argv
234
    from kamaki.clients.test import runTestCase
235
    not_found = True
236
    if not argv[1:] or argv[1] == 'CycladesClient':
237
        not_found = False
238
        runTestCase(CycladesNetworkClient, 'Cyclades Client', argv[2:])
239
    if not argv[1:] or argv[1] == 'CycladesNetworkClient':
240
        not_found = False
241
        runTestCase(CycladesNetworkClient, 'CycladesNetwork Client', argv[2:])
242
    if not argv[1:] or argv[1] == 'CycladesRestClient':
243
        not_found = False
244
        runTestCase(CycladesRestClient, 'CycladesRest Client', argv[2:])
245
    if not_found:
246
        print('TestCase %s not found' % argv[1])