summaryrefslogtreecommitdiff
path: root/novaclient/tests/unit/v2
diff options
context:
space:
mode:
Diffstat (limited to 'novaclient/tests/unit/v2')
-rw-r--r--novaclient/tests/unit/v2/__init__.py0
-rw-r--r--novaclient/tests/unit/v2/contrib/__init__.py0
-rw-r--r--novaclient/tests/unit/v2/contrib/fakes.py151
-rw-r--r--novaclient/tests/unit/v2/contrib/test_assisted_volume_snapshots.py42
-rw-r--r--novaclient/tests/unit/v2/contrib/test_baremetal.py64
-rw-r--r--novaclient/tests/unit/v2/contrib/test_cells.py42
-rw-r--r--novaclient/tests/unit/v2/contrib/test_instance_actions.py43
-rw-r--r--novaclient/tests/unit/v2/contrib/test_list_extensions.py33
-rw-r--r--novaclient/tests/unit/v2/contrib/test_migrations.py40
-rw-r--r--novaclient/tests/unit/v2/contrib/test_server_external_events.py44
-rw-r--r--novaclient/tests/unit/v2/contrib/test_tenant_networks.py46
-rw-r--r--novaclient/tests/unit/v2/fakes.py2211
-rw-r--r--novaclient/tests/unit/v2/test_agents.py104
-rw-r--r--novaclient/tests/unit/v2/test_aggregates.py141
-rw-r--r--novaclient/tests/unit/v2/test_auth.py386
-rw-r--r--novaclient/tests/unit/v2/test_availability_zone.py102
-rw-r--r--novaclient/tests/unit/v2/test_certs.py36
-rw-r--r--novaclient/tests/unit/v2/test_client.py45
-rw-r--r--novaclient/tests/unit/v2/test_cloudpipe.py45
-rw-r--r--novaclient/tests/unit/v2/test_fixed_ips.py44
-rw-r--r--novaclient/tests/unit/v2/test_flavor_access.py70
-rw-r--r--novaclient/tests/unit/v2/test_flavors.py219
-rw-r--r--novaclient/tests/unit/v2/test_floating_ip_dns.py91
-rw-r--r--novaclient/tests/unit/v2/test_floating_ip_pools.py32
-rw-r--r--novaclient/tests/unit/v2/test_floating_ips.py59
-rw-r--r--novaclient/tests/unit/v2/test_floating_ips_bulk.py64
-rw-r--r--novaclient/tests/unit/v2/test_fping.py62
-rw-r--r--novaclient/tests/unit/v2/test_hosts.py84
-rw-r--r--novaclient/tests/unit/v2/test_hypervisors.py178
-rw-r--r--novaclient/tests/unit/v2/test_images.py66
-rw-r--r--novaclient/tests/unit/v2/test_keypairs.py64
-rw-r--r--novaclient/tests/unit/v2/test_limits.py88
-rw-r--r--novaclient/tests/unit/v2/test_networks.py106
-rw-r--r--novaclient/tests/unit/v2/test_quota_classes.py42
-rw-r--r--novaclient/tests/unit/v2/test_quotas.py62
-rw-r--r--novaclient/tests/unit/v2/test_security_group_rules.py89
-rw-r--r--novaclient/tests/unit/v2/test_security_groups.py76
-rw-r--r--novaclient/tests/unit/v2/test_server_groups.py59
-rw-r--r--novaclient/tests/unit/v2/test_servers.py704
-rw-r--r--novaclient/tests/unit/v2/test_services.py99
-rw-r--r--novaclient/tests/unit/v2/test_shell.py2455
-rw-r--r--novaclient/tests/unit/v2/test_usage.py57
-rw-r--r--novaclient/tests/unit/v2/test_volumes.py93
-rw-r--r--novaclient/tests/unit/v2/testfile.txt1
-rw-r--r--novaclient/tests/unit/v2/utils.py42
45 files changed, 8581 insertions, 0 deletions
diff --git a/novaclient/tests/unit/v2/__init__.py b/novaclient/tests/unit/v2/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/novaclient/tests/unit/v2/__init__.py
diff --git a/novaclient/tests/unit/v2/contrib/__init__.py b/novaclient/tests/unit/v2/contrib/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/novaclient/tests/unit/v2/contrib/__init__.py
diff --git a/novaclient/tests/unit/v2/contrib/fakes.py b/novaclient/tests/unit/v2/contrib/fakes.py
new file mode 100644
index 0000000..8703395
--- /dev/null
+++ b/novaclient/tests/unit/v2/contrib/fakes.py
@@ -0,0 +1,151 @@
1# Copyright 2012 OpenStack Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from novaclient.tests.unit.v2 import fakes
16from novaclient.v2 import client
17
18
19class FakeClient(fakes.FakeClient):
20 def __init__(self, *args, **kwargs):
21 client.Client.__init__(self, 'username', 'password',
22 'project_id', 'auth_url',
23 extensions=kwargs.get('extensions'))
24 self.client = FakeHTTPClient(**kwargs)
25
26
27class FakeHTTPClient(fakes.FakeHTTPClient):
28 def get_os_tenant_networks(self):
29 return (200, {}, {
30 'networks': [{"label": "1", "cidr": "10.0.0.0/24",
31 'project_id': '4ffc664c198e435e9853f2538fbcd7a7',
32 'id': '1'}]})
33
34 def get_os_tenant_networks_1(self, **kw):
35 return (200, {}, {
36 'network': {"label": "1", "cidr": "10.0.0.0/24",
37 'project_id': '4ffc664c198e435e9853f2538fbcd7a7',
38 'id': '1'}})
39
40 def post_os_tenant_networks(self, **kw):
41 return (201, {}, {
42 'network': {"label": "1", "cidr": "10.0.0.0/24",
43 'project_id': '4ffc664c198e435e9853f2538fbcd7a7',
44 'id': '1'}})
45
46 def delete_os_tenant_networks_1(self, **kw):
47 return (204, {}, None)
48
49 def get_os_baremetal_nodes(self, **kw):
50 return (
51 200, {}, {
52 'nodes': [
53 {
54 "id": 1,
55 "instance_uuid": None,
56 "interfaces": [],
57 "cpus": 2,
58 "local_gb": 10,
59 "memory_mb": 5,
60 "pm_address": "2.3.4.5",
61 "pm_user": "pmuser",
62 "pm_password": "pmpass",
63 "prov_mac_address": "aa:bb:cc:dd:ee:ff",
64 "prov_vlan_id": 1,
65 "service_host": "somehost",
66 "terminal_port": 8080,
67 }
68 ]
69 }
70 )
71
72 def get_os_baremetal_nodes_1(self, **kw):
73 return (
74 200, {}, {
75 'node': {
76 "id": 1,
77 "instance_uuid": None,
78 "pm_address": "1.2.3.4",
79 "interfaces": [],
80 "cpus": 2,
81 "local_gb": 10,
82 "memory_mb": 5,
83 "pm_user": "pmuser",
84 "pm_password": "pmpass",
85 "prov_mac_address": "aa:bb:cc:dd:ee:ff",
86 "prov_vlan_id": 1,
87 "service_host": "somehost",
88 "terminal_port": 8080,
89 }
90 }
91 )
92
93 def post_os_baremetal_nodes(self, **kw):
94 return (
95 200, {}, {
96 'node': {
97 "id": 1,
98 "instance_uuid": None,
99 "cpus": 2,
100 "local_gb": 10,
101 "memory_mb": 5,
102 "pm_address": "2.3.4.5",
103 "pm_user": "pmuser",
104 "pm_password": "pmpass",
105 "prov_mac_address": "aa:bb:cc:dd:ee:ff",
106 "prov_vlan_id": 1,
107 "service_host": "somehost",
108 "terminal_port": 8080,
109 }
110 }
111 )
112
113 def delete_os_baremetal_nodes_1(self, **kw):
114 return (202, {}, {})
115
116 def post_os_baremetal_nodes_1_action(self, **kw):
117 body = kw['body']
118 action = list(body)[0]
119 if action == "add_interface":
120 return (
121 200, {}, {
122 'interface': {
123 "id": 2,
124 "address": "bb:cc:dd:ee:ff:aa",
125 "datapath_id": 1,
126 "port_no": 2,
127 }
128 }
129 )
130 elif action == "remove_interface":
131 return (202, {}, {})
132 else:
133 return (500, {}, {})
134
135 def post_os_assisted_volume_snapshots(self, **kw):
136 return (202, {}, {'snapshot': {'id': 'blah', 'volumeId': '1'}})
137
138 def delete_os_assisted_volume_snapshots_x(self, **kw):
139 return (202, {}, {})
140
141 def post_os_server_external_events(self, **kw):
142 return (200, {}, {
143 'events': [
144 {'name': 'test-event',
145 'status': 'completed',
146 'tag': 'tag',
147 'server_uuid': 'fake-uuid1'},
148 {'name': 'test-event',
149 'status': 'completed',
150 'tag': 'tag',
151 'server_uuid': 'fake-uuid2'}]})
diff --git a/novaclient/tests/unit/v2/contrib/test_assisted_volume_snapshots.py b/novaclient/tests/unit/v2/contrib/test_assisted_volume_snapshots.py
new file mode 100644
index 0000000..8ab732a
--- /dev/null
+++ b/novaclient/tests/unit/v2/contrib/test_assisted_volume_snapshots.py
@@ -0,0 +1,42 @@
1# Copyright (C) 2013, Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15"""
16Assisted volume snapshots - to be used by Cinder and not end users.
17"""
18
19from novaclient import extension
20from novaclient.tests.unit import utils
21from novaclient.tests.unit.v2.contrib import fakes
22from novaclient.v2.contrib import assisted_volume_snapshots as assisted_snaps
23
24
25extensions = [
26 extension.Extension(assisted_snaps.__name__.split(".")[-1],
27 assisted_snaps),
28]
29cs = fakes.FakeClient(extensions=extensions)
30
31
32class AssistedVolumeSnapshotsTestCase(utils.TestCase):
33
34 def test_create_snap(self):
35 cs.assisted_volume_snapshots.create('1', {})
36 cs.assert_called('POST', '/os-assisted-volume-snapshots')
37
38 def test_delete_snap(self):
39 cs.assisted_volume_snapshots.delete('x', {})
40 cs.assert_called(
41 'DELETE',
42 '/os-assisted-volume-snapshots/x?delete_info={}')
diff --git a/novaclient/tests/unit/v2/contrib/test_baremetal.py b/novaclient/tests/unit/v2/contrib/test_baremetal.py
new file mode 100644
index 0000000..a5ee414
--- /dev/null
+++ b/novaclient/tests/unit/v2/contrib/test_baremetal.py
@@ -0,0 +1,64 @@
1# Copyright 2013 Hewlett-Packard Development Company, L.P.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16
17from novaclient import extension
18from novaclient.tests.unit import utils
19from novaclient.tests.unit.v2.contrib import fakes
20from novaclient.v2.contrib import baremetal
21
22
23extensions = [
24 extension.Extension(baremetal.__name__.split(".")[-1], baremetal),
25]
26cs = fakes.FakeClient(extensions=extensions)
27
28
29class BaremetalExtensionTest(utils.TestCase):
30
31 def test_list_nodes(self):
32 nl = cs.baremetal.list()
33 cs.assert_called('GET', '/os-baremetal-nodes')
34 for n in nl:
35 self.assertIsInstance(n, baremetal.BareMetalNode)
36
37 def test_get_node(self):
38 n = cs.baremetal.get(1)
39 cs.assert_called('GET', '/os-baremetal-nodes/1')
40 self.assertIsInstance(n, baremetal.BareMetalNode)
41
42 def test_create_node(self):
43 n = cs.baremetal.create("service_host", 1, 1024, 2048,
44 "aa:bb:cc:dd:ee:ff")
45 cs.assert_called('POST', '/os-baremetal-nodes')
46 self.assertIsInstance(n, baremetal.BareMetalNode)
47
48 def test_delete_node(self):
49 n = cs.baremetal.get(1)
50 cs.baremetal.delete(n)
51 cs.assert_called('DELETE', '/os-baremetal-nodes/1')
52
53 def test_node_add_interface(self):
54 i = cs.baremetal.add_interface(1, "bb:cc:dd:ee:ff:aa", 1, 2)
55 cs.assert_called('POST', '/os-baremetal-nodes/1/action')
56 self.assertIsInstance(i, baremetal.BareMetalNodeInterface)
57
58 def test_node_remove_interface(self):
59 cs.baremetal.remove_interface(1, "bb:cc:dd:ee:ff:aa")
60 cs.assert_called('POST', '/os-baremetal-nodes/1/action')
61
62 def test_node_list_interfaces(self):
63 cs.baremetal.list_interfaces(1)
64 cs.assert_called('GET', '/os-baremetal-nodes/1')
diff --git a/novaclient/tests/unit/v2/contrib/test_cells.py b/novaclient/tests/unit/v2/contrib/test_cells.py
new file mode 100644
index 0000000..e411502
--- /dev/null
+++ b/novaclient/tests/unit/v2/contrib/test_cells.py
@@ -0,0 +1,42 @@
1# Copyright 2013 Rackspace Hosting
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient import extension
17from novaclient.tests.unit import utils
18from novaclient.tests.unit.v2.contrib import fakes
19from novaclient.v2.contrib import cells
20
21
22extensions = [
23 extension.Extension(cells.__name__.split(".")[-1],
24 cells),
25]
26cs = fakes.FakeClient(extensions=extensions)
27
28
29class CellsExtensionTests(utils.TestCase):
30 def test_get_cells(self):
31 cell_name = 'child_cell'
32 cs.cells.get(cell_name)
33 cs.assert_called('GET', '/os-cells/%s' % cell_name)
34
35 def test_get_capacities_for_a_given_cell(self):
36 cell_name = 'child_cell'
37 cs.cells.capacities(cell_name)
38 cs.assert_called('GET', '/os-cells/%s/capacities' % cell_name)
39
40 def test_get_capacities_for_all_cells(self):
41 cs.cells.capacities()
42 cs.assert_called('GET', '/os-cells/capacities')
diff --git a/novaclient/tests/unit/v2/contrib/test_instance_actions.py b/novaclient/tests/unit/v2/contrib/test_instance_actions.py
new file mode 100644
index 0000000..0b0400a
--- /dev/null
+++ b/novaclient/tests/unit/v2/contrib/test_instance_actions.py
@@ -0,0 +1,43 @@
1# Copyright 2013 Rackspace Hosting
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient import extension
17from novaclient.tests.unit import utils
18from novaclient.tests.unit.v2.contrib import fakes
19from novaclient.v2.contrib import instance_action
20
21
22extensions = [
23 extension.Extension(instance_action.__name__.split(".")[-1],
24 instance_action),
25]
26cs = fakes.FakeClient(extensions=extensions)
27
28
29class InstanceActionExtensionTests(utils.TestCase):
30 def test_list_instance_actions(self):
31 server_uuid = '1234'
32 cs.instance_action.list(server_uuid)
33 cs.assert_called(
34 'GET', '/servers/%s/os-instance-actions' %
35 server_uuid)
36
37 def test_get_instance_action(self):
38 server_uuid = '1234'
39 request_id = 'req-abcde12345'
40 cs.instance_action.get(server_uuid, request_id)
41 cs.assert_called(
42 'GET', '/servers/%s/os-instance-actions/%s'
43 % (server_uuid, request_id))
diff --git a/novaclient/tests/unit/v2/contrib/test_list_extensions.py b/novaclient/tests/unit/v2/contrib/test_list_extensions.py
new file mode 100644
index 0000000..3fa5253
--- /dev/null
+++ b/novaclient/tests/unit/v2/contrib/test_list_extensions.py
@@ -0,0 +1,33 @@
1#
2# Licensed under the Apache License, Version 2.0 (the "License"); you may
3# not use this file except in compliance with the License. You may obtain
4# a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11# License for the specific language governing permissions and limitations
12# under the License.
13
14from novaclient import extension
15from novaclient.tests.unit import utils
16from novaclient.tests.unit.v2 import fakes
17from novaclient.v2.contrib import list_extensions
18
19
20extensions = [
21 extension.Extension(list_extensions.__name__.split(".")[-1],
22 list_extensions),
23]
24cs = fakes.FakeClient(extensions=extensions)
25
26
27class ListExtensionsTests(utils.TestCase):
28 def test_list_extensions(self):
29 all_exts = cs.list_extensions.show_all()
30 cs.assert_called('GET', '/extensions')
31 self.assertTrue(len(all_exts) > 0)
32 for r in all_exts:
33 self.assertTrue(len(r.summary) > 0)
diff --git a/novaclient/tests/unit/v2/contrib/test_migrations.py b/novaclient/tests/unit/v2/contrib/test_migrations.py
new file mode 100644
index 0000000..881fd1e
--- /dev/null
+++ b/novaclient/tests/unit/v2/contrib/test_migrations.py
@@ -0,0 +1,40 @@
1# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13from novaclient import extension
14from novaclient.tests.unit import utils
15from novaclient.tests.unit.v2 import fakes
16from novaclient.v2.contrib import migrations
17
18extensions = [
19 extension.Extension(migrations.__name__.split(".")[-1],
20 migrations),
21]
22cs = fakes.FakeClient(extensions=extensions)
23
24
25class MigrationsTest(utils.TestCase):
26
27 def test_list_migrations(self):
28 ml = cs.migrations.list()
29 cs.assert_called('GET', '/os-migrations')
30 for m in ml:
31 self.assertIsInstance(m, migrations.Migration)
32
33 def test_list_migrations_with_filters(self):
34 ml = cs.migrations.list('host1', 'finished', 'child1')
35
36 cs.assert_called('GET',
37 '/os-migrations?cell_name=child1&host=host1'
38 '&status=finished')
39 for m in ml:
40 self.assertIsInstance(m, migrations.Migration)
diff --git a/novaclient/tests/unit/v2/contrib/test_server_external_events.py b/novaclient/tests/unit/v2/contrib/test_server_external_events.py
new file mode 100644
index 0000000..1b941c9
--- /dev/null
+++ b/novaclient/tests/unit/v2/contrib/test_server_external_events.py
@@ -0,0 +1,44 @@
1# Copyright (C) 2014, Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15"""
16External event triggering for servers, not to be used by users.
17"""
18
19from novaclient import extension
20from novaclient.tests.unit import utils
21from novaclient.tests.unit.v2.contrib import fakes
22from novaclient.v2.contrib import server_external_events as ext_events
23
24
25extensions = [
26 extension.Extension(ext_events.__name__.split(".")[-1],
27 ext_events),
28]
29cs = fakes.FakeClient(extensions=extensions)
30
31
32class ServerExternalEventsTestCase(utils.TestCase):
33 def test_external_event(self):
34 events = [{'server_uuid': 'fake-uuid1',
35 'name': 'test-event',
36 'status': 'completed',
37 'tag': 'tag'},
38 {'server_uuid': 'fake-uuid2',
39 'name': 'test-event',
40 'status': 'completed',
41 'tag': 'tag'}]
42 result = cs.server_external_events.create(events)
43 self.assertEqual(events, result)
44 cs.assert_called('POST', '/os-server-external-events')
diff --git a/novaclient/tests/unit/v2/contrib/test_tenant_networks.py b/novaclient/tests/unit/v2/contrib/test_tenant_networks.py
new file mode 100644
index 0000000..13159ce
--- /dev/null
+++ b/novaclient/tests/unit/v2/contrib/test_tenant_networks.py
@@ -0,0 +1,46 @@
1# Copyright 2012 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient import extension
17from novaclient.tests.unit import utils
18from novaclient.tests.unit.v2.contrib import fakes
19from novaclient.v2.contrib import tenant_networks
20
21
22extensions = [
23 extension.Extension(tenant_networks.__name__.split(".")[-1],
24 tenant_networks),
25]
26cs = fakes.FakeClient(extensions=extensions)
27
28
29class TenantNetworkExtensionTests(utils.TestCase):
30 def test_list_tenant_networks(self):
31 nets = cs.tenant_networks.list()
32 cs.assert_called('GET', '/os-tenant-networks')
33 self.assertTrue(len(nets) > 0)
34
35 def test_get_tenant_network(self):
36 cs.tenant_networks.get(1)
37 cs.assert_called('GET', '/os-tenant-networks/1')
38
39 def test_create_tenant_networks(self):
40 cs.tenant_networks.create(label="net",
41 cidr="10.0.0.0/24")
42 cs.assert_called('POST', '/os-tenant-networks')
43
44 def test_delete_tenant_networks(self):
45 cs.tenant_networks.delete(1)
46 cs.assert_called('DELETE', '/os-tenant-networks/1')
diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py
new file mode 100644
index 0000000..68322a1
--- /dev/null
+++ b/novaclient/tests/unit/v2/fakes.py
@@ -0,0 +1,2211 @@
1# Copyright (c) 2011 X.commerce, a business unit of eBay Inc.
2# Copyright 2011 OpenStack Foundation
3# Copyright 2013 IBM Corp.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import datetime
18
19import mock
20from oslo.utils import strutils
21import six
22from six.moves.urllib import parse
23
24from novaclient import client as base_client
25from novaclient import exceptions
26from novaclient.tests.unit import fakes
27from novaclient.tests.unit import utils
28from novaclient.v2 import client
29
30
31class FakeClient(fakes.FakeClient, client.Client):
32
33 def __init__(self, *args, **kwargs):
34 client.Client.__init__(self, 'username', 'password',
35 'project_id', 'auth_url',
36 extensions=kwargs.get('extensions'))
37 self.client = FakeHTTPClient(**kwargs)
38
39
40class FakeHTTPClient(base_client.HTTPClient):
41
42 def __init__(self, **kwargs):
43 self.username = 'username'
44 self.password = 'password'
45 self.auth_url = 'auth_url'
46 self.tenant_id = 'tenant_id'
47 self.callstack = []
48 self.projectid = 'projectid'
49 self.user = 'user'
50 self.region_name = 'region_name'
51 self.endpoint_type = 'endpoint_type'
52 self.service_type = 'service_type'
53 self.service_name = 'service_name'
54 self.volume_service_name = 'volume_service_name'
55 self.timings = 'timings'
56 self.bypass_url = 'bypass_url'
57 self.os_cache = 'os_cache'
58 self.http_log_debug = 'http_log_debug'
59
60 def _cs_request(self, url, method, **kwargs):
61 # Check that certain things are called correctly
62 if method in ['GET', 'DELETE']:
63 assert 'body' not in kwargs
64 elif method == 'PUT':
65 assert 'body' in kwargs
66
67 # Call the method
68 args = parse.parse_qsl(parse.urlparse(url)[4])
69 kwargs.update(args)
70 munged_url = url.rsplit('?', 1)[0]
71 munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_')
72 munged_url = munged_url.replace('-', '_')
73 munged_url = munged_url.replace(' ', '_')
74
75 callback = "%s_%s" % (method.lower(), munged_url)
76
77 if not hasattr(self, callback):
78 raise AssertionError('Called unknown API method: %s %s, '
79 'expected fakes method name: %s' %
80 (method, url, callback))
81
82 # Note the call
83 self.callstack.append((method, url, kwargs.get('body')))
84
85 status, headers, body = getattr(self, callback)(**kwargs)
86 r = utils.TestResponse({
87 "status_code": status,
88 "text": body,
89 "headers": headers,
90 })
91 return r, body
92
93 #
94 # agents
95 #
96
97 def get_os_agents(self, **kw):
98 hypervisor = kw.get('hypervisor', 'kvm')
99 return (200, {}, {
100 'agents':
101 [{'hypervisor': hypervisor,
102 'os': 'win',
103 'architecture': 'x86',
104 'version': '7.0',
105 'url': 'xxx://xxxx/xxx/xxx',
106 'md5hash': 'add6bb58e139be103324d04d82d8f545',
107 'id': 1},
108 {'hypervisor': hypervisor,
109 'os': 'linux',
110 'architecture': 'x86',
111 'version': '16.0',
112 'url': 'xxx://xxxx/xxx/xxx1',
113 'md5hash': 'add6bb58e139be103324d04d82d8f546',
114 'id': 2}]})
115
116 def post_os_agents(self, body):
117 return (200, {}, {'agent': {
118 'url': '/xxx/xxx/xxx',
119 'hypervisor': body['agent']['hypervisor'],
120 'md5hash': 'add6bb58e139be103324d04d82d8f546',
121 'version': '7.0',
122 'architecture': 'x86',
123 'os': 'win',
124 'id': 1}})
125
126 def delete_os_agents_1(self, **kw):
127 return (202, {}, None)
128
129 def put_os_agents_1(self, body, **kw):
130 return (200, {}, {
131 "agent": {"url": "/yyy/yyyy/yyyy",
132 "version": "8.0",
133 "md5hash": "add6bb58e139be103324d04d82d8f546",
134 'id': 1}})
135
136 #
137 # List all extensions
138 #
139
140 def get_extensions(self, **kw):
141 exts = [
142 {
143 "alias": "NMN",
144 "description": "Multiple network support",
145 "links": [],
146 "name": "Multinic",
147 "namespace": ("http://docs.openstack.org/"
148 "compute/ext/multinic/api/v1.1"),
149 "updated": "2011-06-09T00:00:00+00:00"
150 },
151 {
152 "alias": "OS-DCF",
153 "description": "Disk Management Extension",
154 "links": [],
155 "name": "DiskConfig",
156 "namespace": ("http://docs.openstack.org/"
157 "compute/ext/disk_config/api/v1.1"),
158 "updated": "2011-09-27T00:00:00+00:00"
159 },
160 {
161 "alias": "OS-EXT-SRV-ATTR",
162 "description": "Extended Server Attributes support.",
163 "links": [],
164 "name": "ExtendedServerAttributes",
165 "namespace": ("http://docs.openstack.org/"
166 "compute/ext/extended_status/api/v1.1"),
167 "updated": "2011-11-03T00:00:00+00:00"
168 },
169 {
170 "alias": "OS-EXT-STS",
171 "description": "Extended Status support",
172 "links": [],
173 "name": "ExtendedStatus",
174 "namespace": ("http://docs.openstack.org/"
175 "compute/ext/extended_status/api/v1.1"),
176 "updated": "2011-11-03T00:00:00+00:00"
177 },
178 ]
179 return (200, {}, {
180 "extensions": exts,
181 })
182
183 #
184 # Limits
185 #
186
187 def get_limits(self, **kw):
188 return (200, {}, {"limits": {
189 "rate": [
190 {
191 "uri": "*",
192 "regex": ".*",
193 "limit": [
194 {
195 "value": 10,
196 "verb": "POST",
197 "remaining": 2,
198 "unit": "MINUTE",
199 "next-available": "2011-12-15T22:42:45Z"
200 },
201 {
202 "value": 10,
203 "verb": "PUT",
204 "remaining": 2,
205 "unit": "MINUTE",
206 "next-available": "2011-12-15T22:42:45Z"
207 },
208 {
209 "value": 100,
210 "verb": "DELETE",
211 "remaining": 100,
212 "unit": "MINUTE",
213 "next-available": "2011-12-15T22:42:45Z"
214 }
215 ]
216 },
217 {
218 "uri": "*/servers",
219 "regex": "^/servers",
220 "limit": [
221 {
222 "verb": "POST",
223 "value": 25,
224 "remaining": 24,
225 "unit": "DAY",
226 "next-available": "2011-12-15T22:42:45Z"
227 }
228 ]
229 }
230 ],
231 "absolute": {
232 "maxTotalRAMSize": 51200,
233 "maxServerMeta": 5,
234 "maxImageMeta": 5,
235 "maxPersonality": 5,
236 "maxPersonalitySize": 10240
237 },
238 }})
239
240 #
241 # Servers
242 #
243
244 def get_servers(self, **kw):
245 return (200, {}, {"servers": [
246 {'id': 1234, 'name': 'sample-server'},
247 {'id': 5678, 'name': 'sample-server2'}
248 ]})
249
250 def get_servers_detail(self, **kw):
251 return (200, {}, {"servers": [
252 {
253 "id": 1234,
254 "name": "sample-server",
255 "image": {
256 "id": 2,
257 "name": "sample image",
258 },
259 "flavor": {
260 "id": 1,
261 "name": "256 MB Server",
262 },
263 "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0",
264 "status": "BUILD",
265 "progress": 60,
266 "addresses": {
267 "public": [
268 {
269 "version": 4,
270 "addr": "1.2.3.4",
271 },
272 {
273 "version": 4,
274 "addr": "5.6.7.8",
275 }],
276 "private": [{
277 "version": 4,
278 "addr": "10.11.12.13",
279 }],
280 },
281 "metadata": {
282 "Server Label": "Web Head 1",
283 "Image Version": "2.1"
284 },
285 "OS-EXT-SRV-ATTR:host": "computenode1",
286 "security_groups": [{
287 'id': 1, 'name': 'securitygroup1',
288 'description': 'FAKE_SECURITY_GROUP',
289 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7'
290 }],
291 "OS-EXT-MOD:some_thing": "mod_some_thing_value",
292 },
293 {
294 "id": 5678,
295 "name": "sample-server2",
296 "image": {
297 "id": 2,
298 "name": "sample image",
299 },
300 "flavor": {
301 "id": 1,
302 "name": "256 MB Server",
303 },
304 "hostId": "9e107d9d372bb6826bd81d3542a419d6",
305 "status": "ACTIVE",
306 "addresses": {
307 "public": [
308 {
309 "version": 4,
310 "addr": "4.5.6.7",
311 },
312 {
313 "version": 4,
314 "addr": "5.6.9.8",
315 }],
316 "private": [{
317 "version": 4,
318 "addr": "10.13.12.13",
319 }],
320 },
321 "metadata": {
322 "Server Label": "DB 1"
323 },
324 "OS-EXT-SRV-ATTR:host": "computenode2",
325 "security_groups": [
326 {
327 'id': 1, 'name': 'securitygroup1',
328 'description': 'FAKE_SECURITY_GROUP',
329 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7'
330 },
331 {
332 'id': 2, 'name': 'securitygroup2',
333 'description': 'ANOTHER_FAKE_SECURITY_GROUP',
334 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7'
335 }],
336 },
337 {
338 "id": 9012,
339 "name": "sample-server3",
340 "image": "",
341 "flavor": {
342 "id": 1,
343 "name": "256 MB Server",
344 },
345 "hostId": "9e107d9d372bb6826bd81d3542a419d6",
346 "status": "ACTIVE",
347 "addresses": {
348 "public": [
349 {
350 "version": 4,
351 "addr": "4.5.6.7",
352 },
353 {
354 "version": 4,
355 "addr": "5.6.9.8",
356 }],
357 "private": [{
358 "version": 4,
359 "addr": "10.13.12.13",
360 }],
361 },
362 "metadata": {
363 "Server Label": "DB 1"
364 }
365 }
366 ]})
367
368 def post_servers(self, body, **kw):
369 assert set(body.keys()) <= set(['server', 'os:scheduler_hints'])
370 fakes.assert_has_keys(
371 body['server'],
372 required=['name', 'imageRef', 'flavorRef'],
373 optional=['metadata', 'personality'])
374 if 'personality' in body['server']:
375 for pfile in body['server']['personality']:
376 fakes.assert_has_keys(pfile, required=['path', 'contents'])
377 if body['server']['name'] == 'some-bad-server':
378 return (202, {}, self.get_servers_1235()[2])
379 else:
380 return (202, {}, self.get_servers_1234()[2])
381
382 def post_os_volumes_boot(self, body, **kw):
383 assert set(body.keys()) <= set(['server', 'os:scheduler_hints'])
384 fakes.assert_has_keys(
385 body['server'],
386 required=['name', 'flavorRef'],
387 optional=['imageRef'])
388
389 # Require one, and only one, of the keys for bdm
390 if 'block_device_mapping' not in body['server']:
391 if 'block_device_mapping_v2' not in body['server']:
392 raise AssertionError(
393 "missing required keys: 'block_device_mapping'"
394 )
395 elif 'block_device_mapping_v2' in body['server']:
396 raise AssertionError("found extra keys: 'block_device_mapping'")
397
398 return (202, {}, self.get_servers_9012()[2])
399
400 def get_servers_1234(self, **kw):
401 r = {'server': self.get_servers_detail()[2]['servers'][0]}
402 return (200, {}, r)
403
404 def get_servers_1235(self, **kw):
405 r = {'server': self.get_servers_detail()[2]['servers'][0]}
406 r['server']['id'] = 1235
407 r['server']['status'] = 'error'
408 r['server']['fault'] = {'message': 'something went wrong!'}
409 return (200, {}, r)
410
411 def get_servers_5678(self, **kw):
412 r = {'server': self.get_servers_detail()[2]['servers'][1]}
413 return (200, {}, r)
414
415 def get_servers_9012(self, **kw):
416 r = {'server': self.get_servers_detail()[2]['servers'][2]}
417 return (200, {}, r)
418
419 def put_servers_1234(self, body, **kw):
420 assert list(body) == ['server']
421 fakes.assert_has_keys(body['server'], optional=['name', 'adminPass'])
422 return (204, {}, body)
423
424 def delete_os_server_groups_12345(self, **kw):
425 return (202, {}, None)
426
427 def delete_os_server_groups_56789(self, **kw):
428 return (202, {}, None)
429
430 def delete_servers_1234(self, **kw):
431 return (202, {}, None)
432
433 def delete_servers_5678(self, **kw):
434 return (202, {}, None)
435
436 def delete_servers_1234_metadata_test_key(self, **kw):
437 return (204, {}, None)
438
439 def delete_servers_1234_metadata_key1(self, **kw):
440 return (204, {}, None)
441
442 def delete_servers_1234_metadata_key2(self, **kw):
443 return (204, {}, None)
444
445 def post_servers_1234_metadata(self, **kw):
446 return (204, {}, {'metadata': {'test_key': 'test_value'}})
447
448 def put_servers_1234_metadata_test_key(self, **kw):
449 return (200, {}, {'meta': {'test_key': 'test_value'}})
450
451 def get_servers_1234_diagnostics(self, **kw):
452 return (200, {}, {'data': 'Fake diagnostics'})
453
454 def post_servers_uuid1_metadata(self, **kw):
455 return (204, {}, {'metadata': {'key1': 'val1'}})
456
457 def post_servers_uuid2_metadata(self, **kw):
458 return (204, {}, {'metadata': {'key1': 'val1'}})
459
460 def post_servers_uuid3_metadata(self, **kw):
461 return (204, {}, {'metadata': {'key1': 'val1'}})
462
463 def post_servers_uuid4_metadata(self, **kw):
464 return (204, {}, {'metadata': {'key1': 'val1'}})
465
466 def delete_servers_uuid1_metadata_key1(self, **kw):
467 return (200, {}, {'data': 'Fake diagnostics'})
468
469 def delete_servers_uuid2_metadata_key1(self, **kw):
470 return (200, {}, {'data': 'Fake diagnostics'})
471
472 def delete_servers_uuid3_metadata_key1(self, **kw):
473 return (200, {}, {'data': 'Fake diagnostics'})
474
475 def delete_servers_uuid4_metadata_key1(self, **kw):
476 return (200, {}, {'data': 'Fake diagnostics'})
477
478 def get_servers_1234_os_security_groups(self, **kw):
479 return (200, {}, {
480 "security_groups": [{
481 'id': 1,
482 'name': 'securitygroup1',
483 'description': 'FAKE_SECURITY_GROUP',
484 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7',
485 'rules': []}]
486 })
487
488 #
489 # Server Addresses
490 #
491
492 def get_servers_1234_ips(self, **kw):
493 return (200, {}, {
494 'addresses':
495 self.get_servers_1234()[1]['server']['addresses']})
496
497 def get_servers_1234_ips_public(self, **kw):
498 return (200, {}, {
499 'public':
500 self.get_servers_1234_ips()[1]['addresses']['public']})
501
502 def get_servers_1234_ips_private(self, **kw):
503 return (
504 200, {},
505 {'private':
506 self.get_servers_1234_ips()[1]['addresses']['private']})
507
508 def delete_servers_1234_ips_public_1_2_3_4(self, **kw):
509 return (202, {}, None)
510
511 #
512 # Server password
513 #
514
515 # Testing with the following password and key
516 #
517 # Clear password: FooBar123
518 #
519 # RSA Private Key: novaclient/tests/unit/idfake.pem
520 #
521 # Encrypted password
522 # OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r
523 # qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho
524 # QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw
525 # /y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N
526 # tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk
527 # Hi/fmZZNQQqj1Ijq0caOIw==
528 def get_servers_1234_os_server_password(self, **kw):
529 return (200, {}, {
530 'password':
531 'OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r'
532 'qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho'
533 'QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw'
534 '/y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N'
535 'tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk'
536 'Hi/fmZZNQQqj1Ijq0caOIw=='})
537
538 def delete_servers_1234_os_server_password(self, **kw):
539 return (202, {}, None)
540
541 #
542 # Server actions
543 #
544
545 def post_servers_1234_action(self, body, **kw):
546 _headers = None
547 _body = None
548 resp = 202
549 assert len(body.keys()) == 1
550 action = list(body)[0]
551 if action == 'reboot':
552 assert list(body[action]) == ['type']
553 assert body[action]['type'] in ['HARD', 'SOFT']
554 elif action == 'rebuild':
555 body = body[action]
556 adminPass = body.get('adminPass', 'randompassword')
557 assert 'imageRef' in body
558 _body = self.get_servers_1234()[2]
559 _body['server']['adminPass'] = adminPass
560 elif action == 'resize':
561 keys = body[action].keys()
562 assert 'flavorRef' in keys
563 elif action == 'confirmResize':
564 assert body[action] is None
565 # This one method returns a different response code
566 return (204, {}, None)
567 elif action == 'revertResize':
568 assert body[action] is None
569 elif action == 'migrate':
570 assert body[action] is None
571 elif action == 'os-stop':
572 assert body[action] is None
573 elif action == 'os-start':
574 assert body[action] is None
575 elif action == 'forceDelete':
576 assert body[action] is None
577 elif action == 'restore':
578 assert body[action] is None
579 elif action == 'pause':
580 assert body[action] is None
581 elif action == 'unpause':
582 assert body[action] is None
583 elif action == 'lock':
584 assert body[action] is None
585 elif action == 'unlock':
586 assert body[action] is None
587 elif action == 'rescue':
588 if body[action]:
589 keys = set(body[action].keys())
590 assert not (keys - set(['adminPass', 'rescue_image_ref']))
591 else:
592 assert body[action] is None
593 _body = {'adminPass': 'RescuePassword'}
594 elif action == 'unrescue':
595 assert body[action] is None
596 elif action == 'resume':
597 assert body[action] is None
598 elif action == 'suspend':
599 assert body[action] is None
600 elif action == 'lock':
601 assert body[action] is None
602 elif action == 'unlock':
603 assert body[action] is None
604 elif action == 'shelve':
605 assert body[action] is None
606 elif action == 'shelveOffload':
607 assert body[action] is None
608 elif action == 'unshelve':
609 assert body[action] is None
610 elif action == 'addFixedIp':
611 assert list(body[action]) == ['networkId']
612 elif action == 'removeFixedIp':
613 assert list(body[action]) == ['address']
614 elif action == 'addFloatingIp':
615 assert (list(body[action]) == ['address'] or
616 sorted(list(body[action])) == ['address',
617 'fixed_address'])
618 elif action == 'removeFloatingIp':
619 assert list(body[action]) == ['address']
620 elif action == 'createImage':
621 assert set(body[action].keys()) == set(['name', 'metadata'])
622 _headers = dict(location="http://blah/images/456")
623 elif action == 'changePassword':
624 assert list(body[action]) == ['adminPass']
625 elif action == 'os-getConsoleOutput':
626 assert list(body[action]) == ['length']
627 return (202, {}, {'output': 'foo'})
628 elif action == 'os-getVNCConsole':
629 assert list(body[action]) == ['type']
630 elif action == 'os-getSPICEConsole':
631 assert list(body[action]) == ['type']
632 elif action == 'os-getRDPConsole':
633 assert list(body[action]) == ['type']
634 elif action == 'os-migrateLive':
635 assert set(body[action].keys()) == set(['host',
636 'block_migration',
637 'disk_over_commit'])
638 elif action == 'os-resetState':
639 assert list(body[action]) == ['state']
640 elif action == 'resetNetwork':
641 assert body[action] is None
642 elif action == 'addSecurityGroup':
643 assert list(body[action]) == ['name']
644 elif action == 'removeSecurityGroup':
645 assert list(body[action]) == ['name']
646 elif action == 'createBackup':
647 assert set(body[action]) == set(['name',
648 'backup_type',
649 'rotation'])
650 elif action == 'evacuate':
651 keys = list(body[action])
652 if 'adminPass' in keys:
653 keys.remove('adminPass')
654 if 'host' in keys:
655 keys.remove('host')
656 assert set(keys) == set(['onSharedStorage'])
657 else:
658 raise AssertionError("Unexpected server action: %s" % action)
659 return (resp, _headers, _body)
660
661 def post_servers_5678_action(self, body, **kw):
662 return self.post_servers_1234_action(body, **kw)
663
664 #
665 # Cloudpipe
666 #
667
668 def get_os_cloudpipe(self, **kw):
669 return (
670 200,
671 {},
672 {'cloudpipes': [{'project_id': 1}]}
673 )
674
675 def post_os_cloudpipe(self, **ks):
676 return (
677 202,
678 {},
679 {'instance_id': '9d5824aa-20e6-4b9f-b967-76a699fc51fd'}
680 )
681
682 def put_os_cloudpipe_configure_project(self, **kw):
683 return (202, {}, None)
684
685 #
686 # Flavors
687 #
688
689 def get_flavors(self, **kw):
690 status, header, flavors = self.get_flavors_detail(**kw)
691 for flavor in flavors['flavors']:
692 for k in list(flavor):
693 if k not in ['id', 'name']:
694 del flavor[k]
695
696 return (200, {}, flavors)
697
698 def get_flavors_detail(self, **kw):
699 flavors = {'flavors': [
700 {'id': 1, 'name': '256 MB Server', 'ram': 256, 'disk': 10,
701 'OS-FLV-EXT-DATA:ephemeral': 10,
702 'os-flavor-access:is_public': True,
703 'links': {}},
704 {'id': 2, 'name': '512 MB Server', 'ram': 512, 'disk': 20,
705 'OS-FLV-EXT-DATA:ephemeral': 20,
706 'os-flavor-access:is_public': False,
707 'links': {}},
708 {'id': 4, 'name': '1024 MB Server', 'ram': 1024, 'disk': 10,
709 'OS-FLV-EXT-DATA:ephemeral': 10,
710 'os-flavor-access:is_public': True,
711 'links': {}},
712 {'id': 'aa1', 'name': '128 MB Server', 'ram': 128, 'disk': 0,
713 'OS-FLV-EXT-DATA:ephemeral': 0,
714 'os-flavor-access:is_public': True,
715 'links': {}}
716 ]}
717
718 if 'is_public' not in kw:
719 filter_is_public = True
720 else:
721 if kw['is_public'].lower() == 'none':
722 filter_is_public = None
723 else:
724 filter_is_public = strutils.bool_from_string(kw['is_public'],
725 True)
726
727 if filter_is_public is not None:
728 if filter_is_public:
729 flavors['flavors'] = [
730 v for v in flavors['flavors']
731 if v['os-flavor-access:is_public']
732 ]
733 else:
734 flavors['flavors'] = [
735 v for v in flavors['flavors']
736 if not v['os-flavor-access:is_public']
737 ]
738
739 return (200, {}, flavors)
740
741 def get_flavors_1(self, **kw):
742 return (
743 200,
744 {},
745 {'flavor':
746 self.get_flavors_detail(is_public='None')[2]['flavors'][0]}
747 )
748
749 def get_flavors_2(self, **kw):
750 return (
751 200,
752 {},
753 {'flavor':
754 self.get_flavors_detail(is_public='None')[2]['flavors'][1]}
755 )
756
757 def get_flavors_3(self, **kw):
758 # Diablo has no ephemeral
759 return (
760 200,
761 {},
762 {'flavor': {
763 'id': 3,
764 'name': '256 MB Server',
765 'ram': 256,
766 'disk': 10,
767 }},
768 )
769
770 def get_flavors_512_MB_Server(self, **kw):
771 raise exceptions.NotFound('404')
772
773 def get_flavors_128_MB_Server(self, **kw):
774 raise exceptions.NotFound('404')
775
776 def get_flavors_aa1(self, **kw):
777 # Alphanumeric flavor id are allowed.
778 return (
779 200,
780 {},
781 {'flavor':
782 self.get_flavors_detail(is_public='None')[2]['flavors'][3]}
783 )
784
785 def get_flavors_4(self, **kw):
786 return (
787 200,
788 {},
789 {'flavor':
790 self.get_flavors_detail(is_public='None')[2]['flavors'][2]}
791 )
792
793 def delete_flavors_flavordelete(self, **kw):
794 return (202, {}, None)
795
796 def delete_flavors_2(self, **kw):
797 return (202, {}, None)
798
799 def post_flavors(self, body, **kw):
800 return (
801 202,
802 {},
803 {'flavor':
804 self.get_flavors_detail(is_public='None')[2]['flavors'][0]}
805 )
806
807 def get_flavors_1_os_extra_specs(self, **kw):
808 return (
809 200,
810 {},
811 {'extra_specs': {"k1": "v1"}})
812
813 def get_flavors_2_os_extra_specs(self, **kw):
814 return (
815 200,
816 {},
817 {'extra_specs': {"k2": "v2"}})
818
819 def get_flavors_aa1_os_extra_specs(self, **kw):
820 return (
821 200, {},
822 {'extra_specs': {"k3": "v3"}})
823
824 def get_flavors_4_os_extra_specs(self, **kw):
825 return (
826 200,
827 {},
828 {'extra_specs': {"k4": "v4"}})
829
830 def post_flavors_1_os_extra_specs(self, body, **kw):
831 assert list(body) == ['extra_specs']
832 fakes.assert_has_keys(body['extra_specs'],
833 required=['k1'])
834 return (
835 200,
836 {},
837 {'extra_specs': {"k1": "v1"}})
838
839 def post_flavors_4_os_extra_specs(self, body, **kw):
840 assert list(body) == ['extra_specs']
841
842 return (
843 200,
844 {},
845 body)
846
847 def delete_flavors_1_os_extra_specs_k1(self, **kw):
848 return (204, {}, None)
849
850 #
851 # Flavor access
852 #
853
854 def get_flavors_1_os_flavor_access(self, **kw):
855 return (404, {}, None)
856
857 def get_flavors_2_os_flavor_access(self, **kw):
858 return (
859 200, {},
860 {'flavor_access': [{'flavor_id': '2', 'tenant_id': 'proj1'},
861 {'flavor_id': '2', 'tenant_id': 'proj2'}]})
862
863 def post_flavors_2_action(self, body, **kw):
864 return (202, {}, self.get_flavors_2_os_flavor_access()[2])
865
866 #
867 # Floating IPs
868 #
869
870 def get_os_floating_ip_pools(self):
871 return (
872 200,
873 {},
874 {'floating_ip_pools': [{'name': 'foo'}, {'name': 'bar'}]}
875 )
876
877 def get_os_floating_ips(self, **kw):
878 return (
879 200,
880 {},
881 {'floating_ips': [
882 {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'},
883 {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'},
884 ]},
885 )
886
887 def get_os_floating_ips_1(self, **kw):
888 return (
889 200, {}, {'floating_ip': {'id': 1, 'fixed_ip': '10.0.0.1',
890 'ip': '11.0.0.1'}})
891
892 def post_os_floating_ips(self, body):
893 if body.get('pool'):
894 return (
895 200, {}, {'floating_ip': {'id': 1, 'fixed_ip': '10.0.0.1',
896 'ip': '11.0.0.1',
897 'pool': 'nova'}})
898 else:
899 return (
900 200, {}, {'floating_ip': {'id': 1, 'fixed_ip': '10.0.0.1',
901 'ip': '11.0.0.1',
902 'pool': None}})
903
904 def delete_os_floating_ips_1(self, **kw):
905 return (204, {}, None)
906
907 def get_os_floating_ip_dns(self, **kw):
908 return (205, {}, {'domain_entries':
909 [{'domain': 'example.org'},
910 {'domain': 'example.com'}]})
911
912 def get_os_floating_ip_dns_testdomain_entries(self, **kw):
913 if kw.get('ip'):
914 return (205, {}, {
915 'dns_entries': [
916 {'dns_entry': {'ip': kw.get('ip'),
917 'name': "host1",
918 'type': "A",
919 'domain': 'testdomain'}},
920 {'dns_entry': {'ip': kw.get('ip'),
921 'name': "host2",
922 'type': "A",
923 'domain': 'testdomain'}}]})
924 else:
925 return (404, {}, None)
926
927 def get_os_floating_ip_dns_testdomain_entries_testname(self, **kw):
928 return (205, {}, {
929 'dns_entry': {'ip': "10.10.10.10",
930 'name': 'testname',
931 'type': "A",
932 'domain': 'testdomain'}})
933
934 def put_os_floating_ip_dns_testdomain(self, body, **kw):
935 if body['domain_entry']['scope'] == 'private':
936 fakes.assert_has_keys(body['domain_entry'],
937 required=['availability_zone', 'scope'])
938 elif body['domain_entry']['scope'] == 'public':
939 fakes.assert_has_keys(body['domain_entry'],
940 required=['project', 'scope'])
941
942 else:
943 fakes.assert_has_keys(body['domain_entry'],
944 required=['project', 'scope'])
945 return (205, {}, body)
946
947 def put_os_floating_ip_dns_testdomain_entries_testname(self, body, **kw):
948 fakes.assert_has_keys(body['dns_entry'],
949 required=['ip', 'dns_type'])
950 return (205, {}, body)
951
952 def delete_os_floating_ip_dns_testdomain(self, **kw):
953 return (200, {}, None)
954
955 def delete_os_floating_ip_dns_testdomain_entries_testname(self, **kw):
956 return (200, {}, None)
957
958 def get_os_floating_ips_bulk(self, **kw):
959 return (200, {}, {'floating_ip_info': [
960 {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'},
961 {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'},
962 ]})
963
964 def get_os_floating_ips_bulk_testHost(self, **kw):
965 return (200, {}, {'floating_ip_info': [
966 {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'},
967 {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'},
968 ]})
969
970 def post_os_floating_ips_bulk(self, **kw):
971 params = kw.get('body').get('floating_ips_bulk_create')
972 pool = params.get('pool', 'defaultPool')
973 interface = params.get('interface', 'defaultInterface')
974 return (200, {}, {'floating_ips_bulk_create':
975 {'ip_range': '192.168.1.0/30',
976 'pool': pool,
977 'interface': interface}})
978
979 def put_os_floating_ips_bulk_delete(self, **kw):
980 ip_range = kw.get('body').get('ip_range')
981 return (200, {}, {'floating_ips_bulk_delete': ip_range})
982
983 #
984 # Images
985 #
986 def get_images(self, **kw):
987 return (200, {}, {'images': [
988 {'id': 1, 'name': 'CentOS 5.2'},
989 {'id': 2, 'name': 'My Server Backup'}
990 ]})
991
992 def get_images_detail(self, **kw):
993 return (200, {}, {'images': [
994 {
995 'id': 1,
996 'name': 'CentOS 5.2',
997 "updated": "2010-10-10T12:00:00Z",
998 "created": "2010-08-10T12:00:00Z",
999 "status": "ACTIVE",
1000 "metadata": {
1001 "test_key": "test_value",
1002 },
1003 "links": {},
1004 },
1005 {
1006 "id": 2,
1007 "name": "My Server Backup",
1008 "serverId": 1234,
1009 "updated": "2010-10-10T12:00:00Z",
1010 "created": "2010-08-10T12:00:00Z",
1011 "status": "SAVING",
1012 "progress": 80,
1013 "links": {},
1014 }
1015 ]})
1016
1017 def get_images_1(self, **kw):
1018 return (200, {}, {'image': self.get_images_detail()[2]['images'][0]})
1019
1020 def get_images_2(self, **kw):
1021 return (200, {}, {'image': self.get_images_detail()[2]['images'][1]})
1022
1023 def get_images_456(self, **kw):
1024 return (200, {}, {'image': self.get_images_detail()[2]['images'][1]})
1025
1026 def post_images(self, body, **kw):
1027 assert list(body) == ['image']
1028 fakes.assert_has_keys(body['image'], required=['serverId', 'name'])
1029 return (202, {}, self.get_images_1()[2])
1030
1031 def post_images_1_metadata(self, body, **kw):
1032 assert list(body) == ['metadata']
1033 fakes.assert_has_keys(body['metadata'],
1034 required=['test_key'])
1035 return (
1036 200,
1037 {},
1038 {'metadata': self.get_images_1()[2]['image']['metadata']})
1039
1040 def delete_images_1(self, **kw):
1041 return (204, {}, None)
1042
1043 def delete_images_2(self, **kw):
1044 return (204, {}, None)
1045
1046 def delete_images_1_metadata_test_key(self, **kw):
1047 return (204, {}, None)
1048
1049 #
1050 # Keypairs
1051 #
1052 def get_os_keypairs_test(self, *kw):
1053 return (200, {}, {'keypair':
1054 self.get_os_keypairs()[2]['keypairs'][0]['keypair']})
1055
1056 def get_os_keypairs(self, *kw):
1057 return (200, {}, {
1058 "keypairs": [{"keypair": {
1059 "public_key": "FAKE_SSH_RSA",
1060 "private_key": "FAKE_PRIVATE_KEY",
1061 "user_id": "81e373b596d6466e99c4896826abaa46",
1062 "name": "test",
1063 "deleted": False,
1064 "created_at": "2014-04-19T02:16:44.000000",
1065 "updated_at": "2014-04-19T10:12:3.000000",
1066 "figerprint": "FAKE_KEYPAIR",
1067 "deleted_at": None,
1068 "id": 4}}
1069 ]})
1070
1071 def delete_os_keypairs_test(self, **kw):
1072 return (202, {}, None)
1073
1074 def post_os_keypairs(self, body, **kw):
1075 assert list(body) == ['keypair']
1076 fakes.assert_has_keys(body['keypair'],
1077 required=['name'])
1078 r = {'keypair': self.get_os_keypairs()[2]['keypairs'][0]['keypair']}
1079 return (202, {}, r)
1080
1081 #
1082 # Virtual Interfaces
1083 #
1084 def get_servers_1234_os_virtual_interfaces(self, **kw):
1085 return (200, {}, {"virtual_interfaces": [
1086 {'id': 'fakeid', 'mac_address': 'fakemac'}
1087 ]})
1088
1089 #
1090 # Quotas
1091 #
1092
1093 def get_os_quota_sets_test(self, **kw):
1094 return (200, {}, {
1095 'quota_set': {
1096 'tenant_id': 'test',
1097 'metadata_items': [],
1098 'injected_file_content_bytes': 1,
1099 'injected_file_path_bytes': 1,
1100 'ram': 1,
1101 'floating_ips': 1,
1102 'instances': 1,
1103 'injected_files': 1,
1104 'cores': 1,
1105 'keypairs': 1,
1106 'security_groups': 1,
1107 'security_group_rules': 1}})
1108
1109 def get_os_quota_sets_tenant_id(self, **kw):
1110 return (200, {}, {
1111 'quota_set': {
1112 'tenant_id': 'test',
1113 'metadata_items': [],
1114 'injected_file_content_bytes': 1,
1115 'injected_file_path_bytes': 1,
1116 'ram': 1,
1117 'floating_ips': 1,
1118 'instances': 1,
1119 'injected_files': 1,
1120 'cores': 1,
1121 'keypairs': 1,
1122 'security_groups': 1,
1123 'security_group_rules': 1}})
1124
1125 def get_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, **kw):
1126 return (200, {}, {
1127 'quota_set': {
1128 'tenant_id': '97f4c221bff44578b0300df4ef119353',
1129 'metadata_items': [],
1130 'injected_file_content_bytes': 1,
1131 'injected_file_path_bytes': 1,
1132 'ram': 1,
1133 'floating_ips': 1,
1134 'instances': 1,
1135 'injected_files': 1,
1136 'cores': 1,
1137 'keypairs': 1,
1138 'security_groups': 1,
1139 'security_group_rules': 1}})
1140
1141 def put_os_quota_sets_97f4c221_bff4_4578_b030_0df4ef119353(self, **kw):
1142 return (200, {}, {
1143 'quota_set': {
1144 'tenant_id': '97f4c221-bff4-4578-b030-0df4ef119353',
1145 'metadata_items': [],
1146 'injected_file_content_bytes': 1,
1147 'injected_file_path_bytes': 1,
1148 'ram': 1,
1149 'floating_ips': 1,
1150 'instances': 1,
1151 'injected_files': 1,
1152 'cores': 1,
1153 'keypairs': 1,
1154 'security_groups': 1,
1155 'security_group_rules': 1}})
1156
1157 def get_os_quota_sets_97f4c221_bff4_4578_b030_0df4ef119353(self, **kw):
1158 return (200, {}, {
1159 'quota_set': {
1160 'tenant_id': '97f4c221-bff4-4578-b030-0df4ef119353',
1161 'metadata_items': [],
1162 'injected_file_content_bytes': 1,
1163 'injected_file_path_bytes': 1,
1164 'ram': 1,
1165 'floating_ips': 1,
1166 'instances': 1,
1167 'injected_files': 1,
1168 'cores': 1,
1169 'keypairs': 1,
1170 'security_groups': 1,
1171 'security_group_rules': 1}})
1172
1173 def get_os_quota_sets_97f4c221bff44578b0300df4ef119353_defaults(self):
1174 return (200, {}, {
1175 'quota_set': {
1176 'tenant_id': 'test',
1177 'metadata_items': [],
1178 'injected_file_content_bytes': 1,
1179 'injected_file_path_bytes': 1,
1180 'ram': 1,
1181 'floating_ips': 1,
1182 'instances': 1,
1183 'injected_files': 1,
1184 'cores': 1,
1185 'keypairs': 1,
1186 'security_groups': 1,
1187 'security_group_rules': 1}})
1188
1189 def get_os_quota_sets_tenant_id_defaults(self):
1190 return (200, {}, {
1191 'quota_set': {
1192 'tenant_id': 'test',
1193 'metadata_items': [],
1194 'injected_file_content_bytes': 1,
1195 'injected_file_path_bytes': 1,
1196 'ram': 1,
1197 'floating_ips': 1,
1198 'instances': 1,
1199 'injected_files': 1,
1200 'cores': 1,
1201 'keypairs': 1,
1202 'security_groups': 1,
1203 'security_group_rules': 1}})
1204
1205 def put_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, body, **kw):
1206 assert list(body) == ['quota_set']
1207 fakes.assert_has_keys(body['quota_set'],
1208 required=['tenant_id'])
1209 return (200, {}, {
1210 'quota_set': {
1211 'tenant_id': '97f4c221bff44578b0300df4ef119353',
1212 'metadata_items': [],
1213 'injected_file_content_bytes': 1,
1214 'injected_file_path_bytes': 1,
1215 'ram': 1,
1216 'floating_ips': 1,
1217 'instances': 1,
1218 'injected_files': 1,
1219 'cores': 1,
1220 'keypairs': 1,
1221 'security_groups': 1,
1222 'security_group_rules': 1}})
1223
1224 def delete_os_quota_sets_test(self, **kw):
1225 return (202, {}, {})
1226
1227 def delete_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, **kw):
1228 return (202, {}, {})
1229
1230 #
1231 # Quota Classes
1232 #
1233
1234 def get_os_quota_class_sets_test(self, **kw):
1235 return (200, {}, {
1236 'quota_class_set': {
1237 'id': 'test',
1238 'metadata_items': 1,
1239 'injected_file_content_bytes': 1,
1240 'injected_file_path_bytes': 1,
1241 'ram': 1,
1242 'floating_ips': 1,
1243 'instances': 1,
1244 'injected_files': 1,
1245 'cores': 1,
1246 'key_pairs': 1,
1247 'security_groups': 1,
1248 'security_group_rules': 1}})
1249
1250 def put_os_quota_class_sets_test(self, body, **kw):
1251 assert list(body) == ['quota_class_set']
1252 return (200, {}, {
1253 'quota_class_set': {
1254 'metadata_items': 1,
1255 'injected_file_content_bytes': 1,
1256 'injected_file_path_bytes': 1,
1257 'ram': 1,
1258 'floating_ips': 1,
1259 'instances': 1,
1260 'injected_files': 1,
1261 'cores': 1,
1262 'key_pairs': 1,
1263 'security_groups': 1,
1264 'security_group_rules': 1}})
1265
1266 def put_os_quota_class_sets_97f4c221bff44578b0300df4ef119353(self,
1267 body, **kw):
1268 assert list(body) == ['quota_class_set']
1269 return (200, {}, {
1270 'quota_class_set': {
1271 'metadata_items': 1,
1272 'injected_file_content_bytes': 1,
1273 'injected_file_path_bytes': 1,
1274 'ram': 1,
1275 'floating_ips': 1,
1276 'instances': 1,
1277 'injected_files': 1,
1278 'cores': 1,
1279 'key_pairs': 1,
1280 'security_groups': 1,
1281 'security_group_rules': 1}})
1282
1283 #
1284 # Security Groups
1285 #
1286 def get_os_security_groups(self, **kw):
1287 return (200, {}, {"security_groups": [
1288 {"name": "test",
1289 "description": "FAKE_SECURITY_GROUP",
1290 "tenant_id": "4ffc664c198e435e9853f2538fbcd7a7",
1291 "id": 1,
1292 "rules": [
1293 {"id": 11,
1294 "group": {},
1295 "ip_protocol": "TCP",
1296 "from_port": 22,
1297 "to_port": 22,
1298 "parent_group_id": 1,
1299 "ip_range":
1300 {"cidr": "10.0.0.0/8"}},
1301 {"id": 12,
1302 "group": {
1303 "tenant_id":
1304 "272bee4c1e624cd4a72a6b0ea55b4582",
1305 "name": "test2"},
1306
1307 "ip_protocol": "TCP",
1308 "from_port": 222,
1309 "to_port": 222,
1310 "parent_group_id": 1,
1311 "ip_range": {}},
1312 {"id": 14,
1313 "group": {
1314 "tenant_id":
1315 "272bee4c1e624cd4a72a6b0ea55b4582",
1316 "name": "test4"},
1317
1318 "ip_protocol": "TCP",
1319 "from_port": -1,
1320 "to_port": -1,
1321 "parent_group_id": 1,
1322 "ip_range": {}}]},
1323 {"name": "test2",
1324 "description": "FAKE_SECURITY_GROUP2",
1325 "tenant_id": "272bee4c1e624cd4a72a6b0ea55b4582",
1326 "id": 2,
1327 "rules": []},
1328 {"name": "test4",
1329 "description": "FAKE_SECURITY_GROUP4",
1330 "tenant_id": "272bee4c1e624cd4a72a6b0ea55b4582",
1331 "id": 4,
1332 "rules": []}
1333 ]})
1334
1335 def get_os_security_groups_1(self, **kw):
1336 return (200, {}, {"security_group":
1337 {'id': 1, 'name': 'test', 'description': 'FAKE_SECURITY_GROUP'}
1338 })
1339
1340 def delete_os_security_groups_1(self, **kw):
1341 return (202, {}, None)
1342
1343 def post_os_security_groups(self, body, **kw):
1344 assert list(body) == ['security_group']
1345 fakes.assert_has_keys(body['security_group'],
1346 required=['name', 'description'])
1347 r = {'security_group':
1348 self.get_os_security_groups()[2]['security_groups'][0]}
1349 return (202, {}, r)
1350
1351 def put_os_security_groups_1(self, body, **kw):
1352 assert list(body) == ['security_group']
1353 fakes.assert_has_keys(body['security_group'],
1354 required=['name', 'description'])
1355 return (205, {}, body)
1356
1357 #
1358 # Security Group Rules
1359 #
1360 def get_os_security_group_rules(self, **kw):
1361 return (200, {}, {"security_group_rules": [
1362 {'id': 1, 'parent_group_id': 1, 'group_id': 2,
1363 'ip_protocol': 'TCP', 'from_port': 22, 'to_port': 22,
1364 'cidr': '10.0.0.0/8'}
1365 ]})
1366
1367 def delete_os_security_group_rules_1(self, **kw):
1368 return (202, {}, None)
1369
1370 def delete_os_security_group_rules_11(self, **kw):
1371 return (202, {}, None)
1372
1373 def delete_os_security_group_rules_12(self, **kw):
1374 return (202, {}, None)
1375
1376 def delete_os_security_group_rules_14(self, **kw):
1377 return (202, {}, None)
1378
1379 def post_os_security_group_rules(self, body, **kw):
1380 assert list(body) == ['security_group_rule']
1381 fakes.assert_has_keys(
1382 body['security_group_rule'],
1383 required=['parent_group_id'],
1384 optional=['group_id', 'ip_protocol', 'from_port',
1385 'to_port', 'cidr'])
1386 r = {'security_group_rule':
1387 self.get_os_security_group_rules()[2]['security_group_rules'][0]}
1388 return (202, {}, r)
1389
1390 #
1391 # Security Group Default Rules
1392 #
1393 def get_os_security_group_default_rules(self, **kw):
1394 return (200, {}, {"security_group_default_rules": [
1395 {'id': 1, 'ip_protocol': 'TCP', 'from_port': 22,
1396 'to_port': 22, 'cidr': '10.0.0.0/8'}
1397 ]})
1398
1399 def delete_os_security_group_default_rules_1(self, **kw):
1400 return (202, {}, None)
1401
1402 def delete_os_security_group_default_rules_11(self, **kw):
1403 return (202, {}, None)
1404
1405 def delete_os_security_group_default_rules_12(self, **kw):
1406 return (202, {}, None)
1407
1408 def post_os_security_group_default_rules(self, body, **kw):
1409 assert list(body) == ['security_group_default_rule']
1410 fakes.assert_has_keys(body['security_group_default_rule'],
1411 optional=['ip_protocol', 'from_port',
1412 'to_port', 'cidr'])
1413 rules = self.get_os_security_group_default_rules()
1414 r = {'security_group_default_rule':
1415 rules[2]['security_group_default_rules'][0]}
1416 return (202, {}, r)
1417
1418 #
1419 # Tenant Usage
1420 #
1421 def get_os_simple_tenant_usage(self, **kw):
1422 return (200, {},
1423 {six.u('tenant_usages'): [{
1424 six.u('total_memory_mb_usage'): 25451.762807466665,
1425 six.u('total_vcpus_usage'): 49.71047423333333,
1426 six.u('total_hours'): 49.71047423333333,
1427 six.u('tenant_id'):
1428 six.u('7b0a1d73f8fb41718f3343c207597869'),
1429 six.u('stop'): six.u('2012-01-22 19:48:41.750722'),
1430 six.u('server_usages'): [{
1431 six.u('hours'): 49.71047423333333,
1432 six.u('uptime'): 27035,
1433 six.u('local_gb'): 0,
1434 six.u('ended_at'): None,
1435 six.u('name'): six.u('f15image1'),
1436 six.u('tenant_id'):
1437 six.u('7b0a1d73f8fb41718f3343c207597869'),
1438 six.u('vcpus'): 1,
1439 six.u('memory_mb'): 512,
1440 six.u('state'): six.u('active'),
1441 six.u('flavor'): six.u('m1.tiny'),
1442 six.u('started_at'):
1443 six.u('2012-01-20 18:06:06.479998')}],
1444 six.u('start'): six.u('2011-12-25 19:48:41.750687'),
1445 six.u('total_local_gb_usage'): 0.0}]})
1446
1447 def get_os_simple_tenant_usage_tenantfoo(self, **kw):
1448 return (200, {},
1449 {six.u('tenant_usage'): {
1450 six.u('total_memory_mb_usage'): 25451.762807466665,
1451 six.u('total_vcpus_usage'): 49.71047423333333,
1452 six.u('total_hours'): 49.71047423333333,
1453 six.u('tenant_id'):
1454 six.u('7b0a1d73f8fb41718f3343c207597869'),
1455 six.u('stop'): six.u('2012-01-22 19:48:41.750722'),
1456 six.u('server_usages'): [{
1457 six.u('hours'): 49.71047423333333,
1458 six.u('uptime'): 27035, six.u('local_gb'): 0,
1459 six.u('ended_at'): None,
1460 six.u('name'): six.u('f15image1'),
1461 six.u('tenant_id'):
1462 six.u('7b0a1d73f8fb41718f3343c207597869'),
1463 six.u('vcpus'): 1, six.u('memory_mb'): 512,
1464 six.u('state'): six.u('active'),
1465 six.u('flavor'): six.u('m1.tiny'),
1466 six.u('started_at'):
1467 six.u('2012-01-20 18:06:06.479998')}],
1468 six.u('start'): six.u('2011-12-25 19:48:41.750687'),
1469 six.u('total_local_gb_usage'): 0.0}})
1470
1471 def get_os_simple_tenant_usage_test(self, **kw):
1472 return (200, {}, {six.u('tenant_usage'): {
1473 six.u('total_memory_mb_usage'): 25451.762807466665,
1474 six.u('total_vcpus_usage'): 49.71047423333333,
1475 six.u('total_hours'): 49.71047423333333,
1476 six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'),
1477 six.u('stop'): six.u('2012-01-22 19:48:41.750722'),
1478 six.u('server_usages'): [{
1479 six.u('hours'): 49.71047423333333,
1480 six.u('uptime'): 27035, six.u('local_gb'): 0,
1481 six.u('ended_at'): None,
1482 six.u('name'): six.u('f15image1'),
1483 six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'),
1484 six.u('vcpus'): 1, six.u('memory_mb'): 512,
1485 six.u('state'): six.u('active'),
1486 six.u('flavor'): six.u('m1.tiny'),
1487 six.u('started_at'): six.u('2012-01-20 18:06:06.479998')}],
1488 six.u('start'): six.u('2011-12-25 19:48:41.750687'),
1489 six.u('total_local_gb_usage'): 0.0}})
1490
1491 def get_os_simple_tenant_usage_tenant_id(self, **kw):
1492 return (200, {}, {six.u('tenant_usage'): {
1493 six.u('total_memory_mb_usage'): 25451.762807466665,
1494 six.u('total_vcpus_usage'): 49.71047423333333,
1495 six.u('total_hours'): 49.71047423333333,
1496 six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'),
1497 six.u('stop'): six.u('2012-01-22 19:48:41.750722'),
1498 six.u('server_usages'): [{
1499 six.u('hours'): 49.71047423333333,
1500 six.u('uptime'): 27035, six.u('local_gb'): 0,
1501 six.u('ended_at'): None,
1502 six.u('name'): six.u('f15image1'),
1503 six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'),
1504 six.u('vcpus'): 1, six.u('memory_mb'): 512,
1505 six.u('state'): six.u('active'),
1506 six.u('flavor'): six.u('m1.tiny'),
1507 six.u('started_at'): six.u('2012-01-20 18:06:06.479998')}],
1508 six.u('start'): six.u('2011-12-25 19:48:41.750687'),
1509 six.u('total_local_gb_usage'): 0.0}})
1510 #
1511 # Certificates
1512 #
1513
1514 def get_os_certificates_root(self, **kw):
1515 return (
1516 200,
1517 {},
1518 {'certificate': {'private_key': None, 'data': 'foo'}}
1519 )
1520
1521 def post_os_certificates(self, **kw):
1522 return (
1523 200,
1524 {},
1525 {'certificate': {'private_key': 'foo', 'data': 'bar'}}
1526 )
1527
1528 #
1529 # Aggregates
1530 #
1531
1532 def get_os_aggregates(self, *kw):
1533 return (200, {}, {"aggregates": [
1534 {'id': '1',
1535 'name': 'test',
1536 'availability_zone': 'nova1'},
1537 {'id': '2',
1538 'name': 'test2',
1539 'availability_zone': 'nova1'},
1540 {'id': '3',
1541 'name': 'test3',
1542 'metadata': {'test': "dup", "none_key": "Nine"}},
1543 ]})
1544
1545 def _return_aggregate(self):
1546 r = {'aggregate': self.get_os_aggregates()[2]['aggregates'][0]}
1547 return (200, {}, r)
1548
1549 def _return_aggregate_3(self):
1550 r = {'aggregate': self.get_os_aggregates()[2]['aggregates'][2]}
1551 return (200, {}, r)
1552
1553 def get_os_aggregates_1(self, **kw):
1554 return self._return_aggregate()
1555
1556 def get_os_aggregates_3(self, **kw):
1557 return self._return_aggregate_3()
1558
1559 def post_os_aggregates(self, body, **kw):
1560 return self._return_aggregate()
1561
1562 def put_os_aggregates_1(self, body, **kw):
1563 return self._return_aggregate()
1564
1565 def put_os_aggregates_2(self, body, **kw):
1566 return self._return_aggregate()
1567
1568 def put_os_aggregates_3(self, body, **kw):
1569 return self._return_aggregate_3()
1570
1571 def post_os_aggregates_1_action(self, body, **kw):
1572 return self._return_aggregate()
1573
1574 def post_os_aggregates_2_action(self, body, **kw):
1575 return self._return_aggregate()
1576
1577 def post_os_aggregates_3_action(self, body, **kw):
1578 return self._return_aggregate_3()
1579
1580 def delete_os_aggregates_1(self, **kw):
1581 return (202, {}, None)
1582
1583 #
1584 # Services
1585 #
1586 def get_os_services(self, **kw):
1587 host = kw.get('host', 'host1')
1588 binary = kw.get('binary', 'nova-compute')
1589 return (200, {}, {'services': [{'binary': binary,
1590 'host': host,
1591 'zone': 'nova',
1592 'status': 'enabled',
1593 'state': 'up',
1594 'updated_at': datetime.datetime(
1595 2012, 10, 29, 13, 42, 2)},
1596 {'binary': binary,
1597 'host': host,
1598 'zone': 'nova',
1599 'status': 'disabled',
1600 'state': 'down',
1601 'updated_at': datetime.datetime(
1602 2012, 9, 18, 8, 3, 38)},
1603 ]})
1604
1605 def put_os_services_enable(self, body, **kw):
1606 return (200, {}, {'service': {'host': body['host'],
1607 'binary': body['binary'],
1608 'status': 'enabled'}})
1609
1610 def put_os_services_disable(self, body, **kw):
1611 return (200, {}, {'service': {'host': body['host'],
1612 'binary': body['binary'],
1613 'status': 'disabled'}})
1614
1615 def put_os_services_disable_log_reason(self, body, **kw):
1616 return (200, {}, {'service': {
1617 'host': body['host'],
1618 'binary': body['binary'],
1619 'status': 'disabled',
1620 'disabled_reason': body['disabled_reason']}})
1621
1622 def delete_os_services_1(self, **kw):
1623 return (204, {}, None)
1624
1625 #
1626 # Fixed IPs
1627 #
1628 def get_os_fixed_ips_192_168_1_1(self, *kw):
1629 return (200, {}, {"fixed_ip": {'cidr': '192.168.1.0/24',
1630 'address': '192.168.1.1',
1631 'hostname': 'foo',
1632 'host': 'bar'}})
1633
1634 def post_os_fixed_ips_192_168_1_1_action(self, body, **kw):
1635 return (202, {}, None)
1636
1637 #
1638 # Hosts
1639 #
1640 def get_os_hosts_host(self, *kw):
1641 return (200, {}, {'host':
1642 [{'resource': {'project': '(total)', 'host': 'dummy',
1643 'cpu': 16, 'memory_mb': 32234, 'disk_gb': 128}},
1644 {'resource': {'project': '(used_now)', 'host': 'dummy',
1645 'cpu': 1, 'memory_mb': 2075, 'disk_gb': 45}},
1646 {'resource': {'project': '(used_max)', 'host': 'dummy',
1647 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}},
1648 {'resource': {'project': 'admin', 'host': 'dummy',
1649 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}}]})
1650
1651 def get_os_hosts(self, **kw):
1652 zone = kw.get('zone', 'nova1')
1653 return (200, {}, {'hosts': [{'host': 'host1',
1654 'service': 'nova-compute',
1655 'zone': zone},
1656 {'host': 'host1',
1657 'service': 'nova-cert',
1658 'zone': zone}]})
1659
1660 def get_os_hosts_sample_host(self, *kw):
1661 return (200, {}, {'host': [{'resource': {'host': 'sample_host'}}], })
1662
1663 def put_os_hosts_sample_host_1(self, body, **kw):
1664 return (200, {}, {'host': 'sample-host_1',
1665 'status': 'enabled'})
1666
1667 def put_os_hosts_sample_host_2(self, body, **kw):
1668 return (200, {}, {'host': 'sample-host_2',
1669 'maintenance_mode': 'on_maintenance'})
1670
1671 def put_os_hosts_sample_host_3(self, body, **kw):
1672 return (200, {}, {'host': 'sample-host_3',
1673 'status': 'enabled',
1674 'maintenance_mode': 'on_maintenance'})
1675
1676 def get_os_hosts_sample_host_reboot(self, **kw):
1677 return (200, {}, {'host': 'sample_host',
1678 'power_action': 'reboot'})
1679
1680 def get_os_hosts_sample_host_startup(self, **kw):
1681 return (200, {}, {'host': 'sample_host',
1682 'power_action': 'startup'})
1683
1684 def get_os_hosts_sample_host_shutdown(self, **kw):
1685 return (200, {}, {'host': 'sample_host',
1686 'power_action': 'shutdown'})
1687
1688 def put_os_hosts_sample_host(self, body, **kw):
1689 result = {'host': 'dummy'}
1690 result.update(body)
1691 return (200, {}, result)
1692
1693 def get_os_hypervisors(self, **kw):
1694 return (200, {}, {
1695 "hypervisors": [
1696 {'id': 1234, 'hypervisor_hostname': 'hyper1'},
1697 {'id': 5678, 'hypervisor_hostname': 'hyper2'}]})
1698
1699 def get_os_hypervisors_detail(self, **kw):
1700 return (200, {}, {
1701 "hypervisors": [
1702 {'id': 1234,
1703 'service': {'id': 1, 'host': 'compute1'},
1704 'vcpus': 4,
1705 'memory_mb': 10 * 1024,
1706 'local_gb': 250,
1707 'vcpus_used': 2,
1708 'memory_mb_used': 5 * 1024,
1709 'local_gb_used': 125,
1710 'hypervisor_type': "xen",
1711 'hypervisor_version': 3,
1712 'hypervisor_hostname': "hyper1",
1713 'free_ram_mb': 5 * 1024,
1714 'free_disk_gb': 125,
1715 'current_workload': 2,
1716 'running_vms': 2,
1717 'cpu_info': 'cpu_info',
1718 'disk_available_least': 100},
1719 {'id': 2,
1720 'service': {'id': 2, 'host': "compute2"},
1721 'vcpus': 4,
1722 'memory_mb': 10 * 1024,
1723 'local_gb': 250,
1724 'vcpus_used': 2,
1725 'memory_mb_used': 5 * 1024,
1726 'local_gb_used': 125,
1727 'hypervisor_type': "xen",
1728 'hypervisor_version': 3,
1729 'hypervisor_hostname': "hyper2",
1730 'free_ram_mb': 5 * 1024,
1731 'free_disk_gb': 125,
1732 'current_workload': 2,
1733 'running_vms': 2,
1734 'cpu_info': 'cpu_info',
1735 'disk_available_least': 100}]
1736 })
1737
1738 def get_os_hypervisors_statistics(self, **kw):
1739 return (200, {}, {
1740 "hypervisor_statistics": {
1741 'count': 2,
1742 'vcpus': 8,
1743 'memory_mb': 20 * 1024,
1744 'local_gb': 500,
1745 'vcpus_used': 4,
1746 'memory_mb_used': 10 * 1024,
1747 'local_gb_used': 250,
1748 'free_ram_mb': 10 * 1024,
1749 'free_disk_gb': 250,
1750 'current_workload': 4,
1751 'running_vms': 4,
1752 'disk_available_least': 200}
1753 })
1754
1755 def get_os_hypervisors_hyper_search(self, **kw):
1756 return (200, {}, {
1757 'hypervisors': [
1758 {'id': 1234, 'hypervisor_hostname': 'hyper1'},
1759 {'id': 5678, 'hypervisor_hostname': 'hyper2'}]})
1760
1761 def get_os_hypervisors_hyper_servers(self, **kw):
1762 return (200, {}, {
1763 'hypervisors': [
1764 {'id': 1234,
1765 'hypervisor_hostname': 'hyper1',
1766 'servers': [
1767 {'name': 'inst1', 'uuid': 'uuid1'},
1768 {'name': 'inst2', 'uuid': 'uuid2'}]},
1769 {'id': 5678,
1770 'hypervisor_hostname': 'hyper2',
1771 'servers': [
1772 {'name': 'inst3', 'uuid': 'uuid3'},
1773 {'name': 'inst4', 'uuid': 'uuid4'}]}]
1774 })
1775
1776 def get_os_hypervisors_hyper_no_servers_servers(self, **kw):
1777 return (200, {}, {'hypervisors':
1778 [{'id': 1234, 'hypervisor_hostname': 'hyper1'}]})
1779
1780 def get_os_hypervisors_1234(self, **kw):
1781 return (200, {}, {
1782 'hypervisor':
1783 {'id': 1234,
1784 'service': {'id': 1, 'host': 'compute1'},
1785 'vcpus': 4,
1786 'memory_mb': 10 * 1024,
1787 'local_gb': 250,
1788 'vcpus_used': 2,
1789 'memory_mb_used': 5 * 1024,
1790 'local_gb_used': 125,
1791 'hypervisor_type': "xen",
1792 'hypervisor_version': 3,
1793 'hypervisor_hostname': "hyper1",
1794 'free_ram_mb': 5 * 1024,
1795 'free_disk_gb': 125,
1796 'current_workload': 2,
1797 'running_vms': 2,
1798 'cpu_info': 'cpu_info',
1799 'disk_available_least': 100}})
1800
1801 def get_os_hypervisors_1234_uptime(self, **kw):
1802 return (200, {}, {
1803 'hypervisor': {'id': 1234,
1804 'hypervisor_hostname': "hyper1",
1805 'uptime': "fake uptime"}})
1806
1807 def get_os_networks(self, **kw):
1808 return (200, {}, {'networks': [{"label": "1", "cidr": "10.0.0.0/24",
1809 'project_id':
1810 '4ffc664c198e435e9853f2538fbcd7a7',
1811 'id': '1', 'vlan': '1234'}]})
1812
1813 def delete_os_networks_1(self, **kw):
1814 return (202, {}, None)
1815
1816 def post_os_networks(self, **kw):
1817 return (202, {}, {'network': kw})
1818
1819 def get_os_networks_1(self, **kw):
1820 return (200, {}, {'network': {"label": "1", "cidr": "10.0.0.0/24",
1821 "id": "1"}})
1822
1823 def delete_os_networks_networkdelete(self, **kw):
1824 return (202, {}, None)
1825
1826 def post_os_networks_add(self, **kw):
1827 return (202, {}, None)
1828
1829 def post_os_networks_networkdisassociate_action(self, **kw):
1830 return (202, {}, None)
1831
1832 def get_os_fping(self, **kw):
1833 return (
1834 200, {}, {
1835 'servers': [
1836 {
1837 "id": "1",
1838 "project_id": "fake-project",
1839 "alive": True,
1840 },
1841 {
1842 "id": "2",
1843 "project_id": "fake-project",
1844 "alive": True,
1845 },
1846 ]
1847 }
1848 )
1849
1850 def get_os_fping_1(self, **kw):
1851 return (
1852 200, {}, {
1853 'server': {
1854 "id": "1",
1855 "project_id": "fake-project",
1856 "alive": True,
1857 }
1858 }
1859 )
1860
1861 def post_os_networks_1_action(self, **kw):
1862 return (202, {}, None)
1863
1864 def post_os_networks_networktest_action(self, **kw):
1865 return (202, {}, None)
1866
1867 def post_os_networks_2_action(self, **kw):
1868 return (202, {}, None)
1869
1870 def get_os_availability_zone(self, **kw):
1871 return (200, {}, {
1872 "availabilityZoneInfo": [
1873 {"zoneName": "zone-1",
1874 "zoneState": {"available": True},
1875 "hosts": None},
1876 {"zoneName": "zone-2",
1877 "zoneState": {"available": False},
1878 "hosts": None}]
1879 })
1880
1881 def get_os_availability_zone_detail(self, **kw):
1882 return (200, {}, {
1883 "availabilityZoneInfo": [
1884 {"zoneName": "zone-1",
1885 "zoneState": {"available": True},
1886 "hosts": {
1887 "fake_host-1": {
1888 "nova-compute": {
1889 "active": True,
1890 "available": True,
1891 "updated_at": datetime.datetime(
1892 2012, 12, 26, 14, 45, 25, 0)}}}},
1893 {"zoneName": "internal",
1894 "zoneState": {"available": True},
1895 "hosts": {
1896 "fake_host-1": {
1897 "nova-sched": {
1898 "active": True,
1899 "available": True,
1900 "updated_at": datetime.datetime(
1901 2012, 12, 26, 14, 45, 25, 0)}},
1902 "fake_host-2": {
1903 "nova-network": {
1904 "active": True,
1905 "available": False,
1906 "updated_at": datetime.datetime(
1907 2012, 12, 26, 14, 45, 24, 0)}}}},
1908 {"zoneName": "zone-2",
1909 "zoneState": {"available": False},
1910 "hosts": None}]})
1911
1912 def get_servers_1234_os_interface(self, **kw):
1913 return (200, {}, {
1914 "interfaceAttachments": [
1915 {"port_state": "ACTIVE",
1916 "net_id": "net-id-1",
1917 "port_id": "port-id-1",
1918 "mac_address": "aa:bb:cc:dd:ee:ff",
1919 "fixed_ips": [{"ip_address": "1.2.3.4"}],
1920 },
1921 {"port_state": "ACTIVE",
1922 "net_id": "net-id-1",
1923 "port_id": "port-id-1",
1924 "mac_address": "aa:bb:cc:dd:ee:ff",
1925 "fixed_ips": [{"ip_address": "1.2.3.4"}],
1926 }]
1927 })
1928
1929 def post_servers_1234_os_interface(self, **kw):
1930 return (200, {}, {'interfaceAttachment': {}})
1931
1932 def delete_servers_1234_os_interface_port_id(self, **kw):
1933 return (200, {}, None)
1934
1935 # NOTE (vkhomenko):
1936 # Volume responses was taken from:
1937 # https://wiki.openstack.org/wiki/CreateVolumeFromImage
1938 # http://jorgew.github.com/block-storage-api/content/
1939 # GET_listDetailVolumes_v1__tenantId__volumes_detail_.html
1940 # I suppose they are outdated and should be updated after Cinder released
1941
1942 def get_volumes_detail(self, **kw):
1943 return (200, {}, {"volumes": [
1944 {
1945 "display_name": "Work",
1946 "display_description": "volume for work",
1947 "status": "ATTACHED",
1948 "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983",
1949 "created_at": "2011-09-09T00:00:00Z",
1950 "attached": "2011-11-11T00:00:00Z",
1951 "size": 1024,
1952 "attachments": [
1953 {"id": "3333",
1954 "links": ''}],
1955 "metadata": {}},
1956 {
1957 "display_name": "Work2",
1958 "display_description": "volume for work2",
1959 "status": "ATTACHED",
1960 "id": "15e59938-07d5-11e1-90e3-ee32ba30feaa",
1961 "created_at": "2011-09-09T00:00:00Z",
1962 "attached": "2011-11-11T00:00:00Z",
1963 "size": 1024,
1964 "attachments": [
1965 {"id": "2222",
1966 "links": ''}],
1967 "metadata": {}}]})
1968
1969 def get_volumes(self, **kw):
1970 return (200, {}, {"volumes": [
1971 {
1972 "display_name": "Work",
1973 "display_description": "volume for work",
1974 "status": "ATTACHED",
1975 "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983",
1976 "created_at": "2011-09-09T00:00:00Z",
1977 "attached": "2011-11-11T00:00:00Z",
1978 "size": 1024,
1979 "attachments": [
1980 {"id": "3333",
1981 "links": ''}],
1982 "metadata": {}},
1983 {
1984 "display_name": "Work2",
1985 "display_description": "volume for work2",
1986 "status": "ATTACHED",
1987 "id": "15e59938-07d5-11e1-90e3-ee32ba30feaa",
1988 "created_at": "2011-09-09T00:00:00Z",
1989 "attached": "2011-11-11T00:00:00Z",
1990 "size": 1024,
1991 "attachments": [
1992 {"id": "2222",
1993 "links": ''}],
1994 "metadata": {}}]})
1995
1996 def get_volumes_15e59938_07d5_11e1_90e3_e3dffe0c5983(self, **kw):
1997 return (200, {}, {
1998 "volume": self.get_volumes_detail()[2]['volumes'][0]})
1999
2000 def get_volumes_15e59938_07d5_11e1_90e3_ee32ba30feaa(self, **kw):
2001 return (200, {}, {
2002 "volume": self.get_volumes_detail()[2]['volumes'][1]})
2003
2004 def post_volumes(self, **kw):
2005 return (200, {}, {"volume":
2006 {"status": "creating",
2007 "display_name": "vol-007",
2008 "attachments": [(0)],
2009 "availability_zone": "cinder",
2010 "created_at": "2012-08-13T10:57:17.000000",
2011 "display_description": "create volume from image",
2012 "image_id": "f4cf905f-7c58-4d7b-8314-8dd8a2d1d483",
2013 "volume_type": "None",
2014 "metadata": {},
2015 "id": "5cb239f6-1baf-4fe1-bd78-c852cf00fa39",
2016 "size": 1}})
2017
2018 def delete_volumes_15e59938_07d5_11e1_90e3_e3dffe0c5983(self, **kw):
2019 return (200, {}, {})
2020
2021 def delete_volumes_15e59938_07d5_11e1_90e3_ee32ba30feaa(self, **kw):
2022 return (200, {}, {})
2023
2024 def post_servers_1234_os_volume_attachments(self, **kw):
2025 return (200, {}, {
2026 "volumeAttachment":
2027 {"device": "/dev/vdb",
2028 "volumeId": 2}})
2029
2030 def put_servers_1234_os_volume_attachments_Work(self, **kw):
2031 return (200, {}, {"volumeAttachment": {"volumeId": 2}})
2032
2033 def get_servers_1234_os_volume_attachments(self, **kw):
2034 return (200, {}, {
2035 "volumeAttachments": [
2036 {"display_name": "Work",
2037 "display_description": "volume for work",
2038 "status": "ATTACHED",
2039 "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983",
2040 "created_at": "2011-09-09T00:00:00Z",
2041 "attached": "2011-11-11T00:00:00Z",
2042 "size": 1024,
2043 "attachments": [{"id": "3333", "links": ''}],
2044 "metadata": {}}]})
2045
2046 def get_servers_1234_os_volume_attachments_Work(self, **kw):
2047 return (200, {}, {
2048 "volumeAttachment":
2049 {"display_name": "Work",
2050 "display_description": "volume for work",
2051 "status": "ATTACHED",
2052 "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983",
2053 "created_at": "2011-09-09T00:00:00Z",
2054 "attached": "2011-11-11T00:00:00Z",
2055 "size": 1024,
2056 "attachments": [{"id": "3333", "links": ''}],
2057 "metadata": {}}})
2058
2059 def delete_servers_1234_os_volume_attachments_Work(self, **kw):
2060 return (200, {}, {})
2061
2062 def get_servers_1234_os_instance_actions(self, **kw):
2063 return (200, {}, {
2064 "instanceActions":
2065 [{"instance_uuid": "1234",
2066 "user_id": "b968c25e04ab405f9fe4e6ca54cce9a5",
2067 "start_time": "2013-03-25T13:45:09.000000",
2068 "request_id": "req-abcde12345",
2069 "action": "create",
2070 "message": None,
2071 "project_id": "04019601fe3648c0abd4f4abfb9e6106"}]})
2072
2073 def get_servers_1234_os_instance_actions_req_abcde12345(self, **kw):
2074 return (200, {}, {
2075 "instanceAction":
2076 {"instance_uuid": "1234",
2077 "user_id": "b968c25e04ab405f9fe4e6ca54cce9a5",
2078 "start_time": "2013-03-25T13:45:09.000000",
2079 "request_id": "req-abcde12345",
2080 "action": "create",
2081 "message": None,
2082 "project_id": "04019601fe3648c0abd4f4abfb9e6106"}})
2083
2084 def post_servers_uuid1_action(self, **kw):
2085 return 202, {}, {}
2086
2087 def post_servers_uuid2_action(self, **kw):
2088 return 202, {}, {}
2089
2090 def post_servers_uuid3_action(self, **kw):
2091 return 202, {}, {}
2092
2093 def post_servers_uuid4_action(self, **kw):
2094 return 202, {}, {}
2095
2096 def get_os_cells_child_cell(self, **kw):
2097 cell = {'cell': {
2098 'username': 'cell1_user',
2099 'name': 'cell1',
2100 'rpc_host': '10.0.1.10',
2101 'info': {
2102 'username': 'cell1_user',
2103 'rpc_host': '10.0.1.10',
2104 'type': 'child',
2105 'name': 'cell1',
2106 'rpc_port': 5673},
2107 'type': 'child',
2108 'rpc_port': 5673,
2109 'loaded': True
2110 }}
2111 return (200, {}, cell)
2112
2113 def get_os_cells_capacities(self, **kw):
2114 cell_capacities_response = {"cell": {"capacities": {"ram_free": {
2115 "units_by_mb": {"8192": 0, "512": 13, "4096": 1, "2048": 3,
2116 "16384": 0}, "total_mb": 7680}, "disk_free": {
2117 "units_by_mb": {"81920": 11, "20480": 46, "40960": 23, "163840": 5,
2118 "0": 0}, "total_mb": 1052672}}}}
2119 return (200, {}, cell_capacities_response)
2120
2121 def get_os_cells_child_cell_capacities(self, **kw):
2122 return self.get_os_cells_capacities()
2123
2124 def get_os_migrations(self, **kw):
2125 migrations = {'migrations': [
2126 {
2127 "created_at": "2012-10-29T13:42:02.000000",
2128 "dest_compute": "compute2",
2129 "dest_host": "1.2.3.4",
2130 "dest_node": "node2",
2131 "id": 1234,
2132 "instance_uuid": "instance_id_123",
2133 "new_instance_type_id": 2,
2134 "old_instance_type_id": 1,
2135 "source_compute": "compute1",
2136 "source_node": "node1",
2137 "status": "Done",
2138 "updated_at": "2012-10-29T13:42:02.000000"
2139 }]}
2140 return (200, {}, migrations)
2141
2142 def post_os_server_external_events(self, **kw):
2143 return (200, {}, {'events': [
2144 {'name': 'network-changed',
2145 'server_uuid': '1234'}]})
2146
2147 #
2148 # Server Groups
2149 #
2150
2151 def get_os_server_groups(self, *kw):
2152 return (200, {},
2153 {"server_groups": [
2154 {"members": [], "metadata": {},
2155 "id": "2cbd51f4-fafe-4cdb-801b-cf913a6f288b",
2156 "policies": [], "name": "ig1"},
2157 {"members": [], "metadata": {},
2158 "id": "4473bb03-4370-4bfb-80d3-dc8cffc47d94",
2159 "policies": ["anti-affinity"], "name": "ig2"},
2160 {"members": [], "metadata": {"key": "value"},
2161 "id": "31ab9bdb-55e1-4ac3-b094-97eeb1b65cc4",
2162 "policies": [], "name": "ig3"},
2163 {"members": ["2dccb4a1-02b9-482a-aa23-5799490d6f5d"],
2164 "metadata": {},
2165 "id": "4890bb03-7070-45fb-8453-d34556c87d94",
2166 "policies": ["anti-affinity"], "name": "ig2"}]})
2167
2168 def _return_server_group(self):
2169 r = {'server_group':
2170 self.get_os_server_groups()[2]['server_groups'][0]}
2171 return (200, {}, r)
2172
2173 def post_os_server_groups(self, body, **kw):
2174 return self._return_server_group()
2175
2176 def get_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b(self, **kw):
2177 return self._return_server_group()
2178
2179 def put_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b(self, **kw):
2180 return self._return_server_group()
2181
2182 def post_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b_action(
2183 self, body, **kw):
2184 return self._return_server_group()
2185
2186 def delete_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b(
2187 self, **kw):
2188 return (202, {}, None)
2189
2190
2191class FakeSessionClient(fakes.FakeClient, client.Client):
2192
2193 def __init__(self, *args, **kwargs):
2194 client.Client.__init__(self, 'username', 'password',
2195 'project_id', 'auth_url',
2196 extensions=kwargs.get('extensions'))
2197 self.client = FakeSessionMockClient(**kwargs)
2198
2199
2200class FakeSessionMockClient(base_client.SessionClient, FakeHTTPClient):
2201
2202 def __init__(self, *args, **kwargs):
2203
2204 self.callstack = []
2205 self.auth = mock.Mock()
2206 self.session = mock.Mock()
2207
2208 self.auth.get_auth_ref.return_value.project_id = 'tenant_id'
2209
2210 def request(self, url, method, **kwargs):
2211 return self._cs_request(url, method, **kwargs)
diff --git a/novaclient/tests/unit/v2/test_agents.py b/novaclient/tests/unit/v2/test_agents.py
new file mode 100644
index 0000000..e7fa7d6
--- /dev/null
+++ b/novaclient/tests/unit/v2/test_agents.py
@@ -0,0 +1,104 @@
1# Copyright 2012 IBM Corp.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient.tests.unit.fixture_data import agents as data
17from novaclient.tests.unit.fixture_data import client
18from novaclient.tests.unit import utils
19from novaclient.v2 import agents
20
21
22class AgentsTest(utils.FixturedTestCase):
23
24 data_fixture_class = data.Fixture
25
26 scenarios = [('original', {'client_fixture_class': client.V1}),
27 ('session', {'client_fixture_class': client.SessionV1})]
28
29 def stub_hypervisors(self, hypervisor='kvm'):
30 get_os_agents = {
31 'agents': [
32 {
33 'hypervisor': hypervisor,
34 'os': 'win',
35 'architecture': 'x86',
36 'version': '7.0',
37 'url': 'xxx://xxxx/xxx/xxx',
38 'md5hash': 'add6bb58e139be103324d04d82d8f545',
39 'id': 1
40 },
41 {
42 'hypervisor': hypervisor,
43 'os': 'linux',
44 'architecture': 'x86',
45 'version': '16.0',
46 'url': 'xxx://xxxx/xxx/xxx1',
47 'md5hash': 'add6bb58e139be103324d04d82d8f546',
48 'id': 2
49 },
50 ]
51 }
52
53 headers = {'Content-Type': 'application/json'}
54 self.requests.register_uri('GET', self.data_fixture.url(),
55 json=get_os_agents,
56 headers=headers)
57
58 def test_list_agents(self):
59 self.stub_hypervisors()
60 ags = self.cs.agents.list()
61 self.assert_called('GET', '/os-agents')
62 for a in ags:
63 self.assertIsInstance(a, agents.Agent)
64 self.assertEqual('kvm', a.hypervisor)
65
66 def test_list_agents_with_hypervisor(self):
67 self.stub_hypervisors('xen')
68 ags = self.cs.agents.list('xen')
69 self.assert_called('GET', '/os-agents?hypervisor=xen')
70 for a in ags:
71 self.assertIsInstance(a, agents.Agent)
72 self.assertEqual('xen', a.hypervisor)
73
74 def test_agents_create(self):
75 ag = self.cs.agents.create('win', 'x86', '7.0',
76 '/xxx/xxx/xxx',
77 'add6bb58e139be103324d04d82d8f546',
78 'xen')
79 body = {'agent': {'url': '/xxx/xxx/xxx',
80 'hypervisor': 'xen',
81 'md5hash': 'add6bb58e139be103324d04d82d8f546',
82 'version': '7.0',
83 'architecture': 'x86',
84 'os': 'win'}}
85 self.assert_called('POST', '/os-agents', body)
86 self.assertEqual(1, ag._info.copy()['id'])
87
88 def test_agents_delete(self):
89 self.cs.agents.delete('1')
90 self.assert_called('DELETE', '/os-agents/1')
91
92 def _build_example_update_body(self):
93 return {"para": {
94 "url": "/yyy/yyyy/yyyy",
95 "version": "8.0",
96 "md5hash": "add6bb58e139be103324d04d82d8f546"}}
97
98 def test_agents_modify(self):
99 ag = self.cs.agents.update('1', '8.0',
100 '/yyy/yyyy/yyyy',
101 'add6bb58e139be103324d04d82d8f546')
102 body = self._build_example_update_body()
103 self.assert_called('PUT', '/os-agents/1', body)
104 self.assertEqual(1, ag.id)
diff --git a/novaclient/tests/unit/v2/test_aggregates.py b/novaclient/tests/unit/v2/test_aggregates.py
new file mode 100644
index 0000000..97a3ffc
--- /dev/null
+++ b/novaclient/tests/unit/v2/test_aggregates.py
@@ -0,0 +1,141 @@
1# Copyright 2012 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient.tests.unit.fixture_data import aggregates as data
17from novaclient.tests.unit.fixture_data import client
18from novaclient.tests.unit import utils
19from novaclient.v2 import aggregates
20
21
22class AggregatesTest(utils.FixturedTestCase):
23
24 data_fixture_class = data.Fixture
25
26 scenarios = [('original', {'client_fixture_class': client.V1}),
27 ('session', {'client_fixture_class': client.SessionV1})]
28
29 def test_list_aggregates(self):
30 result = self.cs.aggregates.list()
31 self.assert_called('GET', '/os-aggregates')
32 for aggregate in result:
33 self.assertIsInstance(aggregate, aggregates.Aggregate)
34
35 def test_create_aggregate(self):
36 body = {"aggregate": {"name": "test", "availability_zone": "nova1"}}
37 aggregate = self.cs.aggregates.create("test", "nova1")
38 self.assert_called('POST', '/os-aggregates', body)
39 self.assertIsInstance(aggregate, aggregates.Aggregate)
40
41 def test_get(self):
42 aggregate = self.cs.aggregates.get("1")
43 self.assert_called('GET', '/os-aggregates/1')
44 self.assertIsInstance(aggregate, aggregates.Aggregate)
45
46 aggregate2 = self.cs.aggregates.get(aggregate)
47 self.assert_called('GET', '/os-aggregates/1')
48 self.assertIsInstance(aggregate2, aggregates.Aggregate)
49
50 def test_get_details(self):
51 aggregate = self.cs.aggregates.get_details("1")
52 self.assert_called('GET', '/os-aggregates/1')
53 self.assertIsInstance(aggregate, aggregates.Aggregate)
54
55 aggregate2 = self.cs.aggregates.get_details(aggregate)
56 self.assert_called('GET', '/os-aggregates/1')
57 self.assertIsInstance(aggregate2, aggregates.Aggregate)
58
59 def test_update(self):
60 aggregate = self.cs.aggregates.get("1")
61 values = {"name": "foo"}
62 body = {"aggregate": values}
63
64 result1 = aggregate.update(values)
65 self.assert_called('PUT', '/os-aggregates/1', body)
66 self.assertIsInstance(result1, aggregates.Aggregate)
67
68 result2 = self.cs.aggregates.update(2, values)
69 self.assert_called('PUT', '/os-aggregates/2', body)
70 self.assertIsInstance(result2, aggregates.Aggregate)
71
72 def test_update_with_availability_zone(self):
73 aggregate = self.cs.aggregates.get("1")
74 values = {"name": "foo", "availability_zone": "new_zone"}
75 body = {"aggregate": values}
76
77 result3 = self.cs.aggregates.update(aggregate, values)
78 self.assert_called('PUT', '/os-aggregates/1', body)
79 self.assertIsInstance(result3, aggregates.Aggregate)
80
81 def test_add_host(self):
82 aggregate = self.cs.aggregates.get("1")
83 host = "host1"
84 body = {"add_host": {"host": "host1"}}
85
86 result1 = aggregate.add_host(host)
87 self.assert_called('POST', '/os-aggregates/1/action', body)
88 self.assertIsInstance(result1, aggregates.Aggregate)
89
90 result2 = self.cs.aggregates.add_host("2", host)
91 self.assert_called('POST', '/os-aggregates/2/action', body)
92 self.assertIsInstance(result2, aggregates.Aggregate)
93
94 result3 = self.cs.aggregates.add_host(aggregate, host)
95 self.assert_called('POST', '/os-aggregates/1/action', body)
96 self.assertIsInstance(result3, aggregates.Aggregate)
97
98 def test_remove_host(self):
99 aggregate = self.cs.aggregates.get("1")
100 host = "host1"
101 body = {"remove_host": {"host": "host1"}}
102
103 result1 = aggregate.remove_host(host)
104 self.assert_called('POST', '/os-aggregates/1/action', body)
105 self.assertIsInstance(result1, aggregates.Aggregate)
106
107 result2 = self.cs.aggregates.remove_host("2", host)
108 self.assert_called('POST', '/os-aggregates/2/action', body)
109 self.assertIsInstance(result2, aggregates.Aggregate)
110
111 result3 = self.cs.aggregates.remove_host(aggregate, host)
112 self.assert_called('POST', '/os-aggregates/1/action', body)
113 self.assertIsInstance(result3, aggregates.Aggregate)
114
115 def test_set_metadata(self):
116 aggregate = self.cs.aggregates.get("1")
117 metadata = {"foo": "bar"}
118 body = {"set_metadata": {"metadata": metadata}}
119
120 result1 = aggregate.set_metadata(metadata)
121 self.assert_called('POST', '/os-aggregates/1/action', body)
122 self.assertIsInstance(result1, aggregates.Aggregate)
123
124 result2 = self.cs.aggregates.set_metadata(2, metadata)
125 self.assert_called('POST', '/os-aggregates/2/action', body)
126 self.assertIsInstance(result2, aggregates.Aggregate)
127
128 result3 = self.cs.aggregates.set_metadata(aggregate, metadata)
129 self.assert_called('POST', '/os-aggregates/1/action', body)
130 self.assertIsInstance(result3, aggregates.Aggregate)
131
132 def test_delete_aggregate(self):
133 aggregate = self.cs.aggregates.list()[0]
134 aggregate.delete()
135 self.assert_called('DELETE', '/os-aggregates/1')
136
137 self.cs.aggregates.delete('1')
138 self.assert_called('DELETE', '/os-aggregates/1')
139
140 self.cs.aggregates.delete(aggregate)
141 self.assert_called('DELETE', '/os-aggregates/1')
diff --git a/novaclient/tests/unit/v2/test_auth.py b/novaclient/tests/unit/v2/test_auth.py
new file mode 100644
index 0000000..95e96de
--- /dev/null
+++ b/novaclient/tests/unit/v2/test_auth.py
@@ -0,0 +1,386 @@
1#
2# Licensed under the Apache License, Version 2.0 (the "License"); you may
3# not use this file except in compliance with the License. You may obtain
4# a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11# License for the specific language governing permissions and limitations
12# under the License.
13
14import copy
15import json
16
17from keystoneclient import fixture
18import mock
19import requests
20
21from novaclient import exceptions
22from novaclient.tests.unit import utils
23from novaclient.v2 import client
24
25
26class AuthenticateAgainstKeystoneTests(utils.TestCase):
27
28 def get_token(self, **kwargs):
29 resp = fixture.V2Token(**kwargs)
30 resp.set_scope()
31
32 s = resp.add_service('compute')
33 s.add_endpoint('http://localhost:8774/v1.1', region='RegionOne')
34
35 return resp
36
37 def test_authenticate_success(self):
38 cs = client.Client("username", "password", "project_id",
39 utils.AUTH_URL_V2, service_type='compute')
40 resp = self.get_token()
41
42 auth_response = utils.TestResponse({
43 "status_code": 200,
44 "text": json.dumps(resp),
45 })
46
47 mock_request = mock.Mock(return_value=(auth_response))
48
49 @mock.patch.object(requests, "request", mock_request)
50 def test_auth_call():
51 cs.client.authenticate()
52 headers = {
53 'User-Agent': cs.client.USER_AGENT,
54 'Content-Type': 'application/json',
55 'Accept': 'application/json',
56 }
57 body = {
58 'auth': {
59 'passwordCredentials': {
60 'username': cs.client.user,
61 'password': cs.client.password,
62 },
63 'tenantName': cs.client.projectid,
64 },
65 }
66
67 token_url = cs.client.auth_url + "/tokens"
68 mock_request.assert_called_with(
69 "POST",
70 token_url,
71 headers=headers,
72 data=json.dumps(body),
73 allow_redirects=True,
74 **self.TEST_REQUEST_BASE)
75
76 endpoints = resp["access"]["serviceCatalog"][0]['endpoints']
77 public_url = endpoints[0]["publicURL"].rstrip('/')
78 self.assertEqual(cs.client.management_url, public_url)
79 token_id = resp["access"]["token"]["id"]
80 self.assertEqual(cs.client.auth_token, token_id)
81
82 test_auth_call()
83
84 def test_authenticate_failure(self):
85 cs = client.Client("username", "password", "project_id",
86 utils.AUTH_URL_V2)
87 resp = {"unauthorized": {"message": "Unauthorized", "code": "401"}}
88 auth_response = utils.TestResponse({
89 "status_code": 401,
90 "text": json.dumps(resp),
91 })
92
93 mock_request = mock.Mock(return_value=(auth_response))
94
95 @mock.patch.object(requests.Session, "request", mock_request)
96 def test_auth_call():
97 self.assertRaises(exceptions.Unauthorized, cs.client.authenticate)
98
99 test_auth_call()
100
101 def test_v1_auth_redirect(self):
102 cs = client.Client("username", "password", "project_id",
103 utils.AUTH_URL_V1, service_type='compute')
104 dict_correct_response = self.get_token()
105 correct_response = json.dumps(dict_correct_response)
106 dict_responses = [
107 {"headers": {'location': 'http://127.0.0.1:5001'},
108 "status_code": 305,
109 "text": "Use proxy"},
110 # Configured on admin port, nova redirects to v2.0 port.
111 # When trying to connect on it, keystone auth succeed by v1.0
112 # protocol (through headers) but tokens are being returned in
113 # body (looks like keystone bug). Leaved for compatibility.
114 {"headers": {},
115 "status_code": 200,
116 "text": correct_response},
117 {"headers": {},
118 "status_code": 200,
119 "text": correct_response}
120 ]
121
122 responses = [(utils.TestResponse(resp)) for resp in dict_responses]
123
124 def side_effect(*args, **kwargs):
125 return responses.pop(0)
126
127 mock_request = mock.Mock(side_effect=side_effect)
128
129 @mock.patch.object(requests, "request", mock_request)
130 def test_auth_call():
131 cs.client.authenticate()
132 headers = {
133 'User-Agent': cs.client.USER_AGENT,
134 'Content-Type': 'application/json',
135 'Accept': 'application/json',
136 }
137 body = {
138 'auth': {
139 'passwordCredentials': {
140 'username': cs.client.user,
141 'password': cs.client.password,
142 },
143 'tenantName': cs.client.projectid,
144 },
145 }
146
147 token_url = cs.client.auth_url + "/tokens"
148 kwargs = copy.copy(self.TEST_REQUEST_BASE)
149 kwargs['headers'] = headers
150 kwargs['data'] = json.dumps(body)
151 mock_request.assert_called_with(
152 "POST",
153 token_url,
154 allow_redirects=True,
155 **kwargs)
156
157 resp = dict_correct_response
158 endpoints = resp["access"]["serviceCatalog"][0]['endpoints']
159 public_url = endpoints[0]["publicURL"].rstrip('/')
160 self.assertEqual(cs.client.management_url, public_url)
161 token_id = resp["access"]["token"]["id"]
162 self.assertEqual(cs.client.auth_token, token_id)
163
164 test_auth_call()
165
166 def test_v2_auth_redirect(self):
167 cs = client.Client("username", "password", "project_id",
168 utils.AUTH_URL_V2, service_type='compute')
169 dict_correct_response = self.get_token()
170 correct_response = json.dumps(dict_correct_response)
171 dict_responses = [
172 {"headers": {'location': 'http://127.0.0.1:5001'},
173 "status_code": 305,
174 "text": "Use proxy"},
175 # Configured on admin port, nova redirects to v2.0 port.
176 # When trying to connect on it, keystone auth succeed by v1.0
177 # protocol (through headers) but tokens are being returned in
178 # body (looks like keystone bug). Leaved for compatibility.
179 {"headers": {},
180 "status_code": 200,
181 "text": correct_response},
182 {"headers": {},
183 "status_code": 200,
184 "text": correct_response}
185 ]
186
187 responses = [(utils.TestResponse(resp)) for resp in dict_responses]
188
189 def side_effect(*args, **kwargs):
190 return responses.pop(0)
191
192 mock_request = mock.Mock(side_effect=side_effect)
193
194 @mock.patch.object(requests, "request", mock_request)
195 def test_auth_call():
196 cs.client.authenticate()
197 headers = {
198 'User-Agent': cs.client.USER_AGENT,
199 'Content-Type': 'application/json',
200 'Accept': 'application/json',
201 }
202 body = {
203 'auth': {
204 'passwordCredentials': {
205 'username': cs.client.user,
206 'password': cs.client.password,
207 },
208 'tenantName': cs.client.projectid,
209 },
210 }
211
212 token_url = cs.client.auth_url + "/tokens"
213 kwargs = copy.copy(self.TEST_REQUEST_BASE)
214 kwargs['headers'] = headers
215 kwargs['data'] = json.dumps(body)
216 mock_request.assert_called_with(
217 "POST",
218 token_url,
219 allow_redirects=True,
220 **kwargs)
221
222 resp = dict_correct_response
223 endpoints = resp["access"]["serviceCatalog"][0]['endpoints']
224 public_url = endpoints[0]["publicURL"].rstrip('/')
225 self.assertEqual(cs.client.management_url, public_url)
226 token_id = resp["access"]["token"]["id"]
227 self.assertEqual(cs.client.auth_token, token_id)
228
229 test_auth_call()
230
231 def test_ambiguous_endpoints(self):
232 cs = client.Client("username", "password", "project_id",
233 utils.AUTH_URL_V2, service_type='compute')
234 resp = self.get_token()
235
236 # duplicate existing service
237 s = resp.add_service('compute')
238 s.add_endpoint('http://localhost:8774/v1.1', region='RegionOne')
239
240 auth_response = utils.TestResponse({
241 "status_code": 200,
242 "text": json.dumps(resp),
243 })
244
245 mock_request = mock.Mock(return_value=(auth_response))
246
247 @mock.patch.object(requests.Session, "request", mock_request)
248 def test_auth_call():
249 self.assertRaises(exceptions.AmbiguousEndpoints,
250 cs.client.authenticate)
251
252 test_auth_call()
253
254 def test_authenticate_with_token_success(self):
255 cs = client.Client("username", None, "project_id",
256 utils.AUTH_URL_V2, service_type='compute')
257 cs.client.auth_token = "FAKE_ID"
258 resp = self.get_token(token_id="FAKE_ID")
259 auth_response = utils.TestResponse({
260 "status_code": 200,
261 "text": json.dumps(resp),
262 })
263
264 mock_request = mock.Mock(return_value=(auth_response))
265
266 with mock.patch.object(requests, "request", mock_request):
267 cs.client.authenticate()
268 headers = {
269 'User-Agent': cs.client.USER_AGENT,
270 'Content-Type': 'application/json',
271 'Accept': 'application/json',
272 }
273 body = {
274 'auth': {
275 'token': {
276 'id': cs.client.auth_token,
277 },
278 'tenantName': cs.client.projectid,
279 },
280 }
281
282 token_url = cs.client.auth_url + "/tokens"
283 mock_request.assert_called_with(
284 "POST",
285 token_url,
286 headers=headers,
287 data=json.dumps(body),
288 allow_redirects=True,
289 **self.TEST_REQUEST_BASE)
290
291 endpoints = resp["access"]["serviceCatalog"][0]['endpoints']
292 public_url = endpoints[0]["publicURL"].rstrip('/')
293 self.assertEqual(cs.client.management_url, public_url)
294 token_id = resp["access"]["token"]["id"]
295 self.assertEqual(cs.client.auth_token, token_id)
296
297 def test_authenticate_with_token_failure(self):
298 cs = client.Client("username", None, "project_id", utils.AUTH_URL_V2)
299 cs.client.auth_token = "FAKE_ID"
300 resp = {"unauthorized": {"message": "Unauthorized", "code": "401"}}
301 auth_response = utils.TestResponse({
302 "status_code": 401,
303 "text": json.dumps(resp),
304 })
305
306 mock_request = mock.Mock(return_value=(auth_response))
307
308 with mock.patch.object(requests.Session, "request", mock_request):
309 self.assertRaises(exceptions.Unauthorized, cs.client.authenticate)
310
311
312class AuthenticationTests(utils.TestCase):
313 def test_authenticate_success(self):
314 cs = client.Client("username", "password",
315 "project_id", utils.AUTH_URL)
316 management_url = 'https://localhost/v1.1/443470'
317 auth_response = utils.TestResponse({
318 'status_code': 204,
319 'headers': {
320 'x-server-management-url': management_url,
321 'x-auth-token': '1b751d74-de0c-46ae-84f0-915744b582d1',
322 },
323 })
324 mock_request = mock.Mock(return_value=(auth_response))
325
326 @mock.patch.object(requests, "request", mock_request)
327 def test_auth_call():
328 cs.client.authenticate()
329 headers = {
330 'Accept': 'application/json',
331 'X-Auth-User': 'username',
332 'X-Auth-Key': 'password',
333 'X-Auth-Project-Id': 'project_id',
334 'User-Agent': cs.client.USER_AGENT
335 }
336 mock_request.assert_called_with(
337 "GET",
338 cs.client.auth_url,
339 headers=headers,
340 **self.TEST_REQUEST_BASE)
341
342 self.assertEqual(cs.client.management_url,
343 auth_response.headers['x-server-management-url'])
344 self.assertEqual(cs.client.auth_token,
345 auth_response.headers['x-auth-token'])
346
347 test_auth_call()
348
349 def test_authenticate_failure(self):
350 cs = client.Client("username", "password",
351 "project_id", utils.AUTH_URL)
352 auth_response = utils.TestResponse({'status_code': 401})
353 mock_request = mock.Mock(return_value=(auth_response))
354
355 @mock.patch.object(requests, "request", mock_request)
356 def test_auth_call():
357 self.assertRaises(exceptions.Unauthorized, cs.client.authenticate)
358
359 test_auth_call()
360
361 def test_auth_automatic(self):
362 cs = client.Client("username", "password",
363 "project_id", utils.AUTH_URL)
364 http_client = cs.client
365 http_client.management_url = ''
366 mock_request = mock.Mock(return_value=(None, None))
367
368 @mock.patch.object(http_client, 'request', mock_request)
369 @mock.patch.object(http_client, 'authenticate')
370 def test_auth_call(m):
371 http_client.get('/')
372 self.assertTrue(m.called)
373 self.assertTrue(mock_request.called)
374
375 test_auth_call()
376
377 def test_auth_manual(self):
378 cs = client.Client("username", "password",
379 "project_id", utils.AUTH_URL)
380
381 @mock.patch.object(cs.client, 'authenticate')
382 def test_auth_call(m):
383 cs.authenticate()
384 self.assertTrue(m.called)
385
386 test_auth_call()
diff --git a/novaclient/tests/unit/v2/test_availability_zone.py b/novaclient/tests/unit/v2/test_availability_zone.py
new file mode 100644
index 0000000..a7d6d82
--- /dev/null
+++ b/novaclient/tests/unit/v2/test_availability_zone.py
@@ -0,0 +1,102 @@
1# Copyright 2011 OpenStack Foundation
2# Copyright 2013 IBM Corp.
3# All Rights Reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17import six
18
19from novaclient.tests.unit.fixture_data import availability_zones as data
20from novaclient.tests.unit.fixture_data import client
21from novaclient.tests.unit import utils
22from novaclient.v2 import availability_zones
23
24
25class AvailabilityZoneTest(utils.FixturedTestCase):
26 # NOTE(cyeoh): import shell here so the V3 version of
27 # this class can inherit off the v3 version of shell
28 from novaclient.v2 import shell # noqa
29
30 data_fixture_class = data.V1
31
32 scenarios = [('original', {'client_fixture_class': client.V1}),
33 ('session', {'client_fixture_class': client.SessionV1})]
34
35 def setUp(self):
36 super(AvailabilityZoneTest, self).setUp()
37 self.availability_zone_type = self._get_availability_zone_type()
38
39 def _get_availability_zone_type(self):
40 return availability_zones.AvailabilityZone
41
42 def _assertZone(self, zone, name, status):
43 self.assertEqual(zone.zoneName, name)
44 self.assertEqual(zone.zoneState, status)
45
46 def test_list_availability_zone(self):
47 zones = self.cs.availability_zones.list(detailed=False)
48 self.assert_called('GET', '/os-availability-zone')
49
50 for zone in zones:
51 self.assertIsInstance(zone, self.availability_zone_type)
52
53 self.assertEqual(2, len(zones))
54
55 l0 = [six.u('zone-1'), six.u('available')]
56 l1 = [six.u('zone-2'), six.u('not available')]
57
58 z0 = self.shell._treeizeAvailabilityZone(zones[0])
59 z1 = self.shell._treeizeAvailabilityZone(zones[1])
60
61 self.assertEqual((1, 1), (len(z0), len(z1)))
62
63 self._assertZone(z0[0], l0[0], l0[1])
64 self._assertZone(z1[0], l1[0], l1[1])
65
66 def test_detail_availability_zone(self):
67 zones = self.cs.availability_zones.list(detailed=True)
68 self.assert_called('GET', '/os-availability-zone/detail')
69
70 for zone in zones:
71 self.assertIsInstance(zone, self.availability_zone_type)
72
73 self.assertEqual(3, len(zones))
74
75 l0 = [six.u('zone-1'), six.u('available')]
76 l1 = [six.u('|- fake_host-1'), six.u('')]
77 l2 = [six.u('| |- nova-compute'),
78 six.u('enabled :-) 2012-12-26 14:45:25')]
79 l3 = [six.u('internal'), six.u('available')]
80 l4 = [six.u('|- fake_host-1'), six.u('')]
81 l5 = [six.u('| |- nova-sched'),
82 six.u('enabled :-) 2012-12-26 14:45:25')]
83 l6 = [six.u('|- fake_host-2'), six.u('')]
84 l7 = [six.u('| |- nova-network'),
85 six.u('enabled XXX 2012-12-26 14:45:24')]
86 l8 = [six.u('zone-2'), six.u('not available')]
87