summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsusaant <susaant.kondapaneni@oneconvergence.com>2014-10-24 19:31:27 -0700
committerSusaant Kondapaneni <susaant.kondapaneni@oneconvergence.com>2014-11-11 02:18:23 +0000
commit539862c03b1a8c0b6a4d7c0e5efb19ba3d6504a5 (patch)
tree3b89ce58302b8044181c416163b625416b5d4023
parentca098b6bc56e8073890b4d00223e5acd6dca5288 (diff)
Implementation of GBP ServiceChain resources
This patch implements: ServiceChain Node ServiceChain Spec Implements: blueprint group-based-policy-automation Change-Id: I4ac1e924a492949b54e76f8f99e0dc951a0e82ef
Notes
Notes (review): Verified+2: Jenkins Code-Review+2: Subrahmanyam Ongole <songole@oneconvergence.com> Workflow+1: Subrahmanyam Ongole <songole@oneconvergence.com> Code-Review+2: Hemanth Ravi <hemanth.ravi@oneconvergence.com> Submitted-by: Jenkins Submitted-at: Wed, 12 Nov 2014 20:21:19 +0000 Reviewed-on: https://review.openstack.org/130918 Project: stackforge/group-based-policy-automation Branch: refs/heads/master
-rw-r--r--gbpautomation/heat/engine/resources/neutron/servicechain.py166
-rw-r--r--gbpautomation/heat/tests/test_servicechain.py278
2 files changed, 444 insertions, 0 deletions
diff --git a/gbpautomation/heat/engine/resources/neutron/servicechain.py b/gbpautomation/heat/engine/resources/neutron/servicechain.py
new file mode 100644
index 0000000..c402088
--- /dev/null
+++ b/gbpautomation/heat/engine/resources/neutron/servicechain.py
@@ -0,0 +1,166 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
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 gbpautomation.heat.engine.resources.neutron import gbpresource
17from neutronclient.common.exceptions import NeutronClientException
18
19from heat.engine import properties
20
21
22class ServiceChainNode(gbpresource.GBPResource):
23
24 PROPERTIES = (
25 TENANT_ID, NAME, DESCRIPTION, SERVICE_TYPE, CONFIG
26 ) = (
27 'tenant_id', 'name', 'description', 'service_type', 'config'
28 )
29
30 properties_schema = {
31 TENANT_ID: properties.Schema(
32 properties.Schema.STRING,
33 _('Tenant id of the service chain node.')
34 ),
35 NAME: properties.Schema(
36 properties.Schema.STRING,
37 _('Name of the service chain node.'),
38 update_allowed=True
39 ),
40 DESCRIPTION: properties.Schema(
41 properties.Schema.STRING,
42 _('Description of the service chain node.'),
43 update_allowed=True
44 ),
45 SERVICE_TYPE: properties.Schema(
46 properties.Schema.STRING,
47 _('Type of service in the service chain node.'),
48 required=True,
49 update_allowed=True
50 ),
51 CONFIG: properties.Schema(
52 properties.Schema.STRING,
53 _('Configuration of the service chain node.'),
54 required=True,
55 update_allowed=False
56 )
57 }
58
59 def _show_resource(self):
60 client = self.grouppolicy()
61 sc_node_id = self.resource_id
62 return client.show_servicechain_node(sc_node_id)['servicechain_node']
63
64 def handle_create(self):
65 client = self.grouppolicy()
66
67 props = {}
68 for key in self.properties:
69 if self.properties.get(key) is not None:
70 props[key] = self.properties.get(key)
71
72 sc_node = client.create_servicechain_node(
73 {'servicechain_node': props})['servicechain_node']
74
75 self.resource_id_set(sc_node['id'])
76
77 def handle_delete(self):
78
79 client = self.grouppolicy()
80 sc_node_id = self.resource_id
81
82 try:
83 client.delete_servicechain_node(sc_node_id)
84 except NeutronClientException as ex:
85 self.client_plugin().ignore_not_found(ex)
86 else:
87 return self._delete_task()
88
89 def handle_update(self, json_snippet, tmpl_diff, prop_diff):
90 if prop_diff:
91 self.grouppolicy().update_servicechain_node(
92 self.resource_id, {'servicechain_node': prop_diff})
93
94
95class ServiceChainSpec(gbpresource.GBPResource):
96
97 PROPERTIES = (
98 TENANT_ID, NAME, DESCRIPTION, NODES
99 ) = (
100 'tenant_id', 'name', 'description', 'nodes'
101 )
102
103 properties_schema = {
104 TENANT_ID: properties.Schema(
105 properties.Schema.STRING,
106 _('Tenant id of the service chain spec.')
107 ),
108 NAME: properties.Schema(
109 properties.Schema.STRING,
110 _('Name of the service chain spec.'),
111 update_allowed=True
112 ),
113 DESCRIPTION: properties.Schema(
114 properties.Schema.STRING,
115 _('Description of the service chain spec.'),
116 update_allowed=True
117 ),
118 NODES: properties.Schema(
119 properties.Schema.LIST,
120 _('Nodes in the service chain spec.'),
121 required=True,
122 update_allowed=True
123 )
124 }
125
126 def _show_resource(self):
127 client = self.grouppolicy()
128 sc_spec_id = self.resource_id
129 return client.show_servicechain_spec(sc_spec_id)['servicechain_spec']
130
131 def handle_create(self):
132 client = self.grouppolicy()
133
134 props = {}
135 for key in self.properties:
136 if self.properties.get(key) is not None:
137 props[key] = self.properties.get(key)
138
139 sc_spec = client.create_servicechain_spec(
140 {'servicechain_spec': props})['servicechain_spec']
141
142 self.resource_id_set(sc_spec['id'])
143
144 def handle_delete(self):
145
146 client = self.grouppolicy()
147 sc_spec_id = self.resource_id
148
149 try:
150 client.delete_servicechain_spec(sc_spec_id)
151 except NeutronClientException as ex:
152 self.client_plugin().ignore_not_found(ex)
153 else:
154 return self._delete_task()
155
156 def handle_update(self, json_snippet, tmpl_diff, prop_diff):
157 if prop_diff:
158 self.grouppolicy().update_servicechain_spec(
159 self.resource_id, {'servicechain_spec': prop_diff})
160
161
162def resource_mapping():
163 return {
164 'OS::Neutron::ServiceChainNode': ServiceChainNode,
165 'OS::Neutron::ServiceChainSpec': ServiceChainSpec,
166 }
diff --git a/gbpautomation/heat/tests/test_servicechain.py b/gbpautomation/heat/tests/test_servicechain.py
new file mode 100644
index 0000000..ece8cf2
--- /dev/null
+++ b/gbpautomation/heat/tests/test_servicechain.py
@@ -0,0 +1,278 @@
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
13import copy
14
15from gbpautomation.heat.engine.resources.neutron import servicechain
16from gbpclient.v2_0 import client as gbpclient
17from heat.common import exception
18from heat.common import template_format
19from heat.tests.common import HeatTestCase
20
21from heat.engine import scheduler
22from heat.tests import utils
23
24
25servicechain_node_template = '''
26{
27 "AWSTemplateFormatVersion" : "2010-09-09",
28 "Description" : "Template to test neutron service chain node",
29 "Parameters" : {},
30 "Resources" : {
31 "servicechain_node": {
32 "Type": "OS::Neutron::ServiceChainNode",
33 "Properties": {
34 "name": "test-sc-node",
35 "description": "test service chain node resource",
36 "service_type": "TAP",
37 "config": "{'name': 'sc_node_config'}"
38 }
39 }
40 }
41}
42'''
43
44servicechain_spec_template = '''
45{
46 "AWSTemplateFormatVersion" : "2010-09-09",
47 "Description" : "Template to test neutron service chain spec",
48 "Parameters" : {},
49 "Resources" : {
50 "servicechain_spec": {
51 "Type": "OS::Neutron::ServiceChainSpec",
52 "Properties": {
53 "name": "test-sc-spec",
54 "description": "test service chain spec resource",
55 "nodes": ["1234", "7890"]
56 }
57 }
58 }
59}
60'''
61
62
63class ServiceChainNodeTest(HeatTestCase):
64
65 def setUp(self):
66 super(ServiceChainNodeTest, self).setUp()
67 self.m.StubOutWithMock(gbpclient.Client, 'create_servicechain_node')
68 self.m.StubOutWithMock(gbpclient.Client, 'delete_servicechain_node')
69 self.m.StubOutWithMock(gbpclient.Client, 'show_servicechain_node')
70 self.m.StubOutWithMock(gbpclient.Client, 'update_servicechain_node')
71 self.stub_keystoneclient()
72
73 def create_servicechain_node(self):
74 gbpclient.Client.create_servicechain_node({
75 'servicechain_node': {
76 "name": "test-sc-node",
77 "description": "test service chain node resource",
78 "service_type": "TAP",
79 "config": "{'name': 'sc_node_config'}"
80 }
81 }).AndReturn({'servicechain_node': {'id': '5678'}})
82
83 snippet = template_format.parse(servicechain_node_template)
84 stack = utils.parse_stack(snippet)
85 resource_defns = stack.t.resource_definitions(stack)
86 return servicechain.ServiceChainNode(
87 'servicechain_node', resource_defns['servicechain_node'], stack)
88
89 def test_create(self):
90 rsrc = self.create_servicechain_node()
91 self.m.ReplayAll()
92 scheduler.TaskRunner(rsrc.create)()
93 self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
94 self.m.VerifyAll()
95
96 def test_create_failed(self):
97 gbpclient.Client.create_servicechain_node({
98 'servicechain_node': {
99 "name": "test-sc-node",
100 "description": "test service chain node resource",
101 "service_type": "TAP",
102 "config": "{'name': 'sc_node_config'}"
103 }
104 }).AndRaise(servicechain.NeutronClientException())
105 self.m.ReplayAll()
106
107 snippet = template_format.parse(servicechain_node_template)
108 stack = utils.parse_stack(snippet)
109 resource_defns = stack.t.resource_definitions(stack)
110 rsrc = servicechain.ServiceChainNode(
111 'servicechain_node', resource_defns['servicechain_node'], stack)
112
113 error = self.assertRaises(exception.ResourceFailure,
114 scheduler.TaskRunner(rsrc.create))
115 self.assertEqual(
116 'NeutronClientException: An unknown exception occurred.',
117 str(error))
118 self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
119 self.m.VerifyAll()
120
121 def test_delete(self):
122 gbpclient.Client.delete_servicechain_node('5678')
123 gbpclient.Client.show_servicechain_node('5678').AndRaise(
124 servicechain.NeutronClientException(status_code=404))
125
126 rsrc = self.create_servicechain_node()
127 self.m.ReplayAll()
128 scheduler.TaskRunner(rsrc.create)()
129 scheduler.TaskRunner(rsrc.delete)()
130 self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
131 self.m.VerifyAll()
132
133 def test_delete_already_gone(self):
134 gbpclient.Client.delete_servicechain_node('5678').AndRaise(
135 servicechain.NeutronClientException(status_code=404))
136
137 rsrc = self.create_servicechain_node()
138 self.m.ReplayAll()
139 scheduler.TaskRunner(rsrc.create)()
140 scheduler.TaskRunner(rsrc.delete)()
141 self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
142 self.m.VerifyAll()
143
144 def test_delete_failed(self):
145 gbpclient.Client.delete_servicechain_node('5678').AndRaise(
146 servicechain.NeutronClientException(status_code=400))
147
148 rsrc = self.create_servicechain_node()
149 self.m.ReplayAll()
150 scheduler.TaskRunner(rsrc.create)()
151 error = self.assertRaises(exception.ResourceFailure,
152 scheduler.TaskRunner(rsrc.delete))
153 self.assertEqual(
154 'NeutronClientException: An unknown exception occurred.',
155 str(error))
156 self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
157 self.m.VerifyAll()
158
159 def test_update(self):
160 rsrc = self.create_servicechain_node()
161 gbpclient.Client.update_servicechain_node(
162 '5678', {'servicechain_node': {'name': 'node_update'}})
163 self.m.ReplayAll()
164 scheduler.TaskRunner(rsrc.create)()
165
166 update_template = copy.deepcopy(rsrc.t)
167 update_template['Properties']['name'] = 'node_update'
168 scheduler.TaskRunner(rsrc.update, update_template)()
169
170 self.m.VerifyAll()
171
172
173class ServiceChainSpecTest(HeatTestCase):
174
175 def setUp(self):
176 super(ServiceChainSpecTest, self).setUp()
177 self.m.StubOutWithMock(gbpclient.Client, 'create_servicechain_spec')
178 self.m.StubOutWithMock(gbpclient.Client, 'delete_servicechain_spec')
179 self.m.StubOutWithMock(gbpclient.Client, 'show_servicechain_spec')
180 self.m.StubOutWithMock(gbpclient.Client, 'update_servicechain_spec')
181 self.stub_keystoneclient()
182
183 def create_servicechain_spec(self):
184 gbpclient.Client.create_servicechain_spec({
185 "servicechain_spec": {
186 "name": "test-sc-spec",
187 "description": "test service chain spec resource",
188 "nodes": ["1234", "7890"]
189 }
190 }).AndReturn({'servicechain_spec': {'id': '5678'}})
191
192 snippet = template_format.parse(servicechain_spec_template)
193 stack = utils.parse_stack(snippet)
194 resource_defns = stack.t.resource_definitions(stack)
195 return servicechain.ServiceChainSpec(
196 'servicechain_spec', resource_defns['servicechain_spec'], stack)
197
198 def test_create(self):
199 rsrc = self.create_servicechain_spec()
200 self.m.ReplayAll()
201 scheduler.TaskRunner(rsrc.create)()
202 self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
203 self.m.VerifyAll()
204
205 def test_create_failed(self):
206 gbpclient.Client.create_servicechain_spec({
207 'servicechain_spec': {
208 "name": "test-sc-spec",
209 "description": "test service chain spec resource",
210 "nodes": ["1234", "7890"]
211 }
212 }).AndRaise(servicechain.NeutronClientException())
213 self.m.ReplayAll()
214
215 snippet = template_format.parse(servicechain_spec_template)
216 stack = utils.parse_stack(snippet)
217 resource_defns = stack.t.resource_definitions(stack)
218 rsrc = servicechain.ServiceChainSpec(
219 'servicechain_spec', resource_defns['servicechain_spec'], stack)
220
221 error = self.assertRaises(exception.ResourceFailure,
222 scheduler.TaskRunner(rsrc.create))
223 self.assertEqual(
224 'NeutronClientException: An unknown exception occurred.',
225 str(error))
226 self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
227 self.m.VerifyAll()
228
229 def test_delete(self):
230 gbpclient.Client.delete_servicechain_spec('5678')
231 gbpclient.Client.show_servicechain_spec('5678').AndRaise(
232 servicechain.NeutronClientException(status_code=404))
233
234 rsrc = self.create_servicechain_spec()
235 self.m.ReplayAll()
236 scheduler.TaskRunner(rsrc.create)()
237 scheduler.TaskRunner(rsrc.delete)()
238 self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
239 self.m.VerifyAll()
240
241 def test_delete_already_gone(self):
242 gbpclient.Client.delete_servicechain_spec('5678').AndRaise(
243 servicechain.NeutronClientException(status_code=404))
244
245 rsrc = self.create_servicechain_spec()
246 self.m.ReplayAll()
247 scheduler.TaskRunner(rsrc.create)()
248 scheduler.TaskRunner(rsrc.delete)()
249 self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
250 self.m.VerifyAll()
251
252 def test_delete_failed(self):
253 gbpclient.Client.delete_servicechain_spec('5678').AndRaise(
254 servicechain.NeutronClientException(status_code=400))
255
256 rsrc = self.create_servicechain_spec()
257 self.m.ReplayAll()
258 scheduler.TaskRunner(rsrc.create)()
259 error = self.assertRaises(exception.ResourceFailure,
260 scheduler.TaskRunner(rsrc.delete))
261 self.assertEqual(
262 'NeutronClientException: An unknown exception occurred.',
263 str(error))
264 self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
265 self.m.VerifyAll()
266
267 def test_update(self):
268 rsrc = self.create_servicechain_spec()
269 gbpclient.Client.update_servicechain_spec(
270 '5678', {'servicechain_spec': {'name': 'spec_update'}})
271 self.m.ReplayAll()
272 scheduler.TaskRunner(rsrc.create)()
273
274 update_template = copy.deepcopy(rsrc.t)
275 update_template['Properties']['name'] = 'spec_update'
276 scheduler.TaskRunner(rsrc.update, update_template)()
277
278 self.m.VerifyAll()