ca795456ce5e025679dad01ca1243bc534e8fb43
1 # Copyright 2017-2018 Sandvine
2 # Copyright 2018 Telefonica
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
22 from osmclient
import client
23 from osmclient
.common
.exceptions
import ClientException
, NotFound
24 from prettytable
import PrettyTable
33 from datetime
import datetime
34 from typing
import Any
, Dict
37 def wrap_text(text
, width
):
38 wrapper
= textwrap
.TextWrapper(width
=width
)
39 lines
= text
.splitlines()
40 return "\n".join(map(wrapper
.fill
, lines
))
43 def trunc_text(text
, length
):
44 if len(text
) > length
:
45 return text
[: (length
- 3)] + "..."
50 def check_client_version(obj
, what
, version
="sol005"):
52 Checks the version of the client object and raises error if it not the expected.
54 :param obj: the client object
55 :what: the function or command under evaluation (used when an error is raised)
57 :raises ClientError: if the specified version does not match the client version
60 fullclassname
= obj
.__module
__ + "." + obj
.__class
__.__name
__
61 message
= 'The following commands or options are only supported with the option "--sol005": {}'.format(
65 message
= 'The following commands or options are not supported when using option "--sol005": {}'.format(
68 if fullclassname
!= "osmclient.{}.client.Client".format(version
):
69 raise ClientException(message
)
73 def get_project(project_list
, item
):
74 # project_list = ctx.obj.project.list()
75 item_project_list
= item
.get("_admin", {}).get("projects_read")
79 for p1
in item_project_list
:
81 for p2
in project_list
:
82 if p2
["_id"] == project_id
:
83 project_name
= p2
["name"]
84 return project_id
, project_name
85 return project_id
, project_name
88 def get_vim_name(vim_list
, vim_id
):
91 if v
["uuid"] == vim_id
:
97 def create_config(config_file
, json_string
):
99 Combines a YAML or JSON file with a JSON string into a Python3 structure
100 It loads the YAML or JSON file 'cfile' into a first dictionary.
101 It loads the JSON string into a second dictionary.
102 Then it updates the first dictionary with the info in the second dictionary.
103 If the field is present in both cfile and cdict, the field in cdict prevails.
104 If both cfile and cdict are None, it returns an empty dict (i.e. {})
108 with
open(config_file
, "r") as cf
:
109 config
= yaml
.safe_load(cf
.read())
111 cdict
= yaml
.safe_load(json_string
)
112 for k
, v
in cdict
.items():
118 context_settings
=dict(help_option_names
=["-h", "--help"], max_content_width
=160)
123 envvar
="OSM_HOSTNAME",
124 help="hostname of server. " + "Also can set OSM_HOSTNAME in environment",
126 # @click.option('--sol005/--no-sol005',
128 # envvar='OSM_SOL005',
129 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
130 # 'Also can set OSM_SOL005 in environment')
135 help="user (defaults to admin). " + "Also can set OSM_USER in environment",
140 envvar
="OSM_PASSWORD",
141 help="password (defaults to admin). " + "Also can set OSM_PASSWORD in environment",
146 envvar
="OSM_PROJECT",
147 help="project (defaults to admin). " + "Also can set OSM_PROJECT in environment",
153 help="increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)",
155 @click.option("--all-projects", default
=None, is_flag
=True, help="include all projects")
157 "--public/--no-public",
159 help="flag for public items (packages, instances, VIM accounts, etc.)",
162 "--project-domain-name",
163 "project_domain_name",
165 envvar
="OSM_PROJECT_DOMAIN_NAME",
166 help="project domain name for keystone authentication (default to None). "
167 + "Also can set OSM_PROJECT_DOMAIN_NAME in environment",
170 "--user-domain-name",
173 envvar
="OSM_USER_DOMAIN_NAME",
174 help="user domain name for keystone authentication (default to None). "
175 + "Also can set OSM_USER_DOMAIN_NAME in environment",
177 # @click.option('--so-port',
179 # envvar='OSM_SO_PORT',
180 # help='hostname of server. ' +
181 # 'Also can set OSM_SO_PORT in environment')
182 # @click.option('--so-project',
184 # envvar='OSM_SO_PROJECT',
185 # help='Project Name in SO. ' +
186 # 'Also can set OSM_SO_PROJECT in environment')
187 # @click.option('--ro-hostname',
189 # envvar='OSM_RO_HOSTNAME',
190 # help='hostname of RO server. ' +
191 # 'Also can set OSM_RO_HOSTNAME in environment')
192 # @click.option('--ro-port',
194 # envvar='OSM_RO_PORT',
195 # help='hostname of RO server. ' +
196 # 'Also can set OSM_RO_PORT in environment')
198 def cli_osm(ctx
, **kwargs
):
200 hostname
= kwargs
.pop("hostname", None)
204 "either hostname option or OSM_HOSTNAME "
205 + "environment variable needs to be specified"
210 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
211 # if so_port is not None:
212 # kwargs['so_port']=so_port
213 # if so_project is not None:
214 # kwargs['so_project']=so_project
215 # if ro_hostname is not None:
216 # kwargs['ro_host']=ro_hostname
217 # if ro_port is not None:
218 # kwargs['ro_port']=ro_port
219 sol005
= os
.getenv("OSM_SOL005", True)
220 # if user is not None:
221 # kwargs['user']=user
222 # if password is not None:
223 # kwargs['password']=password
224 # if project is not None:
225 # kwargs['project']=project
227 # kwargs['all_projects']=all_projects
228 # if public is not None:
229 # kwargs['public']=public
230 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
231 logger
= logging
.getLogger("osmclient")
239 @cli_osm.command(name
="ns-list", short_help
="list all NS instances")
244 help="restricts the list to the NS instances matching the filter.",
249 help="get more details of the NS (project, vim, deployment status, configuration status.",
252 def ns_list(ctx
, filter, long):
253 """list all NS instances
257 --filter filterExpr Restricts the list to the NS instances matching the filter
260 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
261 concatenated using the "&" character:
264 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
265 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
266 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
268 value := scalar value
272 * zero or more occurrences
273 ? zero or one occurrence
274 [] grouping of expressions to be used with ? and *
275 "" quotation marks for marking string constants
279 "AttrName" is the name of one attribute in the data type that defines the representation
280 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
281 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
282 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
283 entries, it means that the operator "op" is applied to the attribute addressed by the last
284 <attrName> entry included in the concatenation. All simple filter expressions are combined
285 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
286 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
287 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
288 prefix". If an attribute referenced in an expression is an array, an object that contains a
289 corresponding array shall be considered to match the expression if any of the elements in the
290 array matches all expressions that have the same attribute prefix.
294 --filter admin-status=ENABLED
295 --filter nsd-ref=<NSD_NAME>
296 --filter nsd.vendor=<VENDOR>
297 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
298 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
301 def summarize_deployment_status(status_dict
):
308 net_list
= status_dict
.get("nets", [])
311 if net
["status"] not in status_nets
:
312 status_nets
[net
["status"]] = 1
314 status_nets
[net
["status"]] += 1
316 for k
, v
in status_nets
.items():
317 message
+= "{}:{},".format(k
, v
)
318 message
+= "TOTAL:{}".format(n_nets
)
319 summary
+= "{}".format(message
)
324 vnf_list
= status_dict
["vnfs"]
326 member_vnf_index
= vnf
["member_vnf_index"]
327 if member_vnf_index
not in status_vnfs
:
328 status_vnfs
[member_vnf_index
] = {}
329 for vm
in vnf
["vms"]:
331 if vm
["status"] not in status_vms
:
332 status_vms
[vm
["status"]] = 1
334 status_vms
[vm
["status"]] += 1
335 if vm
["status"] not in status_vnfs
[member_vnf_index
]:
336 status_vnfs
[member_vnf_index
][vm
["status"]] = 1
338 status_vnfs
[member_vnf_index
][vm
["status"]] += 1
340 for k
, v
in status_vms
.items():
341 message
+= "{}:{},".format(k
, v
)
342 message
+= "TOTAL:{}".format(n_vms
)
343 summary
+= "\n{}".format(message
)
345 for k
, v
in status_vnfs
.items():
347 message
= "\n {} VMs: ".format(k
)
348 for k2
, v2
in v
.items():
349 message
+= "{}:{},".format(k2
, v2
)
351 message
+= "TOTAL:{}".format(total
)
355 def summarize_config_status(ee_list
):
363 if ee
["elementType"] not in status_ee
:
364 status_ee
[ee
["elementType"]] = {}
365 status_ee
[ee
["elementType"]][ee
["status"]] = 1
367 if ee
["status"] in status_ee
[ee
["elementType"]]:
368 status_ee
[ee
["elementType"]][ee
["status"]] += 1
370 status_ee
[ee
["elementType"]][ee
["status"]] = 1
371 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
372 if elementType
in status_ee
:
375 for k
, v
in status_ee
[elementType
].items():
376 message
+= "{}:{},".format(k
, v
)
378 message
+= "TOTAL:{}\n".format(total
)
379 summary
+= "{}: {}".format(elementType
, message
)
380 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
385 check_client_version(ctx
.obj
, "--filter")
386 filter = "&".join(filter)
387 resp
= ctx
.obj
.ns
.list(filter)
389 resp
= ctx
.obj
.ns
.list()
402 "configuration status",
405 project_list
= ctx
.obj
.project
.list()
407 vim_list
= ctx
.obj
.vim
.list()
422 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
423 if fullclassname
== "osmclient.sol005.client.Client":
425 logger
.debug("NS info: {}".format(nsr
))
426 nsr_name
= nsr
["name"]
428 date
= datetime
.fromtimestamp(nsr
["create-time"]).strftime(
431 ns_state
= nsr
.get("nsState", nsr
["_admin"]["nsState"])
433 deployment_status
= summarize_deployment_status(
434 nsr
.get("deploymentStatus")
436 config_status
= summarize_config_status(nsr
.get("configurationStatus"))
437 project_id
, project_name
= get_project(project_list
, nsr
)
438 # project = '{} ({})'.format(project_name, project_id)
439 project
= project_name
440 vim_id
= nsr
.get("datacenter")
441 vim_name
= get_vim_name(vim_list
, vim_id
)
443 # vim = '{} ({})'.format(vim_name, vim_id)
445 if "currentOperation" in nsr
:
446 current_operation
= "{} ({})".format(
447 nsr
["currentOperation"], nsr
["currentOperationID"]
450 current_operation
= "{} ({})".format(
451 nsr
["_admin"].get("current-operation", "-"),
452 nsr
["_admin"]["nslcmop"],
454 error_details
= "N/A"
457 or ns_state
== "DEGRADED"
458 or ("currentOperation" not in nsr
and nsr
.get("errorDescription"))
460 error_details
= "{}\nDetail: {}".format(
461 nsr
["errorDescription"], nsr
["errorDetail"]
464 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
["id"])
465 nsr
= nsopdata
["nsr:nsr"]
466 nsr_name
= nsr
["name-ref"]
467 nsr_id
= nsr
["ns-instance-config-ref"]
470 deployment_status
= (
471 nsr
["operational-status"]
472 if "operational-status" in nsr
475 ns_state
= deployment_status
476 config_status
= nsr
.get("config-status", "Not found")
477 current_operation
= "Unknown"
478 error_details
= nsr
.get("detailed-status", "Not found")
479 if config_status
== "config_not_needed":
480 config_status
= "configured (no charms)"
490 wrap_text(text
=error_details
, width
=40),
505 wrap_text(text
=error_details
, width
=40),
510 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
512 'For more details on the current operation, run "osm ns-op-show OPERATION_ID"'
516 def nsd_list(ctx
, filter, long):
519 check_client_version(ctx
.obj
, "--filter")
520 filter = "&".join(filter)
521 resp
= ctx
.obj
.nsd
.list(filter)
523 resp
= ctx
.obj
.nsd
.list()
524 # print(yaml.safe_dump(resp))
525 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
526 if fullclassname
== "osmclient.sol005.client.Client":
540 table
= PrettyTable(["nsd name", "id"])
542 name
= nsd
.get("id", "-")
544 onb_state
= nsd
["_admin"].get("onboardingState", "-")
545 op_state
= nsd
["_admin"].get("operationalState", "-")
546 usage_state
= nsd
["_admin"].get("usageState", "-")
547 date
= datetime
.fromtimestamp(nsd
["_admin"]["created"]).strftime(
550 last_update
= datetime
.fromtimestamp(
551 nsd
["_admin"]["modified"]
552 ).strftime("%Y-%m-%dT%H:%M:%S")
565 table
.add_row([name
, nsd
["_id"]])
567 table
= PrettyTable(["nsd name", "id"])
569 table
.add_row([nsd
["name"], nsd
["id"]])
574 @cli_osm.command(name
="nsd-list", short_help
="list all NS packages")
579 help="restricts the list to the NSD/NSpkg matching the filter",
581 @click.option("--long", is_flag
=True, help="get more details")
583 def nsd_list1(ctx
, filter, long):
584 """list all NSD/NS pkg in the system"""
586 nsd_list(ctx
, filter, long)
589 @cli_osm.command(name
="nspkg-list", short_help
="list all NS packages")
594 help="restricts the list to the NSD/NSpkg matching the filter",
596 @click.option("--long", is_flag
=True, help="get more details")
598 def nsd_list2(ctx
, filter, long):
599 """list all NS packages"""
601 nsd_list(ctx
, filter, long)
604 def pkg_repo_list(ctx
, pkgtype
, filter, repo
, long):
605 resp
= ctx
.obj
.osmrepo
.pkg_list(pkgtype
, filter, repo
)
608 ["nfpkg name", "vendor", "version", "latest", "description", "repository"]
611 table
= PrettyTable(["nfpkg name", "repository"])
613 name
= vnfd
.get("id", vnfd
.get("name", "-"))
614 repository
= vnfd
.get("repository")
616 vendor
= vnfd
.get("provider", vnfd
.get("vendor"))
617 version
= vnfd
.get("version")
618 description
= vnfd
.get("description")
619 latest
= vnfd
.get("latest")
620 table
.add_row([name
, vendor
, version
, latest
, description
, repository
])
622 table
.add_row([name
, repository
])
627 def vnfd_list(ctx
, nf_type
, filter, long):
630 check_client_version(ctx
.obj
, "--nf_type")
632 check_client_version(ctx
.obj
, "--filter")
634 filter = "&".join(filter)
637 nf_filter
= "_admin.type=vnfd"
638 elif nf_type
== "pnf":
639 nf_filter
= "_admin.type=pnfd"
640 elif nf_type
== "hnf":
641 nf_filter
= "_admin.type=hnfd"
643 raise ClientException(
644 'wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf'
647 filter = "{}&{}".format(nf_filter
, filter)
651 resp
= ctx
.obj
.vnfd
.list(filter)
653 resp
= ctx
.obj
.vnfd
.list()
654 # print(yaml.safe_dump(resp))
655 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
656 if fullclassname
== "osmclient.sol005.client.Client":
673 table
= PrettyTable(["nfpkg name", "id", "desc type"])
675 name
= vnfd
.get("id", vnfd
.get("name", "-"))
676 descriptor_type
= "sol006" if "product-name" in vnfd
else "rel8"
678 onb_state
= vnfd
["_admin"].get("onboardingState", "-")
679 op_state
= vnfd
["_admin"].get("operationalState", "-")
680 vendor
= vnfd
.get("provider", vnfd
.get("vendor"))
681 version
= vnfd
.get("version")
682 usage_state
= vnfd
["_admin"].get("usageState", "-")
683 date
= datetime
.fromtimestamp(vnfd
["_admin"]["created"]).strftime(
686 last_update
= datetime
.fromtimestamp(
687 vnfd
["_admin"]["modified"]
688 ).strftime("%Y-%m-%dT%H:%M:%S")
704 table
.add_row([name
, vnfd
["_id"], descriptor_type
])
706 table
= PrettyTable(["nfpkg name", "id"])
708 table
.add_row([vnfd
["name"], vnfd
["id"]])
713 @cli_osm.command(name
="vnfd-list", short_help
="list all xNF packages (VNF, HNF, PNF)")
714 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
719 help="restricts the list to the NF pkg matching the filter",
721 @click.option("--long", is_flag
=True, help="get more details")
723 def vnfd_list1(ctx
, nf_type
, filter, long):
724 """list all xNF packages (VNF, HNF, PNF)"""
726 vnfd_list(ctx
, nf_type
, filter, long)
729 @cli_osm.command(name
="vnfpkg-list", short_help
="list all xNF packages (VNF, HNF, PNF)")
730 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
735 help="restricts the list to the NFpkg matching the filter",
737 @click.option("--long", is_flag
=True, help="get more details")
739 def vnfd_list2(ctx
, nf_type
, filter, long):
740 """list all xNF packages (VNF, HNF, PNF)"""
742 vnfd_list(ctx
, nf_type
, filter, long)
745 @cli_osm.command(name
="nfpkg-list", short_help
="list all xNF packages (VNF, HNF, PNF)")
746 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
751 help="restricts the list to the NFpkg matching the filter",
753 @click.option("--long", is_flag
=True, help="get more details")
755 def nfpkg_list(ctx
, nf_type
, filter, long):
756 """list all xNF packages (VNF, HNF, PNF)"""
759 check_client_version(ctx
.obj
, ctx
.command
.name
)
760 vnfd_list(ctx
, nf_type
, filter, long)
761 # except ClientException as e:
767 name
="vnfpkg-repo-list", short_help
="list all xNF from OSM repositories"
773 help="restricts the list to the NFpkg matching the filter",
776 "--repo", default
=None, help="restricts the list to a particular OSM repository"
778 @click.option("--long", is_flag
=True, help="get more details")
780 def nfpkg_repo_list1(ctx
, filter, repo
, long):
781 """list xNF packages from OSM repositories"""
783 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
787 name
="nfpkg-repo-list", short_help
="list all xNF from OSM repositories"
793 help="restricts the list to the NFpkg matching the filter",
796 "--repo", default
=None, help="restricts the list to a particular OSM repository"
798 @click.option("--long", is_flag
=True, help="get more details")
800 def nfpkg_repo_list2(ctx
, filter, repo
, long):
801 """list xNF packages from OSM repositories"""
803 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
806 def vnf_list(ctx
, ns
, filter, long):
810 check_client_version(ctx
.obj
, "--ns")
812 filter = "&".join(filter)
813 check_client_version(ctx
.obj
, "--filter")
814 resp
= ctx
.obj
.vnf
.list(ns
, filter)
816 resp
= ctx
.obj
.vnf
.list()
817 # except ClientException as e:
820 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
821 if fullclassname
== "osmclient.sol005.client.Client":
843 table
= PrettyTable(field_names
)
845 name
= vnfr
["name"] if "name" in vnfr
else "-"
850 vnfr
["member-vnf-index-ref"],
852 vnfr
["vim-account-id"],
856 date
= datetime
.fromtimestamp(vnfr
["_admin"]["created"]).strftime(
859 last_update
= datetime
.fromtimestamp(
860 vnfr
["_admin"]["modified"]
861 ).strftime("%Y-%m-%dT%H:%M:%S")
862 new_row
.extend([date
, last_update
])
863 table
.add_row(new_row
)
865 table
= PrettyTable(["vnf name", "id", "operational status", "config status"])
867 if "mgmt-interface" not in vnfr
:
868 vnfr
["mgmt-interface"] = {}
869 vnfr
["mgmt-interface"]["ip-address"] = None
874 vnfr
["operational-status"],
875 vnfr
["config-status"],
882 @cli_osm.command(name
="vnf-list", short_help
="list all NF instances")
884 "--ns", default
=None, help="NS instance id or name to restrict the NF list"
890 help="restricts the list to the NF instances matching the filter.",
892 @click.option("--long", is_flag
=True, help="get more details")
894 def vnf_list1(ctx
, ns
, filter, long):
895 """list all NF instances"""
897 vnf_list(ctx
, ns
, filter, long)
900 @cli_osm.command(name
="nsd-repo-list", short_help
="list all NS from OSM repositories")
905 help="restricts the list to the NS matching the filter",
908 "--repo", default
=None, help="restricts the list to a particular OSM repository"
910 @click.option("--long", is_flag
=True, help="get more details")
912 def nspkg_repo_list(ctx
, filter, repo
, long):
913 """list xNF packages from OSM repositories"""
915 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
918 @cli_osm.command(name
="nspkg-repo-list", short_help
="list all NS from OSM repositories")
923 help="restricts the list to the NS matching the filter",
926 "--repo", default
=None, help="restricts the list to a particular OSM repository"
928 @click.option("--long", is_flag
=True, help="get more details")
930 def nspkg_repo_list2(ctx
, filter, repo
, long):
931 """list xNF packages from OSM repositories"""
933 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
936 @cli_osm.command(name
="nf-list", short_help
="list all NF instances")
938 "--ns", default
=None, help="NS instance id or name to restrict the NF list"
944 help="restricts the list to the NF instances matching the filter.",
946 @click.option("--long", is_flag
=True, help="get more details")
948 def nf_list(ctx
, ns
, filter, long):
949 """list all NF instances
953 --ns TEXT NS instance id or name to restrict the VNF list
954 --filter filterExpr Restricts the list to the VNF instances matching the filter
957 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
958 concatenated using the "&" character:
961 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
962 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
963 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
965 value := scalar value
969 * zero or more occurrences
970 ? zero or one occurrence
971 [] grouping of expressions to be used with ? and *
972 "" quotation marks for marking string constants
976 "AttrName" is the name of one attribute in the data type that defines the representation
977 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
978 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
979 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
980 entries, it means that the operator "op" is applied to the attribute addressed by the last
981 <attrName> entry included in the concatenation. All simple filter expressions are combined
982 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
983 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
984 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
985 prefix". If an attribute referenced in an expression is an array, an object that contains a
986 corresponding array shall be considered to match the expression if any of the elements in the
987 array matches all expressions that have the same attribute prefix.
991 --filter vim-account-id=<VIM_ACCOUNT_ID>
992 --filter vnfd-ref=<VNFD_NAME>
993 --filter vdur.ip-address=<IP_ADDRESS>
994 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
997 vnf_list(ctx
, ns
, filter, long)
1001 name
="ns-op-list", short_help
="shows the history of operations over a NS instance"
1003 @click.argument("name")
1005 "--long", is_flag
=True, help="get more details of the NS operation (date, )."
1008 def ns_op_list(ctx
, name
, long):
1009 """shows the history of operations over a NS instance
1011 NAME: name or ID of the NS instance
1014 def formatParams(params
):
1015 if params
["lcmOperationType"] == "instantiate":
1016 params
.pop("nsDescription")
1017 params
.pop("nsName")
1019 params
.pop("nsr_id")
1020 elif params
["lcmOperationType"] == "action":
1021 params
.pop("primitive")
1022 params
.pop("lcmOperationType")
1023 params
.pop("nsInstanceId")
1028 check_client_version(ctx
.obj
, ctx
.command
.name
)
1029 resp
= ctx
.obj
.ns
.list_op(name
)
1030 # except ClientException as e:
1035 table
= PrettyTable(
1048 table
= PrettyTable(
1049 ["id", "operation", "action_name", "status", "date", "detail"]
1052 # print(yaml.safe_dump(resp))
1055 if op
["lcmOperationType"] == "action":
1056 action_name
= op
["operationParams"]["primitive"]
1058 if op
["operationState"] == "PROCESSING":
1059 if op
["queuePosition"] is not None and op
["queuePosition"] > 0:
1060 detail
= "In queue. Current position: {}".format(op
["queuePosition"])
1061 elif op
["lcmOperationType"] in ("instantiate", "terminate"):
1063 detail
= op
["stage"]
1064 elif op
["operationState"] in ("FAILED", "FAILED_TEMP"):
1065 detail
= op
.get("errorMessage", "-")
1066 date
= datetime
.fromtimestamp(op
["startTime"]).strftime("%Y-%m-%dT%H:%M:%S")
1067 last_update
= datetime
.fromtimestamp(op
["statusEnteredTime"]).strftime(
1074 op
["lcmOperationType"],
1077 text
=json
.dumps(formatParams(op
["operationParams"]), indent
=2),
1080 op
["operationState"],
1083 wrap_text(text
=detail
, width
=50),
1090 op
["lcmOperationType"],
1092 op
["operationState"],
1094 wrap_text(text
=detail
or "", width
=50),
1101 def nsi_list(ctx
, filter):
1102 """list all Network Slice Instances"""
1105 check_client_version(ctx
.obj
, ctx
.command
.name
)
1107 filter = "&".join(filter)
1108 resp
= ctx
.obj
.nsi
.list(filter)
1109 # except ClientException as e:
1112 table
= PrettyTable(
1114 "netslice instance name",
1116 "operational status",
1122 nsi_name
= nsi
["name"]
1125 nsi
["operational-status"] if "operational-status" in nsi
else "Not found"
1127 configstatus
= nsi
["config-status"] if "config-status" in nsi
else "Not found"
1129 nsi
["detailed-status"] if "detailed-status" in nsi
else "Not found"
1131 if configstatus
== "config_not_needed":
1132 configstatus
= "configured (no charms)"
1133 table
.add_row([nsi_name
, nsi_id
, opstatus
, configstatus
, detailed_status
])
1138 @cli_osm.command(name
="nsi-list", short_help
="list all Network Slice Instances (NSI)")
1143 help="restricts the list to the Network Slice Instances matching the filter",
1146 def nsi_list1(ctx
, filter):
1147 """list all Network Slice Instances (NSI)"""
1149 nsi_list(ctx
, filter)
1153 name
="netslice-instance-list", short_help
="list all Network Slice Instances (NSI)"
1159 help="restricts the list to the Network Slice Instances matching the filter",
1162 def nsi_list2(ctx
, filter):
1163 """list all Network Slice Instances (NSI)"""
1165 nsi_list(ctx
, filter)
1168 def nst_list(ctx
, filter):
1171 check_client_version(ctx
.obj
, ctx
.command
.name
)
1173 filter = "&".join(filter)
1174 resp
= ctx
.obj
.nst
.list(filter)
1175 # except ClientException as e:
1178 # print(yaml.safe_dump(resp))
1179 table
= PrettyTable(["nst name", "id"])
1181 name
= nst
["name"] if "name" in nst
else "-"
1182 table
.add_row([name
, nst
["_id"]])
1187 @cli_osm.command(name
="nst-list", short_help
="list all Network Slice Templates (NST)")
1192 help="restricts the list to the NST matching the filter",
1195 def nst_list1(ctx
, filter):
1196 """list all Network Slice Templates (NST) in the system"""
1198 nst_list(ctx
, filter)
1202 name
="netslice-template-list", short_help
="list all Network Slice Templates (NST)"
1208 help="restricts the list to the NST matching the filter",
1211 def nst_list2(ctx
, filter):
1212 """list all Network Slice Templates (NST) in the system"""
1214 nst_list(ctx
, filter)
1217 def nsi_op_list(ctx
, name
):
1220 check_client_version(ctx
.obj
, ctx
.command
.name
)
1221 resp
= ctx
.obj
.nsi
.list_op(name
)
1222 # except ClientException as e:
1225 table
= PrettyTable(["id", "operation", "status"])
1227 table
.add_row([op
["id"], op
["lcmOperationType"], op
["operationState"]])
1234 short_help
="shows the history of operations over a Network Slice Instance (NSI)",
1236 @click.argument("name")
1238 def nsi_op_list1(ctx
, name
):
1239 """shows the history of operations over a Network Slice Instance (NSI)
1241 NAME: name or ID of the Network Slice Instance
1244 nsi_op_list(ctx
, name
)
1248 name
="netslice-instance-op-list",
1249 short_help
="shows the history of operations over a Network Slice Instance (NSI)",
1251 @click.argument("name")
1253 def nsi_op_list2(ctx
, name
):
1254 """shows the history of operations over a Network Slice Instance (NSI)
1256 NAME: name or ID of the Network Slice Instance
1259 nsi_op_list(ctx
, name
)
1262 @cli_osm.command(name
="pdu-list", short_help
="list all Physical Deployment Units (PDU)")
1267 help="restricts the list to the Physical Deployment Units matching the filter",
1270 def pdu_list(ctx
, filter):
1271 """list all Physical Deployment Units (PDU)"""
1274 check_client_version(ctx
.obj
, ctx
.command
.name
)
1276 filter = "&".join(filter)
1277 resp
= ctx
.obj
.pdu
.list(filter)
1278 # except ClientException as e:
1281 table
= PrettyTable(["pdu name", "id", "type", "mgmt ip address"])
1283 pdu_name
= pdu
["name"]
1285 pdu_type
= pdu
["type"]
1286 pdu_ipaddress
= "None"
1287 for iface
in pdu
["interfaces"]:
1289 pdu_ipaddress
= iface
["ip-address"]
1291 table
.add_row([pdu_name
, pdu_id
, pdu_type
, pdu_ipaddress
])
1296 ####################
1298 ####################
1301 def nsd_show(ctx
, name
, literal
):
1304 resp
= ctx
.obj
.nsd
.get(name
)
1305 # resp = ctx.obj.nsd.get_individual(name)
1306 # except ClientException as e:
1311 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1314 table
= PrettyTable(["field", "value"])
1315 for k
, v
in list(resp
.items()):
1316 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1321 @cli_osm.command(name
="nsd-show", short_help
="shows the details of a NS package")
1322 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1323 @click.argument("name")
1325 def nsd_show1(ctx
, name
, literal
):
1326 """shows the content of a NSD
1328 NAME: name or ID of the NSD/NSpkg
1331 nsd_show(ctx
, name
, literal
)
1334 @cli_osm.command(name
="nspkg-show", short_help
="shows the details of a NS package")
1335 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1336 @click.argument("name")
1338 def nsd_show2(ctx
, name
, literal
):
1339 """shows the content of a NSD
1341 NAME: name or ID of the NSD/NSpkg
1344 nsd_show(ctx
, name
, literal
)
1347 def vnfd_show(ctx
, name
, literal
):
1350 resp
= ctx
.obj
.vnfd
.get(name
)
1351 # resp = ctx.obj.vnfd.get_individual(name)
1352 # except ClientException as e:
1357 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1360 table
= PrettyTable(["field", "value"])
1361 for k
, v
in list(resp
.items()):
1362 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1367 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1370 filter = "&".join(filter)
1372 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1375 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1378 catalog
= pkgtype
+ "-catalog"
1379 full_catalog
= pkgtype
+ ":" + catalog
1380 if resp
.get(catalog
):
1381 resp
= resp
.pop(catalog
)[pkgtype
][0]
1382 elif resp
.get(full_catalog
):
1383 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1385 table
= PrettyTable(["field", "value"])
1386 for k
, v
in list(resp
.items()):
1387 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1392 @cli_osm.command(name
="vnfd-show", short_help
="shows the details of a NF package")
1393 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1394 @click.argument("name")
1396 def vnfd_show1(ctx
, name
, literal
):
1397 """shows the content of a VNFD
1399 NAME: name or ID of the VNFD/VNFpkg
1402 vnfd_show(ctx
, name
, literal
)
1405 @cli_osm.command(name
="vnfpkg-show", short_help
="shows the details of a NF package")
1406 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1407 @click.argument("name")
1409 def vnfd_show2(ctx
, name
, literal
):
1410 """shows the content of a VNFD
1412 NAME: name or ID of the VNFD/VNFpkg
1415 vnfd_show(ctx
, name
, literal
)
1419 name
="vnfpkg-repo-show",
1420 short_help
="shows the details of a NF package in an OSM repository",
1422 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1423 @click.option("--repo", required
=True, help="Repository name")
1424 @click.argument("name")
1425 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1426 @click.option("--version", default
="latest", help="package version")
1428 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1429 """shows the content of a VNFD in a repository
1431 NAME: name or ID of the VNFD/VNFpkg
1434 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1438 name
="nsd-repo-show",
1439 short_help
="shows the details of a NS package in an OSM repository",
1441 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1442 @click.option("--repo", required
=True, help="Repository name")
1443 @click.argument("name")
1444 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1445 @click.option("--version", default
="latest", help="package version")
1447 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1448 """shows the content of a VNFD in a repository
1450 NAME: name or ID of the VNFD/VNFpkg
1453 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1457 name
="nspkg-repo-show",
1458 short_help
="shows the details of a NS package in an OSM repository",
1460 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1461 @click.option("--repo", required
=True, help="Repository name")
1462 @click.argument("name")
1463 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1464 @click.option("--version", default
="latest", help="package version")
1466 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1467 """shows the content of a VNFD in a repository
1469 NAME: name or ID of the VNFD/VNFpkg
1472 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1475 @cli_osm.command(name
="nfpkg-show", short_help
="shows the details of a NF package")
1476 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1477 @click.argument("name")
1479 def nfpkg_show(ctx
, name
, literal
):
1480 """shows the content of a NF Descriptor
1482 NAME: name or ID of the NFpkg
1485 vnfd_show(ctx
, name
, literal
)
1489 name
="nfpkg-repo-show",
1490 short_help
="shows the details of a NF package in an OSM repository",
1492 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1493 @click.option("--repo", required
=True, help="Repository name")
1494 @click.argument("name")
1495 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1496 @click.option("--version", default
="latest", help="package version")
1498 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1499 """shows the content of a VNFD in a repository
1501 NAME: name or ID of the VNFD/VNFpkg
1504 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1507 @cli_osm.command(name
="ns-show", short_help
="shows the info of a NS instance")
1508 @click.argument("name")
1509 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1513 help="restricts the information to the fields in the filter",
1516 def ns_show(ctx
, name
, literal
, filter):
1517 """shows the info of a NS instance
1519 NAME: name or ID of the NS instance
1523 ns
= ctx
.obj
.ns
.get(name
)
1524 # except ClientException as e:
1529 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1532 table
= PrettyTable(["field", "value"])
1534 for k
, v
in list(ns
.items()):
1535 if not filter or k
in filter:
1536 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1538 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1539 if fullclassname
!= "osmclient.sol005.client.Client":
1540 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
["id"])
1541 nsr_optdata
= nsopdata
["nsr:nsr"]
1542 for k
, v
in list(nsr_optdata
.items()):
1543 if not filter or k
in filter:
1544 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), width
=100)])
1549 @cli_osm.command(name
="vnf-show", short_help
="shows the info of a VNF instance")
1550 @click.argument("name")
1551 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1555 help="restricts the information to the fields in the filter",
1557 @click.option("--kdu", default
=None, help="KDU name (whose status will be shown)")
1559 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1560 """shows the info of a VNF instance
1562 NAME: name or ID of the VNF instance
1565 def print_kdu_status(op_info_status
):
1566 """print KDU status properly formatted"""
1568 op_status
= yaml
.safe_load(op_info_status
)
1570 "namespace" in op_status
1571 and "info" in op_status
1572 and "last_deployed" in op_status
["info"]
1573 and "status" in op_status
["info"]
1574 and "code" in op_status
["info"]["status"]
1575 and "resources" in op_status
["info"]["status"]
1576 and "seconds" in op_status
["info"]["last_deployed"]
1578 last_deployed_time
= datetime
.fromtimestamp(
1579 op_status
["info"]["last_deployed"]["seconds"]
1580 ).strftime("%a %b %d %I:%M:%S %Y")
1581 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1582 print("NAMESPACE: {}".format(op_status
["namespace"]))
1583 status_code
= "UNKNOWN"
1584 if op_status
["info"]["status"]["code"] == 1:
1585 status_code
= "DEPLOYED"
1586 print("STATUS: {}".format(status_code
))
1589 print(op_status
["info"]["status"]["resources"])
1590 if "notes" in op_status
["info"]["status"]:
1592 print(op_status
["info"]["status"]["notes"])
1594 print(op_info_status
)
1596 print(op_info_status
)
1601 raise ClientException(
1602 '"--literal" option is incompatible with "--kdu" option'
1605 raise ClientException(
1606 '"--filter" option is incompatible with "--kdu" option'
1610 check_client_version(ctx
.obj
, ctx
.command
.name
)
1611 resp
= ctx
.obj
.vnf
.get(name
)
1614 ns_id
= resp
["nsr-id-ref"]
1616 op_data
["member_vnf_index"] = resp
["member-vnf-index-ref"]
1617 op_data
["kdu_name"] = kdu
1618 op_data
["primitive"] = "status"
1619 op_data
["primitive_params"] = {}
1620 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
="action", op_data
=op_data
, wait
=False)
1623 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1624 if op_info
["operationState"] == "COMPLETED":
1625 print_kdu_status(op_info
["detailed-status"])
1629 print("Could not determine KDU status")
1633 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1636 table
= PrettyTable(["field", "value"])
1637 for k
, v
in list(resp
.items()):
1638 if not filter or k
in filter:
1639 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1642 # except ClientException as e:
1647 # @cli_osm.command(name='vnf-monitoring-show')
1648 # @click.argument('vnf_name')
1649 # @click.pass_context
1650 # def vnf_monitoring_show(ctx, vnf_name):
1652 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1653 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1654 # except ClientException as e:
1658 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1659 # if resp is not None:
1660 # for monitor in resp:
1664 # monitor['value-integer'],
1665 # monitor['units']])
1670 # @cli_osm.command(name='ns-monitoring-show')
1671 # @click.argument('ns_name')
1672 # @click.pass_context
1673 # def ns_monitoring_show(ctx, ns_name):
1675 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1676 # resp = ctx.obj.ns.get_monitoring(ns_name)
1677 # except ClientException as e:
1681 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1682 # for key, val in list(resp.items()):
1683 # for monitor in val:
1687 # monitor['value-integer'],
1688 # monitor['units']])
1693 @cli_osm.command(name
="ns-op-show", short_help
="shows the info of a NS operation")
1694 @click.argument("id")
1698 help="restricts the information to the fields in the filter",
1700 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1702 def ns_op_show(ctx
, id, filter, literal
):
1703 """shows the detailed info of a NS operation
1705 ID: operation identifier
1709 check_client_version(ctx
.obj
, ctx
.command
.name
)
1710 op_info
= ctx
.obj
.ns
.get_op(id)
1711 # except ClientException as e:
1716 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1719 table
= PrettyTable(["field", "value"])
1720 for k
, v
in list(op_info
.items()):
1721 if not filter or k
in filter:
1722 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1727 def nst_show(ctx
, name
, literal
):
1730 check_client_version(ctx
.obj
, ctx
.command
.name
)
1731 resp
= ctx
.obj
.nst
.get(name
)
1732 # resp = ctx.obj.nst.get_individual(name)
1733 # except ClientException as e:
1738 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1741 table
= PrettyTable(["field", "value"])
1742 for k
, v
in list(resp
.items()):
1743 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1749 name
="nst-show", short_help
="shows the content of a Network Slice Template (NST)"
1751 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1752 @click.argument("name")
1754 def nst_show1(ctx
, name
, literal
):
1755 """shows the content of a Network Slice Template (NST)
1757 NAME: name or ID of the NST
1760 nst_show(ctx
, name
, literal
)
1764 name
="netslice-template-show",
1765 short_help
="shows the content of a Network Slice Template (NST)",
1767 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1768 @click.argument("name")
1770 def nst_show2(ctx
, name
, literal
):
1771 """shows the content of a Network Slice Template (NST)
1773 NAME: name or ID of the NST
1776 nst_show(ctx
, name
, literal
)
1779 def nsi_show(ctx
, name
, literal
, filter):
1782 check_client_version(ctx
.obj
, ctx
.command
.name
)
1783 nsi
= ctx
.obj
.nsi
.get(name
)
1784 # except ClientException as e:
1789 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1792 table
= PrettyTable(["field", "value"])
1794 for k
, v
in list(nsi
.items()):
1795 if not filter or k
in filter:
1796 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1803 name
="nsi-show", short_help
="shows the content of a Network Slice Instance (NSI)"
1805 @click.argument("name")
1806 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1810 help="restricts the information to the fields in the filter",
1813 def nsi_show1(ctx
, name
, literal
, filter):
1814 """shows the content of a Network Slice Instance (NSI)
1816 NAME: name or ID of the Network Slice Instance
1819 nsi_show(ctx
, name
, literal
, filter)
1823 name
="netslice-instance-show",
1824 short_help
="shows the content of a Network Slice Instance (NSI)",
1826 @click.argument("name")
1827 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1831 help="restricts the information to the fields in the filter",
1834 def nsi_show2(ctx
, name
, literal
, filter):
1835 """shows the content of a Network Slice Instance (NSI)
1837 NAME: name or ID of the Network Slice Instance
1840 nsi_show(ctx
, name
, literal
, filter)
1843 def nsi_op_show(ctx
, id, filter):
1846 check_client_version(ctx
.obj
, ctx
.command
.name
)
1847 op_info
= ctx
.obj
.nsi
.get_op(id)
1848 # except ClientException as e:
1852 table
= PrettyTable(["field", "value"])
1853 for k
, v
in list(op_info
.items()):
1854 if not filter or k
in filter:
1855 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1862 short_help
="shows the info of an operation over a Network Slice Instance(NSI)",
1864 @click.argument("id")
1868 help="restricts the information to the fields in the filter",
1871 def nsi_op_show1(ctx
, id, filter):
1872 """shows the info of an operation over a Network Slice Instance(NSI)
1874 ID: operation identifier
1877 nsi_op_show(ctx
, id, filter)
1881 name
="netslice-instance-op-show",
1882 short_help
="shows the info of an operation over a Network Slice Instance(NSI)",
1884 @click.argument("id")
1888 help="restricts the information to the fields in the filter",
1891 def nsi_op_show2(ctx
, id, filter):
1892 """shows the info of an operation over a Network Slice Instance(NSI)
1894 ID: operation identifier
1897 nsi_op_show(ctx
, id, filter)
1901 name
="pdu-show", short_help
="shows the content of a Physical Deployment Unit (PDU)"
1903 @click.argument("name")
1904 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1908 help="restricts the information to the fields in the filter",
1911 def pdu_show(ctx
, name
, literal
, filter):
1912 """shows the content of a Physical Deployment Unit (PDU)
1914 NAME: name or ID of the PDU
1918 check_client_version(ctx
.obj
, ctx
.command
.name
)
1919 pdu
= ctx
.obj
.pdu
.get(name
)
1920 # except ClientException as e:
1925 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1928 table
= PrettyTable(["field", "value"])
1930 for k
, v
in list(pdu
.items()):
1931 if not filter or k
in filter:
1932 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1938 ####################
1940 ####################
1943 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1946 check_client_version(ctx
.obj
, ctx
.command
.name
)
1948 filename
= ctx
.obj
.osmrepo
.get_pkg("ns", filename
, repo
, vendor
, version
)
1949 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1950 # except ClientException as e:
1955 @cli_osm.command(name
="nsd-create", short_help
="creates a new NSD/NSpkg")
1956 @click.argument("filename")
1960 default
=None, # hidden=True,
1961 help="Deprecated. Use override",
1967 help="overrides fields in descriptor, format: "
1968 '"key1.key2...=value[;key3...=value;...]"',
1971 "--skip-charm-build",
1974 help="The charm will not be compiled, it is assumed to already exist",
1976 @click.option("--repo", default
=None, help="[repository]: Repository name")
1977 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
1981 help="[repository]: filter by version. Default: latest",
1984 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1985 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1988 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1989 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1990 If FILENAME is an NF Package folder, it is built and then onboarded.
1996 overwrite
=overwrite
,
1997 skip_charm_build
=skip_charm_build
,
2004 @cli_osm.command(name
="nspkg-create", short_help
="creates a new NSD/NSpkg")
2005 @click.argument("filename")
2009 default
=None, # hidden=True,
2010 help="Deprecated. Use override",
2016 help="overrides fields in descriptor, format: "
2017 '"key1.key2...=value[;key3...=value;...]"',
2020 "--skip-charm-build",
2023 help="The charm will not be compiled, it is assumed to already exist",
2025 @click.option("--repo", default
=None, help="[repository]: Repository name")
2026 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2030 help="[repository]: filter by version. Default: latest",
2033 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
2034 """onboards a new NSpkg
2036 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2037 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2038 If FILENAME is an NF Package folder, it is built and then onboarded.
2044 overwrite
=overwrite
,
2045 skip_charm_build
=skip_charm_build
,
2066 check_client_version(ctx
.obj
, ctx
.command
.name
)
2068 filename
= ctx
.obj
.osmrepo
.get_pkg("vnf", filename
, repo
, vendor
, version
)
2069 ctx
.obj
.vnfd
.create(
2071 overwrite
=overwrite
,
2072 skip_charm_build
=skip_charm_build
,
2073 override_epa
=override_epa
,
2074 override_nonepa
=override_nonepa
,
2075 override_paravirt
=override_paravirt
,
2077 # except ClientException as e:
2082 @cli_osm.command(name
="vnfd-create", short_help
="creates a new VNFD/VNFpkg")
2083 @click.argument("filename")
2085 "--overwrite", "overwrite", default
=None, help="overwrite deprecated, use override"
2091 help="overrides fields in descriptor, format: "
2092 '"key1.key2...=value[;key3...=value;...]"',
2095 "--skip-charm-build",
2098 help="The charm will not be compiled, it is assumed to already exist",
2105 help="adds guest-epa parameters to all VDU",
2108 "--override-nonepa",
2112 help="removes all guest-epa parameters from all VDU",
2115 "--override-paravirt",
2119 help="overrides all VDU interfaces to PARAVIRT",
2121 @click.option("--repo", default
=None, help="[repository]: Repository name")
2122 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2126 help="[repository]: filter by version. Default: latest",
2141 """creates a new VNFD/VNFpkg
2143 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2144 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2145 If FILENAME is an NF Package folder, it is built and then onboarded.
2151 overwrite
=overwrite
,
2152 skip_charm_build
=skip_charm_build
,
2153 override_epa
=override_epa
,
2154 override_nonepa
=override_nonepa
,
2155 override_paravirt
=override_paravirt
,
2162 @cli_osm.command(name
="vnfpkg-create", short_help
="creates a new VNFD/VNFpkg")
2163 @click.argument("filename")
2167 default
=None, # hidden=True,
2168 help="Deprecated. Use override",
2174 help="overrides fields in descriptor, format: "
2175 '"key1.key2...=value[;key3...=value;...]"',
2178 "--skip-charm-build",
2181 help="The charm will not be compiled, it is assumed to already exist",
2188 help="adds guest-epa parameters to all VDU",
2191 "--override-nonepa",
2195 help="removes all guest-epa parameters from all VDU",
2198 "--override-paravirt",
2202 help="overrides all VDU interfaces to PARAVIRT",
2204 @click.option("--repo", default
=None, help="[repository]: Repository name")
2205 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2209 help="[repository]: filter by version. Default: latest",
2224 """creates a new VNFD/VNFpkg
2226 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2227 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2228 If FILENAME is an NF Package folder, it is built and then onboarded.
2234 overwrite
=overwrite
,
2235 skip_charm_build
=skip_charm_build
,
2236 override_epa
=override_epa
,
2237 override_nonepa
=override_nonepa
,
2238 override_paravirt
=override_paravirt
,
2245 @cli_osm.command(name
="nfpkg-create", short_help
="creates a new NFpkg")
2246 @click.argument("filename")
2250 default
=None, # hidden=True,
2251 help="Deprecated. Use override",
2257 help="overrides fields in descriptor, format: "
2258 '"key1.key2...=value[;key3...=value;...]"',
2261 "--skip-charm-build",
2264 help="The charm will not be compiled, it is assumed to already exist",
2271 help="adds guest-epa parameters to all VDU",
2274 "--override-nonepa",
2278 help="removes all guest-epa parameters from all VDU",
2281 "--override-paravirt",
2285 help="overrides all VDU interfaces to PARAVIRT",
2287 @click.option("--repo", default
=None, help="[repository]: Repository name")
2288 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2292 help="[repository]: filter by version. Default: latest",
2307 """creates a new NFpkg
2310 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2311 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2312 If FILENAME is an NF Package folder, it is built and then onboarded.
2318 overwrite
=overwrite
,
2319 skip_charm_build
=skip_charm_build
,
2320 override_epa
=override_epa
,
2321 override_nonepa
=override_nonepa
,
2322 override_paravirt
=override_paravirt
,
2329 @cli_osm.command(name
="ns-create", short_help
="creates a new Network Service instance")
2330 @click.option("--ns_name", prompt
=True, help="name of the NS instance")
2331 @click.option("--nsd_name", prompt
=True, help="name of the NS descriptor")
2335 help="default VIM account id or name for the deployment",
2337 @click.option("--admin_status", default
="ENABLED", help="administration status")
2341 help="comma separated list of public key files to inject to vnfs",
2343 @click.option("--config", default
=None, help="ns specific yaml configuration")
2344 @click.option("--config_file", default
=None, help="ns specific yaml configuration file")
2350 help="do not return the control immediately, but keep it "
2351 "until the operation is completed, or timeout",
2353 @click.option("--timeout", default
=None, help="ns deployment timeout")
2367 """creates a new NS instance"""
2371 check_client_version(ctx
.obj
, "--config_file")
2373 raise ClientException(
2374 '"--config" option is incompatible with "--config_file" option'
2376 with
open(config_file
, "r") as cf
:
2383 account
=vim_account
,
2387 # except ClientException as e:
2392 def nst_create(ctx
, filename
, overwrite
):
2395 check_client_version(ctx
.obj
, ctx
.command
.name
)
2396 ctx
.obj
.nst
.create(filename
, overwrite
)
2397 # except ClientException as e:
2403 name
="nst-create", short_help
="creates a new Network Slice Template (NST)"
2405 @click.argument("filename")
2409 default
=None, # hidden=True,
2410 help="Deprecated. Use override",
2416 help="overrides fields in descriptor, format: "
2417 '"key1.key2...=value[;key3...=value;...]"',
2420 def nst_create1(ctx
, filename
, overwrite
):
2421 """creates a new Network Slice Template (NST)
2423 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
2426 nst_create(ctx
, filename
, overwrite
)
2430 name
="netslice-template-create",
2431 short_help
="creates a new Network Slice Template (NST)",
2433 @click.argument("filename")
2437 default
=None, # hidden=True,
2438 help="Deprecated. Use override",
2444 help="overrides fields in descriptor, format: "
2445 '"key1.key2...=value[;key3...=value;...]"',
2448 def nst_create2(ctx
, filename
, overwrite
):
2449 """creates a new Network Slice Template (NST)
2451 FILENAME: NST yaml file or NSTpkg tar.gz file
2454 nst_create(ctx
, filename
, overwrite
)
2458 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
2460 """creates a new Network Slice Instance (NSI)"""
2463 check_client_version(ctx
.obj
, ctx
.command
.name
)
2466 raise ClientException(
2467 '"--config" option is incompatible with "--config_file" option'
2469 with
open(config_file
, "r") as cf
:
2476 account
=vim_account
,
2479 # except ClientException as e:
2484 @cli_osm.command(name
="nsi-create", short_help
="creates a new Network Slice Instance")
2485 @click.option("--nsi_name", prompt
=True, help="name of the Network Slice Instance")
2486 @click.option("--nst_name", prompt
=True, help="name of the Network Slice Template")
2490 help="default VIM account id or name for the deployment",
2493 "--ssh_keys", default
=None, help="comma separated list of keys to inject to vnfs"
2498 help="Netslice specific yaml configuration:\n"
2499 "netslice_subnet: [\n"
2500 "id: TEXT, vim_account: TEXT,\n"
2501 "vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n"
2502 "vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n"
2503 "additionalParamsForNsi: {param: value, ...}\n"
2504 "additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n"
2506 "netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]",
2509 "--config_file", default
=None, help="nsi specific yaml configuration file"
2516 help="do not return the control immediately, but keep it "
2517 "until the operation is completed, or timeout",
2521 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
2523 """creates a new Network Slice Instance (NSI)"""
2526 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
2531 name
="netslice-instance-create", short_help
="creates a new Network Slice Instance"
2533 @click.option("--nsi_name", prompt
=True, help="name of the Network Slice Instance")
2534 @click.option("--nst_name", prompt
=True, help="name of the Network Slice Template")
2538 help="default VIM account id or name for the deployment",
2541 "--ssh_keys", default
=None, help="comma separated list of keys to inject to vnfs"
2546 help="Netslice specific yaml configuration:\n"
2547 "netslice_subnet: [\n"
2548 "id: TEXT, vim_account: TEXT,\n"
2549 "vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n"
2550 "vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]"
2552 "netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]",
2555 "--config_file", default
=None, help="nsi specific yaml configuration file"
2562 help="do not return the control immediately, but keep it "
2563 "until the operation is completed, or timeout",
2567 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
2569 """creates a new Network Slice Instance (NSI)"""
2572 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
2577 name
="pdu-create", short_help
="adds a new Physical Deployment Unit to the catalog"
2579 @click.option("--name", help="name of the Physical Deployment Unit")
2580 @click.option("--pdu_type", help="type of PDU (e.g. router, firewall, FW001)")
2583 help="interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>"
2584 + "[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]",
2587 @click.option("--description", help="human readable description")
2590 help="list of VIM accounts (in the same VIM) that can reach this PDU\n"
2591 + "The format for multiple VIMs is --vim_account <vim_account_id_1> "
2592 + "--vim_account <vim_account_id_2> ... --vim_account <vim_account_id_N>",
2596 "--descriptor_file",
2598 help="PDU descriptor file (as an alternative to using the other arguments)",
2602 ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
2604 """creates a new Physical Deployment Unit (PDU)"""
2607 check_client_version(ctx
.obj
, ctx
.command
.name
)
2609 pdu
= create_pdu_dictionary(
2610 name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
2612 ctx
.obj
.pdu
.create(pdu
)
2615 ########################
2616 # UPDATE PDU operation #
2617 ########################
2621 name
="pdu-update", short_help
="updates a Physical Deployment Unit to the catalog"
2623 @click.argument("name")
2624 @click.option("--newname", help="New name for the Physical Deployment Unit")
2625 @click.option("--pdu_type", help="type of PDU (e.g. router, firewall, FW001)")
2628 help="interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>"
2629 + "[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]",
2632 @click.option("--description", help="human readable description")
2635 help="list of VIM accounts (in the same VIM) that can reach this PDU\n"
2636 + "The format for multiple VIMs is --vim_account <vim_account_id_1> "
2637 + "--vim_account <vim_account_id_2> ... --vim_account <vim_account_id_N>",
2641 "--descriptor_file",
2643 help="PDU descriptor file (as an alternative to using the other arguments)",
2647 ctx
, name
, newname
, pdu_type
, interface
, description
, vim_account
, descriptor_file
2649 """Updates a new Physical Deployment Unit (PDU)"""
2652 check_client_version(ctx
.obj
, ctx
.command
.name
)
2659 pdu
= create_pdu_dictionary(
2660 newname
, pdu_type
, interface
, description
, vim_account
, descriptor_file
, update
2662 ctx
.obj
.pdu
.update(name
, pdu
)
2665 def create_pdu_dictionary(
2666 name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
, update
=False
2672 if not descriptor_file
:
2675 raise ClientException(
2676 'in absence of descriptor file, option "--name" is mandatory'
2679 raise ClientException(
2680 'in absence of descriptor file, option "--pdu_type" is mandatory'
2683 raise ClientException(
2684 'in absence of descriptor file, option "--interface" is mandatory (at least once)'
2687 raise ClientException(
2688 'in absence of descriptor file, option "--vim_account" is mandatory (at least once)'
2691 with
open(descriptor_file
, "r") as df
:
2692 pdu
= yaml
.safe_load(df
.read())
2696 pdu
["type"] = pdu_type
2698 pdu
["description"] = description
2700 pdu
["vim_accounts"] = vim_account
2703 for iface
in interface
:
2704 new_iface
= {k
: v
for k
, v
in [i
.split("=") for i
in iface
.split(",")]}
2705 new_iface
["mgmt"] = new_iface
.get("mgmt", "false").lower() == "true"
2706 ifaces_list
.append(new_iface
)
2707 pdu
["interfaces"] = ifaces_list
2711 ####################
2713 ####################
2716 def nsd_update(ctx
, name
, content
):
2719 check_client_version(ctx
.obj
, ctx
.command
.name
)
2720 ctx
.obj
.nsd
.update(name
, content
)
2721 # except ClientException as e:
2726 @cli_osm.command(name
="nsd-update", short_help
="updates a NSD/NSpkg")
2727 @click.argument("name")
2731 help="filename with the NSD/NSpkg replacing the current one",
2734 def nsd_update1(ctx
, name
, content
):
2735 """updates a NSD/NSpkg
2737 NAME: name or ID of the NSD/NSpkg
2740 nsd_update(ctx
, name
, content
)
2743 @cli_osm.command(name
="nspkg-update", short_help
="updates a NSD/NSpkg")
2744 @click.argument("name")
2748 help="filename with the NSD/NSpkg replacing the current one",
2751 def nsd_update2(ctx
, name
, content
):
2752 """updates a NSD/NSpkg
2754 NAME: name or ID of the NSD/NSpkg
2757 nsd_update(ctx
, name
, content
)
2760 def vnfd_update(ctx
, name
, content
):
2763 check_client_version(ctx
.obj
, ctx
.command
.name
)
2764 ctx
.obj
.vnfd
.update(name
, content
)
2765 # except ClientException as e:
2770 @cli_osm.command(name
="vnfd-update", short_help
="updates a new VNFD/VNFpkg")
2771 @click.argument("name")
2775 help="filename with the VNFD/VNFpkg replacing the current one",
2778 def vnfd_update1(ctx
, name
, content
):
2779 """updates a VNFD/VNFpkg
2781 NAME: name or ID of the VNFD/VNFpkg
2784 vnfd_update(ctx
, name
, content
)
2787 @cli_osm.command(name
="vnfpkg-update", short_help
="updates a VNFD/VNFpkg")
2788 @click.argument("name")
2792 help="filename with the VNFD/VNFpkg replacing the current one",
2795 def vnfd_update2(ctx
, name
, content
):
2796 """updates a VNFD/VNFpkg
2798 NAME: VNFD yaml file or VNFpkg tar.gz file
2801 vnfd_update(ctx
, name
, content
)
2804 @cli_osm.command(name
="nfpkg-update", short_help
="updates a NFpkg")
2805 @click.argument("name")
2807 "--content", default
=None, help="filename with the NFpkg replacing the current one"
2810 def nfpkg_update(ctx
, name
, content
):
2813 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2816 vnfd_update(ctx
, name
, content
)
2819 def nst_update(ctx
, name
, content
):
2822 check_client_version(ctx
.obj
, ctx
.command
.name
)
2823 ctx
.obj
.nst
.update(name
, content
)
2824 # except ClientException as e:
2829 @cli_osm.command(name
="nst-update", short_help
="updates a Network Slice Template (NST)")
2830 @click.argument("name")
2834 help="filename with the NST/NSTpkg replacing the current one",
2837 def nst_update1(ctx
, name
, content
):
2838 """updates a Network Slice Template (NST)
2840 NAME: name or ID of the NSD/NSpkg
2843 nst_update(ctx
, name
, content
)
2847 name
="netslice-template-update", short_help
="updates a Network Slice Template (NST)"
2849 @click.argument("name")
2853 help="filename with the NST/NSTpkg replacing the current one",
2856 def nst_update2(ctx
, name
, content
):
2857 """updates a Network Slice Template (NST)
2859 NAME: name or ID of the NSD/NSpkg
2862 nst_update(ctx
, name
, content
)
2865 ####################
2867 ####################
2870 def nsd_delete(ctx
, name
, force
):
2874 ctx
.obj
.nsd
.delete(name
)
2876 check_client_version(ctx
.obj
, "--force")
2877 ctx
.obj
.nsd
.delete(name
, force
)
2878 # except ClientException as e:
2883 @cli_osm.command(name
="nsd-delete", short_help
="deletes a NSD/NSpkg")
2884 @click.argument("name")
2886 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2889 def nsd_delete1(ctx
, name
, force
):
2890 """deletes a NSD/NSpkg
2892 NAME: name or ID of the NSD/NSpkg to be deleted
2895 nsd_delete(ctx
, name
, force
)
2898 @cli_osm.command(name
="nspkg-delete", short_help
="deletes a NSD/NSpkg")
2899 @click.argument("name")
2901 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2904 def nsd_delete2(ctx
, name
, force
):
2905 """deletes a NSD/NSpkg
2907 NAME: name or ID of the NSD/NSpkg to be deleted
2910 nsd_delete(ctx
, name
, force
)
2913 def vnfd_delete(ctx
, name
, force
):
2917 ctx
.obj
.vnfd
.delete(name
)
2919 check_client_version(ctx
.obj
, "--force")
2920 ctx
.obj
.vnfd
.delete(name
, force
)
2921 # except ClientException as e:
2926 @cli_osm.command(name
="vnfd-delete", short_help
="deletes a VNFD/VNFpkg")
2927 @click.argument("name")
2929 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2932 def vnfd_delete1(ctx
, name
, force
):
2933 """deletes a VNFD/VNFpkg
2935 NAME: name or ID of the VNFD/VNFpkg to be deleted
2938 vnfd_delete(ctx
, name
, force
)
2941 @cli_osm.command(name
="vnfpkg-delete", short_help
="deletes a VNFD/VNFpkg")
2942 @click.argument("name")
2944 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2947 def vnfd_delete2(ctx
, name
, force
):
2948 """deletes a VNFD/VNFpkg
2950 NAME: name or ID of the VNFD/VNFpkg to be deleted
2953 vnfd_delete(ctx
, name
, force
)
2956 @cli_osm.command(name
="nfpkg-delete", short_help
="deletes a NFpkg")
2957 @click.argument("name")
2959 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2962 def nfpkg_delete(ctx
, name
, force
):
2965 NAME: name or ID of the NFpkg to be deleted
2968 vnfd_delete(ctx
, name
, force
)
2971 @cli_osm.command(name
="ns-delete", short_help
="deletes a NS instance")
2972 @click.argument("name")
2974 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2979 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2980 "600, skip_terminate_primitives: True}'",
2987 help="do not return the control immediately, but keep it "
2988 "until the operation is completed, or timeout",
2991 def ns_delete(ctx
, name
, force
, config
, wait
):
2992 """deletes a NS instance
2994 NAME: name or ID of the NS instance to be deleted
2999 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
3001 check_client_version(ctx
.obj
, "--force")
3002 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
3003 # except ClientException as e:
3008 def nst_delete(ctx
, name
, force
):
3011 check_client_version(ctx
.obj
, ctx
.command
.name
)
3012 ctx
.obj
.nst
.delete(name
, force
)
3013 # except ClientException as e:
3018 @cli_osm.command(name
="nst-delete", short_help
="deletes a Network Slice Template (NST)")
3019 @click.argument("name")
3021 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3024 def nst_delete1(ctx
, name
, force
):
3025 """deletes a Network Slice Template (NST)
3027 NAME: name or ID of the NST/NSTpkg to be deleted
3030 nst_delete(ctx
, name
, force
)
3034 name
="netslice-template-delete", short_help
="deletes a Network Slice Template (NST)"
3036 @click.argument("name")
3038 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3041 def nst_delete2(ctx
, name
, force
):
3042 """deletes a Network Slice Template (NST)
3044 NAME: name or ID of the NST/NSTpkg to be deleted
3047 nst_delete(ctx
, name
, force
)
3050 def nsi_delete(ctx
, name
, force
, wait
):
3053 check_client_version(ctx
.obj
, ctx
.command
.name
)
3054 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
3055 # except ClientException as e:
3060 @cli_osm.command(name
="nsi-delete", short_help
="deletes a Network Slice Instance (NSI)")
3061 @click.argument("name")
3063 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3070 help="do not return the control immediately, but keep it "
3071 "until the operation is completed, or timeout",
3074 def nsi_delete1(ctx
, name
, force
, wait
):
3075 """deletes a Network Slice Instance (NSI)
3077 NAME: name or ID of the Network Slice instance to be deleted
3080 nsi_delete(ctx
, name
, force
, wait
=wait
)
3084 name
="netslice-instance-delete", short_help
="deletes a Network Slice Instance (NSI)"
3086 @click.argument("name")
3088 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3091 def nsi_delete2(ctx
, name
, force
, wait
):
3092 """deletes a Network Slice Instance (NSI)
3094 NAME: name or ID of the Network Slice instance to be deleted
3097 nsi_delete(ctx
, name
, force
, wait
=wait
)
3101 name
="pdu-delete", short_help
="deletes a Physical Deployment Unit (PDU)"
3103 @click.argument("name")
3105 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3108 def pdu_delete(ctx
, name
, force
):
3109 """deletes a Physical Deployment Unit (PDU)
3111 NAME: name or ID of the PDU to be deleted
3115 check_client_version(ctx
.obj
, ctx
.command
.name
)
3116 ctx
.obj
.pdu
.delete(name
, force
)
3117 # except ClientException as e:
3127 @cli_osm.command(name
="vim-create", short_help
="creates a new VIM account")
3128 @click.option("--name", required
=True, help="Name to create datacenter")
3129 @click.option("--user", default
=None, help="VIM username")
3130 @click.option("--password", default
=None, help="VIM password")
3131 @click.option("--auth_url", default
=None, help="VIM url")
3132 @click.option("--tenant", "--project", "tenant", default
=None, help="VIM tenant/project name")
3133 @click.option("--config", default
=None, help="VIM specific config parameters")
3134 @click.option("--config_file", default
=None, help="VIM specific config parameters in YAML or JSON file")
3135 @click.option("--account_type", default
="openstack", help="VIM type")
3136 @click.option("--description", default
=None, help="human readable description")
3140 help="Name or id of the SDN controller associated to this VIM account",
3143 "--sdn_port_mapping",
3145 help="File describing the port mapping between compute nodes' ports and switch ports",
3152 help="do not return the control immediately, but keep it "
3153 "until the operation is completed, or timeout",
3155 @click.option("--vca", default
=None, help="VCA to be used in this VIM account")
3156 @click.option("--creds", default
=None, help="credentials file (only applycable for GCP VIM type)")
3157 @click.option("--prometheus_config_file", default
=None, help="Prometheus configuration to get VIM data")
3175 prometheus_config_file
3177 """creates a new VIM account"""
3181 check_client_version(ctx
.obj
, "--sdn_controller")
3182 if sdn_port_mapping
:
3183 check_client_version(ctx
.obj
, "--sdn_port_mapping")
3185 if prometheus_config_file
:
3186 with
open(prometheus_config_file
) as prometheus_file
:
3187 prometheus_config_dict
= json
.load(prometheus_file
)
3188 vim
["prometheus-config"] = prometheus_config_dict
3190 vim
["vim-username"] = user
3191 vim
["vim-password"] = password
3192 vim
["vim-url"] = auth_url
3193 vim
["vim-tenant-name"] = tenant
3194 vim
["vim-type"] = account_type
3195 vim
["description"] = description
3198 vim_config
= create_config(config_file
, config
)
3200 with
open(creds
, "r") as cf
:
3201 vim_config
["credentials"] = yaml
.safe_load(cf
.read())
3202 ctx
.obj
.vim
.create(name
, vim
, vim_config
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
3203 # except ClientException as e:
3208 @cli_osm.command(name
="vim-update", short_help
="updates a VIM account")
3209 @click.argument("name")
3210 @click.option("--newname", help="New name for the VIM account")
3211 @click.option("--user", help="VIM username")
3212 @click.option("--password", help="VIM password")
3213 @click.option("--auth_url", help="VIM url")
3214 @click.option("--tenant", help="VIM tenant name")
3215 @click.option("--config", help="VIM specific config parameters")
3216 @click.option("--config_file", default
=None, help="VIM specific config parameters in YAML or JSON file")
3217 @click.option("--account_type", help="VIM type")
3218 @click.option("--description", help="human readable description")
3222 help="Name or id of the SDN controller to be associated with this VIM"
3223 "account. Use empty string to disassociate",
3226 "--sdn_port_mapping",
3228 help="File describing the port mapping between compute nodes' ports and switch ports",
3235 help="do not return the control immediately, but keep it "
3236 "until the operation is completed, or timeout",
3238 @click.option("--creds", default
=None, help="credentials file (only applycable for GCP VIM type)")
3239 @click.option("--prometheus_config_file", default
=None, help="Prometheus configuration to get VIM data")
3257 prometheus_config_file
3259 """updates a VIM account
3261 NAME: name or ID of the VIM account
3265 check_client_version(ctx
.obj
, ctx
.command
.name
)
3268 vim
["name"] = newname
3270 vim
["vim_user"] = user
3272 vim
["vim_password"] = password
3274 vim
["vim_url"] = auth_url
3276 vim
["vim-tenant-name"] = tenant
3278 vim
["vim_type"] = account_type
3280 vim
["description"] = description
3282 if config
or config_file
:
3283 vim_config
= create_config(config_file
, config
)
3285 with
open(creds
, "r") as cf
:
3286 vim_config
["credentials"] = yaml
.safe_load(cf
.read())
3287 if prometheus_config_file
:
3288 with
open(prometheus_config_file
) as prometheus_file
:
3289 prometheus_config_dict
= json
.load(prometheus_file
)
3290 vim
["prometheus-config"] = prometheus_config_dict
3291 logger
.info(f
"VIM: {vim}, VIM config: {vim_config}")
3292 ctx
.obj
.vim
.update(name
, vim
, vim_config
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
3293 # except ClientException as e:
3298 @cli_osm.command(name
="vim-delete", short_help
="deletes a VIM account")
3299 @click.argument("name")
3301 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3308 help="do not return the control immediately, but keep it "
3309 "until the operation is completed, or timeout",
3312 def vim_delete(ctx
, name
, force
, wait
):
3313 """deletes a VIM account
3315 NAME: name or ID of the VIM account to be deleted
3320 ctx
.obj
.vim
.delete(name
, wait
=wait
)
3322 check_client_version(ctx
.obj
, "--force")
3323 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
3324 # except ClientException as e:
3329 @cli_osm.command(name
="vim-list", short_help
="list all VIM accounts")
3330 # @click.option('--ro_update/--no_ro_update',
3332 # help='update list from RO')
3337 help="restricts the list to the VIM accounts matching the filter",
3342 help="get more details of the NS (project, vim, deployment status, configuration status.",
3345 def vim_list(ctx
, filter, long):
3346 """list all VIM accounts"""
3349 filter = "&".join(filter)
3350 check_client_version(ctx
.obj
, "--filter")
3352 # check_client_version(ctx.obj, '--ro_update', 'v1')
3353 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3354 if fullclassname
== "osmclient.sol005.client.Client":
3355 resp
= ctx
.obj
.vim
.list(filter)
3357 # resp = ctx.obj.vim.list(ro_update)
3359 table
= PrettyTable(
3360 ["vim name", "uuid", "project", "operational state", "error details"]
3362 project_list
= ctx
.obj
.project
.list()
3364 table
= PrettyTable(["vim name", "uuid", "operational state"])
3367 if "vim_password" in vim
:
3368 vim
["vim_password"] = "********"
3369 if "config" in vim
and "credentials" in vim
["config"]:
3370 vim
["config"]["credentials"] = "********"
3371 logger
.debug("VIM details: {}".format(yaml
.safe_dump(vim
)))
3372 vim_state
= vim
["_admin"].get("operationalState", "-")
3373 error_details
= "N/A"
3374 if vim_state
== "ERROR":
3375 error_details
= vim
["_admin"].get("detailed-status", "Not found")
3376 project_id
, project_name
= get_project(project_list
, vim
)
3377 # project_info = '{} ({})'.format(project_name, project_id)
3378 project_info
= project_name
3385 wrap_text(text
=error_details
, width
=80),
3390 [vim
["name"], vim
["uuid"], vim
["_admin"].get("operationalState", "-")]
3396 @cli_osm.command(name
="vim-show", short_help
="shows the details of a VIM account")
3397 @click.argument("name")
3401 help="restricts the information to the fields in the filter",
3403 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
3405 def vim_show(ctx
, name
, filter, literal
):
3406 """shows the details of a VIM account
3408 NAME: name or ID of the VIM account
3412 resp
= ctx
.obj
.vim
.get(name
)
3413 if "vim_password" in resp
:
3414 resp
["vim_password"] = "********"
3415 if "config" in resp
and "credentials" in resp
["config"]:
3416 resp
["config"]["credentials"] = "********"
3417 # except ClientException as e:
3422 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3424 table
= PrettyTable(["key", "attribute"])
3425 for k
, v
in list(resp
.items()):
3426 if not filter or k
in filter:
3427 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
3432 ####################
3434 ####################
3437 @cli_osm.command(name
="wim-create", short_help
="creates a new WIM account")
3438 @click.option("--name", prompt
=True, help="Name for the WIM account")
3439 @click.option("--user", help="WIM username")
3440 @click.option("--password", help="WIM password")
3441 @click.option("--url", prompt
=True, help="WIM url")
3442 # @click.option('--tenant',
3443 # help='wIM tenant name')
3444 @click.option("--config", default
=None, help="WIM specific config parameters")
3445 @click.option("--wim_type", help="WIM type")
3446 @click.option("--description", default
=None, help="human readable description")
3448 "--wim_port_mapping",
3450 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
3451 "(WAN service endpoint id and info)",
3458 help="do not return the control immediately, but keep it "
3459 "until the operation is completed, or timeout",
3475 """creates a new WIM account"""
3478 check_client_version(ctx
.obj
, ctx
.command
.name
)
3479 # if sdn_controller:
3480 # check_client_version(ctx.obj, '--sdn_controller')
3481 # if sdn_port_mapping:
3482 # check_client_version(ctx.obj, '--sdn_port_mapping')
3487 wim
["password"] = password
3489 wim
["wim_url"] = url
3490 # if tenant: wim['tenant'] = tenant
3491 wim
["wim_type"] = wim_type
3493 wim
["description"] = description
3495 wim
["config"] = config
3496 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
3497 # except ClientException as e:
3502 @cli_osm.command(name
="wim-update", short_help
="updates a WIM account")
3503 @click.argument("name")
3504 @click.option("--newname", help="New name for the WIM account")
3505 @click.option("--user", help="WIM username")
3506 @click.option("--password", help="WIM password")
3507 @click.option("--url", help="WIM url")
3508 @click.option("--config", help="WIM specific config parameters")
3509 @click.option("--wim_type", help="WIM type")
3510 @click.option("--description", help="human readable description")
3512 "--wim_port_mapping",
3514 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
3515 "(WAN service endpoint id and info)",
3522 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3538 """updates a WIM account
3540 NAME: name or ID of the WIM account
3544 check_client_version(ctx
.obj
, ctx
.command
.name
)
3547 wim
["name"] = newname
3551 wim
["password"] = password
3554 # if tenant: wim['tenant'] = tenant
3556 wim
["wim_type"] = wim_type
3558 wim
["description"] = description
3560 wim
["config"] = config
3561 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
3562 # except ClientException as e:
3567 @cli_osm.command(name
="wim-delete", short_help
="deletes a WIM account")
3568 @click.argument("name")
3570 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3577 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3580 def wim_delete(ctx
, name
, force
, wait
):
3581 """deletes a WIM account
3583 NAME: name or ID of the WIM account to be deleted
3587 check_client_version(ctx
.obj
, ctx
.command
.name
)
3588 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
3589 # except ClientException as e:
3594 @cli_osm.command(name
="wim-list", short_help
="list all WIM accounts")
3599 help="restricts the list to the WIM accounts matching the filter",
3602 def wim_list(ctx
, filter):
3603 """list all WIM accounts"""
3606 check_client_version(ctx
.obj
, ctx
.command
.name
)
3608 filter = "&".join(filter)
3609 resp
= ctx
.obj
.wim
.list(filter)
3610 table
= PrettyTable(["wim name", "uuid"])
3612 table
.add_row([wim
["name"], wim
["uuid"]])
3615 # except ClientException as e:
3620 @cli_osm.command(name
="wim-show", short_help
="shows the details of a WIM account")
3621 @click.argument("name")
3623 def wim_show(ctx
, name
):
3624 """shows the details of a WIM account
3626 NAME: name or ID of the WIM account
3630 check_client_version(ctx
.obj
, ctx
.command
.name
)
3631 resp
= ctx
.obj
.wim
.get(name
)
3632 if "password" in resp
:
3633 resp
["wim_password"] = "********"
3634 # except ClientException as e:
3638 table
= PrettyTable(["key", "attribute"])
3639 for k
, v
in list(resp
.items()):
3640 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3645 ####################
3646 # SDN controller operations
3647 ####################
3650 @cli_osm.command(name
="sdnc-create", short_help
="creates a new SDN controller")
3651 @click.option("--name", prompt
=True, help="Name to create sdn controller")
3652 @click.option("--type", prompt
=True, help="SDN controller type")
3654 "--sdn_controller_version", # hidden=True,
3655 help="Deprecated. Use --config {version: sdn_controller_version}",
3657 @click.option("--url", help="URL in format http[s]://HOST:IP/")
3658 @click.option("--ip_address", help="Deprecated. Use --url") # hidden=True,
3659 @click.option("--port", help="Deprecated. Use --url") # hidden=True,
3661 "--switch_dpid", help="Deprecated. Use --config {switch_id: DPID}" # hidden=True,
3665 help="Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: "
3666 "Openflow Datapath ID), version: version}",
3668 @click.option("--user", help="SDN controller username")
3672 confirmation_prompt
=True,
3673 help="SDN controller password",
3675 @click.option("--description", default
=None, help="human readable description")
3681 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3684 def sdnc_create(ctx
, **kwargs
):
3685 """creates a new SDN controller"""
3690 if kwargs
[x
] and x
not in ("wait", "ip_address", "port", "switch_dpid")
3692 if kwargs
.get("port"):
3693 print("option '--port' is deprecated, use '--url' instead")
3694 sdncontroller
["port"] = int(kwargs
["port"])
3695 if kwargs
.get("ip_address"):
3696 print("option '--ip_address' is deprecated, use '--url' instead")
3697 sdncontroller
["ip"] = kwargs
["ip_address"]
3698 if kwargs
.get("switch_dpid"):
3700 "option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead"
3702 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
3703 if kwargs
.get("sdn_controller_version"):
3705 "option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
3709 check_client_version(ctx
.obj
, ctx
.command
.name
)
3710 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
3711 # except ClientException as e:
3716 @cli_osm.command(name
="sdnc-update", short_help
="updates an SDN controller")
3717 @click.argument("name")
3718 @click.option("--newname", help="New name for the SDN controller")
3719 @click.option("--description", default
=None, help="human readable description")
3720 @click.option("--type", help="SDN controller type")
3721 @click.option("--url", help="URL in format http[s]://HOST:IP/")
3724 help="Extra information for SDN in yaml format, as "
3725 "{switch_id: identity used for the plugin (e.g. DPID: "
3726 "Openflow Datapath ID), version: version}",
3728 @click.option("--user", help="SDN controller username")
3729 @click.option("--password", help="SDN controller password")
3730 @click.option("--ip_address", help="Deprecated. Use --url") # hidden=True
3731 @click.option("--port", help="Deprecated. Use --url") # hidden=True
3733 "--switch_dpid", help="Deprecated. Use --config {switch_dpid: DPID}"
3736 "--sdn_controller_version", help="Deprecated. Use --config {version: VERSION}"
3743 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3746 def sdnc_update(ctx
, **kwargs
):
3747 """updates an SDN controller
3749 NAME: name or ID of the SDN controller
3756 and x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")
3758 if kwargs
.get("newname"):
3759 sdncontroller
["name"] = kwargs
["newname"]
3760 if kwargs
.get("port"):
3761 print("option '--port' is deprecated, use '--url' instead")
3762 sdncontroller
["port"] = int(kwargs
["port"])
3763 if kwargs
.get("ip_address"):
3764 print("option '--ip_address' is deprecated, use '--url' instead")
3765 sdncontroller
["ip"] = kwargs
["ip_address"]
3766 if kwargs
.get("switch_dpid"):
3768 "option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead"
3770 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
3771 if kwargs
.get("sdn_controller_version"):
3773 "option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
3778 check_client_version(ctx
.obj
, ctx
.command
.name
)
3779 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
3780 # except ClientException as e:
3785 @cli_osm.command(name
="sdnc-delete", short_help
="deletes an SDN controller")
3786 @click.argument("name")
3788 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3795 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3798 def sdnc_delete(ctx
, name
, force
, wait
):
3799 """deletes an SDN controller
3801 NAME: name or ID of the SDN controller to be deleted
3805 check_client_version(ctx
.obj
, ctx
.command
.name
)
3806 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
3807 # except ClientException as e:
3812 @cli_osm.command(name
="sdnc-list", short_help
="list all SDN controllers")
3817 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'",
3820 def sdnc_list(ctx
, filter):
3821 """list all SDN controllers"""
3824 check_client_version(ctx
.obj
, ctx
.command
.name
)
3826 filter = "&".join(filter)
3827 resp
= ctx
.obj
.sdnc
.list(filter)
3828 # except ClientException as e:
3831 table
= PrettyTable(["sdnc name", "id"])
3833 table
.add_row([sdnc
["name"], sdnc
["_id"]])
3838 @cli_osm.command(name
="sdnc-show", short_help
="shows the details of an SDN controller")
3839 @click.argument("name")
3841 def sdnc_show(ctx
, name
):
3842 """shows the details of an SDN controller
3844 NAME: name or ID of the SDN controller
3848 check_client_version(ctx
.obj
, ctx
.command
.name
)
3849 resp
= ctx
.obj
.sdnc
.get(name
)
3850 # except ClientException as e:
3854 table
= PrettyTable(["key", "attribute"])
3855 for k
, v
in list(resp
.items()):
3856 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3861 ###########################
3862 # K8s cluster operations
3863 ###########################
3866 @cli_osm.command(name
="k8scluster-add", short_help
="adds a K8s cluster to OSM")
3867 @click.argument("name")
3869 "--creds", prompt
=True, help="credentials file, i.e. a valid `.kube/config` file"
3871 @click.option("--version", prompt
=True, help="Kubernetes version")
3873 "--vim", prompt
=True, help="VIM target, the VIM where the cluster resides"
3878 help='''list of VIM networks, in JSON inline format, where the cluster is
3879 accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''',
3882 "--init-helm2/--skip-helm2",
3885 help="Initialize helm v2",
3888 "--init-helm3/--skip-helm3",
3891 help="Initialize helm v3",
3894 "--init-jujubundle/--skip-jujubundle",
3897 help="Initialize juju-bundle",
3899 @click.option("--description", default
=None, help="human readable description")
3902 default
="kube-system",
3903 help="namespace to be used for its operation, defaults to `kube-system`",
3910 help="do not return the control immediately, but keep it "
3911 "until the operation is completed, or timeout",
3916 help="list of CNI plugins, in JSON inline format, used in the cluster",
3918 # @click.option('--skip-init',
3920 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3921 # @click.option('--wait',
3923 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3926 ctx
, name
, creds
, version
, vim
, k8s_nets
, init_helm2
, init_helm3
, init_jujubundle
, description
, namespace
, wait
, cni
3928 """adds a K8s cluster to OSM
3930 NAME: name of the K8s cluster
3933 check_client_version(ctx
.obj
, ctx
.command
.name
)
3935 cluster
["name"] = name
3936 with
open(creds
, "r") as cf
:
3937 cluster
["credentials"] = yaml
.safe_load(cf
.read())
3938 cluster
["k8s_version"] = version
3939 cluster
["vim_account"] = vim
3940 cluster
["nets"] = yaml
.safe_load(k8s_nets
)
3941 if not (init_helm2
and init_jujubundle
and init_helm3
):
3942 cluster
["deployment_methods"] = {"helm-chart": init_helm2
,
3943 "juju-bundle": init_jujubundle
,
3944 "helm-chart-v3": init_helm3
}
3946 cluster
["description"] = description
3948 cluster
["namespace"] = namespace
3950 cluster
["cni"] = yaml
.safe_load(cni
)
3951 ctx
.obj
.k8scluster
.create(name
, cluster
, wait
)
3952 # except ClientException as e:
3957 @cli_osm.command(name
="k8scluster-update", short_help
="updates a K8s cluster")
3958 @click.argument("name")
3959 @click.option("--newname", help="New name for the K8s cluster")
3960 @click.option("--creds", help="credentials file, i.e. a valid `.kube/config` file")
3961 @click.option("--version", help="Kubernetes version")
3962 @click.option("--vim", help="VIM target, the VIM where the cluster resides")
3965 help='''list of VIM networks, in JSON inline format, where the cluster is accessible
3966 via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''',
3968 @click.option("--description", help="human readable description")
3971 help="namespace to be used for its operation, defaults to `kube-system`",
3978 help="do not return the control immediately, but keep it "
3979 "until the operation is completed, or timeout",
3982 "--cni", help="list of CNI plugins, in JSON inline format, used in the cluster"
3985 def k8scluster_update(
3986 ctx
, name
, newname
, creds
, version
, vim
, k8s_nets
, description
, namespace
, wait
, cni
3988 """updates a K8s cluster
3990 NAME: name or ID of the K8s cluster
3993 check_client_version(ctx
.obj
, ctx
.command
.name
)
3996 cluster
["name"] = newname
3998 with
open(creds
, "r") as cf
:
3999 cluster
["credentials"] = yaml
.safe_load(cf
.read())
4001 cluster
["k8s_version"] = version
4003 cluster
["vim_account"] = vim
4005 cluster
["nets"] = yaml
.safe_load(k8s_nets
)
4007 cluster
["description"] = description
4009 cluster
["namespace"] = namespace
4011 cluster
["cni"] = yaml
.safe_load(cni
)
4012 ctx
.obj
.k8scluster
.update(name
, cluster
, wait
)
4013 # except ClientException as e:
4018 @cli_osm.command(name
="k8scluster-delete", short_help
="deletes a K8s cluster")
4019 @click.argument("name")
4021 "--force", is_flag
=True, help="forces the deletion from the DB (not recommended)"
4028 help="do not return the control immediately, but keep it "
4029 "until the operation is completed, or timeout",
4032 def k8scluster_delete(ctx
, name
, force
, wait
):
4033 """deletes a K8s cluster
4035 NAME: name or ID of the K8s cluster to be deleted
4038 check_client_version(ctx
.obj
, ctx
.command
.name
)
4039 ctx
.obj
.k8scluster
.delete(name
, force
, wait
)
4040 # except ClientException as e:
4045 @cli_osm.command(name
="k8scluster-list")
4050 help="restricts the list to the K8s clusters matching the filter",
4052 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4053 @click.option("--long", is_flag
=True, help="get more details")
4055 def k8scluster_list(ctx
, filter, literal
, long):
4056 """list all K8s clusters"""
4058 check_client_version(ctx
.obj
, ctx
.command
.name
)
4060 filter = "&".join(filter)
4061 resp
= ctx
.obj
.k8scluster
.list(filter)
4063 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4066 table
= PrettyTable(
4074 "Deployment methods",
4075 "Operational State",
4076 "Op. state (details)",
4081 project_list
= ctx
.obj
.project
.list()
4083 table
= PrettyTable(
4084 ["Name", "Id", "VIM", "Operational State", "Op. state details"]
4087 vim_list
= ctx
.obj
.vim
.list()
4090 for cluster
in resp
:
4091 logger
.debug("Cluster details: {}".format(yaml
.safe_dump(cluster
)))
4092 vim_name
= get_vim_name(vim_list
, cluster
["vim_account"])
4093 # vim_info = '{} ({})'.format(vim_name,cluster['vim_account'])
4095 op_state_details
= "Helm: {}\nJuju: {}".format(
4096 cluster
["_admin"].get("helm-chart", {}).get("operationalState", "-"),
4097 cluster
["_admin"].get("juju-bundle", {}).get("operationalState", "-"),
4100 project_id
, project_name
= get_project(project_list
, cluster
)
4101 # project_info = '{} ({})'.format(project_name, project_id)
4102 project_info
= project_name
4103 detailed_status
= cluster
["_admin"].get("detailed-status", "-")
4109 cluster
["k8s_version"],
4111 json
.dumps(cluster
["nets"]),
4112 json
.dumps(cluster
["deployment_methods"]),
4113 cluster
["_admin"]["operationalState"],
4115 trunc_text(cluster
.get("description") or "", 40),
4116 wrap_text(text
=detailed_status
, width
=40),
4125 cluster
["_admin"]["operationalState"],
4131 # except ClientException as e:
4137 name
="k8scluster-show", short_help
="shows the details of a K8s cluster"
4139 @click.argument("name")
4140 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4142 def k8scluster_show(ctx
, name
, literal
):
4143 """shows the details of a K8s cluster
4145 NAME: name or ID of the K8s cluster
4148 resp
= ctx
.obj
.k8scluster
.get(name
)
4150 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4152 table
= PrettyTable(["key", "attribute"])
4153 for k
, v
in list(resp
.items()):
4154 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
4157 # except ClientException as e:
4162 ###########################
4164 ###########################
4167 @cli_osm.command(name
="vca-add", short_help
="adds a VCA (Juju controller) to OSM")
4168 @click.argument("name")
4172 help="Comma-separated list of IP or hostnames of the Juju controller",
4174 @click.option("--user", prompt
=True, help="Username with admin priviledges")
4175 @click.option("--secret", prompt
=True, help="Password of the specified username")
4176 @click.option("--cacert", prompt
=True, help="CA certificate")
4180 help="Name of the cloud that will be used for LXD containers (LXD proxy charms)",
4183 "--lxd-credentials",
4185 help="Name of the cloud credentialsto be used for the LXD cloud",
4190 help="Name of the cloud that will be used for K8s containers (K8s proxy charms)",
4193 "--k8s-credentials",
4195 help="Name of the cloud credentialsto be used for the K8s cloud",
4200 help="Configuration options for the models",
4202 @click.option("--description", default
=None, help="human readable description")
4218 """adds a VCA to OSM
4220 NAME: name of the VCA
4222 check_client_version(ctx
.obj
, ctx
.command
.name
)
4225 vca
["endpoints"] = endpoints
.split(",")
4227 vca
["secret"] = secret
4228 vca
["cacert"] = cacert
4229 vca
["lxd-cloud"] = lxd_cloud
4230 vca
["lxd-credentials"] = lxd_credentials
4231 vca
["k8s-cloud"] = k8s_cloud
4232 vca
["k8s-credentials"] = k8s_credentials
4234 vca
["description"] = description
4236 model_config
= load(model_config
)
4237 vca
["model-config"] = model_config
4238 ctx
.obj
.vca
.create(name
, vca
)
4241 def load(data
: Any
):
4242 if os
.path
.isfile(data
):
4243 return load_file(data
)
4246 return json
.loads(data
)
4247 except ValueError as e
:
4248 raise ClientException(e
)
4251 def load_file(file_path
: str) -> Dict
:
4253 with
open(file_path
, "r") as f
:
4256 return yaml
.safe_load(content
)
4257 except yaml
.scanner
.ScannerError
:
4260 return json
.loads(content
)
4263 raise ClientException(f
"{file_path} must be a valid yaml or json file")
4266 @cli_osm.command(name
="vca-update", short_help
="updates a K8s cluster")
4267 @click.argument("name")
4269 "--endpoints", help="Comma-separated list of IP or hostnames of the Juju controller"
4271 @click.option("--user", help="Username with admin priviledges")
4272 @click.option("--secret", help="Password of the specified username")
4273 @click.option("--cacert", help="CA certificate")
4276 help="Name of the cloud that will be used for LXD containers (LXD proxy charms)",
4279 "--lxd-credentials",
4280 help="Name of the cloud credentialsto be used for the LXD cloud",
4284 help="Name of the cloud that will be used for K8s containers (K8s proxy charms)",
4287 "--k8s-credentials",
4288 help="Name of the cloud credentialsto be used for the K8s cloud",
4292 help="Configuration options for the models",
4294 @click.option("--description", default
=None, help="human readable description")
4310 """updates a K8s cluster
4312 NAME: name or ID of the K8s cluster
4314 check_client_version(ctx
.obj
, ctx
.command
.name
)
4318 vca
["endpoints"] = endpoints
.split(",")
4322 vca
["secret"] = secret
4324 vca
["cacert"] = cacert
4326 vca
["lxd-cloud"] = lxd_cloud
4328 vca
["lxd-credentials"] = lxd_credentials
4330 vca
["k8s-cloud"] = k8s_cloud
4332 vca
["k8s-credentials"] = k8s_credentials
4334 vca
["description"] = description
4336 model_config
= load(model_config
)
4337 vca
["model-config"] = model_config
4338 ctx
.obj
.vca
.update(name
, vca
)
4341 @cli_osm.command(name
="vca-delete", short_help
="deletes a K8s cluster")
4342 @click.argument("name")
4344 "--force", is_flag
=True, help="forces the deletion from the DB (not recommended)"
4347 def vca_delete(ctx
, name
, force
):
4348 """deletes a K8s cluster
4350 NAME: name or ID of the K8s cluster to be deleted
4352 check_client_version(ctx
.obj
, ctx
.command
.name
)
4353 ctx
.obj
.vca
.delete(name
, force
=force
)
4356 @cli_osm.command(name
="vca-list")
4361 help="restricts the list to the VCAs matching the filter",
4363 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4364 @click.option("--long", is_flag
=True, help="get more details")
4366 def vca_list(ctx
, filter, literal
, long):
4368 check_client_version(ctx
.obj
, ctx
.command
.name
)
4370 filter = "&".join(filter)
4371 resp
= ctx
.obj
.vca
.list(filter)
4373 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4376 table
= PrettyTable(
4377 ["Name", "Id", "Project", "Operational State", "Detailed Status"]
4379 project_list
= ctx
.obj
.project
.list()
4381 table
= PrettyTable(["Name", "Id", "Operational State"])
4383 logger
.debug("VCA details: {}".format(yaml
.safe_dump(vca
)))
4385 project_id
, project_name
= get_project(project_list
, vca
)
4386 detailed_status
= vca
.get("_admin", {}).get("detailed-status", "-")
4392 vca
.get("_admin", {}).get("operationalState", "-"),
4393 wrap_text(text
=detailed_status
, width
=40),
4401 vca
.get("_admin", {}).get("operationalState", "-"),
4408 @cli_osm.command(name
="vca-show", short_help
="shows the details of a K8s cluster")
4409 @click.argument("name")
4410 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4412 def vca_show(ctx
, name
, literal
):
4413 """shows the details of a K8s cluster
4415 NAME: name or ID of the K8s cluster
4418 resp
= ctx
.obj
.vca
.get(name
)
4420 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4422 table
= PrettyTable(["key", "attribute"])
4423 for k
, v
in list(resp
.items()):
4424 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
4429 ###########################
4431 ###########################
4434 @cli_osm.command(name
="repo-add", short_help
="adds a repo to OSM")
4435 @click.argument("name")
4436 @click.argument("uri")
4439 type=click
.Choice(["helm-chart", "juju-bundle", "osm"]),
4441 help="type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)",
4443 @click.option("--description", default
=None, help="human readable description")
4445 "--user", default
=None, help="OSM repository: The username of the OSM repository"
4450 help="OSM repository: The password of the OSM repository",
4452 # @click.option('--wait',
4454 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4456 def repo_add(ctx
, **kwargs
):
4457 """adds a repo to OSM
4459 NAME: name of the repo
4460 URI: URI of the repo
4463 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
4465 repo
["url"] = repo
.pop("uri")
4466 if repo
["type"] in ["helm-chart", "juju-bundle"]:
4467 ctx
.obj
.repo
.create(repo
["name"], repo
)
4469 ctx
.obj
.osmrepo
.create(repo
["name"], repo
)
4470 # except ClientException as e:
4475 @cli_osm.command(name
="repo-update", short_help
="updates a repo in OSM")
4476 @click.argument("name")
4477 @click.option("--newname", help="New name for the repo")
4478 @click.option("--uri", help="URI of the repo")
4479 @click.option("--description", help="human readable description")
4480 # @click.option('--wait',
4482 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4484 def repo_update(ctx
, name
, newname
, uri
, description
):
4485 """updates a repo in OSM
4487 NAME: name of the repo
4490 check_client_version(ctx
.obj
, ctx
.command
.name
)
4493 repo
["name"] = newname
4497 repo
["description"] = description
4499 ctx
.obj
.repo
.update(name
, repo
)
4501 ctx
.obj
.osmrepo
.update(name
, repo
)
4503 # except ClientException as e:
4509 name
="repo-index", short_help
="Index a repository from a folder with artifacts"
4512 "--origin", default
=".", help="origin path where the artifacts are located"
4515 "--destination", default
=".", help="destination path where the index is deployed"
4518 def repo_index(ctx
, origin
, destination
):
4519 """Index a repository
4521 NAME: name or ID of the repo to be deleted
4523 check_client_version(ctx
.obj
, ctx
.command
.name
)
4524 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
4527 @cli_osm.command(name
="repo-delete", short_help
="deletes a repo")
4528 @click.argument("name")
4530 "--force", is_flag
=True, help="forces the deletion from the DB (not recommended)"
4532 # @click.option('--wait',
4534 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4536 def repo_delete(ctx
, name
, force
):
4539 NAME: name or ID of the repo to be deleted
4543 ctx
.obj
.repo
.delete(name
, force
=force
)
4545 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
4546 # except ClientException as e:
4551 @cli_osm.command(name
="repo-list")
4556 help="restricts the list to the repos matching the filter",
4558 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4560 def repo_list(ctx
, filter, literal
):
4561 """list all repos"""
4564 check_client_version(ctx
.obj
, ctx
.command
.name
)
4566 filter = "&".join(filter)
4567 resp
= ctx
.obj
.repo
.list(filter)
4568 resp
+= ctx
.obj
.osmrepo
.list(filter)
4570 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4572 table
= PrettyTable(["Name", "Id", "Type", "URI", "Description"])
4574 # cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
4581 trunc_text(repo
.get("description") or "", 40),
4587 # except ClientException as e:
4592 @cli_osm.command(name
="repo-show", short_help
="shows the details of a repo")
4593 @click.argument("name")
4594 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4596 def repo_show(ctx
, name
, literal
):
4597 """shows the details of a repo
4599 NAME: name or ID of the repo
4602 resp
= ctx
.obj
.repo
.get(name
)
4604 resp
= ctx
.obj
.osmrepo
.get(name
)
4608 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4610 table
= PrettyTable(["key", "attribute"])
4612 for k
, v
in list(resp
.items()):
4613 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4617 # except ClientException as e:
4622 ####################
4623 # Project mgmt operations
4624 ####################
4627 @cli_osm.command(name
="project-create", short_help
="creates a new project")
4628 @click.argument("name")
4629 # @click.option('--description',
4630 # default='no description',
4631 # help='human readable description')
4632 @click.option("--domain-name", "domain_name", default
=None, help="assign to a domain")
4638 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
4639 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos",
4642 def project_create(ctx
, name
, domain_name
, quotas
):
4643 """Creates a new project
4645 NAME: name of the project
4646 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
4647 QUOTAS: set quotas for the project
4650 project
= {"name": name
}
4652 project
["domain_name"] = domain_name
4653 quotas_dict
= _process_project_quotas(quotas
)
4655 project
["quotas"] = quotas_dict
4658 check_client_version(ctx
.obj
, ctx
.command
.name
)
4659 ctx
.obj
.project
.create(name
, project
)
4660 # except ClientException as e:
4665 def _process_project_quotas(quota_list
):
4670 for quota
in quota_list
:
4671 for single_quota
in quota
.split(","):
4672 k
, v
= single_quota
.split("=")
4673 quotas_dict
[k
] = None if v
in ("None", "null", "") else int(v
)
4674 except (ValueError, TypeError):
4675 raise ClientException(
4676 "invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null"
4681 @cli_osm.command(name
="project-delete", short_help
="deletes a project")
4682 @click.argument("name")
4683 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4685 def project_delete(ctx
, name
):
4686 """deletes a project
4688 NAME: name or ID of the project to be deleted
4692 check_client_version(ctx
.obj
, ctx
.command
.name
)
4693 ctx
.obj
.project
.delete(name
)
4694 # except ClientException as e:
4699 @cli_osm.command(name
="project-list", short_help
="list all projects")
4704 help="restricts the list to the projects matching the filter",
4707 def project_list(ctx
, filter):
4708 """list all projects"""
4711 check_client_version(ctx
.obj
, ctx
.command
.name
)
4713 filter = "&".join(filter)
4714 resp
= ctx
.obj
.project
.list(filter)
4715 # except ClientException as e:
4718 table
= PrettyTable(["name", "id"])
4720 table
.add_row([proj
["name"], proj
["_id"]])
4725 @cli_osm.command(name
="project-show", short_help
="shows the details of a project")
4726 @click.argument("name")
4728 def project_show(ctx
, name
):
4729 """shows the details of a project
4731 NAME: name or ID of the project
4735 check_client_version(ctx
.obj
, ctx
.command
.name
)
4736 resp
= ctx
.obj
.project
.get(name
)
4737 # except ClientException as e:
4741 table
= PrettyTable(["key", "attribute"])
4742 for k
, v
in resp
.items():
4743 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4749 name
="project-update", short_help
="updates a project (only the name can be updated)"
4751 @click.argument("project")
4752 @click.option("--name", default
=None, help="new name for the project")
4758 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
4759 "(use empty to reset quota to default",
4762 def project_update(ctx
, project
, name
, quotas
):
4764 Update a project name
4767 :param project: id or name of the project to modify
4768 :param name: new name for the project
4769 :param quotas: change quotas of the project
4773 project_changes
= {}
4775 project_changes
["name"] = name
4776 quotas_dict
= _process_project_quotas(quotas
)
4778 project_changes
["quotas"] = quotas_dict
4781 check_client_version(ctx
.obj
, ctx
.command
.name
)
4782 ctx
.obj
.project
.update(project
, project_changes
)
4783 # except ClientException as e:
4787 ####################
4788 # User mgmt operations
4789 ####################
4792 @cli_osm.command(name
="user-create", short_help
="creates a new user")
4793 @click.argument("username")
4798 confirmation_prompt
=True,
4799 help="user password",
4803 # prompt="Comma separate list of projects",
4805 callback
=lambda ctx
, param
, value
: "".join(value
).split(",")
4806 if all(len(x
) == 1 for x
in value
)
4808 help="list of project ids that the user belongs to",
4811 "--project-role-mappings",
4812 "project_role_mappings",
4815 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4817 @click.option("--domain-name", "domain_name", default
=None, help="assign to a domain")
4819 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
4820 """Creates a new user
4823 USERNAME: name of the user
4824 PASSWORD: password of the user
4825 PROJECTS: projects assigned to user (internal only)
4826 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
4827 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
4831 user
["username"] = username
4832 user
["password"] = password
4833 user
["projects"] = projects
4834 user
["project_role_mappings"] = project_role_mappings
4836 user
["domain_name"] = domain_name
4839 check_client_version(ctx
.obj
, ctx
.command
.name
)
4840 ctx
.obj
.user
.create(username
, user
)
4841 # except ClientException as e:
4846 @cli_osm.command(name
="user-update", short_help
="updates user information")
4847 @click.argument("username")
4852 # confirmation_prompt=True,
4853 help="user password",
4855 @click.option("--set-username", "set_username", default
=None, help="change username")
4861 help="create/replace the roles for this project: 'project,role1[,role2,...]'",
4868 help="removes project from user: 'project'",
4871 "--add-project-role",
4875 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4878 "--remove-project-role",
4879 "remove_project_role",
4882 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4885 "--change_password",
4887 help="user's current password"
4892 help="user's new password to update in expiry condition"
4903 remove_project_role
,
4907 """Update a user information
4910 USERNAME: name of the user
4911 PASSWORD: new password
4912 SET_USERNAME: new username
4913 SET_PROJECT: creating mappings for project/role(s)
4914 REMOVE_PROJECT: deleting mappings for project/role(s)
4915 ADD_PROJECT_ROLE: adding mappings for project/role(s)
4916 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
4917 CHANGE_PASSWORD: user's current password to change
4918 NEW_PASSWORD: user's new password to update in expiry condition
4922 user
["password"] = password
4923 user
["username"] = set_username
4924 user
["set-project"] = set_project
4925 user
["remove-project"] = remove_project
4926 user
["add-project-role"] = add_project_role
4927 user
["remove-project-role"] = remove_project_role
4928 user
["change_password"] = change_password
4929 user
["new_password"] = new_password
4932 check_client_version(ctx
.obj
, ctx
.command
.name
)
4933 if not user
.get("change_password"):
4934 ctx
.obj
.user
.update(username
, user
)
4936 ctx
.obj
.user
.update(username
, user
, pwd_change
=True)
4937 # except ClientException as e:
4942 @cli_osm.command(name
="user-delete", short_help
="deletes a user")
4943 @click.argument("name")
4944 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4946 def user_delete(ctx
, name
):
4950 NAME: name or ID of the user to be deleted
4954 check_client_version(ctx
.obj
, ctx
.command
.name
)
4955 ctx
.obj
.user
.delete(name
)
4956 # except ClientException as e:
4961 @cli_osm.command(name
="user-list", short_help
="list all users")
4966 help="restricts the list to the users matching the filter",
4969 def user_list(ctx
, filter):
4970 """list all users"""
4972 check_client_version(ctx
.obj
, ctx
.command
.name
)
4974 filter = "&".join(filter)
4975 resp
= ctx
.obj
.user
.list(filter)
4976 # except ClientException as e:
4979 table
= PrettyTable(["name", "id"])
4981 table
.add_row([user
["username"], user
["_id"]])
4986 @cli_osm.command(name
="user-show", short_help
="shows the details of a user")
4987 @click.argument("name")
4989 def user_show(ctx
, name
):
4990 """shows the details of a user
4992 NAME: name or ID of the user
4996 check_client_version(ctx
.obj
, ctx
.command
.name
)
4997 resp
= ctx
.obj
.user
.get(name
)
4998 if "password" in resp
:
4999 resp
["password"] = "********"
5000 # except ClientException as e:
5004 table
= PrettyTable(["key", "attribute"])
5005 for k
, v
in resp
.items():
5006 table
.add_row([k
, json
.dumps(v
, indent
=2)])
5011 ####################
5012 # Fault Management operations
5013 ####################
5016 @cli_osm.command(name
="ns-alarm-create")
5017 @click.argument("name")
5018 @click.option("--ns", prompt
=True, help="NS instance id or name")
5020 "--vnf", prompt
=True, help="VNF name (VNF member index as declared in the NSD)"
5022 @click.option("--vdu", prompt
=True, help="VDU name (VDU name as declared in the VNFD)")
5023 @click.option("--metric", prompt
=True, help="Name of the metric (e.g. cpu_utilization)")
5027 help="severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)",
5030 "--threshold_value",
5032 help="threshold value that, when crossed, an alarm is triggered",
5035 "--threshold_operator",
5037 help="threshold operator describing the comparison (GE, LE, GT, LT, EQ)",
5042 help="statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)",
5045 def ns_alarm_create(
5057 """creates a new alarm for a NS instance"""
5058 # TODO: Check how to validate threshold_value.
5059 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
5062 ns_instance
= ctx
.obj
.ns
.get(ns
)
5064 alarm
["alarm_name"] = name
5065 alarm
["ns_id"] = ns_instance
["_id"]
5066 alarm
["correlation_id"] = ns_instance
["_id"]
5067 alarm
["vnf_member_index"] = vnf
5068 alarm
["vdu_name"] = vdu
5069 alarm
["metric_name"] = metric
5070 alarm
["severity"] = severity
5071 alarm
["threshold_value"] = int(threshold_value
)
5072 alarm
["operation"] = threshold_operator
5073 alarm
["statistic"] = statistic
5074 check_client_version(ctx
.obj
, ctx
.command
.name
)
5075 ctx
.obj
.ns
.create_alarm(alarm
)
5076 # except ClientException as e:
5081 # @cli_osm.command(name='ns-alarm-delete')
5082 # @click.argument('name')
5083 # @click.pass_context
5084 # def ns_alarm_delete(ctx, name):
5085 # """deletes an alarm
5087 # NAME: name of the alarm to be deleted
5090 # check_client_version(ctx.obj, ctx.command.name)
5091 # ctx.obj.ns.delete_alarm(name)
5092 # except ClientException as e:
5097 ####################
5098 # Performance Management operations
5099 ####################
5103 name
="ns-metric-export",
5104 short_help
="exports a metric to the internal OSM bus, which can be read by other apps",
5106 @click.option("--ns", prompt
=True, help="NS instance id or name")
5108 "--vnf", prompt
=True, help="VNF name (VNF member index as declared in the NSD)"
5110 @click.option("--vdu", prompt
=True, help="VDU name (VDU name as declared in the VNFD)")
5111 @click.option("--metric", prompt
=True, help="name of the metric (e.g. cpu_utilization)")
5112 # @click.option('--period', default='1w',
5113 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
5115 "--interval", help="periodic interval (seconds) to export metrics continuously"
5118 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
5119 """exports a metric to the internal OSM bus, which can be read by other apps"""
5120 # TODO: Check how to validate interval.
5121 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
5124 ns_instance
= ctx
.obj
.ns
.get(ns
)
5126 metric_data
["ns_id"] = ns_instance
["_id"]
5127 metric_data
["correlation_id"] = ns_instance
["_id"]
5128 metric_data
["vnf_member_index"] = vnf
5129 metric_data
["vdu_name"] = vdu
5130 metric_data
["metric_name"] = metric
5131 metric_data
["collection_unit"] = "WEEK"
5132 metric_data
["collection_period"] = 1
5133 check_client_version(ctx
.obj
, ctx
.command
.name
)
5135 print("{}".format(ctx
.obj
.ns
.export_metric(metric_data
)))
5139 print("{} {}".format(ctx
.obj
.ns
.export_metric(metric_data
), i
))
5140 time
.sleep(int(interval
))
5142 # except ClientException as e:
5148 # Subscription operations
5153 name
="subscription-create",
5154 short_help
="creates a new subscription to a specific event",
5158 # type=click.Choice(['ns', 'nspkg', 'vnfpkg'], case_sensitive=False))
5159 type=click
.Choice(["ns"], case_sensitive
=False),
5160 help="event type to be subscribed (for the moment, only ns is supported)",
5162 @click.option("--event", default
=None, help="specific yaml configuration for the event")
5164 "--event_file", default
=None, help="specific yaml configuration file for the event"
5167 def subscription_create(ctx
, event_type
, event
, event_file
):
5168 """creates a new subscription to a specific event"""
5170 check_client_version(ctx
.obj
, ctx
.command
.name
)
5173 raise ClientException(
5174 '"--event" option is incompatible with "--event_file" option'
5176 with
open(event_file
, "r") as cf
:
5178 ctx
.obj
.subscription
.create(event_type
, event
)
5181 @cli_osm.command(name
="subscription-delete", short_help
="deletes a subscription")
5184 # type=click.Choice(['ns', 'nspkg', 'vnfpkg'], case_sensitive=False))
5185 type=click
.Choice(["ns"], case_sensitive
=False),
5186 help="event type to be subscribed (for the moment, only ns is supported)",
5188 @click.argument("subscription_id")
5190 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
5193 def subscription_delete(ctx
, event_type
, subscription_id
, force
):
5194 """deletes a subscription
5196 SUBSCRIPTION_ID: ID of the subscription to be deleted
5199 check_client_version(ctx
.obj
, ctx
.command
.name
)
5200 ctx
.obj
.subscription
.delete(event_type
, subscription_id
, force
)
5203 @cli_osm.command(name
="subscription-list", short_help
="list all subscriptions")
5206 # type=click.Choice(['ns', 'nspkg', 'vnfpkg'], case_sensitive=False))
5207 type=click
.Choice(["ns"], case_sensitive
=False),
5208 help="event type to be subscribed (for the moment, only ns is supported)",
5214 help="restricts the list to the subscriptions matching the filter",
5217 def subscription_list(ctx
, event_type
, filter):
5218 """list all subscriptions"""
5220 check_client_version(ctx
.obj
, ctx
.command
.name
)
5222 filter = "&".join(filter)
5223 resp
= ctx
.obj
.subscription
.list(event_type
, filter)
5224 table
= PrettyTable(["id", "filter", "CallbackUri"])
5229 wrap_text(text
=json
.dumps(sub
["filter"], indent
=2), width
=70),
5238 name
="subscription-show", short_help
="shows the details of a subscription"
5240 @click.argument("subscription_id")
5243 # type=click.Choice(['ns', 'nspkg', 'vnfpkg'], case_sensitive=False))
5244 type=click
.Choice(["ns"], case_sensitive
=False),
5245 help="event type to be subscribed (for the moment, only ns is supported)",
5250 help="restricts the information to the fields in the filter",
5253 def subscription_show(ctx
, event_type
, subscription_id
, filter):
5254 """shows the details of a subscription
5256 SUBSCRIPTION_ID: ID of the subscription
5260 resp
= ctx
.obj
.subscription
.get(subscription_id
)
5261 table
= PrettyTable(["key", "attribute"])
5262 for k
, v
in list(resp
.items()):
5263 if not filter or k
in filter:
5264 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
5269 ####################
5271 ####################
5274 @cli_osm.command(name
="version", short_help
="shows client and server versions")
5276 def get_version(ctx
):
5277 """shows client and server versions"""
5279 check_client_version(ctx
.obj
, "version")
5280 print("Server version: {}".format(ctx
.obj
.get_version()))
5282 "Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
)
5284 # except ClientException as e:
5290 name
="upload-package", short_help
="uploads a VNF package or NS package"
5292 @click.argument("filename")
5294 "--skip-charm-build",
5297 help="the charm will not be compiled, it is assumed to already exist",
5300 def upload_package(ctx
, filename
, skip_charm_build
):
5301 """uploads a vnf package or ns package
5303 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
5307 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
5308 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
5309 if fullclassname
!= "osmclient.sol005.client.Client":
5310 ctx
.obj
.package
.wait_for_upload(filename
)
5311 # except ClientException as e:
5316 # @cli_osm.command(name='ns-scaling-show')
5317 # @click.argument('ns_name')
5318 # @click.pass_context
5319 # def show_ns_scaling(ctx, ns_name):
5320 # """shows the status of a NS scaling operation
5322 # NS_NAME: name of the NS instance being scaled
5325 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5326 # resp = ctx.obj.ns.list()
5327 # except ClientException as e:
5331 # table = PrettyTable(
5334 # 'operational status',
5339 # if ns_name == ns['name']:
5340 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
5341 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
5342 # for record in scaling_records:
5343 # if 'instance' in record:
5344 # instances = record['instance']
5345 # for inst in instances:
5347 # [record['scaling-group-name-ref'],
5348 # inst['instance-id'],
5349 # inst['op-status'],
5350 # time.strftime('%Y-%m-%d %H:%M:%S',
5352 # inst['create-time'])),
5358 # @cli_osm.command(name='ns-scale')
5359 # @click.argument('ns_name')
5360 # @click.option('--ns_scale_group', prompt=True)
5361 # @click.option('--index', prompt=True)
5362 # @click.option('--wait',
5366 # help='do not return the control immediately, but keep it \
5367 # until the operation is completed, or timeout')
5368 # @click.pass_context
5369 # def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
5372 # NS_NAME: name of the NS instance to be scaled
5375 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5376 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
5377 # except ClientException as e:
5382 # @cli_osm.command(name='config-agent-list')
5383 # @click.pass_context
5384 # def config_agent_list(ctx):
5385 # """list config agents"""
5387 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5388 # except ClientException as e:
5391 # table = PrettyTable(['name', 'account-type', 'details'])
5392 # for account in ctx.obj.vca.list():
5395 # account['account-type'],
5401 # @cli_osm.command(name='config-agent-delete')
5402 # @click.argument('name')
5403 # @click.pass_context
5404 # def config_agent_delete(ctx, name):
5405 # """deletes a config agent
5407 # NAME: name of the config agent to be deleted
5410 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5411 # ctx.obj.vca.delete(name)
5412 # except ClientException as e:
5417 # @cli_osm.command(name='config-agent-add')
5418 # @click.option('--name',
5420 # @click.option('--account_type',
5422 # @click.option('--server',
5424 # @click.option('--user',
5426 # @click.option('--secret',
5429 # confirmation_prompt=True)
5430 # @click.pass_context
5431 # def config_agent_add(ctx, name, account_type, server, user, secret):
5432 # """adds a config agent"""
5434 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5435 # ctx.obj.vca.create(name, account_type, server, user, secret)
5436 # except ClientException as e:
5441 # @cli_osm.command(name='ro-dump')
5442 # @click.pass_context
5444 # """shows RO agent information"""
5445 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5446 # resp = ctx.obj.vim.get_resource_orchestrator()
5447 # table = PrettyTable(['key', 'attribute'])
5448 # for k, v in list(resp.items()):
5449 # table.add_row([k, json.dumps(v, indent=2)])
5454 # @cli_osm.command(name='vcs-list')
5455 # @click.pass_context
5456 # def vcs_list(ctx):
5457 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5458 # resp = ctx.obj.utils.get_vcs_info()
5459 # table = PrettyTable(['component name', 'state'])
5460 # for component in resp:
5461 # table.add_row([component['component_name'], component['state']])
5467 name
="ns-action", short_help
="executes an action/primitive over a NS instance"
5469 @click.argument("ns_name")
5473 help="member-vnf-index if the target is a vnf instead of a ns)",
5475 @click.option("--kdu_name", default
=None, help="kdu-name if the target is a kdu)")
5476 @click.option("--vdu_id", default
=None, help="vdu-id if the target is a vdu")
5478 "--vdu_count", default
=None, type=int, help="number of vdu instance of this vdu_id"
5480 @click.option("--action_name", prompt
=True, help="action name")
5481 @click.option("--params", default
=None, help="action params in YAML/JSON inline string")
5482 @click.option("--params_file", default
=None, help="YAML/JSON file with action params")
5484 "--timeout", required
=False, default
=None, type=int, help="timeout in seconds"
5491 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
5507 """executes an action/primitive over a NS instance
5509 NS_NAME: name or ID of the NS instance
5513 check_client_version(ctx
.obj
, ctx
.command
.name
)
5516 op_data
["member_vnf_index"] = vnf_name
5518 op_data
["kdu_name"] = kdu_name
5520 op_data
["vdu_id"] = vdu_id
5521 if vdu_count
is not None:
5522 op_data
["vdu_count_index"] = vdu_count
5524 op_data
["timeout_ns_action"] = timeout
5525 op_data
["primitive"] = action_name
5527 with
open(params_file
, "r") as pf
:
5530 op_data
["primitive_params"] = yaml
.safe_load(params
)
5532 op_data
["primitive_params"] = {}
5533 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
="action", op_data
=op_data
, wait
=wait
))
5535 # except ClientException as e:
5541 name
="vnf-scale", short_help
="executes a VNF scale (adding/removing VDUs)"
5543 @click.argument("ns_name")
5544 @click.argument("vnf_name")
5546 "--scaling-group", prompt
=True, help="scaling-group-descriptor name to use"
5549 "--scale-in", default
=False, is_flag
=True, help="performs a scale in operation"
5555 help="performs a scale out operation (by default)",
5558 "--timeout", required
=False, default
=None, type=int, help="timeout in seconds"
5565 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
5569 ctx
, ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, timeout
, wait
5572 Executes a VNF scale (adding/removing VDUs)
5575 NS_NAME: name or ID of the NS instance.
5576 VNF_NAME: member-vnf-index in the NS to be scaled.
5580 check_client_version(ctx
.obj
, ctx
.command
.name
)
5581 if not scale_in
and not scale_out
:
5583 ctx
.obj
.ns
.scale_vnf(
5584 ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
5586 # except ClientException as e:
5592 name
="ns-update", short_help
="executes an update of a Network Service."
5594 @click.argument("ns_name")
5596 "--updatetype", required
=True, type=str, help="available types: CHANGE_VNFPKG"
5602 help="extra information for update operation as YAML/JSON inline string as --config"
5603 " '{changeVnfPackageData:[{vnfInstanceId: xxx, vnfdId: yyy}]}'",
5606 "--timeout", required
=False, default
=None, type=int, help="timeout in seconds"
5613 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
5616 def update(ctx
, ns_name
, updatetype
, config
, timeout
, wait
):
5617 """Executes an update of a Network Service.
5619 The update will check new revisions of the Network Functions that are part of the
5620 Network Service, and it will update them if needed.
5621 Sample update command: osm ns-update ns_instance_id --updatetype CHANGE_VNFPKG
5622 --config '{changeVnfPackageData: [{vnfInstanceId: id_x,vnfdId: id_y}]}' --timeout 300 --wait
5624 NS_NAME: Network service instance name or ID.
5629 "updateType": updatetype
,
5632 op_data
["config"] = yaml
.safe_load(config
)
5634 check_client_version(ctx
.obj
, ctx
.command
.name
)
5635 ctx
.obj
.ns
.update(ns_name
, op_data
, wait
=wait
)
5638 @cli_osm.command(name
="alarm-show", short_help
="show alarm details")
5639 @click.argument("uuid")
5641 def alarm_show(ctx
, uuid
):
5642 """Show alarm's detail information"""
5644 check_client_version(ctx
.obj
, ctx
.command
.name
)
5645 resp
= ctx
.obj
.ns
.get_alarm(uuid
=uuid
)
5659 table
= PrettyTable(["key", "attribute"])
5661 # Arrange and return the response data
5662 alarm
= resp
.replace("ObjectId", "")
5663 for key
in alarm_filter
:
5665 value
= alarm
.get(key
)
5668 value
= alarm
.get(key
)
5670 elif key
== "ns-id":
5671 value
= alarm
["tags"].get("ns_id")
5672 elif key
== "vdu_name":
5673 value
= alarm
["tags"].get("vdu_name")
5674 elif key
== "status":
5675 value
= alarm
["alarm_status"]
5678 table
.add_row([key
, wrap_text(text
=json
.dumps(value
, indent
=2), width
=100)])
5686 @cli_osm.command(name
="alarm-list", short_help
="list all alarms")
5688 "--ns_id", default
=None, required
=False, help="List out alarm for given ns id"
5691 def alarm_list(ctx
, ns_id
):
5692 """list all alarm"""
5694 check_client_version(ctx
.obj
, ctx
.command
.name
)
5695 project_name
= os
.getenv("OSM_PROJECT", "admin")
5696 resp
= ctx
.obj
.ns
.get_alarm(project_name
=project_name
, ns_id
=ns_id
)
5698 table
= PrettyTable(
5699 ["alarm-id", "metric", "threshold", "operation", "action", "status"]
5702 # return the response data in a table
5703 resp
= resp
.replace("ObjectId", "")
5707 wrap_text(text
=str(alarm
["uuid"]), width
=38),
5711 wrap_text(text
=alarm
["action"], width
=25),
5712 alarm
["alarm_status"],
5720 @cli_osm.command(name
="alarm-update", short_help
="Update a alarm")
5721 @click.argument("uuid")
5722 @click.option("--threshold", default
=None, help="Alarm threshold")
5723 @click.option("--is_enable", default
=None, type=bool, help="enable or disable alarm")
5725 def alarm_update(ctx
, uuid
, threshold
, is_enable
):
5730 if not threshold
and is_enable
is None:
5731 raise ClientException(
5732 "Please provide option to update i.e threshold or is_enable"
5734 ctx
.obj
.ns
.update_alarm(uuid
, threshold
, is_enable
)
5737 ##############################
5738 # Role Management Operations #
5739 ##############################
5742 @cli_osm.command(name
="role-create", short_help
="creates a new role")
5743 @click.argument("name")
5744 @click.option("--permissions", default
=None, help="role permissions using a dictionary")
5746 def role_create(ctx
, name
, permissions
):
5751 NAME: Name or ID of the role.
5752 DEFINITION: Definition of grant/denial of access to resources.
5756 check_client_version(ctx
.obj
, ctx
.command
.name
)
5757 ctx
.obj
.role
.create(name
, permissions
)
5758 # except ClientException as e:
5763 @cli_osm.command(name
="role-update", short_help
="updates a role")
5764 @click.argument("name")
5765 @click.option("--set-name", default
=None, help="change name of rle")
5766 # @click.option('--permissions',
5768 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
5772 help="yaml format dictionary with permission: True/False to access grant/denial",
5774 @click.option("--remove", default
=None, help="yaml format list to remove a permission")
5776 def role_update(ctx
, name
, set_name
, add
, remove
):
5781 NAME: Name or ID of the role.
5782 DEFINITION: Definition overwrites the old definition.
5783 ADD: Grant/denial of access to resource to add.
5784 REMOVE: Grant/denial of access to resource to remove.
5788 check_client_version(ctx
.obj
, ctx
.command
.name
)
5789 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
5790 # except ClientException as e:
5795 @cli_osm.command(name
="role-delete", short_help
="deletes a role")
5796 @click.argument("name")
5797 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
5799 def role_delete(ctx
, name
):
5804 NAME: Name or ID of the role.
5808 check_client_version(ctx
.obj
, ctx
.command
.name
)
5809 ctx
.obj
.role
.delete(name
)
5810 # except ClientException as e:
5815 @cli_osm.command(name
="role-list", short_help
="list all roles")
5820 help="restricts the list to the projects matching the filter",
5823 def role_list(ctx
, filter):
5829 check_client_version(ctx
.obj
, ctx
.command
.name
)
5831 filter = "&".join(filter)
5832 resp
= ctx
.obj
.role
.list(filter)
5833 # except ClientException as e:
5836 table
= PrettyTable(["name", "id"])
5838 table
.add_row([role
["name"], role
["_id"]])
5843 @cli_osm.command(name
="role-show", short_help
="show specific role")
5844 @click.argument("name")
5846 def role_show(ctx
, name
):
5848 Shows the details of a role.
5851 NAME: Name or ID of the role.
5855 check_client_version(ctx
.obj
, ctx
.command
.name
)
5856 resp
= ctx
.obj
.role
.get(name
)
5857 # except ClientException as e:
5861 table
= PrettyTable(["key", "attribute"])
5862 for k
, v
in resp
.items():
5863 table
.add_row([k
, json
.dumps(v
, indent
=2)])
5868 @cli_osm.command(name
="package-create", short_help
="Create empty NS package structure")
5869 @click.argument("package-type")
5870 @click.argument("package-name")
5874 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'),
5878 default
="image-name",
5879 help='(VNF) Set the name of the vdu image. Default "image-name"',
5882 "--vdus", default
=1, help="(VNF) Set the number of vdus in a VNF. Default 1"
5885 "--vcpu", default
=1, help="(VNF) Set the number of virtual CPUs in a vdu. Default 1"
5890 help="(VNF) Set the memory size (MB) of the vdu. Default 1024",
5893 "--storage", default
=10, help="(VNF) Set the disk size (GB) of the vdu. Default 10"
5898 help="(VNF) Set the number of additional interfaces apart from the management interface. Default 0",
5901 "--vendor", default
="OSM", help='(NS/VNF) Set the descriptor vendor. Default "OSM"'
5907 help="(NS/VNF/NST) Flag for overriding the package if exists.",
5913 help="(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options",
5916 "--netslice-subnets", default
=1, help="(NST) Number of netslice subnets. Default 1"
5919 "--netslice-vlds", default
=1, help="(NST) Number of netslice vlds. Default 1"
5925 help="Flag to create a descriptor using the previous OSM format (pre SOL006, OSM<9)",
5947 Creates an OSM NS, VNF, NST package
5950 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
5951 PACKAGE_NAME: Name of the package to create the folder with the content.
5956 check_client_version(ctx
.obj
, ctx
.command
.name
)
5958 "Creating the {} structure: {}/{}".format(
5959 package_type
.upper(), base_directory
, package_name
5962 resp
= ctx
.obj
.package_tool
.create(
5972 interfaces
=interfaces
,
5975 netslice_subnets
=netslice_subnets
,
5976 netslice_vlds
=netslice_vlds
,
5980 # except ClientException as inst:
5981 # print("ERROR: {}".format(inst))
5986 name
="package-validate", short_help
="Validate descriptors given a base directory"
5988 @click.argument("base-directory", default
=".", required
=False)
5990 "--recursive/--no-recursive",
5992 help="The activated recursive option will validate the yaml files"
5993 " within the indicated directory and in its subdirectories",
5999 help="Validates also the descriptors using the previous OSM format (pre SOL006)",
6002 def package_validate(ctx
, base_directory
, recursive
, old
):
6004 Validate descriptors given a base directory.
6007 BASE_DIRECTORY: Base folder for NS, VNF or NST package.
6011 check_client_version(ctx
.obj
, ctx
.command
.name
)
6012 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
, old
)
6013 table
= PrettyTable()
6014 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
6015 # Print the dictionary generated by the validation function
6016 for result
in results
:
6018 [result
["type"], result
["path"], result
["valid"], result
["error"]]
6020 table
.sortby
= "VALID"
6021 table
.align
["PATH"] = "l"
6022 table
.align
["TYPE"] = "l"
6023 table
.align
["ERROR"] = "l"
6025 # except ClientException as inst:
6026 # print("ERROR: {}".format(inst))
6031 name
="package-translate", short_help
="Translate descriptors given a base directory"
6033 @click.argument("base-directory", default
=".", required
=False)
6035 "--recursive/--no-recursive",
6037 help="The activated recursive option will translate the yaml files"
6038 " within the indicated directory and in its subdirectories",
6044 help="Do not translate yet, only make a dry-run to test translation",
6047 def package_translate(ctx
, base_directory
, recursive
, dryrun
):
6049 Translate descriptors given a base directory.
6052 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
6055 check_client_version(ctx
.obj
, ctx
.command
.name
)
6056 results
= ctx
.obj
.package_tool
.translate(base_directory
, recursive
, dryrun
)
6057 table
= PrettyTable()
6058 table
.field_names
= [
6066 # Print the dictionary generated by the validation function
6067 for result
in results
:
6070 result
["current type"],
6074 result
["translated"],
6078 table
.sortby
= "TRANSLATED"
6079 table
.align
["PATH"] = "l"
6080 table
.align
["TYPE"] = "l"
6081 table
.align
["ERROR"] = "l"
6083 # except ClientException as inst:
6084 # print("ERROR: {}".format(inst))
6088 @cli_osm.command(name
="package-build", short_help
="Build the tar.gz of the package")
6089 @click.argument("package-folder")
6091 "--skip-validation", default
=False, is_flag
=True, help="skip package validation"
6094 "--skip-charm-build",
6097 help="the charm will not be compiled, it is assumed to already exist",
6100 def package_build(ctx
, package_folder
, skip_validation
, skip_charm_build
):
6102 Build the package NS, VNF given the package_folder.
6105 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
6109 check_client_version(ctx
.obj
, ctx
.command
.name
)
6110 results
= ctx
.obj
.package_tool
.build(
6112 skip_validation
=skip_validation
,
6113 skip_charm_build
=skip_charm_build
,
6116 # except ClientException as inst:
6117 # print("ERROR: {}".format(inst))
6122 name
="descriptor-translate",
6123 short_help
="Translate input descriptor file from Rel EIGHT OSM descriptors to SOL006 and prints in standard output",
6125 @click.argument("descriptor-file", required
=True)
6127 def descriptor_translate(ctx
, descriptor_file
):
6129 Translate input descriptor.
6132 DESCRIPTOR_FILE: Descriptor file for NS, VNF or Network Slice.
6135 check_client_version(ctx
.obj
, ctx
.command
.name
)
6136 result
= ctx
.obj
.package_tool
.descriptor_translate(descriptor_file
)
6144 except pycurl
.error
as exc
:
6147 'Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified'
6149 except ClientException
as exc
:
6150 print("ERROR: {}".format(exc
))
6151 except (FileNotFoundError
, PermissionError
) as exc
:
6152 print("Cannot open file: {}".format(exc
))
6153 except yaml
.YAMLError
as exc
:
6154 print("Invalid YAML format: {}".format(exc
))
6156 # TODO capture other controlled exceptions here
6157 # TODO remove the ClientException captures from all places, unless they do something different
6160 if __name__
== "__main__":