+ """
+ logger.debug("")
+ # try:
+ check_client_version(ctx.obj, ctx.command.name)
+ if not scale_in and not scale_out:
+ scale_out = True
+ ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out)
+ # except ClientException as e:
+ # print(str(e))
+ # exit(1)
+
+
+##############################
+# Role Management Operations #
+##############################
+
+@cli_osm.command(name='role-create', short_help='creates a new role')
+@click.argument('name')
+@click.option('--permissions',
+ default=None,
+ help='role permissions using a dictionary')
+@click.pass_context
+def role_create(ctx, name, permissions):
+ """
+ Creates a new role.
+
+ \b
+ NAME: Name or ID of the role.
+ DEFINITION: Definition of grant/denial of access to resources.
+ """
+ logger.debug("")
+ # try:
+ check_client_version(ctx.obj, ctx.command.name)
+ ctx.obj.role.create(name, permissions)
+ # except ClientException as e:
+ # print(str(e))
+ # exit(1)
+
+
+@cli_osm.command(name='role-update', short_help='updates a role')
+@click.argument('name')
+@click.option('--set-name',
+ default=None,
+ help='change name of rle')
+# @click.option('--permissions',
+# default=None,
+# help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
+@click.option('--add',
+ default=None,
+ help='yaml format dictionary with permission: True/False to access grant/denial')
+@click.option('--remove',
+ default=None,
+ help='yaml format list to remove a permission')
+@click.pass_context
+def role_update(ctx, name, set_name, add, remove):
+ """
+ Updates a role.
+
+ \b
+ NAME: Name or ID of the role.
+ DEFINITION: Definition overwrites the old definition.
+ ADD: Grant/denial of access to resource to add.
+ REMOVE: Grant/denial of access to resource to remove.
+ """
+ logger.debug("")
+ # try:
+ check_client_version(ctx.obj, ctx.command.name)
+ ctx.obj.role.update(name, set_name, None, add, remove)
+ # except ClientException as e:
+ # print(str(e))
+ # exit(1)
+
+
+@cli_osm.command(name='role-delete', short_help='deletes a role')
+@click.argument('name')
+# @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
+@click.pass_context
+def role_delete(ctx, name):
+ """
+ Deletes a role.
+
+ \b
+ NAME: Name or ID of the role.
+ """
+ logger.debug("")
+ # try:
+ check_client_version(ctx.obj, ctx.command.name)
+ ctx.obj.role.delete(name)
+ # except ClientException as e:
+ # print(str(e))
+ # exit(1)
+
+
+@cli_osm.command(name='role-list', short_help='list all roles')
+@click.option('--filter', default=None,
+ help='restricts the list to the projects matching the filter')
+@click.pass_context
+def role_list(ctx, filter):
+ """
+ List all roles.
+ """
+ logger.debug("")
+ # try:
+ check_client_version(ctx.obj, ctx.command.name)
+ resp = ctx.obj.role.list(filter)
+ # except ClientException as e:
+ # print(str(e))
+ # exit(1)
+ table = PrettyTable(['name', 'id'])
+ for role in resp:
+ table.add_row([role['name'], role['_id']])
+ table.align = 'l'
+ print(table)
+
+
+@cli_osm.command(name='role-show', short_help='show specific role')
+@click.argument('name')
+@click.pass_context
+def role_show(ctx, name):
+ """
+ Shows the details of a role.
+
+ \b
+ NAME: Name or ID of the role.
+ """
+ logger.debug("")
+ # try:
+ check_client_version(ctx.obj, ctx.command.name)
+ resp = ctx.obj.role.get(name)
+ # except ClientException as e:
+ # print(str(e))
+ # exit(1)
+
+ table = PrettyTable(['key', 'attribute'])
+ for k, v in resp.items():
+ table.add_row([k, json.dumps(v, indent=2)])
+ table.align = 'l'
+ print(table)
+
+
+@cli_osm.command(name='package-create',
+ short_help='Create a package descriptor')
+@click.argument('package-type')
+@click.argument('package-name')
+@click.option('--base-directory',
+ default='.',
+ help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
+@click.option('--image',
+ default="image-name",
+ help='(VNF) Set the name of the vdu image. Default "image-name"')
+@click.option('--vdus',
+ default=1,
+ help='(VNF) Set the number of vdus in a VNF. Default 1')
+@click.option('--vcpu',
+ default=1,
+ help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
+@click.option('--memory',
+ default=1024,
+ help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
+@click.option('--storage',
+ default=10,
+ help='(VNF) Set the disk size (GB) of the vdu. Default 10')
+@click.option('--interfaces',
+ default=0,
+ help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
+@click.option('--vendor',
+ default="OSM",
+ help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
+@click.option('--override',
+ default=False,
+ is_flag=True,
+ help='(NS/VNF/NST) Flag for overriding the package if exists.')
+@click.option('--detailed',
+ is_flag=True,
+ default=False,
+ help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
+@click.option('--netslice-subnets',
+ default=1,
+ help='(NST) Number of netslice subnets. Default 1')
+@click.option('--netslice-vlds',
+ default=1,
+ help='(NST) Number of netslice vlds. Default 1')
+@click.pass_context
+def package_create(ctx,
+ package_type,
+ base_directory,
+ package_name,
+ override,
+ image,
+ vdus,
+ vcpu,
+ memory,
+ storage,
+ interfaces,
+ vendor,
+ detailed,
+ netslice_subnets,
+ netslice_vlds):
+ """
+ Creates an OSM NS, VNF, NST package
+
+ \b
+ PACKAGE_TYPE: Package to be created: NS, VNF or NST.
+ PACKAGE_NAME: Name of the package to create the folder with the content.
+ """
+
+ # try:
+ check_client_version(ctx.obj, ctx.command.name)
+ print("Creating the {} structure: {}/{}".format(package_type.upper(), base_directory, package_name))
+ resp = ctx.obj.package_tool.create(package_type,
+ base_directory,
+ package_name,
+ override=override,
+ image=image,
+ vdus=vdus,
+ vcpu=vcpu,
+ memory=memory,
+ storage=storage,
+ interfaces=interfaces,
+ vendor=vendor,
+ detailed=detailed,
+ netslice_subnets=netslice_subnets,
+ netslice_vlds=netslice_vlds)
+ print(resp)
+ # except ClientException as inst:
+ # print("ERROR: {}".format(inst))
+ # exit(1)
+
+@cli_osm.command(name='package-validate',
+ short_help='Validate a package descriptor')
+@click.argument('base-directory',
+ default=".",
+ required=False)
+@click.pass_context
+def package_validate(ctx,
+ base_directory):
+ """
+ Validate descriptors given a base directory.
+
+ \b
+ BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
+ """
+ # try:
+ check_client_version(ctx.obj, ctx.command.name)
+ results = ctx.obj.package_tool.validate(base_directory)
+ table = PrettyTable()
+ table.field_names = ["TYPE", "PATH", "VALID", "ERROR"]
+ # Print the dictionary generated by the validation function
+ for result in results:
+ table.add_row([result["type"], result["path"], result["valid"], result["error"]])
+ table.sortby = "VALID"
+ table.align["PATH"] = "l"
+ table.align["TYPE"] = "l"
+ table.align["ERROR"] = "l"
+ print(table)
+ # except ClientException as inst:
+ # print("ERROR: {}".format(inst))
+ # exit(1)
+
+@cli_osm.command(name='package-build',
+ short_help='Build the tar.gz of the package')
+@click.argument('package-folder')
+@click.option('--skip-validation',
+ default=False,
+ is_flag=True,
+ help='skip package validation')
+@click.pass_context
+def package_build(ctx,
+ package_folder,
+ skip_validation):
+ """
+ Build the package NS, VNF given the package_folder.
+
+ \b
+ PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
+ """
+ # try:
+ check_client_version(ctx.obj, ctx.command.name)
+ results = ctx.obj.package_tool.build(package_folder, skip_validation)
+ print(results)
+ # except ClientException as inst:
+ # print("ERROR: {}".format(inst))
+ # exit(1)
+
+
+def cli():
+ try:
+ cli_osm()
+ exit(0)
+ except pycurl.error as exc:
+ print(exc)
+ print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
+ except ClientException as exc:
+ print("ERROR: {}".format(exc))
+ except (FileNotFoundError, PermissionError) as exc:
+ print("Cannot open file: {}".format(exc))
+ except yaml.YAMLError as exc:
+ print("Invalid YAML format: {}".format(exc))
+ exit(1)
+ # TODO capture other controlled exceptions here
+ # TODO remove the ClientException captures from all places, unless they do something different