1165b3de9bbb548931f38342c332241a1edd5a7b
1 # Copyright 2018 Telefonica
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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
21 from osmclient
.common
import utils
22 from osmclient
.common
import wait
as WaitForStatus
23 from osmclient
.common
.exceptions
import ClientException
24 from osmclient
.common
.exceptions
import NotFound
31 def __init__(self
, http
=None, client
=None):
34 self
._apiName
= '/nslcm'
35 self
._apiVersion
= '/v1'
36 self
._apiResource
= '/ns_instances_content'
37 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
38 self
._apiVersion
, self
._apiResource
)
41 def _wait(self
, id, deleteFlag
=False):
42 # Endpoint to get operation status
43 apiUrlStatus
= '{}{}{}'.format(self
._apiName
, self
._apiVersion
, '/ns_lcm_op_occs')
44 # Wait for status for NS instance creation/update/deletion
45 WaitForStatus
.wait_for_status(
48 WaitForStatus
.TIMEOUT_NS_OPERATION
,
51 deleteFlag
=deleteFlag
)
53 def list(self
, filter=None):
54 """Returns a list of NS
56 self
._client
.get_token()
59 filter_string
= '?{}'.format(filter)
60 resp
= self
._http
.get_cmd('{}{}'.format(self
._apiBase
,filter_string
))
66 """Returns an NS based on name or id
68 self
._client
.get_token()
69 if utils
.validate_uuid4(name
):
70 for ns
in self
.list():
74 for ns
in self
.list():
75 if name
== ns
['name']:
77 raise NotFound("ns {} not found".format(name
))
79 def get_individual(self
, name
):
80 self
._client
.get_token()
82 if not utils
.validate_uuid4(name
):
83 for ns
in self
.list():
84 if name
== ns
['name']:
87 resp
= self
._http
.get_cmd('{}/{}'.format(self
._apiBase
, ns_id
))
88 #resp = self._http.get_cmd('{}/{}/nsd_content'.format(self._apiBase, ns_id))
89 #print(yaml.safe_dump(resp))
92 raise NotFound("ns {} not found".format(name
))
94 def delete(self
, name
, force
=False, wait
=False):
98 querystring
= '?FORCE=True'
99 http_code
, resp
= self
._http
.delete_cmd('{}/{}{}'.format(self
._apiBase
,
100 ns
['_id'], querystring
))
101 # print('HTTP CODE: {}'.format(http_code))
102 # print('RESP: {}'.format(resp))
105 resp
= json
.loads(resp
)
106 # For the 'delete' operation, '_id' is used
107 self
._wait
(resp
.get('_id'), deleteFlag
=True)
109 print('Deletion in progress')
110 elif http_code
== 204:
116 msg
= json
.loads(resp
)
119 raise ClientException("failed to delete ns {} - {}".format(name
, msg
))
121 def create(self
, nsd_name
, nsr_name
, account
, config
=None,
122 ssh_keys
=None, description
='default description',
123 admin_status
='ENABLED', wait
=False):
124 self
._client
.get_token()
125 nsd
= self
._client
.nsd
.get(nsd_name
)
130 def get_vim_account_id(vim_account
):
131 if vim_account_id
.get(vim_account
):
132 return vim_account_id
[vim_account
]
134 vim
= self
._client
.vim
.get(vim_account
)
136 raise NotFound("cannot find vim account '{}'".format(vim_account
))
137 vim_account_id
[vim_account
] = vim
['_id']
140 def get_wim_account_id(wim_account
):
141 if not isinstance(wim_account
, str):
143 if wim_account_id
.get(wim_account
):
144 return wim_account_id
[wim_account
]
146 wim
= self
._client
.wim
.get(wim_account
)
148 raise NotFound("cannot find wim account '{}'".format(wim_account
))
149 wim_account_id
[wim_account
] = wim
['_id']
153 ns
['nsdId'] = nsd
['_id']
154 ns
['nsName'] = nsr_name
155 ns
['nsDescription'] = description
156 ns
['vimAccountId'] = get_vim_account_id(account
)
158 #ns['userdata']['key1']='value1'
159 #ns['userdata']['key2']='value2'
161 if ssh_keys
is not None:
163 for pubkeyfile
in ssh_keys
.split(','):
164 with
open(pubkeyfile
, 'r') as f
:
165 ns
['ssh_keys'].append(f
.read())
167 ns_config
= yaml
.safe_load(config
)
168 if "vim-network-name" in ns_config
:
169 ns_config
["vld"] = ns_config
.pop("vim-network-name")
170 if "vld" in ns_config
:
171 for vld
in ns_config
["vld"]:
172 if vld
.get("vim-network-name"):
173 if isinstance(vld
["vim-network-name"], dict):
174 vim_network_name_dict
= {}
175 for vim_account
, vim_net
in list(vld
["vim-network-name"].items()):
176 vim_network_name_dict
[get_vim_account_id(vim_account
)] = vim_net
177 vld
["vim-network-name"] = vim_network_name_dict
178 if "wim_account" in vld
and vld
["wim_account"] is not None:
179 vld
["wimAccountId"] = get_wim_account_id(vld
.pop("wim_account"))
180 ns
["vld"] = ns_config
["vld"]
181 if "vnf" in ns_config
:
182 for vnf
in ns_config
["vnf"]:
183 if vnf
.get("vim_account"):
184 vnf
["vimAccountId"] = get_vim_account_id(vnf
.pop("vim_account"))
185 ns
["vnf"] = ns_config
["vnf"]
187 if "additionalParamsForNs" in ns_config
:
188 ns
["additionalParamsForNs"] = ns_config
.pop("additionalParamsForNs")
189 if not isinstance(ns
["additionalParamsForNs"], dict):
190 raise ValueError("Error at --config 'additionalParamsForNs' must be a dictionary")
191 if "additionalParamsForVnf" in ns_config
:
192 ns
["additionalParamsForVnf"] = ns_config
.pop("additionalParamsForVnf")
193 if not isinstance(ns
["additionalParamsForVnf"], list):
194 raise ValueError("Error at --config 'additionalParamsForVnf' must be a list")
195 for additional_param_vnf
in ns
["additionalParamsForVnf"]:
196 if not isinstance(additional_param_vnf
, dict):
197 raise ValueError("Error at --config 'additionalParamsForVnf' items must be dictionaries")
198 if not additional_param_vnf
.get("member-vnf-index"):
199 raise ValueError("Error at --config 'additionalParamsForVnf' items must contain "
200 "'member-vnf-index'")
201 if not additional_param_vnf
.get("additionalParams"):
202 raise ValueError("Error at --config 'additionalParamsForVnf' items must contain "
203 "'additionalParams'")
204 if "wim_account" in ns_config
:
205 wim_account
= ns_config
.pop("wim_account")
206 if wim_account
is not None:
207 ns
['wimAccountId'] = get_wim_account_id(wim_account
)
209 # print(yaml.safe_dump(ns))
211 self
._apiResource
= '/ns_instances_content'
212 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
213 self
._apiVersion
, self
._apiResource
)
214 headers
= self
._client
._headers
215 headers
['Content-Type'] = 'application/yaml'
216 http_header
= ['{}: {}'.format(key
,val
)
217 for (key
,val
) in list(headers
.items())]
218 self
._http
.set_http_header(http_header
)
219 http_code
, resp
= self
._http
.post_cmd(endpoint
=self
._apiBase
,
221 # print('HTTP CODE: {}'.format(http_code))
222 # print('RESP: {}'.format(resp))
223 if http_code
in (200, 201, 202, 204):
225 resp
= json
.loads(resp
)
226 if not resp
or 'id' not in resp
:
227 raise ClientException('unexpected response from server - {} '.format(
230 # Wait for status for NS instance creation
231 self
._wait
(resp
.get('nslcmop_id'))
237 msg
= json
.loads(resp
)
240 raise ClientException(msg
)
241 except ClientException
as exc
:
242 message
="failed to create ns: {} nsd: {}\nerror:\n{}".format(
246 raise ClientException(message
)
248 def list_op(self
, name
, filter=None):
249 """Returns the list of operations of a NS
253 self
._apiResource
= '/ns_lcm_op_occs'
254 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
255 self
._apiVersion
, self
._apiResource
)
258 filter_string
= '&{}'.format(filter)
259 http_code
, resp
= self
._http
.get2_cmd('{}?nsInstanceId={}'.format(
260 self
._apiBase
, ns
['_id'],
262 #print('HTTP CODE: {}'.format(http_code))
263 #print('RESP: {}'.format(resp))
266 resp
= json
.loads(resp
)
269 raise ClientException('unexpected response from server')
274 resp
= json
.loads(resp
)
278 raise ClientException(msg
)
279 except ClientException
as exc
:
280 message
="failed to get operation list of NS {}:\nerror:\n{}".format(
283 raise ClientException(message
)
285 def get_op(self
, operationId
):
286 """Returns the status of an operation
288 self
._client
.get_token()
290 self
._apiResource
= '/ns_lcm_op_occs'
291 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
292 self
._apiVersion
, self
._apiResource
)
293 http_code
, resp
= self
._http
.get2_cmd('{}/{}'.format(self
._apiBase
, operationId
))
294 #print('HTTP CODE: {}'.format(http_code))
295 #print('RESP: {}'.format(resp))
298 resp
= json
.loads(resp
)
301 raise ClientException('unexpected response from server')
306 resp
= json
.loads(resp
)
310 raise ClientException(msg
)
311 except ClientException
as exc
:
312 message
="failed to get status of operation {}:\nerror:\n{}".format(
315 raise ClientException(message
)
317 def exec_op(self
, name
, op_name
, op_data
=None, wait
=False, ):
318 """Executes an operation on a NS
322 self
._apiResource
= '/ns_instances'
323 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
324 self
._apiVersion
, self
._apiResource
)
325 endpoint
= '{}/{}/{}'.format(self
._apiBase
, ns
['_id'], op_name
)
326 #print('OP_NAME: {}'.format(op_name))
327 #print('OP_DATA: {}'.format(json.dumps(op_data)))
328 http_code
, resp
= self
._http
.post_cmd(endpoint
=endpoint
, postfields_dict
=op_data
)
329 #print('HTTP CODE: {}'.format(http_code))
330 #print('RESP: {}'.format(resp))
331 if http_code
in (200, 201, 202, 204):
333 resp
= json
.loads(resp
)
334 if not resp
or 'id' not in resp
:
335 raise ClientException('unexpected response from server - {}'.format(
338 # Wait for status for NS instance action
339 # For the 'action' operation, 'id' is used
340 self
._wait
(resp
.get('id'))
346 msg
= json
.loads(resp
)
349 raise ClientException(msg
)
350 except ClientException
as exc
:
351 message
="failed to exec operation {}:\nerror:\n{}".format(
354 raise ClientException(message
)
356 def scale_vnf(self
, ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
=False):
357 """Scales a VNF by adding/removing VDUs
359 self
._client
.get_token()
362 op_data
["scaleType"] = "SCALE_VNF"
363 op_data
["scaleVnfData"] = {}
365 op_data
["scaleVnfData"]["scaleVnfType"] = "SCALE_IN"
367 op_data
["scaleVnfData"]["scaleVnfType"] = "SCALE_OUT"
368 op_data
["scaleVnfData"]["scaleByStepData"] = {
369 "member-vnf-index": vnf_name
,
370 "scaling-group-descriptor": scaling_group
,
372 op_id
= self
.exec_op(ns_name
, op_name
='scale', op_data
=op_data
, wait
=wait
)
374 except ClientException
as exc
:
375 message
="failed to scale vnf {} of ns {}:\nerror:\n{}".format(
376 vnf_name
, ns_name
, str(exc
))
377 raise ClientException(message
)
379 def create_alarm(self
, alarm
):
380 self
._client
.get_token()
382 data
["create_alarm_request"] = {}
383 data
["create_alarm_request"]["alarm_create_request"] = alarm
385 http_code
, resp
= self
._http
.post_cmd(endpoint
='/test/message/alarm_request',
386 postfields_dict
=data
)
387 #print('HTTP CODE: {}'.format(http_code))
388 #print('RESP: {}'.format(resp))
389 if http_code
in (200, 201, 202, 204):
390 #resp = json.loads(resp)
391 print('Alarm created')
396 msg
= json
.loads(resp
)
399 raise ClientException('error: code: {}, resp: {}'.format(
401 except ClientException
as exc
:
402 message
="failed to create alarm: alarm {}\n{}".format(
405 raise ClientException(message
)
407 def delete_alarm(self
, name
):
408 self
._client
.get_token()
410 data
["delete_alarm_request"] = {}
411 data
["delete_alarm_request"]["alarm_delete_request"] = {}
412 data
["delete_alarm_request"]["alarm_delete_request"]["alarm_uuid"] = name
414 http_code
, resp
= self
._http
.post_cmd(endpoint
='/test/message/alarm_request',
415 postfields_dict
=data
)
416 #print('HTTP CODE: {}'.format(http_code))
417 #print('RESP: {}'.format(resp))
418 if http_code
in (200, 201, 202, 204):
419 #resp = json.loads(resp)
420 print('Alarm deleted')
425 msg
= json
.loads(resp
)
428 raise ClientException('error: code: {}, resp: {}'.format(
430 except ClientException
as exc
:
431 message
="failed to delete alarm: alarm {}\n{}".format(
434 raise ClientException(message
)
436 def export_metric(self
, metric
):
437 self
._client
.get_token()
439 data
["read_metric_data_request"] = metric
441 http_code
, resp
= self
._http
.post_cmd(endpoint
='/test/message/metric_request',
442 postfields_dict
=data
)
443 #print('HTTP CODE: {}'.format(http_code))
444 #print('RESP: {}'.format(resp))
445 if http_code
in (200, 201, 202, 204):
446 #resp = json.loads(resp)
447 return 'Metric exported'
452 msg
= json
.loads(resp
)
455 raise ClientException('error: code: {}, resp: {}'.format(
457 except ClientException
as exc
:
458 message
="failed to export metric: metric {}\n{}".format(
461 raise ClientException(message
)
463 def get_field(self
, ns_name
, field
):
464 nsr
= self
.get(ns_name
)
465 print(yaml
.safe_dump(nsr
))
467 raise NotFound("failed to retrieve ns {}".format(ns_name
))
472 raise NotFound("failed to find {} in ns {}".format(field
, ns_name
))