blob: 65f816da235d7d27133d246b8e7f781d802a5369 [file] [log] [blame]
# Copyright 2017 Sandvine
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
OSM ns API handling
"""
from osmclient.common import utils
from osmclient.common.exceptions import ClientException
from osmclient.common.exceptions import NotFound
import uuid
import yaml
class Ns(object):
def __init__(self, http=None, client=None):
self._http = http
self._client = client
def list(self):
"""Returns a list of ns's
"""
resp = self._http.get_cmd('api/running/{}ns-instance-config'
.format(self._client.so_rbac_project_path))
if not resp or 'nsr:ns-instance-config' not in resp:
return list()
if 'nsr' not in resp['nsr:ns-instance-config']:
return list()
return resp['nsr:ns-instance-config']['nsr']
def get(self, name):
"""Returns an ns based on name
"""
for ns in self.list():
if name == ns['name']:
return ns
raise NotFound("ns {} not found".format(name))
def scale(self, ns_name, ns_scale_group, instance_index):
postdata = {}
postdata['instance'] = list()
instance = {}
instance['id'] = instance_index
postdata['instance'].append(instance)
ns = self.get(ns_name)
resp = self._http.post_cmd(
'v1/api/config/{}ns-instance-config/nsr/{}/scaling-group/{}/instance'
.format(self._client.so_rbac_project_path, ns['id'], ns_scale_group), postdata)
if 'success' not in resp:
raise ClientException(
"failed to scale ns: {} result: {}".format(
ns_name,
resp))
def create(self, nsd_name, nsr_name, account, config=None,
ssh_keys=None, description='default description',
admin_status='ENABLED'):
postdata = {}
postdata['nsr'] = list()
nsr = {}
nsr['id'] = str(uuid.uuid1())
nsd = self._client.nsd.get(nsd_name)
if self._client._so_version == 'v3':
datacenter, resource_orchestrator = self._client.vim.get_datacenter(account)
if datacenter is None or resource_orchestrator is None:
raise NotFound("cannot find datacenter account {}".format(account))
if 'uuid' not in datacenter:
raise NotFound("The RO Datacenter - {} is invalid. Please select another".format(account))
else:
# Backwards Compatiility
datacenter = self._client.vim.get_datacenter(account)
if datacenter is None:
raise NotFound("cannot find datacenter account {}".format(account))
nsr['nsd'] = nsd
nsr['name'] = nsr_name
nsr['short-name'] = nsr_name
nsr['description'] = description
nsr['admin-status'] = admin_status
if self._client._so_version == 'v3':
# New format for V3
nsr['resource-orchestrator'] = resource_orchestrator
nsr['datacenter'] = datacenter['name']
else:
# Backwards Compatiility
nsr['om-datacenter'] = datacenter['uuid']
if ssh_keys is not None:
# ssh_keys is comma separate list
ssh_keys_format = []
for key in ssh_keys.split(','):
ssh_keys_format.append({'key-pair-ref': key})
nsr['ssh-authorized-key'] = ssh_keys_format
ns_config = {}
if config:
ns_config = yaml.load(config)
if ns_config and 'vim-network-name' in ns_config:
for network in ns_config['vim-network-name']:
# now find this network
vld_name = network['name']
vim_vld_name = network['vim-network-name']
for index, vld in enumerate(nsr['nsd']['vld']):
if vld['name'] == vld_name:
nsr['nsd']['vld'][index]['vim-network-name'] = network['vim-network-name']
postdata['nsr'].append(nsr)
resp = self._http.post_cmd(
'api/config/{}ns-instance-config/nsr'
.format(self._client.so_rbac_project_path),
postdata)
if 'success' not in resp:
raise ClientException(
"failed to create ns: {} nsd: {} result: {}".format(
nsr_name,
nsd_name,
resp))
def get_opdata(self, id):
return self._http.get_cmd(
'api/operational/{}ns-instance-opdata/nsr/{}?deep'
.format(self._client.so_rbac_project_path, id))
def get_field(self, ns_name, field):
nsr = self.get(ns_name)
if nsr is None:
raise NotFound("failed to retrieve ns {}".format(ns_name))
if field in nsr:
return nsr[field]
nsopdata = self.get_opdata(nsr['id'])
if field in nsopdata['nsr:nsr']:
return nsopdata['nsr:nsr'][field]
raise NotFound("failed to find {} in ns {}".format(field, ns_name))
def _terminate(self, ns_name):
ns = self.get(ns_name)
if ns is None:
raise NotFound("cannot find ns {}".format(ns_name))
return self._http.delete_cmd('api/config/{}ns-instance-config/nsr/{}'
.format(self._client.so_rbac_project_path, ns['id']))
def delete(self, ns_name, wait=True):
vnfs = self.get_field(ns_name, 'constituent-vnfr-ref')
resp = self._terminate(ns_name)
if 'success' not in resp:
raise ClientException("failed to delete ns {}".format(ns_name))
# helper method to check if pkg exists
def check_not_exists(func):
try:
func()
return False
except NotFound:
return True
for vnf in vnfs:
if (not utils.wait_for_value(
lambda:
check_not_exists(lambda:
self._client.vnf.get(vnf['vnfr-id'])))):
raise ClientException(
"vnf {} failed to delete".format(vnf['vnfr-id']))
if not utils.wait_for_value(lambda:
check_not_exists(lambda:
self.get(ns_name))):
raise ClientException("ns {} failed to delete".format(ns_name))
def get_monitoring(self, ns_name):
ns = self.get(ns_name)
mon_list = {}
if ns is None:
return mon_list
vnfs = self._client.vnf.list()
for vnf in vnfs:
if ns['id'] == vnf['nsr-id-ref']:
if 'monitoring-param' in vnf:
mon_list[vnf['name']] = vnf['monitoring-param']
return mon_list