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
18 OSM NSI (Network Slice Instance) API handling
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
= '/nsilcm'
34 self
._apiVersion
= '/v1'
35 self
._apiResource
= '/netslice_instances_content'
36 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
37 self
._apiVersion
, self
._apiResource
)
39 def list(self
, filter=None):
40 """Returns a list of NSI
44 filter_string
= '?{}'.format(filter)
45 resp
= self
._http
.get_cmd('{}{}'.format(self
._apiBase
,filter_string
))
51 """Returns an NSI based on name or id
53 if utils
.validate_uuid4(name
):
54 for nsi
in self
.list():
55 if name
== nsi
['_id']:
58 for nsi
in self
.list():
59 if name
== nsi
['name']:
61 raise NotFound("nsi {} not found".format(name
))
63 def get_individual(self
, name
):
65 if not utils
.validate_uuid4(name
):
66 for nsi
in self
.list():
67 if name
== nsi
['name']:
70 resp
= self
._http
.get_cmd('{}/{}'.format(self
._apiBase
, nsi_id
))
71 #resp = self._http.get_cmd('{}/{}/nsd_content'.format(self._apiBase, nsi_id))
72 #print yaml.safe_dump(resp)
75 raise NotFound("nsi {} 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 nsi
['_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 nsi {} - {}".format(name
, msg
))
99 def create(self
, nst_name
, nsi_name
, account
, config
=None,
100 ssh_keys
=None, description
='default description',
101 admin_status
='ENABLED'):
103 nst
= self
._client
.nst
.get(nst_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 nsi
['nstId'] = nst
['_id']
119 nsi
['nsiName'] = nsi_name
120 nsi
['nsiDescription'] = description
121 nsi
['vimAccountId'] = get_vim_account_id(account
)
122 #nsi['userdata'] = {}
123 #nsi['userdata']['key1']='value1'
124 #nsi['userdata']['key2']='value2'
126 if ssh_keys
is not None:
127 # ssh_keys is comma separate list
128 # ssh_keys_format = []
129 # for key in ssh_keys.split(','):
130 # ssh_keys_format.append({'key-pair-ref': key})
132 # ns['ssh-authorized-key'] = ssh_keys_format
134 for pubkeyfile
in ssh_keys
.split(','):
135 with
open(pubkeyfile
, 'r') as f
:
136 nsi
['ssh_keys'].append(f
.read())
138 nsi_config
= yaml
.load(config
)
139 if "netslice-vld" in nsi_config
:
140 for vld
in nsi_config
["netslice-vld"]:
141 if vld
.get("vim-network-name"):
142 if isinstance(vld
["vim-network-name"], dict):
143 vim_network_name_dict
= {}
144 for vim_account
, vim_net
in list(vld
["vim-network-name"].items()):
145 vim_network_name_dict
[get_vim_account_id(vim_account
)] = vim_net
146 vld
["vim-network-name"] = vim_network_name_dict
147 nsi
["netslice-vld"] = nsi_config
["netslice-vld"]
148 if "netslice-subnet" in nsi_config
:
149 for nssubnet
in nsi_config
["netslice-subnet"]:
150 if "vld" in nssubnet
:
151 for vld
in nssubnet
["vld"]:
152 if vld
.get("vim-network-name"):
153 if isinstance(vld
["vim-network-name"], dict):
154 vim_network_name_dict
= {}
155 for vim_account
, vim_net
in list(vld
["vim-network-name"].items()):
156 vim_network_name_dict
[get_vim_account_id(vim_account
)] = vim_net
157 vld
["vim-network-name"] = vim_network_name_dict
158 if "vnf" in nssubnet
:
159 for vnf
in nsi_config
["vnf"]:
160 if vnf
.get("vim_account"):
161 vnf
["vimAccountId"] = get_vim_account_id(vnf
.pop("vim_account"))
162 nsi
["netslice-subnet"] = nsi_config
["netslice-subnet"]
164 #print yaml.safe_dump(nsi)
166 self
._apiResource
= '/netslice_instances_content'
167 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
168 self
._apiVersion
, self
._apiResource
)
169 headers
= self
._client
._headers
170 headers
['Content-Type'] = 'application/yaml'
171 http_header
= ['{}: {}'.format(key
,val
)
172 for (key
,val
) in list(headers
.items())]
173 self
._http
.set_http_header(http_header
)
174 http_code
, resp
= self
._http
.post_cmd(endpoint
=self
._apiBase
,
176 #print 'HTTP CODE: {}'.format(http_code)
177 #print 'RESP: {}'.format(resp)
178 if http_code
in (200, 201, 202, 204):
180 resp
= json
.loads(resp
)
181 if not resp
or 'id' not in resp
:
182 raise ClientException('unexpected response from server - {} '.format(
189 msg
= json
.loads(resp
)
192 raise ClientException(msg
)
193 except ClientException
as exc
:
194 message
="failed to create nsi: {} nst: {}\nerror:\n{}".format(
198 raise ClientException(message
)
200 def list_op(self
, name
, filter=None):
201 """Returns the list of operations of a NSI
205 self
._apiResource
= '/nsi_lcm_op_occs'
206 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
207 self
._apiVersion
, self
._apiResource
)
210 filter_string
= '&{}'.format(filter)
211 http_code
, resp
= self
._http
.get2_cmd('{}?nsiInstanceId={}'.format(
212 self
._apiBase
, nsi
['_id'],
214 #print 'HTTP CODE: {}'.format(http_code)
215 #print 'RESP: {}'.format(resp)
218 resp
= json
.loads(resp
)
221 raise ClientException('unexpected response from server')
226 resp
= json
.loads(resp
)
230 raise ClientException(msg
)
231 except ClientException
as exc
:
232 message
="failed to get operation list of NSI {}:\nerror:\n{}".format(
235 raise ClientException(message
)
237 def get_op(self
, operationId
):
238 """Returns the status of an operation
241 self
._apiResource
= '/nsi_lcm_op_occs'
242 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
243 self
._apiVersion
, self
._apiResource
)
244 http_code
, resp
= self
._http
.get2_cmd('{}/{}'.format(self
._apiBase
, operationId
))
245 #print 'HTTP CODE: {}'.format(http_code)
246 #print 'RESP: {}'.format(resp)
249 resp
= json
.loads(resp
)
252 raise ClientException('unexpected response from server')
257 resp
= json
.loads(resp
)
261 raise ClientException(msg
)
262 except ClientException
as exc
:
263 message
="failed to get status of operation {}:\nerror:\n{}".format(
266 raise ClientException(message
)
268 def exec_op(self
, name
, op_name
, op_data
=None):
269 """Executes an operation on a NSI
273 self
._apiResource
= '/netslice_instances'
274 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
275 self
._apiVersion
, self
._apiResource
)
276 endpoint
= '{}/{}/{}'.format(self
._apiBase
, nsi
['_id'], op_name
)
277 #print 'OP_NAME: {}'.format(op_name)
278 #print 'OP_DATA: {}'.format(json.dumps(op_data))
279 http_code
, resp
= self
._http
.post_cmd(endpoint
=endpoint
, postfields_dict
=op_data
)
280 #print 'HTTP CODE: {}'.format(http_code)
281 #print 'RESP: {}'.format(resp)
282 if http_code
in (200, 201, 202, 204):
284 resp
= json
.loads(resp
)
285 if not resp
or 'id' not in resp
:
286 raise ClientException('unexpected response from server - {}'.format(
293 msg
= json
.loads(resp
)
296 raise ClientException(msg
)
297 except ClientException
as exc
:
298 message
="failed to exec operation {}:\nerror:\n{}".format(
301 raise ClientException(message
)