From 9e7817e31ea1f913c9f673fd51f58da71de9c03c Mon Sep 17 00:00:00 2001 From: garciadeblas Date: Fri, 4 May 2018 14:15:04 +0200 Subject: [PATCH] new commands: ns-op-list, ns-op-show, ns-action Change-Id: Ie19c0f88d85cffbad41d5e71a3cb29ccd21473d4 Signed-off-by: garciadeblas --- osmclient/scripts/osm.py | 72 +++++++++++++++++++++++++++++++++++++++ osmclient/sol005/http.py | 5 ++- osmclient/sol005/ns.py | 73 +++++++++++++++++++++++++++++++++++++++- osmclient/sol005/nsd.py | 2 +- osmclient/sol005/vnfd.py | 2 +- 5 files changed, 150 insertions(+), 4 deletions(-) diff --git a/osmclient/scripts/osm.py b/osmclient/scripts/osm.py index 75b3be2..23f258e 100755 --- a/osmclient/scripts/osm.py +++ b/osmclient/scripts/osm.py @@ -243,6 +243,27 @@ def vnf_list(ctx): table.align = 'l' print(table) +@cli.command(name='ns-op-list') +@click.argument('name') +@click.pass_context +def ns_op_list(ctx, name): + '''shows the history of operations over a NS instance + + NAME: name or ID of the NS instance + ''' + try: + check_client_version(ctx.obj, ctx.command.name) + resp = ctx.obj.ns.list_op(name) + except ClientException as inst: + print(inst.message) + exit(1) + + table = PrettyTable(['id', 'operation', 'status']) + for op in resp: + table.add_row([op['id'], op['lcmOperationType'], + op['operationState']]) + table.align = 'l' + print(table) #################### # SHOW operations @@ -451,6 +472,29 @@ def ns_monitoring_show(ctx, ns_name): table.align = 'l' print(table) +@cli.command(name='ns-op-show', short_help='shows the info of an operation') +@click.argument('id') +@click.option('--filter', default=None) +@click.pass_context +def ns_op_show(ctx, id, filter): + '''shows the detailed info of an operation + + ID: operation identifier + ''' + try: + check_client_version(ctx.obj, ctx.command.name) + op_info = ctx.obj.ns.get_op(id) + except ClientException as inst: + print(inst.message) + exit(1) + + table = PrettyTable(['field', 'value']) + for k, v in op_info.items(): + if filter is None or filter in k: + table.add_row([k, json.dumps(v, indent=2)]) + table.align = 'l' + print(table) + #################### # CREATE operations @@ -1020,5 +1064,33 @@ def vcs_list(ctx): print(table) +@cli.command(name='ns-action') +@click.argument('ns_name') +@click.option('--vnf_name', default=None) +@click.option('--action_name', prompt=True) +@click.option('--params', prompt=True) +@click.pass_context +def ns_action(ctx, + ns_name, + vnf_name, + params): + '''executes an action/primitive over a NS instance + + NS_NAME: name or ID of the NS instance + ''' + try: + check_client_version(ctx.obj, ctx.command.name) + op_data={} + if vnf_name: + op_data['vnf_member_index'] = vnf_name + op_data['primitive'] = action_name + op_data['primitive_params'] = yaml.load(params) + ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data) + + except ClientException as inst: + print(inst.message) + exit(1) + + if __name__ == '__main__': cli() diff --git a/osmclient/sol005/http.py b/osmclient/sol005/http.py index 20593b8..d76e41e 100644 --- a/osmclient/sol005/http.py +++ b/osmclient/sol005/http.py @@ -120,6 +120,9 @@ class Http(http.Http): curl_cmd.setopt(pycurl.HTTPGET, 1) curl_cmd.setopt(pycurl.WRITEFUNCTION, data.write) curl_cmd.perform() + http_code = curl_cmd.getinfo(pycurl.HTTP_CODE) curl_cmd.close() - return data.getvalue() + if data.getvalue(): + return http_code, data.getvalue() + return http_code, None diff --git a/osmclient/sol005/ns.py b/osmclient/sol005/ns.py index 590cdb1..99fb83e 100644 --- a/osmclient/sol005/ns.py +++ b/osmclient/sol005/ns.py @@ -22,6 +22,7 @@ from osmclient.common import utils from osmclient.common.exceptions import ClientException from osmclient.common.exceptions import NotFound import yaml +import json class Ns(object): @@ -144,9 +145,9 @@ class Ns(object): self._apiResource = '/ns_instances_content' self._apiBase = '{}{}{}'.format(self._apiName, self._apiVersion, self._apiResource) - #print resp resp = self._http.post_cmd(endpoint=self._apiBase, postfields_dict=ns) + #print 'RESP: {}'.format(resp) if not resp or 'id' not in resp: raise ClientException('unexpected response from server: '.format( resp)) @@ -159,3 +160,73 @@ class Ns(object): exc.message) raise ClientException(message) + def list_op(self, name, filter=None): + """Returns the list of operations of a NS + """ + ns = self.get(name) + try: + self._apiResource = '/ns_lcm_op_occs' + self._apiBase = '{}{}{}'.format(self._apiName, + self._apiVersion, self._apiResource) + filter_string = '' + if filter: + filter_string = '&{}'.format(filter) + http_code, resp = self._http.get2_cmd('{}?nsInstanceId={}'.format(self._apiBase, ns['_id'], + filter_string) ) + resp = json.loads(resp.decode()) + #print 'RESP: {}'.format(resp) + if http_code == 200: + return resp + else: + raise ClientException('{}'.format(resp['detail'])) + + except ClientException as exc: + message="failed to get operation list of NS {}:\nerror:\n{}".format( + name, + exc.message) + raise ClientException(message) + + def get_op(self, operationId): + """Returns the status of an operation + """ + try: + self._apiResource = '/ns_lcm_op_occs' + self._apiBase = '{}{}{}'.format(self._apiName, + self._apiVersion, self._apiResource) + http_code, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, operationId)) + resp = json.loads(resp.decode()) + #print 'RESP: {}'.format(resp) + if http_code == 200: + return resp + else: + raise ClientException("{}".format(resp['detail'])) + except ClientException as exc: + message="failed to get status of operation {}:\nerror:\n{}".format( + operationId, + exc.message) + raise ClientException(message) + + def exec_op(self, name, op_name, op_data=None): + """Executes an operation on a NS + """ + ns = self.get(name) + try: + self._apiResource = '/ns_instances' + self._apiBase = '{}{}{}'.format(self._apiName, + self._apiVersion, self._apiResource) + endpoint = '{}/{}/{}'.format(self._apiBase, ns['_id'], op_name) + #print 'OP_NAME: {}'.format(op_name) + #print 'OP_DATA: {}'.format(json.dumps(op_data)) + resp = self._http.post_cmd(endpoint=endpoint, postfields_dict=op_data) + #print 'RESP: {}'.format(resp) + if not resp or 'id' not in resp: + raise ClientException('unexpected response from server: '.format( + resp)) + else: + print resp['id'] + except ClientException as exc: + message="failed to exec operation {}:\nerror:\n{}".format( + name, + exc.message) + raise ClientException(message) + diff --git a/osmclient/sol005/nsd.py b/osmclient/sol005/nsd.py index dac0adc..95fc92a 100644 --- a/osmclient/sol005/nsd.py +++ b/osmclient/sol005/nsd.py @@ -73,7 +73,7 @@ class Nsd(object): nsd = self.get(name) headers = self._client._headers headers['Accept'] = 'application/binary' - resp2 = self._http.get2_cmd('{}/{}/{}'.format(self._apiBase, nsd['_id'], thing)) + http_code, resp2 = self._http.get2_cmd('{}/{}/{}'.format(self._apiBase, nsd['_id'], thing)) #print yaml.safe_dump(resp2) if resp2: #store in a file diff --git a/osmclient/sol005/vnfd.py b/osmclient/sol005/vnfd.py index 28ded17..6b09a1f 100644 --- a/osmclient/sol005/vnfd.py +++ b/osmclient/sol005/vnfd.py @@ -72,7 +72,7 @@ class Vnfd(object): vnfd = self.get(name) headers = self._client._headers headers['Accept'] = 'application/binary' - resp2 = self._http.get2_cmd('{}/{}/{}'.format(self._apiBase, vnfd['_id'], thing)) + http_code, resp2 = self._http.get2_cmd('{}/{}/{}'.format(self._apiBase, vnfd['_id'], thing)) #print yaml.safe_dump(resp2) if resp2: #store in a file -- 2.25.1