Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / test / cyclades.py @ 27f04e4f

History | View | Annotate | Download (23.9 kB)

1 c1004a00 Stavros Sachtouris
# Copyright 2012-2013 GRNET S.A. All rights reserved.
2 c1004a00 Stavros Sachtouris
#
3 c1004a00 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 c1004a00 Stavros Sachtouris
# without modification, are permitted provided that the following
5 c1004a00 Stavros Sachtouris
# conditions are met:
6 c1004a00 Stavros Sachtouris
#
7 c1004a00 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 c1004a00 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 c1004a00 Stavros Sachtouris
#      disclaimer.
10 c1004a00 Stavros Sachtouris
#
11 c1004a00 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 c1004a00 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 c1004a00 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 c1004a00 Stavros Sachtouris
#      provided with the distribution.
15 c1004a00 Stavros Sachtouris
#
16 c1004a00 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 c1004a00 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 c1004a00 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 c1004a00 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 c1004a00 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 c1004a00 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 c1004a00 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 c1004a00 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 c1004a00 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 c1004a00 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 c1004a00 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 c1004a00 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 c1004a00 Stavros Sachtouris
#
29 c1004a00 Stavros Sachtouris
# The views and conclusions contained in the software and
30 c1004a00 Stavros Sachtouris
# documentation are those of the authors and should not be
31 c1004a00 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 c1004a00 Stavros Sachtouris
# or implied, of GRNET S.A.
33 03493855 Stavros Sachtouris
from mock import patch, Mock
34 03493855 Stavros Sachtouris
from unittest import TestCase
35 03493855 Stavros Sachtouris
from json import loads
36 03493855 Stavros Sachtouris
37 03493855 Stavros Sachtouris
from kamaki.clients import Client, ClientError
38 b3efa972 Stavros Sachtouris
from kamaki.clients.cyclades import CycladesClient
39 5ad6a119 Stavros Sachtouris
from kamaki.clients.cyclades_rest_api import CycladesClientApi
40 03493855 Stavros Sachtouris
41 03493855 Stavros Sachtouris
img_ref = "1m4g3-r3f3r3nc3"
42 03493855 Stavros Sachtouris
vm_name = "my new VM"
43 03493855 Stavros Sachtouris
fid = 42
44 03493855 Stavros Sachtouris
vm_send = dict(server=dict(
45 03493855 Stavros Sachtouris
    flavorRef=fid,
46 03493855 Stavros Sachtouris
    name=vm_name,
47 03493855 Stavros Sachtouris
    imageRef=img_ref,
48 03493855 Stavros Sachtouris
    metadata=dict(os="debian", users="root")))
49 03493855 Stavros Sachtouris
vm_recv = dict(server=dict(
50 03493855 Stavros Sachtouris
    status="BUILD",
51 03493855 Stavros Sachtouris
    updated="2013-03-01T10:04:00.637152+00:00",
52 03493855 Stavros Sachtouris
    hostId="",
53 5e194c99 Stavros Sachtouris
    name=vm_name,
54 5e194c99 Stavros Sachtouris
    imageRef=img_ref,
55 03493855 Stavros Sachtouris
    created="2013-03-01T10:04:00.087324+00:00",
56 03493855 Stavros Sachtouris
    flavorRef=fid,
57 03493855 Stavros Sachtouris
    adminPass="n0n3sh@11p@55",
58 03493855 Stavros Sachtouris
    suspended=False,
59 03493855 Stavros Sachtouris
    progress=0,
60 03493855 Stavros Sachtouris
    id=31173,
61 03493855 Stavros Sachtouris
    metadata=dict(values=dict(os="debian", users="root"))))
62 03493855 Stavros Sachtouris
img_recv = dict(image=dict(
63 03493855 Stavros Sachtouris
    status="ACTIVE",
64 03493855 Stavros Sachtouris
    updated="2013-02-26T11:10:14+00:00",
65 03493855 Stavros Sachtouris
    name="Debian Base",
66 03493855 Stavros Sachtouris
    created="2013-02-26T11:03:29+00:00",
67 03493855 Stavros Sachtouris
    progress=100,
68 03493855 Stavros Sachtouris
    id=img_ref,
69 03493855 Stavros Sachtouris
    metadata=dict(values=dict(
70 03493855 Stavros Sachtouris
        partition_table="msdos",
71 03493855 Stavros Sachtouris
        kernel="2.6.32",
72 03493855 Stavros Sachtouris
        osfamily="linux",
73 03493855 Stavros Sachtouris
        users="root",
74 03493855 Stavros Sachtouris
        gui="No GUI",
75 03493855 Stavros Sachtouris
        sortorder="1",
76 03493855 Stavros Sachtouris
        os="debian",
77 03493855 Stavros Sachtouris
        root_partition="1",
78 03493855 Stavros Sachtouris
        description="Debian 6.0.7 (Squeeze) Base System"))))
79 257b931a Stavros Sachtouris
vm_list = dict(servers=dict(values=[
80 257b931a Stavros Sachtouris
    dict(name='n1', id=1),
81 257b931a Stavros Sachtouris
    dict(name='n2', id=2)]))
82 8f5d38df Stavros Sachtouris
flavor_list = dict(flavors=dict(values=[
83 c24d4b5f Stavros Sachtouris
        dict(id=41, name="C1R1024D20"),
84 c24d4b5f Stavros Sachtouris
        dict(id=42, name="C1R1024D40"),
85 c701321b Stavros Sachtouris
        dict(id=43, name="C1R1028D20")]))
86 c701321b Stavros Sachtouris
img_list = dict(images=dict(values=[
87 c701321b Stavros Sachtouris
    dict(name="maelstrom", id="0fb03e45-7d5a-4515-bd4e-e6bbf6457f06"),
88 c701321b Stavros Sachtouris
    dict(name="edx_saas", id="1357163d-5fd8-488e-a117-48734c526206"),
89 c701321b Stavros Sachtouris
    dict(name="Debian_Wheezy_Base", id="1f8454f0-8e3e-4b6c-ab8e-5236b728dffe"),
90 c701321b Stavros Sachtouris
    dict(name="CentOS", id="21894b48-c805-4568-ac8b-7d4bb8eb533d"),
91 c701321b Stavros Sachtouris
    dict(name="Ubuntu Desktop", id="37bc522c-c479-4085-bfb9-464f9b9e2e31"),
92 c701321b Stavros Sachtouris
    dict(name="Ubuntu 12.10", id="3a24fef9-1a8c-47d1-8f11-e07bd5e544fd"),
93 c701321b Stavros Sachtouris
    dict(name="Debian Base", id="40ace203-6254-4e17-a5cb-518d55418a7d"),
94 c701321b Stavros Sachtouris
    dict(name="ubuntu_bundled", id="5336e265-5c7c-4127-95cb-2bf832a79903")]))
95 03493855 Stavros Sachtouris
96 03493855 Stavros Sachtouris
97 03493855 Stavros Sachtouris
class Cyclades(TestCase):
98 03493855 Stavros Sachtouris
99 257b931a Stavros Sachtouris
    def assert_dicts_are_equal(self, d1, d2):
100 03493855 Stavros Sachtouris
        for k, v in d1.items():
101 03493855 Stavros Sachtouris
            self.assertTrue(k in d2)
102 03493855 Stavros Sachtouris
            if isinstance(v, dict):
103 257b931a Stavros Sachtouris
                self.assert_dicts_are_equal(v, d2[k])
104 03493855 Stavros Sachtouris
            else:
105 03493855 Stavros Sachtouris
                self.assertEqual(unicode(v), unicode(d2[k]))
106 03493855 Stavros Sachtouris
107 03493855 Stavros Sachtouris
    class FR(object):
108 03493855 Stavros Sachtouris
        """FR stands for Fake Response"""
109 03493855 Stavros Sachtouris
        json = vm_recv
110 03493855 Stavros Sachtouris
        headers = {}
111 03493855 Stavros Sachtouris
        content = json
112 03493855 Stavros Sachtouris
        status = None
113 03493855 Stavros Sachtouris
        status_code = 200
114 03493855 Stavros Sachtouris
115 03493855 Stavros Sachtouris
        def release(self):
116 03493855 Stavros Sachtouris
            pass
117 c1004a00 Stavros Sachtouris
118 c1004a00 Stavros Sachtouris
    """Set up a Cyclades thorough test"""
119 c1004a00 Stavros Sachtouris
    def setUp(self):
120 03493855 Stavros Sachtouris
        self.url = 'http://cyclades.example.com'
121 03493855 Stavros Sachtouris
        self.token = 'cyc14d3s70k3n'
122 03493855 Stavros Sachtouris
        self.client = CycladesClient(self.url, self.token)
123 03493855 Stavros Sachtouris
        from kamaki.clients.connection.kamakicon import KamakiHTTPConnection
124 03493855 Stavros Sachtouris
        self.C = KamakiHTTPConnection
125 c1004a00 Stavros Sachtouris
126 c1004a00 Stavros Sachtouris
    def tearDown(self):
127 257b931a Stavros Sachtouris
        self.FR.status_code = 200
128 e5613073 Stavros Sachtouris
        self.FR.json = vm_recv
129 c1004a00 Stavros Sachtouris
130 c1004a00 Stavros Sachtouris
    def test_create_server(self):
131 03493855 Stavros Sachtouris
        self.client.get_image_details = Mock(return_value=img_recv['image'])
132 03493855 Stavros Sachtouris
        with patch.object(Client, 'request', side_effect=ClientError(
133 03493855 Stavros Sachtouris
                'REQUEST ENTITY TOO LARGE',
134 03493855 Stavros Sachtouris
                status=403)):
135 03493855 Stavros Sachtouris
            self.assertRaises(
136 03493855 Stavros Sachtouris
                ClientError,
137 03493855 Stavros Sachtouris
                self.client.create_server,
138 03493855 Stavros Sachtouris
                vm_name, fid, img_ref)
139 03493855 Stavros Sachtouris
140 03493855 Stavros Sachtouris
        with patch.object(
141 03493855 Stavros Sachtouris
                self.C,
142 03493855 Stavros Sachtouris
                'perform_request',
143 03493855 Stavros Sachtouris
                return_value=self.FR()) as perform_req:
144 03493855 Stavros Sachtouris
            self.assertRaises(
145 03493855 Stavros Sachtouris
                ClientError,
146 03493855 Stavros Sachtouris
                self.client.create_server,
147 03493855 Stavros Sachtouris
                vm_name, fid, img_ref)
148 03493855 Stavros Sachtouris
            self.FR.status_code = 202
149 03493855 Stavros Sachtouris
            r = self.client.create_server(vm_name, fid, img_ref)
150 03493855 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
151 03493855 Stavros Sachtouris
            self.assertEqual(self.client.http_client.path, '/servers')
152 03493855 Stavros Sachtouris
            (method, data, a_headers, a_params) = perform_req.call_args[0]
153 257b931a Stavros Sachtouris
            self.assert_dicts_are_equal(loads(data), vm_send)
154 257b931a Stavros Sachtouris
            self.assert_dicts_are_equal(r, vm_recv['server'])
155 03493855 Stavros Sachtouris
            prsn = 'Personality string (does not work with real servers)'
156 03493855 Stavros Sachtouris
            self.client.create_server(vm_name, fid, img_ref, prsn)
157 03493855 Stavros Sachtouris
            (method, data, a_headers, a_params) = perform_req.call_args[0]
158 03493855 Stavros Sachtouris
            data = loads(data)
159 03493855 Stavros Sachtouris
            self.assertTrue('personality' in data['server'])
160 03493855 Stavros Sachtouris
            self.assertEqual(prsn, data['server']['personality'])
161 c1004a00 Stavros Sachtouris
162 c1004a00 Stavros Sachtouris
    def test_list_servers(self):
163 257b931a Stavros Sachtouris
        self.FR.json = vm_list
164 257b931a Stavros Sachtouris
        with patch.object(
165 257b931a Stavros Sachtouris
                self.C,
166 257b931a Stavros Sachtouris
                'perform_request',
167 257b931a Stavros Sachtouris
                return_value=self.FR()) as perform_req:
168 257b931a Stavros Sachtouris
            r = self.client.list_servers()
169 257b931a Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
170 257b931a Stavros Sachtouris
            self.assertEqual(self.client.http_client.path, '/servers')
171 257b931a Stavros Sachtouris
            (method, data, a_headers, a_params) = perform_req.call_args[0]
172 257b931a Stavros Sachtouris
            self.assert_dicts_are_equal(dict(values=r), vm_list['servers'])
173 257b931a Stavros Sachtouris
            r = self.client.list_servers(detail=True)
174 257b931a Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
175 257b931a Stavros Sachtouris
            self.assertEqual(self.client.http_client.path, '/servers/detail')
176 257b931a Stavros Sachtouris
        with patch.object(
177 257b931a Stavros Sachtouris
                CycladesClientApi,
178 257b931a Stavros Sachtouris
                'servers_get',
179 257b931a Stavros Sachtouris
                return_value=self.FR()) as servers_get:
180 257b931a Stavros Sachtouris
            self.client.list_servers(changes_since=True)
181 257b931a Stavros Sachtouris
            self.assertTrue(servers_get.call_args[1]['changes_since'])
182 c1004a00 Stavros Sachtouris
183 e5613073 Stavros Sachtouris
    def test_get_server_details(self):
184 e5613073 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
185 e5613073 Stavros Sachtouris
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
186 e5613073 Stavros Sachtouris
            r = self.client.get_server_details(vm_id)
187 e5613073 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
188 e5613073 Stavros Sachtouris
            self.assertEqual(
189 e5613073 Stavros Sachtouris
                self.client.http_client.path,
190 e5613073 Stavros Sachtouris
                '/servers/%s' % vm_id)
191 e5613073 Stavros Sachtouris
            self.assert_dicts_are_equal(r, vm_recv['server'])
192 c1004a00 Stavros Sachtouris
193 5e194c99 Stavros Sachtouris
    def test_update_server_name(self):
194 5e194c99 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
195 5e194c99 Stavros Sachtouris
        new_name = vm_name + '_new'
196 5e194c99 Stavros Sachtouris
        self.FR.status_code = 204
197 5e194c99 Stavros Sachtouris
        with patch.object(
198 5e194c99 Stavros Sachtouris
                self.C,
199 5e194c99 Stavros Sachtouris
                'perform_request',
200 5e194c99 Stavros Sachtouris
                return_value=self.FR()) as perform_req:
201 5e194c99 Stavros Sachtouris
            self.client.update_server_name(vm_id, new_name)
202 5e194c99 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
203 5e194c99 Stavros Sachtouris
            self.assertEqual(
204 5e194c99 Stavros Sachtouris
                self.client.http_client.path,
205 5e194c99 Stavros Sachtouris
                '/servers/%s' % vm_id)
206 5e194c99 Stavros Sachtouris
            (method, data, a_headers, a_params) = perform_req.call_args[0]
207 5e194c99 Stavros Sachtouris
            self.assert_dicts_are_equal(
208 5e194c99 Stavros Sachtouris
                dict(server=dict(name=new_name)),
209 5e194c99 Stavros Sachtouris
                loads(data))
210 c1004a00 Stavros Sachtouris
211 c1004a00 Stavros Sachtouris
    def test_reboot_server(self):
212 e711efe2 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
213 e711efe2 Stavros Sachtouris
        self.FR.status_code = 202
214 e711efe2 Stavros Sachtouris
        with patch.object(
215 e711efe2 Stavros Sachtouris
                self.C,
216 e711efe2 Stavros Sachtouris
                'perform_request',
217 e711efe2 Stavros Sachtouris
                return_value=self.FR()) as perform_req:
218 e711efe2 Stavros Sachtouris
            self.client.reboot_server(vm_id)
219 e711efe2 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
220 e711efe2 Stavros Sachtouris
            self.assertEqual(
221 e711efe2 Stavros Sachtouris
                self.client.http_client.path,
222 e711efe2 Stavros Sachtouris
                '/servers/%s/action' % vm_id)
223 e711efe2 Stavros Sachtouris
            (method, data, a_headers, a_params) = perform_req.call_args[0]
224 e711efe2 Stavros Sachtouris
            self.assert_dicts_are_equal(
225 e711efe2 Stavros Sachtouris
                dict(reboot=dict(type='SOFT')),
226 e711efe2 Stavros Sachtouris
                loads(data))
227 c1004a00 Stavros Sachtouris
228 c1004a00 Stavros Sachtouris
    def test_create_server_metadata(self):
229 f1cab3a1 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
230 f1cab3a1 Stavros Sachtouris
        metadata = dict(m1='v1', m2='v2', m3='v3')
231 f1cab3a1 Stavros Sachtouris
        self.FR.json = dict(meta=vm_recv['server'])
232 774cc124 Stavros Sachtouris
        with patch.object(
233 774cc124 Stavros Sachtouris
                self.C,
234 774cc124 Stavros Sachtouris
                'perform_request',
235 774cc124 Stavros Sachtouris
                return_value=self.FR()) as perform_req:
236 f1cab3a1 Stavros Sachtouris
            self.assertRaises(
237 f1cab3a1 Stavros Sachtouris
                ClientError,
238 f1cab3a1 Stavros Sachtouris
                self.client.create_server_metadata,
239 f1cab3a1 Stavros Sachtouris
                vm_id, 'key', 'value')
240 774cc124 Stavros Sachtouris
            self.FR.status_code = 201
241 f1cab3a1 Stavros Sachtouris
            for k, v in metadata.items():
242 f1cab3a1 Stavros Sachtouris
                r = self.client.create_server_metadata(vm_id, k, v)
243 f1cab3a1 Stavros Sachtouris
                self.assertEqual(self.client.http_client.url, self.url)
244 f1cab3a1 Stavros Sachtouris
                self.assertEqual(
245 f1cab3a1 Stavros Sachtouris
                    self.client.http_client.path,
246 f1cab3a1 Stavros Sachtouris
                    '/servers/%s/meta/%s' % (vm_id, k))
247 774cc124 Stavros Sachtouris
                (method, data, a_headers, a_params) = perform_req.call_args[0]
248 774cc124 Stavros Sachtouris
                self.assertEqual(dict(meta={k: v}), loads(data))
249 f1cab3a1 Stavros Sachtouris
                self.assert_dicts_are_equal(r, vm_recv['server'])
250 c1004a00 Stavros Sachtouris
251 c1004a00 Stavros Sachtouris
    def test_get_server_metadata(self):
252 774cc124 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
253 774cc124 Stavros Sachtouris
        metadata = dict(m1='v1', m2='v2', m3='v3')
254 774cc124 Stavros Sachtouris
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
255 774cc124 Stavros Sachtouris
            self.FR.json = dict(metadata=dict(values=metadata))
256 774cc124 Stavros Sachtouris
            r = self.client.get_server_metadata(vm_id)
257 774cc124 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
258 774cc124 Stavros Sachtouris
            self.assertEqual(
259 774cc124 Stavros Sachtouris
                self.client.http_client.path,
260 774cc124 Stavros Sachtouris
                '/servers/%s/meta' % vm_id)
261 774cc124 Stavros Sachtouris
            self.assert_dicts_are_equal(r, metadata)
262 774cc124 Stavros Sachtouris
263 774cc124 Stavros Sachtouris
            for k, v in metadata.items():
264 774cc124 Stavros Sachtouris
                self.FR.json = dict(meta={k: v})
265 774cc124 Stavros Sachtouris
                r = self.client.get_server_metadata(vm_id, k)
266 774cc124 Stavros Sachtouris
                self.assertEqual(self.client.http_client.url, self.url)
267 774cc124 Stavros Sachtouris
                self.assertEqual(
268 774cc124 Stavros Sachtouris
                    self.client.http_client.path,
269 774cc124 Stavros Sachtouris
                    '/servers/%s/meta/%s' % (vm_id, k))
270 774cc124 Stavros Sachtouris
                self.assert_dicts_are_equal(r, {k: v})
271 c1004a00 Stavros Sachtouris
272 c1004a00 Stavros Sachtouris
    def test_update_server_metadata(self):
273 7bbaf88b Stavros Sachtouris
        vm_id = vm_recv['server']['id']
274 7bbaf88b Stavros Sachtouris
        metadata = dict(m1='v1', m2='v2', m3='v3')
275 7bbaf88b Stavros Sachtouris
        self.FR.json = dict(metadata=metadata)
276 7bbaf88b Stavros Sachtouris
        with patch.object(
277 7bbaf88b Stavros Sachtouris
                CycladesClientApi,
278 7bbaf88b Stavros Sachtouris
                'servers_post',
279 7bbaf88b Stavros Sachtouris
                return_value=self.FR()) as servers_post:
280 7bbaf88b Stavros Sachtouris
            r = self.client.update_server_metadata(vm_id, **metadata)
281 7bbaf88b Stavros Sachtouris
            self.assert_dicts_are_equal(r, metadata)
282 7bbaf88b Stavros Sachtouris
            (called_id, cmd) = servers_post.call_args[0]
283 7bbaf88b Stavros Sachtouris
            self.assertEqual(called_id, vm_id)
284 7bbaf88b Stavros Sachtouris
            self.assertEqual(cmd, 'meta')
285 7bbaf88b Stavros Sachtouris
            data = servers_post.call_args[1]['json_data']
286 7bbaf88b Stavros Sachtouris
            self.assert_dicts_are_equal(data, dict(metadata=metadata))
287 c1004a00 Stavros Sachtouris
288 c1004a00 Stavros Sachtouris
    def test_delete_server_metadata(self):
289 5ad6a119 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
290 5ad6a119 Stavros Sachtouris
        key = 'metakey'
291 5ad6a119 Stavros Sachtouris
        with patch.object(
292 5ad6a119 Stavros Sachtouris
                CycladesClientApi,
293 5ad6a119 Stavros Sachtouris
                'servers_delete',
294 5ad6a119 Stavros Sachtouris
                return_value=self.FR()) as servers_delete:
295 5ad6a119 Stavros Sachtouris
            self.client.delete_server_metadata(vm_id, key)
296 5ad6a119 Stavros Sachtouris
            self.assertEqual(
297 5ad6a119 Stavros Sachtouris
                (vm_id, 'meta/' + key),
298 5ad6a119 Stavros Sachtouris
                servers_delete.call_args[0])
299 c1004a00 Stavros Sachtouris
300 c1004a00 Stavros Sachtouris
    def test_list_flavors(self):
301 8f5d38df Stavros Sachtouris
        self.FR.json = flavor_list
302 8f5d38df Stavros Sachtouris
        with patch.object(
303 8f5d38df Stavros Sachtouris
                self.C,
304 8f5d38df Stavros Sachtouris
                'perform_request',
305 8f5d38df Stavros Sachtouris
                return_value=self.FR()) as perform_req:
306 8f5d38df Stavros Sachtouris
            r = self.client.list_flavors()
307 8f5d38df Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
308 8f5d38df Stavros Sachtouris
            self.assertEqual(self.client.http_client.path, '/flavors')
309 8f5d38df Stavros Sachtouris
            (method, data, a_headers, a_params) = perform_req.call_args[0]
310 8f5d38df Stavros Sachtouris
            self.assert_dicts_are_equal(dict(values=r), flavor_list['flavors'])
311 8f5d38df Stavros Sachtouris
            r = self.client.list_flavors(detail=True)
312 8f5d38df Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
313 8f5d38df Stavros Sachtouris
            self.assertEqual(self.client.http_client.path, '/flavors/detail')
314 c1004a00 Stavros Sachtouris
315 c1004a00 Stavros Sachtouris
    def test_get_flavor_details(self):
316 c24d4b5f Stavros Sachtouris
        self.FR.json = dict(flavor=flavor_list['flavors'])
317 c24d4b5f Stavros Sachtouris
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
318 c24d4b5f Stavros Sachtouris
            r = self.client.get_flavor_details(fid)
319 c24d4b5f Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
320 c24d4b5f Stavros Sachtouris
            self.assertEqual(
321 c24d4b5f Stavros Sachtouris
                self.client.http_client.path,
322 c24d4b5f Stavros Sachtouris
                '/flavors/%s' % fid)
323 c24d4b5f Stavros Sachtouris
            self.assert_dicts_are_equal(r, flavor_list['flavors'])
324 c1004a00 Stavros Sachtouris
325 c701321b Stavros Sachtouris
    def test_list_images(self):
326 c701321b Stavros Sachtouris
        self.FR.json = img_list
327 c701321b Stavros Sachtouris
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
328 c701321b Stavros Sachtouris
            r = self.client.list_images()
329 c701321b Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
330 c701321b Stavros Sachtouris
            self.assertEqual(self.client.http_client.path, '/images')
331 c701321b Stavros Sachtouris
            expected = img_list['images']['values']
332 c701321b Stavros Sachtouris
            for i in range(len(r)):
333 c701321b Stavros Sachtouris
                self.assert_dicts_are_equal(expected[i], r[i])
334 c701321b Stavros Sachtouris
            self.client.list_images(detail=True)
335 c701321b Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
336 c701321b Stavros Sachtouris
            self.assertEqual(self.client.http_client.path, '/images/detail')
337 c701321b Stavros Sachtouris
338 ff5334e4 Stavros Sachtouris
    def test_get_image_details(self):
339 ff5334e4 Stavros Sachtouris
        self.FR.json = img_recv
340 ff5334e4 Stavros Sachtouris
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
341 ff5334e4 Stavros Sachtouris
            r = self.client.get_image_details(img_ref)
342 ff5334e4 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
343 ff5334e4 Stavros Sachtouris
            self.assertEqual(
344 ff5334e4 Stavros Sachtouris
                self.client.http_client.path,
345 ff5334e4 Stavros Sachtouris
                '/images/%s' % img_ref)
346 ff5334e4 Stavros Sachtouris
            self.assert_dicts_are_equal(r, img_recv['image'])
347 c1004a00 Stavros Sachtouris
348 c1004a00 Stavros Sachtouris
    def test_get_image_metadata(self):
349 b3efa972 Stavros Sachtouris
        self.FR.json = dict(metadata=dict(values=img_recv['image']))
350 b3efa972 Stavros Sachtouris
        with patch.object(
351 b3efa972 Stavros Sachtouris
                CycladesClient,
352 b3efa972 Stavros Sachtouris
                'images_get',
353 b3efa972 Stavros Sachtouris
                return_value=self.FR()) as inner:
354 b3efa972 Stavros Sachtouris
            r = self.client.get_image_metadata(img_ref)
355 b3efa972 Stavros Sachtouris
            self.assertEqual(inner.call_args[0], ('%s' % img_ref, '/meta'))
356 b3efa972 Stavros Sachtouris
            self.assert_dicts_are_equal(img_recv['image'], r)
357 b3efa972 Stavros Sachtouris
            self.FR.json = dict(meta=img_recv['image'])
358 b3efa972 Stavros Sachtouris
            key = 'somekey'
359 b3efa972 Stavros Sachtouris
            self.client.get_image_metadata(img_ref, key)
360 b3efa972 Stavros Sachtouris
            self.assertEqual(
361 b3efa972 Stavros Sachtouris
                inner.call_args[0],
362 b3efa972 Stavros Sachtouris
                ('%s' % img_ref, '/meta/%s' % key))
363 c1004a00 Stavros Sachtouris
364 c1004a00 Stavros Sachtouris
    def test_shutdown_server(self):
365 386d82a1 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
366 386d82a1 Stavros Sachtouris
        self.FR.status_code = 202
367 386d82a1 Stavros Sachtouris
        with patch.object(
368 386d82a1 Stavros Sachtouris
                self.C,
369 386d82a1 Stavros Sachtouris
                'perform_request',
370 386d82a1 Stavros Sachtouris
                return_value=self.FR()) as perform_req:
371 386d82a1 Stavros Sachtouris
            self.client.shutdown_server(vm_id)
372 386d82a1 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
373 386d82a1 Stavros Sachtouris
            self.assertEqual(
374 386d82a1 Stavros Sachtouris
                self.client.http_client.path,
375 386d82a1 Stavros Sachtouris
                '/servers/%s/action' % vm_id)
376 386d82a1 Stavros Sachtouris
            self.assertEqual(
377 386d82a1 Stavros Sachtouris
                perform_req.call_args[0],
378 386d82a1 Stavros Sachtouris
                ('post',  '{"shutdown": {}}', {}, {}))
379 c1004a00 Stavros Sachtouris
380 2c987e80 Stavros Sachtouris
    def test_start_server(self):
381 2c987e80 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
382 2c987e80 Stavros Sachtouris
        self.FR.status_code = 202
383 2c987e80 Stavros Sachtouris
        with patch.object(
384 2c987e80 Stavros Sachtouris
                self.C,
385 2c987e80 Stavros Sachtouris
                'perform_request',
386 2c987e80 Stavros Sachtouris
                return_value=self.FR()) as perform_req:
387 2c987e80 Stavros Sachtouris
            self.client.start_server(vm_id)
388 2c987e80 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
389 2c987e80 Stavros Sachtouris
            self.assertEqual(
390 2c987e80 Stavros Sachtouris
                self.client.http_client.path,
391 2c987e80 Stavros Sachtouris
                '/servers/%s/action' % vm_id)
392 2c987e80 Stavros Sachtouris
            self.assertEqual(
393 2c987e80 Stavros Sachtouris
                perform_req.call_args[0],
394 2c987e80 Stavros Sachtouris
                ('post',  '{"start": {}}', {}, {}))
395 2c987e80 Stavros Sachtouris
396 c1004a00 Stavros Sachtouris
    def test_get_server_console(self):
397 33ebcd22 Stavros Sachtouris
        cnsl = dict(console=dict(info1='i1', info2='i2', info3='i3'))
398 33ebcd22 Stavros Sachtouris
        self.FR.json = cnsl
399 33ebcd22 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
400 33ebcd22 Stavros Sachtouris
        with patch.object(
401 33ebcd22 Stavros Sachtouris
                self.C,
402 33ebcd22 Stavros Sachtouris
                'perform_request',
403 33ebcd22 Stavros Sachtouris
                return_value=self.FR()) as perform_req:
404 33ebcd22 Stavros Sachtouris
            r = self.client.get_server_console(vm_id)
405 33ebcd22 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
406 33ebcd22 Stavros Sachtouris
            self.assertEqual(
407 33ebcd22 Stavros Sachtouris
                self.client.http_client.path,
408 33ebcd22 Stavros Sachtouris
                '/servers/%s/action' % vm_id)
409 33ebcd22 Stavros Sachtouris
            self.assert_dicts_are_equal(cnsl['console'], r)
410 33ebcd22 Stavros Sachtouris
            self.assertEqual(
411 33ebcd22 Stavros Sachtouris
                perform_req.call_args[0],
412 33ebcd22 Stavros Sachtouris
                ('post',  '{"console": {"type": "vnc"}}', {}, {}))
413 c1004a00 Stavros Sachtouris
414 c1004a00 Stavros Sachtouris
    def test_get_firewall_profile(self):
415 7d768bc6 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
416 7d768bc6 Stavros Sachtouris
        v = 'Some profile'
417 7d768bc6 Stavros Sachtouris
        ret = {'attachments': {'values': [{'firewallProfile': v, 1:1}]}}
418 7d768bc6 Stavros Sachtouris
        with patch.object(
419 7d768bc6 Stavros Sachtouris
                CycladesClient,
420 7d768bc6 Stavros Sachtouris
                'get_server_details',
421 7d768bc6 Stavros Sachtouris
                return_value=ret) as gsd:
422 7d768bc6 Stavros Sachtouris
            r = self.client.get_firewall_profile(vm_id)
423 7d768bc6 Stavros Sachtouris
            self.assertEqual(r, v)
424 7d768bc6 Stavros Sachtouris
            self.assertEqual(gsd.call_args[0], (vm_id,))
425 7d768bc6 Stavros Sachtouris
            ret['attachments']['values'][0].pop('firewallProfile')
426 7d768bc6 Stavros Sachtouris
            self.assertRaises(
427 27f04e4f Stavros Sachtouris
                ClientError, self.client.get_firewall_profile,
428 7d768bc6 Stavros Sachtouris
                vm_id)
429 c1004a00 Stavros Sachtouris
430 c1004a00 Stavros Sachtouris
    def test_set_firewall_profile(self):
431 278f2eb3 Stavros Sachtouris
        vm_id = vm_recv['server']['id']
432 278f2eb3 Stavros Sachtouris
        v = 'Some profile'
433 278f2eb3 Stavros Sachtouris
        self.FR.status_code = 202
434 278f2eb3 Stavros Sachtouris
        with patch.object(
435 278f2eb3 Stavros Sachtouris
                self.C,
436 278f2eb3 Stavros Sachtouris
                'perform_request',
437 278f2eb3 Stavros Sachtouris
                return_value=self.FR()) as perform_req:
438 278f2eb3 Stavros Sachtouris
            self.client.set_firewall_profile(vm_id, v)
439 278f2eb3 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
440 278f2eb3 Stavros Sachtouris
            self.assertEqual(
441 278f2eb3 Stavros Sachtouris
                self.client.http_client.path,
442 278f2eb3 Stavros Sachtouris
                '/servers/%s/action' % vm_id)
443 278f2eb3 Stavros Sachtouris
            self.assertEqual(perform_req.call_args[0], (
444 278f2eb3 Stavros Sachtouris
                'post',
445 278f2eb3 Stavros Sachtouris
                '{"firewallProfile": {"profile": "%s"}}' % v,
446 278f2eb3 Stavros Sachtouris
                {},
447 278f2eb3 Stavros Sachtouris
                {}))
448 c1004a00 Stavros Sachtouris
449 c1004a00 Stavros Sachtouris
    def test_get_server_stats(self):
450 27f04e4f Stavros Sachtouris
        vm_id = vm_recv['server']['id']
451 27f04e4f Stavros Sachtouris
        stats = dict(stat1='v1', stat2='v2', stat3='v3', stat4='v4')
452 27f04e4f Stavros Sachtouris
        self.FR.json = dict(stats=stats)
453 27f04e4f Stavros Sachtouris
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
454 27f04e4f Stavros Sachtouris
            r = self.client.get_server_stats(vm_id)
455 27f04e4f Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
456 27f04e4f Stavros Sachtouris
            self.assertEqual(
457 27f04e4f Stavros Sachtouris
                self.client.http_client.path,
458 27f04e4f Stavros Sachtouris
                '/servers/%s/stats' % vm_id)
459 27f04e4f Stavros Sachtouris
            self.assert_dicts_are_equal(stats, r)
460 c1004a00 Stavros Sachtouris
461 27f04e4f Stavros Sachtouris
    """
462 c1004a00 Stavros Sachtouris
    def test_create_network(self):
463 c1004a00 Stavros Sachtouris
        print('\twith no params')
464 c1004a00 Stavros Sachtouris
        self.network1 = self._create_network(self.netname1)
465 c1004a00 Stavros Sachtouris
        self._wait_for_network(self.network1['id'], 'ACTIVE')
466 c1004a00 Stavros Sachtouris
        n1id = self.network1['id']
467 c1004a00 Stavros Sachtouris
        self.network1 = self.client.get_network_details(n1id)
468 c1004a00 Stavros Sachtouris
        nets = self.client.list_networks(self.network1['id'])
469 c1004a00 Stavros Sachtouris
        chosen = [net for net in nets if net['id'] == n1id][0]
470 c1004a00 Stavros Sachtouris
        chosen.pop('updated')
471 c1004a00 Stavros Sachtouris
        net1 = dict(self.network1)
472 c1004a00 Stavros Sachtouris
        net1.pop('updated')
473 257b931a Stavros Sachtouris
        self.assert_dicts_are_equal(chosen, net1)
474 c1004a00 Stavros Sachtouris
        for param, val in dict(
475 c1004a00 Stavros Sachtouris
                cidr='192.168.0.0/24',
476 c1004a00 Stavros Sachtouris
                gateway='192.168.0.1',
477 c1004a00 Stavros Sachtouris
                type='MAC_FILTERED',
478 c1004a00 Stavros Sachtouris
                dhcp=True).items():
479 c1004a00 Stavros Sachtouris
            print('\tdelete %s to avoid max net limit' % n1id)
480 c1004a00 Stavros Sachtouris
            self._delete_network(n1id)
481 c1004a00 Stavros Sachtouris
            kwargs = {param: val}
482 c1004a00 Stavros Sachtouris
            print('\twith %s=%s' % (param, val))
483 c1004a00 Stavros Sachtouris
            self.network1 = self._create_network(self.netname1, **kwargs)
484 c1004a00 Stavros Sachtouris
            n1id = self.network1['id']
485 c1004a00 Stavros Sachtouris
            self._wait_for_network(n1id, 'ACTIVE')
486 c1004a00 Stavros Sachtouris
            self.network1 = self.client.get_network_details(n1id)
487 c1004a00 Stavros Sachtouris
            self.assertEqual(self.network1[param], val)
488 c1004a00 Stavros Sachtouris

489 c1004a00 Stavros Sachtouris
    def test_connect_server(self):
490 c1004a00 Stavros Sachtouris
        self.client.connect_server(self.server1['id'], self.network1['id'])
491 c1004a00 Stavros Sachtouris
        self.assertTrue(self._wait_for_nic(
492 c1004a00 Stavros Sachtouris
            self.network1['id'],
493 c1004a00 Stavros Sachtouris
            self.server1['id']))
494 c1004a00 Stavros Sachtouris

495 c1004a00 Stavros Sachtouris
    def test_disconnect_server(self):
496 c1004a00 Stavros Sachtouris
        self.client.disconnect_server(self.server1['id'], self.network1['id'])
497 c1004a00 Stavros Sachtouris
        self.assertTrue(self._wait_for_nic(
498 c1004a00 Stavros Sachtouris
            self.network1['id'],
499 c1004a00 Stavros Sachtouris
            self.server1['id'],
500 c1004a00 Stavros Sachtouris
            in_creation=False))
501 c1004a00 Stavros Sachtouris

502 c1004a00 Stavros Sachtouris
    def _test_0260_wait_for_second_network(self):
503 c1004a00 Stavros Sachtouris
        self.server1 = self._create_server(
504 c1004a00 Stavros Sachtouris
            self.servname1,
505 c1004a00 Stavros Sachtouris
            self.flavorid,
506 c1004a00 Stavros Sachtouris
            self.img)
507 c1004a00 Stavros Sachtouris
        self.network2 = self._create_network(self.netname2)
508 c1004a00 Stavros Sachtouris
        self._wait_for_status(self.server1['id'], 'BUILD')
509 c1004a00 Stavros Sachtouris
        self._wait_for_network(self.network2['id'], 'ACTIVE')
510 c1004a00 Stavros Sachtouris
        self._test_0280_list_server_nics()
511 c1004a00 Stavros Sachtouris

512 c1004a00 Stavros Sachtouris
    def _test_0280_list_server_nics(self):
513 c1004a00 Stavros Sachtouris
        r = self.client.list_server_nics(self.server1['id'])
514 c1004a00 Stavros Sachtouris
        len0 = len(r)
515 c1004a00 Stavros Sachtouris
        self.client.connect_server(self.server1['id'], self.network2['id'])
516 c1004a00 Stavros Sachtouris
        self.assertTrue(self._wait_for_nic(
517 c1004a00 Stavros Sachtouris
            self.network2['id'],
518 c1004a00 Stavros Sachtouris
            self.server1['id']))
519 c1004a00 Stavros Sachtouris
        r = self.client.list_server_nics(self.server1['id'])
520 c1004a00 Stavros Sachtouris
        self.assertTrue(len(r) > len0)
521 c1004a00 Stavros Sachtouris

522 c1004a00 Stavros Sachtouris
    def test_list_networks(self):
523 c1004a00 Stavros Sachtouris
        r = self.client.list_networks()
524 c1004a00 Stavros Sachtouris
        self.assertTrue(len(r) > 1)
525 c1004a00 Stavros Sachtouris
        ids = [net['id'] for net in r]
526 c1004a00 Stavros Sachtouris
        names = [net['name'] for net in r]
527 c1004a00 Stavros Sachtouris
        self.assertTrue('1' in ids)
528 c1004a00 Stavros Sachtouris
        #self.assertTrue('public' in names)
529 c1004a00 Stavros Sachtouris
        self.assertTrue(self.network1['id'] in ids)
530 c1004a00 Stavros Sachtouris
        self.assertTrue(self.network1['name'] in names)
531 c1004a00 Stavros Sachtouris

532 c1004a00 Stavros Sachtouris
        r = self.client.list_networks(detail=True)
533 c1004a00 Stavros Sachtouris
        ids = [net['id'] for net in r]
534 c1004a00 Stavros Sachtouris
        names = [net['name'] for net in r]
535 c1004a00 Stavros Sachtouris
        for net in r:
536 c1004a00 Stavros Sachtouris
            self.assertTrue(net['id'] in ids)
537 c1004a00 Stavros Sachtouris
            self.assertTrue(net['name'] in names)
538 c1004a00 Stavros Sachtouris
            for term in ('status', 'updated', 'created'):
539 c1004a00 Stavros Sachtouris
                self.assertTrue(term in net.keys())
540 c1004a00 Stavros Sachtouris

541 c1004a00 Stavros Sachtouris
    def test_get_network_details(self):
542 c1004a00 Stavros Sachtouris
        r = self.client.get_network_details(self.network1['id'])
543 c1004a00 Stavros Sachtouris
        net1 = dict(self.network1)
544 c1004a00 Stavros Sachtouris
        net1.pop('status')
545 c1004a00 Stavros Sachtouris
        net1.pop('updated', None)
546 c1004a00 Stavros Sachtouris
        net1.pop('attachments')
547 c1004a00 Stavros Sachtouris
        r.pop('status')
548 c1004a00 Stavros Sachtouris
        r.pop('updated', None)
549 c1004a00 Stavros Sachtouris
        r.pop('attachments')
550 257b931a Stavros Sachtouris
        self.assert_dicts_are_equal(net1, r)
551 c1004a00 Stavros Sachtouris

552 c1004a00 Stavros Sachtouris
    def test_update_network_name(self):
553 c1004a00 Stavros Sachtouris
        updated_name = self.netname2 + '_upd'
554 c1004a00 Stavros Sachtouris
        self.client.update_network_name(self.network2['id'], updated_name)
555 c1004a00 Stavros Sachtouris

556 c1004a00 Stavros Sachtouris
        def netwait(wait):
557 c1004a00 Stavros Sachtouris
            r = self.client.get_network_details(self.network2['id'])
558 c1004a00 Stavros Sachtouris
            if r['name'] == updated_name:
559 c1004a00 Stavros Sachtouris
                return
560 c1004a00 Stavros Sachtouris
            time.sleep(wait)
561 c1004a00 Stavros Sachtouris
        self.do_with_progress_bar(
562 c1004a00 Stavros Sachtouris
            netwait,
563 c1004a00 Stavros Sachtouris
            'Network %s name is changing:' % self.network2['id'],
564 c1004a00 Stavros Sachtouris
            self._waits[:5])
565 c1004a00 Stavros Sachtouris

566 c1004a00 Stavros Sachtouris
        r = self.client.get_network_details(self.network2['id'])
567 c1004a00 Stavros Sachtouris
        self.assertEqual(r['name'], updated_name)
568 c1004a00 Stavros Sachtouris

569 c1004a00 Stavros Sachtouris
    def test_delete_image(self):
570 c1004a00 Stavros Sachtouris
        images = self.client.list_images()
571 c1004a00 Stavros Sachtouris
        self.client.delete_image(images[2]['id'])
572 c1004a00 Stavros Sachtouris
        try:
573 c1004a00 Stavros Sachtouris
            r = self.client.get_image_details(images[2]['id'], success=(400))
574 c1004a00 Stavros Sachtouris
        except ClientError as err:
575 c1004a00 Stavros Sachtouris
            self.assertEqual(err.status, 404)
576 c1004a00 Stavros Sachtouris

577 c1004a00 Stavros Sachtouris
    def test_create_image_metadata(self):
578 c1004a00 Stavros Sachtouris
        r = self.client.create_image_metadata(self.img, 'mykey', 'myval')
579 c1004a00 Stavros Sachtouris
        self.assertEqual(r['mykey'], 'myval')
580 c1004a00 Stavros Sachtouris

581 c1004a00 Stavros Sachtouris
    def test_update_image_metadata(self):
582 c1004a00 Stavros Sachtouris
        r = self.client.create_image_metadata(self.img, 'mykey0', 'myval')
583 c1004a00 Stavros Sachtouris
        r = self.client.update_image_metadata(self.img, 'mykey0', 'myval0')
584 c1004a00 Stavros Sachtouris
        self.assertEqual(r['mykey0'], 'myval0')
585 c1004a00 Stavros Sachtouris

586 c1004a00 Stavros Sachtouris
    def test_delete_image_metadata(self):
587 c1004a00 Stavros Sachtouris
        self.client.create_image_metadata(self.img, 'mykey1', 'myval1')
588 c1004a00 Stavros Sachtouris
        self.client.delete_image_metadata(self.img, 'mykey1')
589 c1004a00 Stavros Sachtouris
        r = self.client.get_image_metadata(self.img)
590 c1004a00 Stavros Sachtouris
        self.assertNotEqual('mykey1' in r)
591 c1004a00 Stavros Sachtouris
    """