X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osmclient%2Fscripts%2Fosm.py;h=a369c48afd1d6c11952a9f7e54337e3d507871de;hb=c706f69a072bef2b6e68d82fa1917d79ee2ee867;hp=c5e821266a615a752b15a2d5f4e121e68a849d6d;hpb=0c1b375821761f39be1be0e7f42c0a732cc819ac;p=osm%2Fosmclient.git diff --git a/osmclient/scripts/osm.py b/osmclient/scripts/osm.py index c5e8212..a369c48 100755 --- a/osmclient/scripts/osm.py +++ b/osmclient/scripts/osm.py @@ -20,7 +20,7 @@ OSM shell/cli import click from osmclient import client -from osmclient.common.exceptions import ClientException +from osmclient.common.exceptions import ClientException, NotFound from prettytable import PrettyTable import yaml import json @@ -290,7 +290,7 @@ def ns_list(ctx, filter, long): if ee['elementType'] not in status_ee: status_ee[ee['elementType']] = {} status_ee[ee['elementType']][ee['status']] = 1 - continue; + continue if ee['status'] in status_ee[ee['elementType']]: status_ee[ee['elementType']][ee['status']] += 1 else: @@ -368,7 +368,8 @@ def ns_list(ctx, filter, long): else: current_operation = "{} ({})".format(nsr['_admin'].get('current-operation','-'), nsr['_admin']['nslcmop']) error_details = "N/A" - if ns_state == "BROKEN" or ns_state == "DEGRADED" or nsr.get('errorDescription'): + if ns_state == "BROKEN" or ns_state == "DEGRADED" or \ + ('currentOperation' not in nsr and nsr.get('errorDescription')): error_details = "{}\nDetail: {}".format(nsr['errorDescription'], nsr['errorDetail']) else: nsopdata = ctx.obj.ns.get_opdata(ns['id']) @@ -466,6 +467,26 @@ def nsd_list2(ctx, filter, long): nsd_list(ctx, filter, long) +def pkg_repo_list(ctx, pkgtype, filter, repo, long): + resp = ctx.obj.osmrepo.pkg_list(pkgtype, filter, repo) + if long: + table = PrettyTable(['nfpkg name', 'vendor', 'version', 'latest', 'description', 'repository']) + else: + table = PrettyTable(['nfpkg name', 'repository']) + for vnfd in resp: + name = vnfd.get('name', '-') + repository = vnfd.get('repository') + if long: + vendor = vnfd.get('vendor') + version = vnfd.get('version') + description = vnfd.get('description') + latest = vnfd.get('latest') + table.add_row([name, vendor, version, latest, description, repository]) + else: + table.add_row([name, repository]) + table.align = 'l' + print(table) + def vnfd_list(ctx, nf_type, filter, long): logger.debug("") if nf_type: @@ -493,7 +514,7 @@ def vnfd_list(ctx, nf_type, filter, long): fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__ if fullclassname == 'osmclient.sol005.client.Client': if long: - table = PrettyTable(['nfpkg name', 'id', 'onboarding state', 'operational state', + table = PrettyTable(['nfpkg name', 'id', 'vendor', 'version', 'onboarding state', 'operational state', 'usage state', 'date', 'last update']) else: table = PrettyTable(['nfpkg name', 'id']) @@ -502,10 +523,12 @@ def vnfd_list(ctx, nf_type, filter, long): if long: onb_state = vnfd['_admin'].get('onboardingState','-') op_state = vnfd['_admin'].get('operationalState','-') + vendor = vnfd.get('vendor') + version = vnfd.get('version') usage_state = vnfd['_admin'].get('usageState','-') date = datetime.fromtimestamp(vnfd['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S") last_update = datetime.fromtimestamp(vnfd['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S") - table.add_row([name, vnfd['_id'], onb_state, op_state, usage_state, date, last_update]) + table.add_row([name, vnfd['_id'], vendor, version, onb_state, op_state, usage_state, date, last_update]) else: table.add_row([name, vnfd['_id']]) else: @@ -539,6 +562,17 @@ def vnfd_list2(ctx, nf_type, filter, long): logger.debug("") vnfd_list(ctx, nf_type, filter, long) +@cli_osm.command(name='vnfpkg-repo-list', short_help='list all xNF from OSM repositories') +@click.option('--filter', default=None, + help='restricts the list to the NFpkg matching the filter') +@click.option('--repo', default=None, + help='restricts the list to a particular OSM repository') +@click.option('--long', is_flag=True, help='get more details') +@click.pass_context +def vnfd_list3(ctx, filter, repo, long): + """list xNF packages from OSM repositories""" + pkgtype = 'vnf' + pkg_repo_list(ctx, pkgtype, filter, repo, long) @cli_osm.command(name='nfpkg-list', short_help='list all xNF packages (VNF, HNF, PNF)') @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)') @@ -556,6 +590,17 @@ def nfpkg_list(ctx, nf_type, filter, long): # print(str(e)) # exit(1) +@cli_osm.command(name='nfpkg-repo-list', short_help='list all xNF from OSM repositories') +@click.option('--filter', default=None, + help='restricts the list to the NFpkg matching the filter') +@click.option('--repo', default=None, + help='restricts the list to a particular OSM repository') +@click.option('--long', is_flag=True, help='get more details') +@click.pass_context +def vnfd_list4(ctx, filter, repo, long): + """list xNF packages from OSM repositories""" + pkgtype = 'vnf' + pkg_repo_list(ctx, pkgtype, filter, repo, long) def vnf_list(ctx, ns, filter, long): # try: @@ -619,6 +664,29 @@ def vnf_list1(ctx, ns, filter, long): logger.debug("") vnf_list(ctx, ns, filter, long) +@cli_osm.command(name='nsd-repo-list', short_help='list all NS from OSM repositories') +@click.option('--filter', default=None, + help='restricts the list to the NS matching the filter') +@click.option('--repo', default=None, + help='restricts the list to a particular OSM repository') +@click.option('--long', is_flag=True, help='get more details') +@click.pass_context +def nsd_list3(ctx, filter, repo, long): + """list xNF packages from OSM repositories""" + pkgtype = 'ns' + pkg_repo_list(ctx, pkgtype, filter, repo, long) + +@cli_osm.command(name='nspkg-repo-list', short_help='list all NS from OSM repositories') +@click.option('--filter', default=None, + help='restricts the list to the NS matching the filter') +@click.option('--repo', default=None, + help='restricts the list to a particular OSM repository') +@click.option('--long', is_flag=True, help='get more details') +@click.pass_context +def nspkg_list(ctx, filter, repo, long): + """list xNF packages from OSM repositories""" + pkgtype = 'ns' + pkg_repo_list(ctx, pkgtype, filter, repo, long) @cli_osm.command(name='nf-list', short_help='list all NF instances') @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list') @@ -675,7 +743,7 @@ def nf_list(ctx, ns, filter, long): --filter vnfd-ref=,vdur.ip-address= """ logger.debug("") - vnf_list(ctx, ns, filter) + vnf_list(ctx, ns, filter, long) @cli_osm.command(name='ns-op-list', short_help='shows the history of operations over a NS instance') @@ -925,7 +993,7 @@ def nsd_show(ctx, name, literal): # exit(1) if literal: - print(yaml.safe_dump(resp)) + print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return table = PrettyTable(['field', 'value']) @@ -935,7 +1003,7 @@ def nsd_show(ctx, name, literal): print(table) -@cli_osm.command(name='nsd-show', short_help='shows the content of a NSD') +@cli_osm.command(name='nsd-show', short_help='shows the details of a NS package') @click.option('--literal', is_flag=True, help='print literally, no pretty table') @click.argument('name') @@ -949,7 +1017,7 @@ def nsd_show1(ctx, name, literal): nsd_show(ctx, name, literal) -@cli_osm.command(name='nspkg-show', short_help='shows the content of a NSD') +@cli_osm.command(name='nspkg-show', short_help='shows the details of a NS package') @click.option('--literal', is_flag=True, help='print literally, no pretty table') @click.argument('name') @@ -973,7 +1041,7 @@ def vnfd_show(ctx, name, literal): # exit(1) if literal: - print(yaml.safe_dump(resp)) + print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return table = PrettyTable(['field', 'value']) @@ -983,7 +1051,29 @@ def vnfd_show(ctx, name, literal): print(table) -@cli_osm.command(name='vnfd-show', short_help='shows the content of a VNFD') +def pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal): + logger.debug("") + # try: + resp = ctx.obj.osmrepo.pkg_get(pkgtype, name, repo, version, filter) + + if literal: + print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) + return + pkgtype += 'd' + catalog = pkgtype + '-catalog' + full_catalog = pkgtype + ':' + catalog + if resp.get(catalog): + resp = resp.pop(catalog)[pkgtype][0] + elif resp.get(full_catalog): + resp = resp.pop(full_catalog)[pkgtype][0] + + table = PrettyTable(['field', 'value']) + for k, v in list(resp.items()): + table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)]) + table.align = 'l' + print(table) + +@cli_osm.command(name='vnfd-show', short_help='shows the details of a NF package') @click.option('--literal', is_flag=True, help='print literally, no pretty table') @click.argument('name') @@ -997,7 +1087,7 @@ def vnfd_show1(ctx, name, literal): vnfd_show(ctx, name, literal) -@cli_osm.command(name='vnfpkg-show', short_help='shows the content of a VNFD') +@cli_osm.command(name='vnfpkg-show', short_help='shows the details of a NF package') @click.option('--literal', is_flag=True, help='print literally, no pretty table') @click.argument('name') @@ -1010,8 +1100,71 @@ def vnfd_show2(ctx, name, literal): logger.debug("") vnfd_show(ctx, name, literal) +@cli_osm.command(name='vnfpkg-repo-show', short_help='shows the details of a NF package in an OSM repository') +@click.option('--literal', is_flag=True, + help='print literally, no pretty table') +@click.option('--repo', + required=True, + help='Repository name') +@click.argument('name') +@click.option('--filter', + help='filter by fields') +@click.option('--version', + default='latest', + help='package version') +@click.pass_context +def vnfd_show3(ctx, name, repo, version, literal=None, filter=None): + """shows the content of a VNFD in a repository + + NAME: name or ID of the VNFD/VNFpkg + """ + pkgtype = 'vnf' + pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal) + + +@cli_osm.command(name='nsd-repo-show', short_help='shows the details of a NS package in an OSM repository') +@click.option('--literal', is_flag=True, + help='print literally, no pretty table') +@click.option('--repo', + required=True, + help='Repository name') +@click.argument('name') +@click.option('--filter', + help='filter by fields') +@click.option('--version', + default='latest', + help='package version') +@click.pass_context +def nsd_repo_show(ctx, name, repo, version, literal=None, filter=None): + """shows the content of a VNFD in a repository + + NAME: name or ID of the VNFD/VNFpkg + """ + pkgtype = 'ns' + pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal) + +@cli_osm.command(name='nspkg-repo-show', short_help='shows the details of a NS package in an OSM repository') +@click.option('--literal', is_flag=True, + help='print literally, no pretty table') +@click.option('--repo', + required=True, + help='Repository name') +@click.argument('name') +@click.option('--filter', + help='filter by fields') +@click.option('--version', + default='latest', + help='package version') +@click.pass_context +def nsd_repo_show2(ctx, name, repo, version, literal=None, filter=None): + """shows the content of a VNFD in a repository + + NAME: name or ID of the VNFD/VNFpkg + """ + pkgtype = 'ns' + pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal) -@cli_osm.command(name='nfpkg-show', short_help='shows the content of a NF Descriptor') +@cli_osm.command(name='nfpkg-show', short_help='shows the details of a NF package') @click.option('--literal', is_flag=True, help='print literally, no pretty table') @click.argument('name') @@ -1025,6 +1178,28 @@ def nfpkg_show(ctx, name, literal): vnfd_show(ctx, name, literal) +@cli_osm.command(name='nfpkg-repo-show', short_help='shows the details of a NF package in an OSM repository') +@click.option('--literal', is_flag=True, + help='print literally, no pretty table') +@click.option('--repo', + required=True, + help='Repository name') +@click.argument('name') +@click.option('--filter', + help='filter by fields') +@click.option('--version', + default='latest', + help='package version') +@click.pass_context +def vnfd_show4(ctx, name, repo, version, literal=None, filter=None): + """shows the content of a VNFD in a repository + + NAME: name or ID of the VNFD/VNFpkg + """ + pkgtype = 'vnf' + pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal) + + @cli_osm.command(name='ns-show', short_help='shows the info of a NS instance') @click.argument('name') @click.option('--literal', is_flag=True, @@ -1044,7 +1219,7 @@ def ns_show(ctx, name, literal, filter): # exit(1) if literal: - print(yaml.safe_dump(ns)) + print(yaml.safe_dump(ns, indent=4, default_flow_style=False)) return table = PrettyTable(['field', 'value']) @@ -1133,7 +1308,7 @@ def vnf_show(ctx, name, literal, filter, kdu): print ("Could not determine KDU status") if literal: - print(yaml.safe_dump(resp)) + print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return table = PrettyTable(['field', 'value']) @@ -1214,7 +1389,7 @@ def ns_op_show(ctx, id, filter, literal): # exit(1) if literal: - print(yaml.safe_dump(op_info)) + print(yaml.safe_dump(op_info, indent=4, default_flow_style=False)) return table = PrettyTable(['field', 'value']) @@ -1236,7 +1411,7 @@ def nst_show(ctx, name, literal): # exit(1) if literal: - print(yaml.safe_dump(resp)) + print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return table = PrettyTable(['field', 'value']) @@ -1284,7 +1459,7 @@ def nsi_show(ctx, name, literal, filter): # exit(1) if literal: - print(yaml.safe_dump(nsi)) + print(yaml.safe_dump(nsi, indent=4, default_flow_style=False)) return table = PrettyTable(['field', 'value']) @@ -1390,7 +1565,7 @@ def pdu_show(ctx, name, literal, filter): # exit(1) if literal: - print(yaml.safe_dump(pdu)) + print(yaml.safe_dump(pdu, indent=4, default_flow_style=False)) return table = PrettyTable(['field', 'value']) @@ -1407,10 +1582,12 @@ def pdu_show(ctx, name, literal, filter): # CREATE operations #################### -def nsd_create(ctx, filename, overwrite, skip_charm_build): +def nsd_create(ctx, filename, overwrite, skip_charm_build, repo, vendor, version): logger.debug("") # try: check_client_version(ctx.obj, ctx.command.name) + if repo: + filename = ctx.obj.osmrepo.get_pkg('ns', filename, repo, vendor, version) ctx.obj.nsd.create(filename, overwrite=overwrite, skip_charm_build=skip_charm_build) # except ClientException as e: # print(str(e)) @@ -1426,8 +1603,14 @@ def nsd_create(ctx, filename, overwrite, skip_charm_build): '"key1.key2...=value[;key3...=value;...]"') @click.option('--skip-charm-build', default=False, is_flag=True, help='The charm will not be compiled, it is assumed to already exist') +@click.option('--repo', default=None, + help='[repository]: Repository name') +@click.option('--vendor', default=None, + help='[repository]: filter by vendor]') +@click.option('--version', default='latest', + help='[repository]: filter by version. Default: latest') @click.pass_context -def nsd_create1(ctx, filename, overwrite, skip_charm_build): +def nsd_create1(ctx, filename, overwrite, skip_charm_build, repo, vendor, version): """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED) \b @@ -1436,7 +1619,8 @@ def nsd_create1(ctx, filename, overwrite, skip_charm_build): If FILENAME is an NF Package folder, it is built and then onboarded. """ logger.debug("") - nsd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build) + nsd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, repo=repo, vendor=vendor, + version=version) @cli_osm.command(name='nspkg-create', short_help='creates a new NSD/NSpkg') @@ -1448,23 +1632,32 @@ def nsd_create1(ctx, filename, overwrite, skip_charm_build): '"key1.key2...=value[;key3...=value;...]"') @click.option('--skip-charm-build', default=False, is_flag=True, help='The charm will not be compiled, it is assumed to already exist') +@click.option('--repo', default=None, + help='[repository]: Repository name') +@click.option('--vendor', default=None, + help='[repository]: filter by vendor]') +@click.option('--version', default='latest', + help='[repository]: filter by version. Default: latest') @click.pass_context -def nsd_create2(ctx, filename, overwrite, skip_charm_build): +def nsd_pkg_create(ctx, filename, overwrite, skip_charm_build, repo, vendor, version): """onboards a new NSpkg - \b FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded. If FILENAME is an NF Package folder, it is built and then onboarded. """ logger.debug("") - nsd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build) + nsd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, repo=repo, vendor=vendor, + version=version) -def vnfd_create(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt): +def vnfd_create(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt, + repo, vendor, version): logger.debug("") # try: check_client_version(ctx.obj, ctx.command.name) + if repo: + filename = ctx.obj.osmrepo.get_pkg('vnf', filename, repo, vendor, version) ctx.obj.vnfd.create(filename, overwrite=overwrite, skip_charm_build=skip_charm_build, override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt) @@ -1488,10 +1681,16 @@ def vnfd_create(ctx, filename, overwrite, skip_charm_build, override_epa, overri help='removes all guest-epa parameters from all VDU') @click.option('--override-paravirt', required=False, default=False, is_flag=True, help='overrides all VDU interfaces to PARAVIRT') +@click.option('--repo', default=None, + help='[repository]: Repository name') +@click.option('--vendor', default=None, + help='[repository]: filter by vendor]') +@click.option('--version', default='latest', + help='[repository]: filter by version. Default: latest') @click.pass_context -def vnfd_create1(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt): - """onboards a new NFpkg (alias of nfpkg-create) (TO BE DEPRECATED) - +def vnfd_create1(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt, + repo,vendor, version): + """creates a new VNFD/VNFpkg \b FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded. @@ -1499,7 +1698,8 @@ def vnfd_create1(ctx, filename, overwrite, skip_charm_build, override_epa, overr """ logger.debug("") vnfd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, - override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt) + override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt, + repo=repo, vendor=vendor, version=version) @cli_osm.command(name='vnfpkg-create', short_help='creates a new VNFD/VNFpkg') @@ -1517,10 +1717,16 @@ def vnfd_create1(ctx, filename, overwrite, skip_charm_build, override_epa, overr help='removes all guest-epa parameters from all VDU') @click.option('--override-paravirt', required=False, default=False, is_flag=True, help='overrides all VDU interfaces to PARAVIRT') +@click.option('--repo', default=None, + help='[repository]: Repository name') +@click.option('--vendor', default=None, + help='[repository]: filter by vendor]') +@click.option('--version', default='latest', + help='[repository]: filter by version. Default: latest') @click.pass_context -def vnfd_create2(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt): - """onboards a new NFpkg (alias of nfpkg-create) - +def vnfd_create2(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt, + repo, vendor, version): + """creates a new VNFD/VNFpkg \b FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded. @@ -1528,8 +1734,8 @@ def vnfd_create2(ctx, filename, overwrite, skip_charm_build, override_epa, overr """ logger.debug("") vnfd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, - override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt) - + override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt, + repo=repo, vendor=vendor, version=version) @cli_osm.command(name='nfpkg-create', short_help='creates a new NFpkg') @click.argument('filename') @@ -1546,9 +1752,16 @@ def vnfd_create2(ctx, filename, overwrite, skip_charm_build, override_epa, overr help='removes all guest-epa parameters from all VDU') @click.option('--override-paravirt', required=False, default=False, is_flag=True, help='overrides all VDU interfaces to PARAVIRT') +@click.option('--repo', default=None, + help='[repository]: Repository name') +@click.option('--vendor', default=None, + help='[repository]: filter by vendor]') +@click.option('--version', default='latest', + help='[repository]: filter by version. Default: latest') @click.pass_context -def nfpkg_create(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt): - """onboards a new NFpkg (alias of nfpkg-create) +def nfpkg_create(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt, + repo, vendor, version): + """creates a new NFpkg \b FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder @@ -1557,7 +1770,8 @@ def nfpkg_create(ctx, filename, overwrite, skip_charm_build, override_epa, overr """ logger.debug("") vnfd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, - override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt) + override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt, + repo=repo, vendor=vendor, version=version) @cli_osm.command(name='ns-create', short_help='creates a new Network Service instance') @@ -1634,13 +1848,13 @@ def nst_create(ctx, filename, overwrite): help='overrides fields in descriptor, format: ' '"key1.key2...=value[;key3...=value;...]"') @click.pass_context -def nst_create1(ctx, charm_folder, overwrite): +def nst_create1(ctx, filename, overwrite): """creates a new Network Slice Template (NST) FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file """ logger.debug("") - nst_create(ctx, charm_folder, overwrite) + nst_create(ctx, filename, overwrite) @cli_osm.command(name='netslice-template-create', short_help='creates a new Network Slice Template (NST)') @@ -2878,13 +3092,13 @@ def k8scluster_list(ctx, filter, literal): check_client_version(ctx.obj, ctx.command.name) resp = ctx.obj.k8scluster.list(filter) if literal: - print(yaml.safe_dump(resp)) + print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return table = PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description']) for cluster in resp: table.add_row([cluster['name'], cluster['_id'], cluster['k8s_version'], cluster['vim_account'], json.dumps(cluster['nets']), cluster["_admin"]["operationalState"], - trunc_text(cluster.get('description',''),40)]) + trunc_text(cluster.get('description') or '', 40)]) table.align = 'l' print(table) # except ClientException as e: @@ -2905,7 +3119,7 @@ def k8scluster_show(ctx, name, literal): # try: resp = ctx.obj.k8scluster.get(name) if literal: - print(yaml.safe_dump(resp)) + print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return table = PrettyTable(['key', 'attribute']) for k, v in list(resp.items()): @@ -2926,35 +3140,36 @@ def k8scluster_show(ctx, name, literal): @click.argument('name') @click.argument('uri') @click.option('--type', - type=click.Choice(['helm-chart', 'juju-bundle']), - prompt=True, - help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)') + type=click.Choice(['helm-chart', 'juju-bundle', 'osm']), + default='osm', + help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)') @click.option('--description', default=None, help='human readable description') +@click.option('--user', + default=None, + help='OSM repository: The username of the OSM repository') +@click.option('--password', + default=None, + help='OSM repository: The password of the OSM repository') #@click.option('--wait', # is_flag=True, # help='do not return the control immediately, but keep it until the operation is completed, or timeout') @click.pass_context -def repo_add(ctx, - name, - uri, - type, - description): +def repo_add(ctx, **kwargs): """adds a repo to OSM NAME: name of the repo URI: URI of the repo """ # try: - check_client_version(ctx.obj, ctx.command.name) - repo = {} - repo['name'] = name - repo['url'] = uri - repo['type'] = type - if description: - repo['description'] = description - ctx.obj.repo.create(name, repo) + kwargs = {k: v for k, v in kwargs.items() if v is not None} + repo = kwargs + repo["url"] = repo.pop("uri") + if repo["type"] in ['helm-chart', 'juju-bundle']: + ctx.obj.repo.create(repo['name'], repo) + else: + ctx.obj.osmrepo.create(repo['name'], repo) # except ClientException as e: # print(str(e)) # exit(1) @@ -2964,8 +3179,6 @@ def repo_add(ctx, @click.argument('name') @click.option('--newname', help='New name for the repo') @click.option('--uri', help='URI of the repo') -@click.option('--type', type=click.Choice(['helm-chart', 'juju-bundle']), - help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)') @click.option('--description', help='human readable description') #@click.option('--wait', # is_flag=True, @@ -2975,7 +3188,6 @@ def repo_update(ctx, name, newname, uri, - type, description): """updates a repo in OSM @@ -2984,16 +3196,34 @@ def repo_update(ctx, # try: check_client_version(ctx.obj, ctx.command.name) repo = {} - if newname: repo['name'] = newname - if uri: repo['uri'] = uri - if type: repo['type'] = type + if newname: + repo['name'] = newname + if uri: + repo['uri'] = uri if description: repo['description'] = description - ctx.obj.repo.update(name, repo) + try: + ctx.obj.repo.update(name, repo) + except NotFound: + ctx.obj.osmrepo.update(name, repo) + # except ClientException as e: # print(str(e)) # exit(1) +@cli_osm.command(name='repo-index', short_help='Index a repository from a folder with artifacts') +@click.option('--origin', default='.', help='origin path where the artifacts are located') +@click.option('--destination', default='.', help='destination path where the index is deployed') +@click.pass_context +def repo_index(ctx, origin, destination): + """Index a repository + + NAME: name or ID of the repo to be deleted + """ + check_client_version(ctx.obj, ctx.command.name) + ctx.obj.osmrepo.repo_index(origin, destination) + + @cli_osm.command(name='repo-delete', short_help='deletes a repo') @click.argument('name') @click.option('--force', is_flag=True, help='forces the deletion from the DB (not recommended)') @@ -3006,9 +3236,11 @@ def repo_delete(ctx, name, force): NAME: name or ID of the repo to be deleted """ - # try: - check_client_version(ctx.obj, ctx.command.name) - ctx.obj.repo.delete(name, force=force) + logger.debug("") + try: + ctx.obj.repo.delete(name, force=force) + except NotFound: + ctx.obj.osmrepo.delete(name, force=force) # except ClientException as e: # print(str(e)) # exit(1) @@ -3023,17 +3255,20 @@ def repo_delete(ctx, name, force): def repo_list(ctx, filter, literal): """list all repos""" # try: + # K8s Repositories check_client_version(ctx.obj, ctx.command.name) resp = ctx.obj.repo.list(filter) + resp += ctx.obj.osmrepo.list(filter) if literal: - print(yaml.safe_dump(resp)) + print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return table = PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description']) for repo in resp: #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets'])) - table.add_row([repo['name'], repo['_id'], repo['type'], repo['url'], trunc_text(repo.get('description',''),40)]) + table.add_row([repo['name'], repo['_id'], repo['type'], repo['url'], trunc_text(repo.get('description') or '',40)]) table.align = 'l' print(table) + # except ClientException as e: # print(str(e)) # exit(1) @@ -3049,14 +3284,20 @@ def repo_show(ctx, name, literal): NAME: name or ID of the repo """ - # try: - resp = ctx.obj.repo.get(name) + try: + resp = ctx.obj.repo.get(name) + except NotFound: + resp = ctx.obj.osmrepo.get(name) + if literal: - print(yaml.safe_dump(resp)) + if resp: + print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return table = PrettyTable(['key', 'attribute']) - for k, v in list(resp.items()): - table.add_row([k, json.dumps(v, indent=2)]) + if resp: + for k, v in list(resp.items()): + table.add_row([k, json.dumps(v, indent=2)]) + table.align = 'l' print(table) # except ClientException as e: @@ -3077,18 +3318,25 @@ def repo_show(ctx, name, literal): @click.option('--domain-name', 'domain_name', default=None, help='assign to a domain') +@click.option('--quotas', 'quotas', multiple=True, default=None, + help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one " + "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos") @click.pass_context -def project_create(ctx, name, domain_name): +def project_create(ctx, name, domain_name, quotas): """Creates a new project NAME: name of the project DOMAIN_NAME: optional domain name for the project when keystone authentication is used + QUOTAS: set quotas for the project """ logger.debug("") - project = {} - project['name'] = name + project = {'name': name} if domain_name: project['domain_name'] = domain_name + quotas_dict = _process_project_quotas(quotas) + if quotas_dict: + project['quotas'] = quotas_dict + # try: check_client_version(ctx.obj, ctx.command.name) ctx.obj.project.create(name, project) @@ -3097,6 +3345,20 @@ def project_create(ctx, name, domain_name): # exit(1) +def _process_project_quotas(quota_list): + quotas_dict = {} + if not quota_list: + return quotas_dict + try: + for quota in quota_list: + for single_quota in quota.split(","): + k, v = single_quota.split("=") + quotas_dict[k] = None if v in ('None', 'null', '') else int(v) + except (ValueError, TypeError): + raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null") + return quotas_dict + + @cli_osm.command(name='project-delete', short_help='deletes a project') @click.argument('name') #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') @@ -3160,23 +3422,29 @@ def project_show(ctx, name): @cli_osm.command(name='project-update', short_help='updates a project (only the name can be updated)') @click.argument('project') -@click.option('--name', - prompt=True, +@click.option('--name', default=None, help='new name for the project') - +@click.option('--quotas', 'quotas', multiple=True, default=None, + help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' " + "(use empty to reset quota to default") @click.pass_context -def project_update(ctx, project, name): +def project_update(ctx, project, name, quotas): """ Update a project name :param ctx: :param project: id or name of the project to modify :param name: new name for the project + :param quotas: change quotas of the project :return: """ logger.debug("") project_changes = {} - project_changes['name'] = name + if name: + project_changes['name'] = name + quotas_dict = _process_project_quotas(quotas) + if quotas_dict: + project_changes['quotas'] = quotas_dict # try: check_client_version(ctx.obj, ctx.command.name)