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
.exceptions
import ClientException
23 from osmclient
.common
.exceptions
import NotFound
30 def __init__(self
, http
=None, client
=None):
33 self
._apiName
= '/nslcm'
34 self
._apiVersion
= '/v1'
35 self
._apiResource
= '/ns_instances_content'
36 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
37 self
._apiVersion
, self
._apiResource
)
39 def list(self
, filter=None):
40 """Returns a list of NS
44 filter_string
= '?{}'.format(filter)
45 resp
= self
._http
.get_cmd('{}{}'.format(self
._apiBase
,filter_string
))
51 """Returns an NS based on name or id
53 if utils
.validate_uuid4(name
):
54 for ns
in self
.list():
58 for ns
in self
.list():
59 if name
== ns
['name']:
61 raise NotFound("ns {} not found".format(name
))
63 def get_individual(self
, name
):
65 if not utils
.validate_uuid4(name
):
66 for ns
in self
.list():
67 if name
== ns
['name']:
70 resp
= self
._http
.get_cmd('{}/{}'.format(self
._apiBase
, ns_id
))
71 #resp = self._http.get_cmd('{}/{}/nsd_content'.format(self._apiBase, ns_id))
72 #print yaml.safe_dump(resp)
75 raise NotFound("ns {} not found".format(name
))
77 def delete(self
, name
, force
=False):
81 querystring
= '?FORCE=True'
82 http_code
, resp
= self
._http
.delete_cmd('{}/{}{}'.format(self
._apiBase
,
83 ns
['_id'], querystring
))
84 #print 'HTTP CODE: {}'.format(http_code)
85 #print 'RESP: {}'.format(resp)
87 print('Deletion in progress')
88 elif http_code
== 204:
94 msg
= json
.loads(resp
)
97 raise ClientException("failed to delete ns {} - {}".format(name
, msg
))
99 def create(self
, nsd_name
, nsr_name
, account
, config
=None,
100 ssh_keys
=None, description
='default description',
101 admin_status
='ENABLED'):
103 nsd
= self
._client
.nsd
.get(nsd_name
)
107 def get_vim_account_id(vim_account
):
108 if vim_account_id
.get(vim_account
):
109 return vim_account_id
[vim_account
]
111 vim
= self
._client
.vim
.get(vim_account
)
113 raise NotFound("cannot find vim account '{}'".format(vim_account
))
114 vim_account_id
[vim_account
] = vim
['_id']
118 ns
['nsdId'] = nsd
['_id']
119 ns
['nsName'] = nsr_name
120 ns
['nsDescription'] = description
121 ns
['vimAccountId'] = get_vim_account_id(account
)
123 #ns['userdata']['key1']='value1'
124 #ns['userdata']['key2']='value2'
126 if ssh_keys
is not None:
128 for pubkeyfile
in ssh_keys
.split(','):
129 with
open(pubkeyfile
, 'r') as f
:
130 ns
['ssh_keys'].append(f
.read())
132 ns_config
= yaml
.load(config
)
133 if "vim-network-name" in ns_config
:
134 ns_config
["vld"] = ns_config
.pop("vim-network-name")
135 if "vld" in ns_config
:
136 for vld
in ns_config
["vld"]:
137 if vld
.get("vim-network-name"):
138 if isinstance(vld
["vim-network-name"], dict):
139 vim_network_name_dict
= {}
140 for vim_account
, vim_net
in list(vld
["vim-network-name"].items()):
141 vim_network_name_dict
[get_vim_account_id(vim_account
)] = vim_net
142 vld
["vim-network-name"] = vim_network_name_dict
143 ns
["vld"] = ns_config
["vld"]
144 if "vnf" in ns_config
:
145 for vnf
in ns_config
["vnf"]:
146 if vnf
.get("vim_account"):
147 vnf
["vimAccountId"] = get_vim_account_id(vnf
.pop("vim_account"))
148 ns
["vnf"] = ns_config
["vnf"]
150 #print yaml.safe_dump(ns)
152 self
._apiResource
= '/ns_instances_content'
153 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
154 self
._apiVersion
, self
._apiResource
)
155 headers
= self
._client
._headers
156 headers
['Content-Type'] = 'application/yaml'
157 http_header
= ['{}: {}'.format(key
,val
)
158 for (key
,val
) in list(headers
.items())]
159 self
._http
.set_http_header(http_header
)
160 http_code
, resp
= self
._http
.post_cmd(endpoint
=self
._apiBase
,
162 #print 'HTTP CODE: {}'.format(http_code)
163 #print 'RESP: {}'.format(resp)
164 if http_code
in (200, 201, 202, 204):
166 resp
= json
.loads(resp
)
167 if not resp
or 'id' not in resp
:
168 raise ClientException('unexpected response from server - {} '.format(
175 msg
= json
.loads(resp
)
178 raise ClientException(msg
)
179 except ClientException
as exc
:
180 message
="failed to create ns: {} nsd: {}\nerror:\n{}".format(
184 raise ClientException(message
)
186 def list_op(self
, name
, filter=None):
187 """Returns the list of operations of a NS
191 self
._apiResource
= '/ns_lcm_op_occs'
192 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
193 self
._apiVersion
, self
._apiResource
)
196 filter_string
= '&{}'.format(filter)
197 http_code
, resp
= self
._http
.get2_cmd('{}?nsInstanceId={}'.format(
198 self
._apiBase
, ns
['_id'],
200 #print 'HTTP CODE: {}'.format(http_code)
201 #print 'RESP: {}'.format(resp)
204 resp
= json
.loads(resp
)
207 raise ClientException('unexpected response from server')
212 resp
= json
.loads(resp
)
216 raise ClientException(msg
)
217 except ClientException
as exc
:
218 message
="failed to get operation list of NS {}:\nerror:\n{}".format(
221 raise ClientException(message
)
223 def get_op(self
, operationId
):
224 """Returns the status of an operation
227 self
._apiResource
= '/ns_lcm_op_occs'
228 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
229 self
._apiVersion
, self
._apiResource
)
230 http_code
, resp
= self
._http
.get2_cmd('{}/{}'.format(self
._apiBase
, operationId
))
231 #print 'HTTP CODE: {}'.format(http_code)
232 #print 'RESP: {}'.format(resp)
235 resp
= json
.loads(resp
)
238 raise ClientException('unexpected response from server')
243 resp
= json
.loads(resp
)
247 raise ClientException(msg
)
248 except ClientException
as exc
:
249 message
="failed to get status of operation {}:\nerror:\n{}".format(
252 raise ClientException(message
)
254 def exec_op(self
, name
, op_name
, op_data
=None):
255 """Executes an operation on a NS
259 self
._apiResource
= '/ns_instances'
260 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
261 self
._apiVersion
, self
._apiResource
)
262 endpoint
= '{}/{}/{}'.format(self
._apiBase
, ns
['_id'], op_name
)
263 #print 'OP_NAME: {}'.format(op_name)
264 #print 'OP_DATA: {}'.format(json.dumps(op_data))
265 http_code
, resp
= self
._http
.post_cmd(endpoint
=endpoint
, postfields_dict
=op_data
)
266 #print 'HTTP CODE: {}'.format(http_code)
267 #print 'RESP: {}'.format(resp)
268 if http_code
in (200, 201, 202, 204):
270 resp
= json
.loads(resp
)
271 if not resp
or 'id' not in resp
:
272 raise ClientException('unexpected response from server - {}'.format(
279 msg
= json
.loads(resp
)
282 raise ClientException(msg
)
283 except ClientException
as exc
:
284 message
="failed to exec operation {}:\nerror:\n{}".format(
287 raise ClientException(message
)
289 def scale_vnf(self
, ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
):
290 """Scales a VNF by adding/removing VDUs
294 op_data
["scaleType"] = "SCALE_VNF"
295 op_data
["scaleVnfData"] = {}
297 op_data
["scaleVnfData"]["scaleVnfType"] = "SCALE_IN"
299 op_data
["scaleVnfData"]["scaleVnfType"] = "SCALE_OUT"
300 op_data
["scaleVnfData"]["scaleByStepData"] = {
301 "member-vnf-index": vnf_name
,
302 "scaling-group-descriptor": scaling_group
,
304 self
.exec_op(ns_name
, op_name
='scale', op_data
=op_data
)
305 except ClientException
as exc
:
306 message
="failed to scale vnf {} of ns {}:\nerror:\n{}".format(
307 vnf_name
, ns_name
, exc
.message
)
308 raise ClientException(message
)
310 def create_alarm(self
, alarm
):
312 data
["create_alarm_request"] = {}
313 data
["create_alarm_request"]["alarm_create_request"] = alarm
315 http_code
, resp
= self
._http
.post_cmd(endpoint
='/test/message/alarm_request',
316 postfields_dict
=data
)
317 #print 'HTTP CODE: {}'.format(http_code)
318 #print 'RESP: {}'.format(resp)
319 if http_code
in (200, 201, 202, 204):
320 #resp = json.loads(resp)
321 print('Alarm created')
326 msg
= json
.loads(resp
)
329 raise ClientException('error: code: {}, resp: {}'.format(
331 except ClientException
as exc
:
332 message
="failed to create alarm: alarm {}\n{}".format(
335 raise ClientException(message
)
337 def delete_alarm(self
, name
):
339 data
["delete_alarm_request"] = {}
340 data
["delete_alarm_request"]["alarm_delete_request"] = {}
341 data
["delete_alarm_request"]["alarm_delete_request"]["alarm_uuid"] = name
343 http_code
, resp
= self
._http
.post_cmd(endpoint
='/test/message/alarm_request',
344 postfields_dict
=data
)
345 #print 'HTTP CODE: {}'.format(http_code)
346 #print 'RESP: {}'.format(resp)
347 if http_code
in (200, 201, 202, 204):
348 #resp = json.loads(resp)
349 print('Alarm deleted')
354 msg
= json
.loads(resp
)
357 raise ClientException('error: code: {}, resp: {}'.format(
359 except ClientException
as exc
:
360 message
="failed to delete alarm: alarm {}\n{}".format(
363 raise ClientException(message
)
365 def export_metric(self
, metric
):
367 data
["read_metric_data_request"] = metric
369 http_code
, resp
= self
._http
.post_cmd(endpoint
='/test/message/metric_request',
370 postfields_dict
=data
)
371 #print 'HTTP CODE: {}'.format(http_code)
372 #print 'RESP: {}'.format(resp)
373 if http_code
in (200, 201, 202, 204):
374 #resp = json.loads(resp)
375 return 'Metric exported'
380 msg
= json
.loads(resp
)
383 raise ClientException('error: code: {}, resp: {}'.format(
385 except ClientException
as exc
:
386 message
="failed to export metric: metric {}\n{}".format(
389 raise ClientException(message
)
391 def get_field(self
, ns_name
, field
):
392 nsr
= self
.get(ns_name
)
394 raise NotFound("failed to retrieve ns {}".format(ns_name
))
399 raise NotFound("failed to find {} in ns {}".format(field
, ns_name
))