envvar='OSM_SO_PORT',
help='hostname of server. ' +
'Also can set OSM_SO_PORT in environment')
+@click.option('--so-project',
+ default='default',
+ envvar='OSM_SO_PROJECT',
+ help='Project Name in SO. ' +
+ 'Also can set OSM_SO_PROJECT in environment')
@click.option('--ro-hostname',
default=None,
envvar='OSM_RO_HOSTNAME',
help='hostname of RO server. ' +
'Also can set OSM_RO_PORT in environment')
@click.pass_context
-def cli(ctx, hostname, so_port, ro_hostname, ro_port):
+def cli(ctx, hostname, so_port, so_project, ro_hostname, ro_port):
if hostname is None:
print(
"either hostname option or OSM_HOSTNAME " +
ctx.obj = client.Client(
host=hostname,
so_port=so_port,
+ so_project=so_project,
ro_host=ro_hostname,
ro_port=ro_port)
self,
host=None,
so_port=8008,
+ so_project='default',
ro_host=None,
ro_port=9090,
upload_port=8443,
self._host = host
self._so_port = so_port
+ self._so_project = so_project
+
http_client = http.Http(
'https://{}:{}/'.format(
self._host,
['Accept: application/vnd.yand.data+json',
'Content-Type: application/json'])
+ self._so_version = self.get_so_version(http_client)
+
if ro_host is None:
ro_host = host
ro_http_client = http.Http('http://{}:{}/'.format(ro_host, ro_port))
['Accept: application/vnd.yand.data+json',
'Content-Type: application/json'])
- upload_client = http.Http(
- 'https://{}:{}/composer/upload?api_server={}{}'.format(
+ upload_client_url = 'https://{}:{}/composer/upload?api_server={}{}'.format(
self._host,
upload_port,
'https://localhost&upload_server=https://',
- self._host))
+ self._host)
+
+ if self._so_version == 'v3':
+ upload_client_url = 'https://{}:{}/composer/upload?api_server={}{}&project_name={}'.format(
+ self._host,
+ upload_port,
+ 'https://localhost&upload_server=https://',
+ self._host,
+ self._so_project)
- self.vnf = vnf.Vnf(http_client, **kwargs)
- self.vnfd = vnfd.Vnfd(http_client, **kwargs)
+ upload_client = http.Http(upload_client_url)
+
+ self.vnf = vnf.Vnf(http_client, client=self, **kwargs)
+ self.vnfd = vnfd.Vnfd(http_client, client=self, **kwargs)
self.ns = ns.Ns(http=http_client, client=self, **kwargs)
- self.nsd = nsd.Nsd(http_client, **kwargs)
+ self.nsd = nsd.Nsd(http_client, client=self, **kwargs)
self.vim = vim.Vim(
http=http_client,
ro_http=ro_http_client,
upload_http=upload_client,
client=self,
**kwargs)
- self.vca = vca.Vca(http_client, **kwargs)
+ self.vca = vca.Vca(http_client, client=self, **kwargs)
self.utils = utils.Utils(http_client, **kwargs)
+
+ @property
+ def so_rbac_project_path(self):
+ if self._so_version == 'v3':
+ return 'project/{}/'.format(self._so_project)
+ else:
+ return ''
+
+ def get_so_version(self, http_client):
+ try:
+ resp = http_client.get_cmd('api/operational/version')
+ if not resp or 'rw-base:version' not in resp:
+ return 'v2'
+
+ if resp['rw-base:version']['version'].split('.')[0] == '5':
+ # SO Version 5.x.x.x.x translates to OSM V3
+ return 'v3'
+ return 'v2'
+ except Exception as e:
+ return 'v2'
+
+
def list(self):
"""Returns a list of ns's
"""
- resp = self._http.get_cmd('api/running/ns-instance-config')
-
+ 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()
ns = self.get(ns_name)
resp = self._http.post_cmd(
- 'v1/api/config/ns-instance-config/nsr/{}/scaling-group/{}/instance'
- .format(ns['id'], ns_scale_group), postdata)
+ '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(
nsr['id'] = str(uuid.uuid1())
nsd = self._client.nsd.get(nsd_name)
-
- datacenter = self._client.vim.get_datacenter(account)
- if datacenter is None:
- raise NotFound("cannot find datacenter account {}".format(account))
+
+ 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
- nsr['om-datacenter'] = datacenter['uuid']
+
+ 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
postdata['nsr'].append(nsr)
resp = self._http.post_cmd(
- 'api/config/ns-instance-config/nsr',
+ 'api/config/{}ns-instance-config/nsr'
+ .format(self._client.so_rbac_project_path),
postdata)
if 'success' not in resp:
def get_opdata(self, id):
return self._http.get_cmd(
- 'api/operational/ns-instance-opdata/nsr/{}?deep'.format(id))
+ '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 ns is None:
raise NotFound("cannot find ns {}".format(ns_name))
- return self._http.delete_cmd('api/config/ns-instance-config/nsr/' +
- ns['id'])
+ 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')
class Nsd(object):
- def __init__(self, http=None):
+ def __init__(self, http=None, client=None):
self._http = http
+ self._client = client
def list(self):
- resp = self._http.get_cmd('api/running/nsd-catalog/nsd')
- if resp and 'nsd:nsd' in resp:
- return resp['nsd:nsd']
+ resp = self._http.get_cmd('api/running/{}nsd-catalog/nsd'
+ .format(self._client.so_rbac_project_path))
+
+ if self._client._so_version == 'v3':
+ if resp and 'project-nsd:nsd' in resp:
+ return resp['project-nsd:nsd']
+ else:
+ # Backwards Compatibility
+ if resp and 'nsd:nsd' in resp:
+ return resp['nsd:nsd']
+
return list()
def get(self, name):
raise NotFound("cannot find nsd {}".format(nsd_name))
resp = self._http.delete_cmd(
- 'api/running/nsd-catalog/nsd/{}'.format(nsd['id']))
+ 'api/running/{}nsd-catalog/nsd/{}'
+ .format(self._client.so_rbac_project_path, nsd['id']))
if 'success' not in resp:
raise ClientException("failed to delete nsd {}".format(nsd_name))
import unittest
from mock import Mock
from osmclient.v1 import ns
+from osmclient.v1 import client
from osmclient.common.exceptions import NotFound
-class TestNs(unittest.TestCase):
-
+class TestNs(unittest.TestCase):
def test_list_empty(self):
mock = Mock()
mock.get_cmd.return_value = list()
- assert len(ns.Ns(mock).list()) == 0
+ assert len(ns.Ns(mock, client=client.Client(host='127.0.0.1')).list()) == 0
def test_get_notfound(self):
mock = Mock()
mock.get_cmd.return_value = 'foo'
- self.assertRaises(NotFound, ns.Ns(mock).get, 'bar')
+ self.assertRaises(NotFound, ns.Ns(mock, client=client.Client(host='127.0.0.1')).get, 'bar')
def test_get_found(self):
mock = Mock()
mock.get_cmd.return_value = {'nsr:ns-instance-config':
{'nsr': [{'name': 'foo'}]}}
- assert ns.Ns(mock).get('foo')
+ assert ns.Ns(mock, client=client.Client(host='127.0.0.1')).get('foo')
def test_get_monitoring_notfound(self):
mock = Mock()
mock.get_cmd.return_value = 'foo'
- self.assertRaises(NotFound, ns.Ns(mock).get_monitoring, 'bar')
+ self.assertRaises(NotFound, ns.Ns(mock, client=client.Client(host='127.0.0.1')).get_monitoring, 'bar')
import unittest
from mock import Mock
from osmclient.v1 import nsd
+from osmclient.v1 import client
from osmclient.common.exceptions import NotFound
class TestNsd(unittest.TestCase):
-
def test_list_empty(self):
mock = Mock()
mock.get_cmd.return_value = list()
- assert len(nsd.Nsd(mock).list()) == 0
+ assert len(nsd.Nsd(mock, client=client.Client(host='127.0.0.1')).list()) == 0
def test_get_notfound(self):
mock = Mock()
mock.get_cmd.return_value = 'foo'
- self.assertRaises(NotFound, nsd.Nsd(mock).get, 'bar')
+ self.assertRaises(NotFound, nsd.Nsd(mock, client=client.Client(host='127.0.0.1')).get, 'bar')
def test_get_found(self):
mock = Mock()
- mock.get_cmd.return_value = {'nsd:nsd': [{'name': 'foo'}]}
- assert nsd.Nsd(mock).get('foo')
+ if client.Client(host='127.0.0.1')._so_version == 'v3':
+ mock.get_cmd.return_value = {'project-nsd:nsd': [{'name': 'foo'}]}
+ else:
+ # Backwards Compatibility
+ mock.get_cmd.return_value = {'nsd:nsd': [{'name': 'foo'}]}
+ assert nsd.Nsd(mock, client=client.Client(host='127.0.0.1')).get('foo')
import unittest
from mock import Mock
from osmclient.v1 import vnf
+from osmclient.v1 import client
from osmclient.common.exceptions import NotFound
class TestVnf(unittest.TestCase):
-
def test_list_empty(self):
mock = Mock()
mock.get_cmd.return_value = list()
- assert len(vnf.Vnf(mock).list()) == 0
+ assert len(vnf.Vnf(mock, client=client.Client(host='127.0.0.1')).list()) == 0
def test_get_notfound(self):
mock = Mock()
mock.get_cmd.return_value = 'foo'
- self.assertRaises(NotFound, vnf.Vnf(mock).get, 'bar')
+ self.assertRaises(NotFound, vnf.Vnf(mock, client=client.Client(host='127.0.0.1')).get, 'bar')
def test_get_found(self):
mock = Mock()
mock.get_cmd.return_value = {'vnfr:vnfr': [{'name': 'foo'}]}
- assert vnf.Vnf(mock).get('foo')
+ assert vnf.Vnf(mock, client=client.Client(host='127.0.0.1')).get('foo')
def test_get_monitoring_notfound(self):
mock = Mock()
mock.get_cmd.return_value = 'foo'
- self.assertRaises(NotFound, vnf.Vnf(mock).get_monitoring, 'bar')
+ self.assertRaises(NotFound, vnf.Vnf(mock, client=client.Client(host='127.0.0.1')).get_monitoring, 'bar')
def test_get_monitoring_found(self):
mock = Mock()
mock.get_cmd.return_value = {'vnfr:vnfr': [{'name': 'foo',
'monitoring-param': True}]}
- assert vnf.Vnf(mock).get_monitoring('foo')
+ assert vnf.Vnf(mock, client=client.Client(host='127.0.0.1')).get_monitoring('foo')
import unittest
from mock import Mock
from osmclient.v1 import vnfd
+from osmclient.v1 import client
from osmclient.common.exceptions import NotFound
class TestVnfd(unittest.TestCase):
-
def test_list_empty(self):
mock = Mock()
mock.get_cmd.return_value = list()
- assert len(vnfd.Vnfd(mock).list()) == 0
+ assert len(vnfd.Vnfd(mock, client=client.Client(host='127.0.0.1')).list()) == 0
def test_get_notfound(self):
mock = Mock()
mock.get_cmd.return_value = 'foo'
- self.assertRaises(NotFound, vnfd.Vnfd(mock).get, 'bar')
+ self.assertRaises(NotFound, vnfd.Vnfd(mock, client=client.Client(host='127.0.0.1')).get, 'bar')
def test_get_found(self):
mock = Mock()
- mock.get_cmd.return_value = {'vnfd:vnfd': [{'name': 'foo'}]}
- assert vnfd.Vnfd(mock).get('foo')
+ if client.Client(host='127.0.0.1')._so_version == 'v3':
+ mock.get_cmd.return_value = {'project-vnfd:vnfd': [{'name': 'foo'}]}
+ else:
+ # Backwards Compatibility
+ mock.get_cmd.return_value = {'vnfd:vnfd': [{'name': 'foo'}]}
+
+ assert vnfd.Vnfd(mock, client=client.Client(host='127.0.0.1')).get('foo')
class Vca(object):
- def __init__(self, http=None):
+ def __init__(self, http=None, client=None):
self._http = http
+ self._client = client
def list(self):
- resp = self._http.get_cmd('api/config/config-agent')
+ resp = self._http.get_cmd('api/config/{}config-agent'
+ .format(self._client.so_rbac_project_path))
if resp and 'rw-config-agent:config-agent' in resp:
return resp['rw-config-agent:config-agent']['account']
return list()
def delete(self, name):
if ('success' not in
- self._http.delete_cmd('api/config/config-agent/account/{}'
- .format(name))):
+ self._http.delete_cmd('api/config/{}config-agent/account/{}'
+ .format(self._client.so_rbac_project_path, name))):
raise ClientException("failed to delete config agent {}"
.format(name))
account['juju']['ip-address'] = server
postdata['account'].append(account)
- if 'success' not in self._http.post_cmd('api/config/config-agent',
- postdata):
+ if 'success' not in self._http.post_cmd('api/config/{}config-agent'
+ .format(self._client.so_rbac_project_path), postdata):
raise ClientException("failed to create config agent {}"
.format(name))
raise ClientException("failed to delete vim {}".format(vim_name))
def list(self):
- resp = self._http.get_cmd('v1/api/operational/datacenters')
- if not resp or 'rw-launchpad:datacenters' not in resp:
- return list()
-
- datacenters = resp['rw-launchpad:datacenters']
-
- vim_accounts = list()
- if 'ro-accounts' not in datacenters:
+ if self._client._so_version == 'v3':
+ resp = self._http.get_cmd('v1/api/operational/{}ro-account-state'
+ .format(self._client.so_rbac_project_path))
+ datacenters = []
+ if not resp or 'rw-ro-account:ro-account-state' not in resp:
+ return list()
+
+ ro_accounts = resp['rw-ro-account:ro-account-state']
+ for ro_account in ro_accounts['account']:
+ for datacenter in ro_account['datacenters']['datacenters']:
+ datacenters.append({"name": datacenter['name'], "uuid": datacenter['uuid']
+ if 'uuid' in datacenter else None})
+
+ vim_accounts = datacenters
return vim_accounts
-
- tenant = self._get_ro_tenant()
- if tenant is None:
+ else:
+ # Backwards Compatibility
+ resp = self._http.get_cmd('v1/api/operational/datacenters')
+ if not resp or 'rw-launchpad:datacenters' not in resp:
+ return list()
+
+ datacenters = resp['rw-launchpad:datacenters']
+
+ vim_accounts = list()
+ if 'ro-accounts' not in datacenters:
+ return vim_accounts
+
+ tenant = self._get_ro_tenant()
+ if tenant is None:
+ return vim_accounts
+
+ for roaccount in datacenters['ro-accounts']:
+ if 'datacenters' not in roaccount:
+ continue
+ for datacenter in roaccount['datacenters']:
+ vim_accounts.append(self._get_ro_datacenter(datacenter['name'],
+ tenant['uuid']))
return vim_accounts
- for roaccount in datacenters['ro-accounts']:
- if 'datacenters' not in roaccount:
- continue
- for datacenter in roaccount['datacenters']:
- vim_accounts.append(self._get_ro_datacenter(datacenter['name'],
- tenant['uuid']))
- return vim_accounts
-
def _get_ro_tenant(self, name='osm'):
resp = self._ro_http.get_cmd('openmano/tenants/{}'.format(name))
return self._get_ro_datacenter(name, tenant['uuid'])
def get_datacenter(self, name):
- resp = self._http.get_cmd('v1/api/operational/datacenters')
- if not resp:
- return None
-
- if not resp or 'rw-launchpad:datacenters' not in resp:
- return None
- if 'ro-accounts' not in resp['rw-launchpad:datacenters']:
+ if self._client._so_version == 'v3':
+ resp = self._http.get_cmd('v1/api/operational/{}ro-account-state'
+ .format(self._client.so_rbac_project_path))
+ if not resp:
+ return None, None
+
+ if not resp or 'rw-ro-account:ro-account-state' not in resp:
+ return None, None
+
+ ro_accounts = resp['rw-ro-account:ro-account-state']
+ for ro_account in ro_accounts['account']:
+ for datacenter in ro_account['datacenters']['datacenters']:
+ if datacenter['name'] == name:
+ return datacenter, ro_account['name']
+ return None, None
+ else:
+ # Backwards Compatibility
+ resp = self._http.get_cmd('v1/api/operational/datacenters')
+ if not resp:
+ return None
+
+ if not resp or 'rw-launchpad:datacenters' not in resp:
+ return None
+ if 'ro-accounts' not in resp['rw-launchpad:datacenters']:
+ return None
+ for roaccount in resp['rw-launchpad:datacenters']['ro-accounts']:
+ if 'datacenters' not in roaccount:
+ continue
+ for datacenter in roaccount['datacenters']:
+ if datacenter['name'] == name:
+ return datacenter
return None
- for roaccount in resp['rw-launchpad:datacenters']['ro-accounts']:
- if 'datacenters' not in roaccount:
- continue
- for datacenter in roaccount['datacenters']:
- if datacenter['name'] == name:
- return datacenter
- return None
def get_resource_orchestrator(self):
- resp = self._http.get_cmd('v1/api/operational/resource-orchestrator')
+ resp = self._http.get_cmd('v1/api/operational/{}resource-orchestrator'
+ .format(self._client.so_rbac_project_path))
+
if not resp or 'rw-launchpad:resource-orchestrator' not in resp:
return None
return resp['rw-launchpad:resource-orchestrator']
class Vnf(object):
- def __init__(self, http=None):
+ def __init__(self, http=None, client=None):
self._http = http
+ self._client = client
def list(self):
- resp = self._http.get_cmd('v1/api/operational/vnfr-catalog/vnfr')
+ resp = self._http.get_cmd('v1/api/operational/{}vnfr-catalog/vnfr'
+ .format(self._client.so_rbac_project_path))
if resp and 'vnfr:vnfr' in resp:
return resp['vnfr:vnfr']
return list()
class Vnfd(object):
- def __init__(self, http=None):
+ def __init__(self, http=None, client=None):
self._http = http
+ self._client = client
def list(self):
- resp = self._http.get_cmd('api/running/vnfd-catalog/vnfd')
- if resp and 'vnfd:vnfd' in resp:
- return resp['vnfd:vnfd']
+ resp = self._http.get_cmd('api/running/{}vnfd-catalog/vnfd'
+ .format(self._client.so_rbac_project_path))
+
+ if self._client._so_version == 'v3':
+ if resp and 'project-vnfd:vnfd' in resp:
+ return resp['project-vnfd:vnfd']
+ else:
+ # Backwards Compatibility
+ if resp and 'vnfd:vnfd' in resp:
+ return resp['vnfd:vnfd']
+
return list()
def get(self, name):
def delete(self, vnfd_name):
vnfd = self.get(vnfd_name)
- resp = self._http.delete_cmd('api/running/vnfd-catalog/vnfd/{}'
- .format(vnfd['id']))
+ resp = self._http.delete_cmd('api/running/{}vnfd-catalog/vnfd/{}'
+ .format(self._client.so_rbac_project_path, vnfd['id']))
if 'success' not in resp:
raise ClientException("failed to delete vnfd {}".format(vnfd_name))