Merge "[odl-sfc] Add timeout to get_vnf_id and create_vnf functions"
[functest.git] / functest / utils / openstack_tacker.py
1 ###########################################################################
2 # Copyright (c) 2016 Ericsson AB and others.
3 # Author: George Paraskevopoulos <geopar@intracom-telecom.com>
4 #
5 # Wrappers for trozet's python-tackerclient v1.0
6 # (https://github.com/trozet/python-tackerclient)
7 #
8 # All rights reserved. This program and the accompanying materials
9 # are made available under the terms of the Apache License, Version 2.0
10 # which accompanies this distribution, and is available at
11 # http://www.apache.org/licenses/LICENSE-2.0
12 ##########################################################################
13
14
15 from tackerclient.v1_0 import client as tackerclient
16 import functest.utils.functest_logger as ft_logger
17 import functest.utils.openstack_utils as os_utils
18 import time
19
20 logger = ft_logger.Logger("tacker_utils").getLogger()
21
22
23 def get_tacker_client(other_creds={}):
24     sess = os_utils.get_session(other_creds)
25     return tackerclient.Client(session=sess)
26
27
28 # *********************************************
29 #   TACKER
30 # *********************************************
31 def get_id_from_name(tacker_client, resource_type, resource_name):
32     try:
33         req_params = {'fields': 'id', 'name': resource_name}
34         endpoint = '/{0}s'.format(resource_type)
35         resp = tacker_client.get(endpoint, params=req_params)
36         endpoint = endpoint.replace('-', '_')
37         return resp[endpoint[1:]][0]['id']
38     except Exception, e:
39         logger.error("Error [get_id_from_name(tacker_client, "
40                      "resource_type, resource_name)]: %s" % e)
41         return None
42
43
44 def get_vnfd_id(tacker_client, vnfd_name):
45     return get_id_from_name(tacker_client, 'vnfd', vnfd_name)
46
47
48 def get_vnf_id(tacker_client, vnf_name, timeout=5):
49     vnf_id = None
50     while vnf_id is None and timeout >= 0:
51         try:
52             vnf_id = get_id_from_name(tacker_client, 'vnf', vnf_name)
53         except:
54             logger.info("Could not retrieve ID for vnf with name [%s]."
55                         " Retrying." % vnf_name)
56             time.sleep(1)
57             timeout -= 1
58     return vnf_id
59
60
61 def get_sfc_id(tacker_client, sfc_name):
62     return get_id_from_name(tacker_client, 'sfc', sfc_name)
63
64
65 def get_sfc_classifier_id(tacker_client, sfc_clf_name):
66     return get_id_from_name(tacker_client, 'sfc-classifier', sfc_clf_name)
67
68
69 def list_vnfds(tacker_client, verbose=False):
70     try:
71         vnfds = tacker_client.list_vnfds(retrieve_all=True)
72         if not verbose:
73             vnfds = [vnfd['id'] for vnfd in vnfds['vnfds']]
74         return vnfds
75     except Exception, e:
76         logger.error("Error [list_vnfds(tacker_client)]: %s" % e)
77         return None
78
79
80 def create_vnfd(tacker_client, tosca_file=None):
81     try:
82         vnfd_body = {}
83         if tosca_file is not None:
84             with open(tosca_file) as tosca_fd:
85                 vnfd_body = tosca_fd.read()
86             logger.info('VNFD template:\n{0}'.format(vnfd_body))
87         return tacker_client.create_vnfd(
88             body={"vnfd": {"attributes": {"vnfd": vnfd_body}}})
89     except Exception, e:
90         logger.error("Error [create_vnfd(tacker_client, '%s')]: %s"
91                      % (tosca_file, e))
92         return None
93
94
95 def delete_vnfd(tacker_client, vnfd_id=None, vnfd_name=None):
96     try:
97         vnfd = vnfd_id
98         if vnfd is None:
99             if vnfd_name is None:
100                 raise Exception('You need to provide VNFD id or VNFD name')
101             vnfd = get_vnfd_id(tacker_client, vnfd_name)
102         return tacker_client.delete_vnfd(vnfd)
103     except Exception, e:
104         logger.error("Error [delete_vnfd(tacker_client, '%s', '%s')]: %s"
105                      % (vnfd_id, vnfd_name, e))
106         return None
107
108
109 def list_vnfs(tacker_client, verbose=False):
110     try:
111         vnfs = tacker_client.list_vnfs(retrieve_all=True)
112         if not verbose:
113             vnfs = [vnf['id'] for vnf in vnfs['vnfs']]
114         return vnfs
115     except Exception, e:
116         logger.error("Error [list_vnfs(tacker_client)]: %s" % e)
117         return None
118
119
120 def create_vnf(tacker_client, vnf_name, vnfd_id=None,
121                vnfd_name=None, param_file=None):
122     try:
123         vnf_body = {
124             'vnf': {
125                 'attributes': {},
126                 'name': vnf_name
127             }
128         }
129         if param_file is not None:
130             params = None
131             with open(param_file) as f:
132                 params = f.read()
133             vnf_body['vnf']['attributes']['param_values'] = params
134         if vnfd_id is not None:
135             vnf_body['vnf']['vnfd_id'] = vnfd_id
136         else:
137             if vnfd_name is None:
138                 raise Exception('vnfd id or vnfd name is required')
139             vnf_body['vnf']['vnfd_id'] = get_vnfd_id(tacker_client, vnfd_name)
140         return tacker_client.create_vnf(body=vnf_body)
141     except Exception, e:
142         logger.error("error [create_vnf(tacker_client,"
143                      " '%s', '%s', '%s')]: %s"
144                      % (vnf_name, vnfd_id, vnfd_name, e))
145         return None
146
147
148 def wait_for_vnf(tacker_client, vnf_id=None, vnf_name=None, timeout=60):
149     try:
150         if vnf_id is None and vnf_name is None:
151             raise Exception('You must specify vnf_id or vnf_name')
152         _id = get_vnf_id(tacker_client, vnf_name) if vnf_id is None else vnf_id
153
154         vnf = next((v for v in list_vnfs(tacker_client, verbose=True)['vnfs']
155                    if v['id'] == _id), None)
156         if vnf is None:
157             raise Exception("Could not retrieve VNF with ID [%s]" % _id)
158         logger.info('Waiting for vnf {0}'.format(str(vnf)))
159         while True and timeout >= 0:
160             if vnf['status'] == 'ERROR':
161                 raise Exception('Error when booting vnf %s' % _id)
162             elif vnf['status'] == 'PENDING_CREATE':
163                 time.sleep(3)
164                 timeout -= 3
165                 continue
166             else:
167                 break
168         return _id
169     except Exception, e:
170         logger.error("error [wait_for_vnf(tacker_client, '%s', '%s')]: %s"
171                      % (vnf_id, vnf_name, e))
172         return None
173
174
175 def delete_vnf(tacker_client, vnf_id=None, vnf_name=None):
176     try:
177         vnf = vnf_id
178         if vnf is None:
179             if vnf_name is None:
180                 raise Exception('You need to provide a VNF id or name')
181             vnf = get_vnf_id(tacker_client, vnf_name)
182         return tacker_client.delete_vnf(vnf)
183     except Exception, e:
184         logger.error("Error [delete_vnf(tacker_client, '%s', '%s')]: %s"
185                      % (vnf_id, vnf_name, e))
186         return None
187
188
189 def list_sfcs(tacker_client, verbose=False):
190     try:
191         sfcs = tacker_client.list_sfcs(retrieve_all=True)
192         if not verbose:
193             sfcs = [sfc['id'] for sfc in sfcs['sfcs']]
194         return sfcs
195     except Exception, e:
196         logger.error("Error [list_sfcs(tacker_client)]: %s" % e)
197         return None
198
199
200 def create_sfc(tacker_client, sfc_name,
201                chain_vnf_ids=None,
202                chain_vnf_names=None,
203                symmetrical=False):
204     try:
205         sfc_body = {
206             'sfc': {
207                 'attributes': {},
208                 'name': sfc_name,
209                 'chain': []
210             }
211         }
212         if symmetrical:
213             sfc_body['sfc']['symmetrical'] = True
214         if chain_vnf_ids is not None:
215             sfc_body['sfc']['chain'] = chain_vnf_ids
216         else:
217             if chain_vnf_names is None:
218                 raise Exception('You need to provide a chain of VNFs')
219             sfc_body['sfc']['chain'] = [get_vnf_id(tacker_client, name)
220                                         for name in chain_vnf_names]
221         return tacker_client.create_sfc(body=sfc_body)
222     except Exception, e:
223         logger.error("error [create_sfc(tacker_client,"
224                      " '%s', '%s', '%s')]: %s"
225                      % (sfc_name, chain_vnf_ids, chain_vnf_names, e))
226         return None
227
228
229 def delete_sfc(tacker_client, sfc_id=None, sfc_name=None):
230     try:
231         sfc = sfc_id
232         if sfc is None:
233             if sfc_name is None:
234                 raise Exception('You need to provide an SFC id or name')
235             sfc = get_sfc_id(tacker_client, sfc_name)
236         return tacker_client.delete_sfc(sfc)
237     except Exception, e:
238         logger.error("Error [delete_sfc(tacker_client, '%s', '%s')]: %s"
239                      % (sfc_id, sfc_name, e))
240         return None
241
242
243 def list_sfc_classifiers(tacker_client, verbose=False):
244     try:
245         sfc_clfs = tacker_client.list_sfc_classifiers(retrieve_all=True)
246         if not verbose:
247             sfc_clfs = [sfc_clf['id']
248                         for sfc_clf in sfc_clfs['sfc_classifiers']]
249         return sfc_clfs
250     except Exception, e:
251         logger.error("Error [list_sfc_classifiers(tacker_client)]: %s" % e)
252         return None
253
254
255 def create_sfc_classifier(tacker_client, sfc_clf_name, sfc_id=None,
256                           sfc_name=None, match={}):
257     # Example match:
258     # match: {
259     #     "source_port": "0",
260     #     "protocol": "6",
261     #     "dest_port": "80"
262     # }
263     try:
264         sfc_clf_body = {
265             'sfc_classifier': {
266                 'attributes': {},
267                 'name': sfc_clf_name,
268                 'match': match,
269                 'chain': ''
270             }
271         }
272         if sfc_id is not None:
273             sfc_clf_body['sfc_classifier']['chain'] = sfc_id
274         else:
275             if sfc_name is None:
276                 raise Exception('You need to provide an SFC id or name')
277             sfc_clf_body['sfc_classifier']['chain'] = get_sfc_id(
278                 tacker_client, sfc_name)
279         return tacker_client.create_sfc_classifier(body=sfc_clf_body)
280     except Exception, e:
281         logger.error("error [create_sfc_classifier(tacker_client,"
282                      " '%s', '%s','%s', '%s')]: '%s'"
283                      % (sfc_clf_name, sfc_id, sfc_name, str(match), e))
284         return None
285
286
287 def delete_sfc_classifier(tacker_client,
288                           sfc_clf_id=None,
289                           sfc_clf_name=None):
290     try:
291         sfc_clf = sfc_clf_id
292         if sfc_clf is None:
293             if sfc_clf_name is None:
294                 raise Exception('You need to provide an SFC'
295                                 'classifier id or name')
296             sfc_clf = get_sfc_classifier_id(tacker_client, sfc_clf_name)
297         return tacker_client.delete_sfc_classifier(sfc_clf)
298     except Exception, e:
299         logger.error("Error [delete_sfc_classifier(tacker_client, '%s', "
300                      "'%s')]: %s" % (sfc_clf_id, sfc_clf_name, e))
301         return None