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
36 def wrap_text(text
, width
):
37 wrapper
= textwrap
.TextWrapper(width
=width
)
38 lines
= text
.splitlines()
39 return "\n".join(map(wrapper
.fill
, lines
))
42 def trunc_text(text
, length
):
43 if len(text
) > length
:
44 return text
[: (length
- 3)] + "..."
49 def check_client_version(obj
, what
, version
="sol005"):
51 Checks the version of the client object and raises error if it not the expected.
53 :param obj: the client object
54 :what: the function or command under evaluation (used when an error is raised)
56 :raises ClientError: if the specified version does not match the client version
59 fullclassname
= obj
.__module
__ + "." + obj
.__class
__.__name
__
60 message
= 'The following commands or options are only supported with the option "--sol005": {}'.format(
64 message
= 'The following commands or options are not supported when using option "--sol005": {}'.format(
67 if fullclassname
!= "osmclient.{}.client.Client".format(version
):
68 raise ClientException(message
)
72 def get_project(project_list
, item
):
73 # project_list = ctx.obj.project.list()
74 item_project_list
= item
.get("_admin", {}).get("projects_read")
78 for p1
in item_project_list
:
80 for p2
in project_list
:
81 if p2
["_id"] == project_id
:
82 project_name
= p2
["name"]
83 return project_id
, project_name
84 return project_id
, project_name
87 def get_vim_name(vim_list
, vim_id
):
90 if v
["uuid"] == vim_id
:
97 context_settings
=dict(help_option_names
=["-h", "--help"], max_content_width
=160)
102 envvar
="OSM_HOSTNAME",
103 help="hostname of server. " + "Also can set OSM_HOSTNAME in environment",
105 # @click.option('--sol005/--no-sol005',
107 # envvar='OSM_SOL005',
108 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
109 # 'Also can set OSM_SOL005 in environment')
114 help="user (defaults to admin). " + "Also can set OSM_USER in environment",
119 envvar
="OSM_PASSWORD",
120 help="password (defaults to admin). " + "Also can set OSM_PASSWORD in environment",
125 envvar
="OSM_PROJECT",
126 help="project (defaults to admin). " + "Also can set OSM_PROJECT in environment",
132 help="increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)",
134 @click.option("--all-projects", default
=None, is_flag
=True, help="include all projects")
136 "--public/--no-public",
138 help="flag for public items (packages, instances, VIM accounts, etc.)",
141 "--project-domain-name",
142 "project_domain_name",
144 envvar
="OSM_PROJECT_DOMAIN_NAME",
145 help="project domain name for keystone authentication (default to None). "
146 + "Also can set OSM_PROJECT_DOMAIN_NAME in environment",
149 "--user-domain-name",
152 envvar
="OSM_USER_DOMAIN_NAME",
153 help="user domain name for keystone authentication (default to None). "
154 + "Also can set OSM_USER_DOMAIN_NAME in environment",
156 # @click.option('--so-port',
158 # envvar='OSM_SO_PORT',
159 # help='hostname of server. ' +
160 # 'Also can set OSM_SO_PORT in environment')
161 # @click.option('--so-project',
163 # envvar='OSM_SO_PROJECT',
164 # help='Project Name in SO. ' +
165 # 'Also can set OSM_SO_PROJECT in environment')
166 # @click.option('--ro-hostname',
168 # envvar='OSM_RO_HOSTNAME',
169 # help='hostname of RO server. ' +
170 # 'Also can set OSM_RO_HOSTNAME in environment')
171 # @click.option('--ro-port',
173 # envvar='OSM_RO_PORT',
174 # help='hostname of RO server. ' +
175 # 'Also can set OSM_RO_PORT in environment')
177 def cli_osm(ctx
, **kwargs
):
179 hostname
= kwargs
.pop("hostname", None)
183 "either hostname option or OSM_HOSTNAME "
184 + "environment variable needs to be specified"
189 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
190 # if so_port is not None:
191 # kwargs['so_port']=so_port
192 # if so_project is not None:
193 # kwargs['so_project']=so_project
194 # if ro_hostname is not None:
195 # kwargs['ro_host']=ro_hostname
196 # if ro_port is not None:
197 # kwargs['ro_port']=ro_port
198 sol005
= os
.getenv("OSM_SOL005", True)
199 # if user is not None:
200 # kwargs['user']=user
201 # if password is not None:
202 # kwargs['password']=password
203 # if project is not None:
204 # kwargs['project']=project
206 # kwargs['all_projects']=all_projects
207 # if public is not None:
208 # kwargs['public']=public
209 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
210 logger
= logging
.getLogger("osmclient")
218 @cli_osm.command(name
="ns-list", short_help
="list all NS instances")
223 help="restricts the list to the NS instances matching the filter.",
228 help="get more details of the NS (project, vim, deployment status, configuration status.",
231 def ns_list(ctx
, filter, long):
232 """list all NS instances
236 --filter filterExpr Restricts the list to the NS instances matching the filter
239 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
240 concatenated using the "&" character:
243 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
244 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
245 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
247 value := scalar value
251 * zero or more occurrences
252 ? zero or one occurrence
253 [] grouping of expressions to be used with ? and *
254 "" quotation marks for marking string constants
258 "AttrName" is the name of one attribute in the data type that defines the representation
259 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
260 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
261 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
262 entries, it means that the operator "op" is applied to the attribute addressed by the last
263 <attrName> entry included in the concatenation. All simple filter expressions are combined
264 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
265 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
266 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
267 prefix". If an attribute referenced in an expression is an array, an object that contains a
268 corresponding array shall be considered to match the expression if any of the elements in the
269 array matches all expressions that have the same attribute prefix.
273 --filter admin-status=ENABLED
274 --filter nsd-ref=<NSD_NAME>
275 --filter nsd.vendor=<VENDOR>
276 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
277 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
280 def summarize_deployment_status(status_dict
):
287 net_list
= status_dict
.get("nets", [])
290 if net
["status"] not in status_nets
:
291 status_nets
[net
["status"]] = 1
293 status_nets
[net
["status"]] += 1
295 for k
, v
in status_nets
.items():
296 message
+= "{}:{},".format(k
, v
)
297 message
+= "TOTAL:{}".format(n_nets
)
298 summary
+= "{}".format(message
)
303 vnf_list
= status_dict
["vnfs"]
305 member_vnf_index
= vnf
["member_vnf_index"]
306 if member_vnf_index
not in status_vnfs
:
307 status_vnfs
[member_vnf_index
] = {}
308 for vm
in vnf
["vms"]:
310 if vm
["status"] not in status_vms
:
311 status_vms
[vm
["status"]] = 1
313 status_vms
[vm
["status"]] += 1
314 if vm
["status"] not in status_vnfs
[member_vnf_index
]:
315 status_vnfs
[member_vnf_index
][vm
["status"]] = 1
317 status_vnfs
[member_vnf_index
][vm
["status"]] += 1
319 for k
, v
in status_vms
.items():
320 message
+= "{}:{},".format(k
, v
)
321 message
+= "TOTAL:{}".format(n_vms
)
322 summary
+= "\n{}".format(message
)
324 for k
, v
in status_vnfs
.items():
326 message
= "\n {} VMs: ".format(k
)
327 for k2
, v2
in v
.items():
328 message
+= "{}:{},".format(k2
, v2
)
330 message
+= "TOTAL:{}".format(total
)
334 def summarize_config_status(ee_list
):
342 if ee
["elementType"] not in status_ee
:
343 status_ee
[ee
["elementType"]] = {}
344 status_ee
[ee
["elementType"]][ee
["status"]] = 1
346 if ee
["status"] in status_ee
[ee
["elementType"]]:
347 status_ee
[ee
["elementType"]][ee
["status"]] += 1
349 status_ee
[ee
["elementType"]][ee
["status"]] = 1
350 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
351 if elementType
in status_ee
:
354 for k
, v
in status_ee
[elementType
].items():
355 message
+= "{}:{},".format(k
, v
)
357 message
+= "TOTAL:{}\n".format(total
)
358 summary
+= "{}: {}".format(elementType
, message
)
359 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
364 check_client_version(ctx
.obj
, "--filter")
365 filter = "&".join(filter)
366 resp
= ctx
.obj
.ns
.list(filter)
368 resp
= ctx
.obj
.ns
.list()
381 "configuration status",
384 project_list
= ctx
.obj
.project
.list()
386 vim_list
= ctx
.obj
.vim
.list()
401 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
402 if fullclassname
== "osmclient.sol005.client.Client":
404 logger
.debug("NS info: {}".format(nsr
))
405 nsr_name
= nsr
["name"]
407 date
= datetime
.fromtimestamp(nsr
["create-time"]).strftime(
410 ns_state
= nsr
.get("nsState", nsr
["_admin"]["nsState"])
412 deployment_status
= summarize_deployment_status(
413 nsr
.get("deploymentStatus")
415 config_status
= summarize_config_status(nsr
.get("configurationStatus"))
416 project_id
, project_name
= get_project(project_list
, nsr
)
417 # project = '{} ({})'.format(project_name, project_id)
418 project
= project_name
419 vim_id
= nsr
.get("datacenter")
420 vim_name
= get_vim_name(vim_list
, vim_id
)
422 # vim = '{} ({})'.format(vim_name, vim_id)
424 if "currentOperation" in nsr
:
425 current_operation
= "{} ({})".format(
426 nsr
["currentOperation"], nsr
["currentOperationID"]
429 current_operation
= "{} ({})".format(
430 nsr
["_admin"].get("current-operation", "-"),
431 nsr
["_admin"]["nslcmop"],
433 error_details
= "N/A"
436 or ns_state
== "DEGRADED"
437 or ("currentOperation" not in nsr
and nsr
.get("errorDescription"))
439 error_details
= "{}\nDetail: {}".format(
440 nsr
["errorDescription"], nsr
["errorDetail"]
443 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
["id"])
444 nsr
= nsopdata
["nsr:nsr"]
445 nsr_name
= nsr
["name-ref"]
446 nsr_id
= nsr
["ns-instance-config-ref"]
449 deployment_status
= (
450 nsr
["operational-status"]
451 if "operational-status" in nsr
454 ns_state
= deployment_status
455 config_status
= nsr
.get("config-status", "Not found")
456 current_operation
= "Unknown"
457 error_details
= nsr
.get("detailed-status", "Not found")
458 if config_status
== "config_not_needed":
459 config_status
= "configured (no charms)"
469 wrap_text(text
=error_details
, width
=40),
484 wrap_text(text
=error_details
, width
=40),
489 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
491 'For more details on the current operation, run "osm ns-op-show OPERATION_ID"'
495 def nsd_list(ctx
, filter, long):
498 check_client_version(ctx
.obj
, "--filter")
499 filter = "&".join(filter)
500 resp
= ctx
.obj
.nsd
.list(filter)
502 resp
= ctx
.obj
.nsd
.list()
503 # print(yaml.safe_dump(resp))
504 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
505 if fullclassname
== "osmclient.sol005.client.Client":
519 table
= PrettyTable(["nsd name", "id"])
521 name
= nsd
.get("id", "-")
523 onb_state
= nsd
["_admin"].get("onboardingState", "-")
524 op_state
= nsd
["_admin"].get("operationalState", "-")
525 usage_state
= nsd
["_admin"].get("usageState", "-")
526 date
= datetime
.fromtimestamp(nsd
["_admin"]["created"]).strftime(
529 last_update
= datetime
.fromtimestamp(
530 nsd
["_admin"]["modified"]
531 ).strftime("%Y-%m-%dT%H:%M:%S")
544 table
.add_row([name
, nsd
["_id"]])
546 table
= PrettyTable(["nsd name", "id"])
548 table
.add_row([nsd
["name"], nsd
["id"]])
553 @cli_osm.command(name
="nsd-list", short_help
="list all NS packages")
558 help="restricts the list to the NSD/NSpkg matching the filter",
560 @click.option("--long", is_flag
=True, help="get more details")
562 def nsd_list1(ctx
, filter, long):
563 """list all NSD/NS pkg in the system"""
565 nsd_list(ctx
, filter, long)
568 @cli_osm.command(name
="nspkg-list", short_help
="list all NS packages")
573 help="restricts the list to the NSD/NSpkg matching the filter",
575 @click.option("--long", is_flag
=True, help="get more details")
577 def nsd_list2(ctx
, filter, long):
578 """list all NS packages"""
580 nsd_list(ctx
, filter, long)
583 def pkg_repo_list(ctx
, pkgtype
, filter, repo
, long):
584 resp
= ctx
.obj
.osmrepo
.pkg_list(pkgtype
, filter, repo
)
587 ["nfpkg name", "vendor", "version", "latest", "description", "repository"]
590 table
= PrettyTable(["nfpkg name", "repository"])
592 name
= vnfd
.get("id", vnfd
.get("name", "-"))
593 repository
= vnfd
.get("repository")
595 vendor
= vnfd
.get("provider", vnfd
.get("vendor"))
596 version
= vnfd
.get("version")
597 description
= vnfd
.get("description")
598 latest
= vnfd
.get("latest")
599 table
.add_row([name
, vendor
, version
, latest
, description
, repository
])
601 table
.add_row([name
, repository
])
606 def vnfd_list(ctx
, nf_type
, filter, long):
609 check_client_version(ctx
.obj
, "--nf_type")
611 check_client_version(ctx
.obj
, "--filter")
613 filter = "&".join(filter)
616 nf_filter
= "_admin.type=vnfd"
617 elif nf_type
== "pnf":
618 nf_filter
= "_admin.type=pnfd"
619 elif nf_type
== "hnf":
620 nf_filter
= "_admin.type=hnfd"
622 raise ClientException(
623 'wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf'
626 filter = "{}&{}".format(nf_filter
, filter)
630 resp
= ctx
.obj
.vnfd
.list(filter)
632 resp
= ctx
.obj
.vnfd
.list()
633 # print(yaml.safe_dump(resp))
634 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
635 if fullclassname
== "osmclient.sol005.client.Client":
652 table
= PrettyTable(["nfpkg name", "id", "desc type"])
654 name
= vnfd
.get("id", vnfd
.get("name", "-"))
655 descriptor_type
= "sol006" if "product-name" in vnfd
else "rel8"
657 onb_state
= vnfd
["_admin"].get("onboardingState", "-")
658 op_state
= vnfd
["_admin"].get("operationalState", "-")
659 vendor
= vnfd
.get("provider", vnfd
.get("vendor"))
660 version
= vnfd
.get("version")
661 usage_state
= vnfd
["_admin"].get("usageState", "-")
662 date
= datetime
.fromtimestamp(vnfd
["_admin"]["created"]).strftime(
665 last_update
= datetime
.fromtimestamp(
666 vnfd
["_admin"]["modified"]
667 ).strftime("%Y-%m-%dT%H:%M:%S")
683 table
.add_row([name
, vnfd
["_id"], descriptor_type
])
685 table
= PrettyTable(["nfpkg name", "id"])
687 table
.add_row([vnfd
["name"], vnfd
["id"]])
692 @cli_osm.command(name
="vnfd-list", short_help
="list all xNF packages (VNF, HNF, PNF)")
693 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
698 help="restricts the list to the NF pkg matching the filter",
700 @click.option("--long", is_flag
=True, help="get more details")
702 def vnfd_list1(ctx
, nf_type
, filter, long):
703 """list all xNF packages (VNF, HNF, PNF)"""
705 vnfd_list(ctx
, nf_type
, filter, long)
708 @cli_osm.command(name
="vnfpkg-list", short_help
="list all xNF packages (VNF, HNF, PNF)")
709 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
714 help="restricts the list to the NFpkg matching the filter",
716 @click.option("--long", is_flag
=True, help="get more details")
718 def vnfd_list2(ctx
, nf_type
, filter, long):
719 """list all xNF packages (VNF, HNF, PNF)"""
721 vnfd_list(ctx
, nf_type
, filter, long)
724 @cli_osm.command(name
="nfpkg-list", short_help
="list all xNF packages (VNF, HNF, PNF)")
725 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
730 help="restricts the list to the NFpkg matching the filter",
732 @click.option("--long", is_flag
=True, help="get more details")
734 def nfpkg_list(ctx
, nf_type
, filter, long):
735 """list all xNF packages (VNF, HNF, PNF)"""
738 check_client_version(ctx
.obj
, ctx
.command
.name
)
739 vnfd_list(ctx
, nf_type
, filter, long)
740 # except ClientException as e:
746 name
="vnfpkg-repo-list", short_help
="list all xNF from OSM repositories"
752 help="restricts the list to the NFpkg matching the filter",
755 "--repo", default
=None, help="restricts the list to a particular OSM repository"
757 @click.option("--long", is_flag
=True, help="get more details")
759 def nfpkg_repo_list1(ctx
, filter, repo
, long):
760 """list xNF packages from OSM repositories"""
762 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
766 name
="nfpkg-repo-list", short_help
="list all xNF from OSM repositories"
772 help="restricts the list to the NFpkg matching the filter",
775 "--repo", default
=None, help="restricts the list to a particular OSM repository"
777 @click.option("--long", is_flag
=True, help="get more details")
779 def nfpkg_repo_list2(ctx
, filter, repo
, long):
780 """list xNF packages from OSM repositories"""
782 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
785 def vnf_list(ctx
, ns
, filter, long):
789 check_client_version(ctx
.obj
, "--ns")
791 filter = "&".join(filter)
792 check_client_version(ctx
.obj
, "--filter")
793 resp
= ctx
.obj
.vnf
.list(ns
, filter)
795 resp
= ctx
.obj
.vnf
.list()
796 # except ClientException as e:
799 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
800 if fullclassname
== "osmclient.sol005.client.Client":
822 table
= PrettyTable(field_names
)
824 name
= vnfr
["name"] if "name" in vnfr
else "-"
829 vnfr
["member-vnf-index-ref"],
831 vnfr
["vim-account-id"],
835 date
= datetime
.fromtimestamp(vnfr
["_admin"]["created"]).strftime(
838 last_update
= datetime
.fromtimestamp(
839 vnfr
["_admin"]["modified"]
840 ).strftime("%Y-%m-%dT%H:%M:%S")
841 new_row
.extend([date
, last_update
])
842 table
.add_row(new_row
)
844 table
= PrettyTable(["vnf name", "id", "operational status", "config status"])
846 if "mgmt-interface" not in vnfr
:
847 vnfr
["mgmt-interface"] = {}
848 vnfr
["mgmt-interface"]["ip-address"] = None
853 vnfr
["operational-status"],
854 vnfr
["config-status"],
861 @cli_osm.command(name
="vnf-list", short_help
="list all NF instances")
863 "--ns", default
=None, help="NS instance id or name to restrict the NF list"
869 help="restricts the list to the NF instances matching the filter.",
871 @click.option("--long", is_flag
=True, help="get more details")
873 def vnf_list1(ctx
, ns
, filter, long):
874 """list all NF instances"""
876 vnf_list(ctx
, ns
, filter, long)
879 @cli_osm.command(name
="nsd-repo-list", short_help
="list all NS from OSM repositories")
884 help="restricts the list to the NS matching the filter",
887 "--repo", default
=None, help="restricts the list to a particular OSM repository"
889 @click.option("--long", is_flag
=True, help="get more details")
891 def nspkg_repo_list(ctx
, filter, repo
, long):
892 """list xNF packages from OSM repositories"""
894 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
897 @cli_osm.command(name
="nspkg-repo-list", short_help
="list all NS from OSM repositories")
902 help="restricts the list to the NS matching the filter",
905 "--repo", default
=None, help="restricts the list to a particular OSM repository"
907 @click.option("--long", is_flag
=True, help="get more details")
909 def nspkg_repo_list2(ctx
, filter, repo
, long):
910 """list xNF packages from OSM repositories"""
912 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
915 @cli_osm.command(name
="nf-list", short_help
="list all NF instances")
917 "--ns", default
=None, help="NS instance id or name to restrict the NF list"
923 help="restricts the list to the NF instances matching the filter.",
925 @click.option("--long", is_flag
=True, help="get more details")
927 def nf_list(ctx
, ns
, filter, long):
928 """list all NF instances
932 --ns TEXT NS instance id or name to restrict the VNF list
933 --filter filterExpr Restricts the list to the VNF instances matching the filter
936 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
937 concatenated using the "&" character:
940 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
941 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
942 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
944 value := scalar value
948 * zero or more occurrences
949 ? zero or one occurrence
950 [] grouping of expressions to be used with ? and *
951 "" quotation marks for marking string constants
955 "AttrName" is the name of one attribute in the data type that defines the representation
956 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
957 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
958 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
959 entries, it means that the operator "op" is applied to the attribute addressed by the last
960 <attrName> entry included in the concatenation. All simple filter expressions are combined
961 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
962 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
963 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
964 prefix". If an attribute referenced in an expression is an array, an object that contains a
965 corresponding array shall be considered to match the expression if any of the elements in the
966 array matches all expressions that have the same attribute prefix.
970 --filter vim-account-id=<VIM_ACCOUNT_ID>
971 --filter vnfd-ref=<VNFD_NAME>
972 --filter vdur.ip-address=<IP_ADDRESS>
973 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
976 vnf_list(ctx
, ns
, filter, long)
980 name
="ns-op-list", short_help
="shows the history of operations over a NS instance"
982 @click.argument("name")
984 "--long", is_flag
=True, help="get more details of the NS operation (date, )."
987 def ns_op_list(ctx
, name
, long):
988 """shows the history of operations over a NS instance
990 NAME: name or ID of the NS instance
993 def formatParams(params
):
994 if params
["lcmOperationType"] == "instantiate":
995 params
.pop("nsDescription")
999 elif params
["lcmOperationType"] == "action":
1000 params
.pop("primitive")
1001 params
.pop("lcmOperationType")
1002 params
.pop("nsInstanceId")
1007 check_client_version(ctx
.obj
, ctx
.command
.name
)
1008 resp
= ctx
.obj
.ns
.list_op(name
)
1009 # except ClientException as e:
1014 table
= PrettyTable(
1027 table
= PrettyTable(
1028 ["id", "operation", "action_name", "status", "date", "detail"]
1031 # print(yaml.safe_dump(resp))
1034 if op
["lcmOperationType"] == "action":
1035 action_name
= op
["operationParams"]["primitive"]
1037 if op
["operationState"] == "PROCESSING":
1038 if op
["queuePosition"] is not None and op
["queuePosition"] > 0:
1039 detail
= "In queue. Current position: {}".format(op
["queuePosition"])
1040 elif op
["lcmOperationType"] in ("instantiate", "terminate"):
1042 detail
= op
["stage"]
1043 elif op
["operationState"] in ("FAILED", "FAILED_TEMP"):
1044 detail
= op
.get("errorMessage", "-")
1045 date
= datetime
.fromtimestamp(op
["startTime"]).strftime("%Y-%m-%dT%H:%M:%S")
1046 last_update
= datetime
.fromtimestamp(op
["statusEnteredTime"]).strftime(
1053 op
["lcmOperationType"],
1056 text
=json
.dumps(formatParams(op
["operationParams"]), indent
=2),
1059 op
["operationState"],
1062 wrap_text(text
=detail
, width
=50),
1069 op
["lcmOperationType"],
1071 op
["operationState"],
1073 wrap_text(text
=detail
or "", width
=50),
1080 def nsi_list(ctx
, filter):
1081 """list all Network Slice Instances"""
1084 check_client_version(ctx
.obj
, ctx
.command
.name
)
1086 filter = "&".join(filter)
1087 resp
= ctx
.obj
.nsi
.list(filter)
1088 # except ClientException as e:
1091 table
= PrettyTable(
1093 "netslice instance name",
1095 "operational status",
1101 nsi_name
= nsi
["name"]
1104 nsi
["operational-status"] if "operational-status" in nsi
else "Not found"
1106 configstatus
= nsi
["config-status"] if "config-status" in nsi
else "Not found"
1108 nsi
["detailed-status"] if "detailed-status" in nsi
else "Not found"
1110 if configstatus
== "config_not_needed":
1111 configstatus
= "configured (no charms)"
1112 table
.add_row([nsi_name
, nsi_id
, opstatus
, configstatus
, detailed_status
])
1117 @cli_osm.command(name
="nsi-list", short_help
="list all Network Slice Instances (NSI)")
1122 help="restricts the list to the Network Slice Instances matching the filter",
1125 def nsi_list1(ctx
, filter):
1126 """list all Network Slice Instances (NSI)"""
1128 nsi_list(ctx
, filter)
1132 name
="netslice-instance-list", short_help
="list all Network Slice Instances (NSI)"
1138 help="restricts the list to the Network Slice Instances matching the filter",
1141 def nsi_list2(ctx
, filter):
1142 """list all Network Slice Instances (NSI)"""
1144 nsi_list(ctx
, filter)
1147 def nst_list(ctx
, filter):
1150 check_client_version(ctx
.obj
, ctx
.command
.name
)
1152 filter = "&".join(filter)
1153 resp
= ctx
.obj
.nst
.list(filter)
1154 # except ClientException as e:
1157 # print(yaml.safe_dump(resp))
1158 table
= PrettyTable(["nst name", "id"])
1160 name
= nst
["name"] if "name" in nst
else "-"
1161 table
.add_row([name
, nst
["_id"]])
1166 @cli_osm.command(name
="nst-list", short_help
="list all Network Slice Templates (NST)")
1171 help="restricts the list to the NST matching the filter",
1174 def nst_list1(ctx
, filter):
1175 """list all Network Slice Templates (NST) in the system"""
1177 nst_list(ctx
, filter)
1181 name
="netslice-template-list", short_help
="list all Network Slice Templates (NST)"
1187 help="restricts the list to the NST matching the filter",
1190 def nst_list2(ctx
, filter):
1191 """list all Network Slice Templates (NST) in the system"""
1193 nst_list(ctx
, filter)
1196 def nsi_op_list(ctx
, name
):
1199 check_client_version(ctx
.obj
, ctx
.command
.name
)
1200 resp
= ctx
.obj
.nsi
.list_op(name
)
1201 # except ClientException as e:
1204 table
= PrettyTable(["id", "operation", "status"])
1206 table
.add_row([op
["id"], op
["lcmOperationType"], op
["operationState"]])
1213 short_help
="shows the history of operations over a Network Slice Instance (NSI)",
1215 @click.argument("name")
1217 def nsi_op_list1(ctx
, name
):
1218 """shows the history of operations over a Network Slice Instance (NSI)
1220 NAME: name or ID of the Network Slice Instance
1223 nsi_op_list(ctx
, name
)
1227 name
="netslice-instance-op-list",
1228 short_help
="shows the history of operations over a Network Slice Instance (NSI)",
1230 @click.argument("name")
1232 def nsi_op_list2(ctx
, name
):
1233 """shows the history of operations over a Network Slice Instance (NSI)
1235 NAME: name or ID of the Network Slice Instance
1238 nsi_op_list(ctx
, name
)
1241 @cli_osm.command(name
="pdu-list", short_help
="list all Physical Deployment Units (PDU)")
1246 help="restricts the list to the Physical Deployment Units matching the filter",
1249 def pdu_list(ctx
, filter):
1250 """list all Physical Deployment Units (PDU)"""
1253 check_client_version(ctx
.obj
, ctx
.command
.name
)
1255 filter = "&".join(filter)
1256 resp
= ctx
.obj
.pdu
.list(filter)
1257 # except ClientException as e:
1260 table
= PrettyTable(["pdu name", "id", "type", "mgmt ip address"])
1262 pdu_name
= pdu
["name"]
1264 pdu_type
= pdu
["type"]
1265 pdu_ipaddress
= "None"
1266 for iface
in pdu
["interfaces"]:
1268 pdu_ipaddress
= iface
["ip-address"]
1270 table
.add_row([pdu_name
, pdu_id
, pdu_type
, pdu_ipaddress
])
1275 ####################
1277 ####################
1280 def nsd_show(ctx
, name
, literal
):
1283 resp
= ctx
.obj
.nsd
.get(name
)
1284 # resp = ctx.obj.nsd.get_individual(name)
1285 # except ClientException as e:
1290 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1293 table
= PrettyTable(["field", "value"])
1294 for k
, v
in list(resp
.items()):
1295 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1300 @cli_osm.command(name
="nsd-show", short_help
="shows the details of a NS package")
1301 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1302 @click.argument("name")
1304 def nsd_show1(ctx
, name
, literal
):
1305 """shows the content of a NSD
1307 NAME: name or ID of the NSD/NSpkg
1310 nsd_show(ctx
, name
, literal
)
1313 @cli_osm.command(name
="nspkg-show", short_help
="shows the details of a NS package")
1314 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1315 @click.argument("name")
1317 def nsd_show2(ctx
, name
, literal
):
1318 """shows the content of a NSD
1320 NAME: name or ID of the NSD/NSpkg
1323 nsd_show(ctx
, name
, literal
)
1326 def vnfd_show(ctx
, name
, literal
):
1329 resp
= ctx
.obj
.vnfd
.get(name
)
1330 # resp = ctx.obj.vnfd.get_individual(name)
1331 # except ClientException as e:
1336 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1339 table
= PrettyTable(["field", "value"])
1340 for k
, v
in list(resp
.items()):
1341 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1346 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1349 filter = "&".join(filter)
1351 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1354 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1357 catalog
= pkgtype
+ "-catalog"
1358 full_catalog
= pkgtype
+ ":" + catalog
1359 if resp
.get(catalog
):
1360 resp
= resp
.pop(catalog
)[pkgtype
][0]
1361 elif resp
.get(full_catalog
):
1362 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1364 table
= PrettyTable(["field", "value"])
1365 for k
, v
in list(resp
.items()):
1366 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1371 @cli_osm.command(name
="vnfd-show", short_help
="shows the details of a NF package")
1372 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1373 @click.argument("name")
1375 def vnfd_show1(ctx
, name
, literal
):
1376 """shows the content of a VNFD
1378 NAME: name or ID of the VNFD/VNFpkg
1381 vnfd_show(ctx
, name
, literal
)
1384 @cli_osm.command(name
="vnfpkg-show", short_help
="shows the details of a NF package")
1385 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1386 @click.argument("name")
1388 def vnfd_show2(ctx
, name
, literal
):
1389 """shows the content of a VNFD
1391 NAME: name or ID of the VNFD/VNFpkg
1394 vnfd_show(ctx
, name
, literal
)
1398 name
="vnfpkg-repo-show",
1399 short_help
="shows the details of a NF package in an OSM repository",
1401 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1402 @click.option("--repo", required
=True, help="Repository name")
1403 @click.argument("name")
1404 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1405 @click.option("--version", default
="latest", help="package version")
1407 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1408 """shows the content of a VNFD in a repository
1410 NAME: name or ID of the VNFD/VNFpkg
1413 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1417 name
="nsd-repo-show",
1418 short_help
="shows the details of a NS package in an OSM repository",
1420 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1421 @click.option("--repo", required
=True, help="Repository name")
1422 @click.argument("name")
1423 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1424 @click.option("--version", default
="latest", help="package version")
1426 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1427 """shows the content of a VNFD in a repository
1429 NAME: name or ID of the VNFD/VNFpkg
1432 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1436 name
="nspkg-repo-show",
1437 short_help
="shows the details of a NS package in an OSM repository",
1439 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1440 @click.option("--repo", required
=True, help="Repository name")
1441 @click.argument("name")
1442 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1443 @click.option("--version", default
="latest", help="package version")
1445 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1446 """shows the content of a VNFD in a repository
1448 NAME: name or ID of the VNFD/VNFpkg
1451 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1454 @cli_osm.command(name
="nfpkg-show", short_help
="shows the details of a NF package")
1455 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1456 @click.argument("name")
1458 def nfpkg_show(ctx
, name
, literal
):
1459 """shows the content of a NF Descriptor
1461 NAME: name or ID of the NFpkg
1464 vnfd_show(ctx
, name
, literal
)
1468 name
="nfpkg-repo-show",
1469 short_help
="shows the details of a NF package in an OSM repository",
1471 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1472 @click.option("--repo", required
=True, help="Repository name")
1473 @click.argument("name")
1474 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1475 @click.option("--version", default
="latest", help="package version")
1477 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1478 """shows the content of a VNFD in a repository
1480 NAME: name or ID of the VNFD/VNFpkg
1483 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1486 @cli_osm.command(name
="ns-show", short_help
="shows the info of a NS instance")
1487 @click.argument("name")
1488 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1492 help="restricts the information to the fields in the filter",
1495 def ns_show(ctx
, name
, literal
, filter):
1496 """shows the info of a NS instance
1498 NAME: name or ID of the NS instance
1502 ns
= ctx
.obj
.ns
.get(name
)
1503 # except ClientException as e:
1508 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1511 table
= PrettyTable(["field", "value"])
1513 for k
, v
in list(ns
.items()):
1514 if not filter or k
in filter:
1515 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1517 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1518 if fullclassname
!= "osmclient.sol005.client.Client":
1519 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
["id"])
1520 nsr_optdata
= nsopdata
["nsr:nsr"]
1521 for k
, v
in list(nsr_optdata
.items()):
1522 if not filter or k
in filter:
1523 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), width
=100)])
1528 @cli_osm.command(name
="vnf-show", short_help
="shows the info of a VNF instance")
1529 @click.argument("name")
1530 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1534 help="restricts the information to the fields in the filter",
1536 @click.option("--kdu", default
=None, help="KDU name (whose status will be shown)")
1538 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1539 """shows the info of a VNF instance
1541 NAME: name or ID of the VNF instance
1544 def print_kdu_status(op_info_status
):
1545 """print KDU status properly formatted"""
1547 op_status
= yaml
.safe_load(op_info_status
)
1549 "namespace" in op_status
1550 and "info" in op_status
1551 and "last_deployed" in op_status
["info"]
1552 and "status" in op_status
["info"]
1553 and "code" in op_status
["info"]["status"]
1554 and "resources" in op_status
["info"]["status"]
1555 and "seconds" in op_status
["info"]["last_deployed"]
1557 last_deployed_time
= datetime
.fromtimestamp(
1558 op_status
["info"]["last_deployed"]["seconds"]
1559 ).strftime("%a %b %d %I:%M:%S %Y")
1560 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1561 print("NAMESPACE: {}".format(op_status
["namespace"]))
1562 status_code
= "UNKNOWN"
1563 if op_status
["info"]["status"]["code"] == 1:
1564 status_code
= "DEPLOYED"
1565 print("STATUS: {}".format(status_code
))
1568 print(op_status
["info"]["status"]["resources"])
1569 if "notes" in op_status
["info"]["status"]:
1571 print(op_status
["info"]["status"]["notes"])
1573 print(op_info_status
)
1575 print(op_info_status
)
1580 raise ClientException(
1581 '"--literal" option is incompatible with "--kdu" option'
1584 raise ClientException(
1585 '"--filter" option is incompatible with "--kdu" option'
1589 check_client_version(ctx
.obj
, ctx
.command
.name
)
1590 resp
= ctx
.obj
.vnf
.get(name
)
1593 ns_id
= resp
["nsr-id-ref"]
1595 op_data
["member_vnf_index"] = resp
["member-vnf-index-ref"]
1596 op_data
["kdu_name"] = kdu
1597 op_data
["primitive"] = "status"
1598 op_data
["primitive_params"] = {}
1599 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
="action", op_data
=op_data
, wait
=False)
1602 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1603 if op_info
["operationState"] == "COMPLETED":
1604 print_kdu_status(op_info
["detailed-status"])
1608 print("Could not determine KDU status")
1612 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1615 table
= PrettyTable(["field", "value"])
1616 for k
, v
in list(resp
.items()):
1617 if not filter or k
in filter:
1618 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1621 # except ClientException as e:
1626 # @cli_osm.command(name='vnf-monitoring-show')
1627 # @click.argument('vnf_name')
1628 # @click.pass_context
1629 # def vnf_monitoring_show(ctx, vnf_name):
1631 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1632 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1633 # except ClientException as e:
1637 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1638 # if resp is not None:
1639 # for monitor in resp:
1643 # monitor['value-integer'],
1644 # monitor['units']])
1649 # @cli_osm.command(name='ns-monitoring-show')
1650 # @click.argument('ns_name')
1651 # @click.pass_context
1652 # def ns_monitoring_show(ctx, ns_name):
1654 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1655 # resp = ctx.obj.ns.get_monitoring(ns_name)
1656 # except ClientException as e:
1660 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1661 # for key, val in list(resp.items()):
1662 # for monitor in val:
1666 # monitor['value-integer'],
1667 # monitor['units']])
1672 @cli_osm.command(name
="ns-op-show", short_help
="shows the info of a NS operation")
1673 @click.argument("id")
1677 help="restricts the information to the fields in the filter",
1679 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1681 def ns_op_show(ctx
, id, filter, literal
):
1682 """shows the detailed info of a NS operation
1684 ID: operation identifier
1688 check_client_version(ctx
.obj
, ctx
.command
.name
)
1689 op_info
= ctx
.obj
.ns
.get_op(id)
1690 # except ClientException as e:
1695 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1698 table
= PrettyTable(["field", "value"])
1699 for k
, v
in list(op_info
.items()):
1700 if not filter or k
in filter:
1701 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1706 def nst_show(ctx
, name
, literal
):
1709 check_client_version(ctx
.obj
, ctx
.command
.name
)
1710 resp
= ctx
.obj
.nst
.get(name
)
1711 # resp = ctx.obj.nst.get_individual(name)
1712 # except ClientException as e:
1717 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1720 table
= PrettyTable(["field", "value"])
1721 for k
, v
in list(resp
.items()):
1722 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1728 name
="nst-show", short_help
="shows the content of a Network Slice Template (NST)"
1730 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1731 @click.argument("name")
1733 def nst_show1(ctx
, name
, literal
):
1734 """shows the content of a Network Slice Template (NST)
1736 NAME: name or ID of the NST
1739 nst_show(ctx
, name
, literal
)
1743 name
="netslice-template-show",
1744 short_help
="shows the content of a Network Slice Template (NST)",
1746 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1747 @click.argument("name")
1749 def nst_show2(ctx
, name
, literal
):
1750 """shows the content of a Network Slice Template (NST)
1752 NAME: name or ID of the NST
1755 nst_show(ctx
, name
, literal
)
1758 def nsi_show(ctx
, name
, literal
, filter):
1761 check_client_version(ctx
.obj
, ctx
.command
.name
)
1762 nsi
= ctx
.obj
.nsi
.get(name
)
1763 # except ClientException as e:
1768 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1771 table
= PrettyTable(["field", "value"])
1773 for k
, v
in list(nsi
.items()):
1774 if not filter or k
in filter:
1775 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1782 name
="nsi-show", short_help
="shows the content of a Network Slice Instance (NSI)"
1784 @click.argument("name")
1785 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1789 help="restricts the information to the fields in the filter",
1792 def nsi_show1(ctx
, name
, literal
, filter):
1793 """shows the content of a Network Slice Instance (NSI)
1795 NAME: name or ID of the Network Slice Instance
1798 nsi_show(ctx
, name
, literal
, filter)
1802 name
="netslice-instance-show",
1803 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_show2(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)
1822 def nsi_op_show(ctx
, id, filter):
1825 check_client_version(ctx
.obj
, ctx
.command
.name
)
1826 op_info
= ctx
.obj
.nsi
.get_op(id)
1827 # except ClientException as e:
1831 table
= PrettyTable(["field", "value"])
1832 for k
, v
in list(op_info
.items()):
1833 if not filter or k
in filter:
1834 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1841 short_help
="shows the info of an operation over a Network Slice Instance(NSI)",
1843 @click.argument("id")
1847 help="restricts the information to the fields in the filter",
1850 def nsi_op_show1(ctx
, id, filter):
1851 """shows the info of an operation over a Network Slice Instance(NSI)
1853 ID: operation identifier
1856 nsi_op_show(ctx
, id, filter)
1860 name
="netslice-instance-op-show",
1861 short_help
="shows the info of an operation over a Network Slice Instance(NSI)",
1863 @click.argument("id")
1867 help="restricts the information to the fields in the filter",
1870 def nsi_op_show2(ctx
, id, filter):
1871 """shows the info of an operation over a Network Slice Instance(NSI)
1873 ID: operation identifier
1876 nsi_op_show(ctx
, id, filter)
1880 name
="pdu-show", short_help
="shows the content of a Physical Deployment Unit (PDU)"
1882 @click.argument("name")
1883 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1887 help="restricts the information to the fields in the filter",
1890 def pdu_show(ctx
, name
, literal
, filter):
1891 """shows the content of a Physical Deployment Unit (PDU)
1893 NAME: name or ID of the PDU
1897 check_client_version(ctx
.obj
, ctx
.command
.name
)
1898 pdu
= ctx
.obj
.pdu
.get(name
)
1899 # except ClientException as e:
1904 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1907 table
= PrettyTable(["field", "value"])
1909 for k
, v
in list(pdu
.items()):
1910 if not filter or k
in filter:
1911 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1917 ####################
1919 ####################
1922 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1925 check_client_version(ctx
.obj
, ctx
.command
.name
)
1927 filename
= ctx
.obj
.osmrepo
.get_pkg("ns", filename
, repo
, vendor
, version
)
1928 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1929 # except ClientException as e:
1934 @cli_osm.command(name
="nsd-create", short_help
="creates a new NSD/NSpkg")
1935 @click.argument("filename")
1939 default
=None, # hidden=True,
1940 help="Deprecated. Use override",
1946 help="overrides fields in descriptor, format: "
1947 '"key1.key2...=value[;key3...=value;...]"',
1950 "--skip-charm-build",
1953 help="The charm will not be compiled, it is assumed to already exist",
1955 @click.option("--repo", default
=None, help="[repository]: Repository name")
1956 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
1960 help="[repository]: filter by version. Default: latest",
1963 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1964 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1967 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1968 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1969 If FILENAME is an NF Package folder, it is built and then onboarded.
1975 overwrite
=overwrite
,
1976 skip_charm_build
=skip_charm_build
,
1983 @cli_osm.command(name
="nspkg-create", short_help
="creates a new NSD/NSpkg")
1984 @click.argument("filename")
1988 default
=None, # hidden=True,
1989 help="Deprecated. Use override",
1995 help="overrides fields in descriptor, format: "
1996 '"key1.key2...=value[;key3...=value;...]"',
1999 "--skip-charm-build",
2002 help="The charm will not be compiled, it is assumed to already exist",
2004 @click.option("--repo", default
=None, help="[repository]: Repository name")
2005 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2009 help="[repository]: filter by version. Default: latest",
2012 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
2013 """onboards a new NSpkg
2015 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2016 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2017 If FILENAME is an NF Package folder, it is built and then onboarded.
2023 overwrite
=overwrite
,
2024 skip_charm_build
=skip_charm_build
,
2045 check_client_version(ctx
.obj
, ctx
.command
.name
)
2047 filename
= ctx
.obj
.osmrepo
.get_pkg("vnf", filename
, repo
, vendor
, version
)
2048 ctx
.obj
.vnfd
.create(
2050 overwrite
=overwrite
,
2051 skip_charm_build
=skip_charm_build
,
2052 override_epa
=override_epa
,
2053 override_nonepa
=override_nonepa
,
2054 override_paravirt
=override_paravirt
,
2056 # except ClientException as e:
2061 @cli_osm.command(name
="vnfd-create", short_help
="creates a new VNFD/VNFpkg")
2062 @click.argument("filename")
2064 "--overwrite", "overwrite", default
=None, help="overwrite deprecated, use override"
2070 help="overrides fields in descriptor, format: "
2071 '"key1.key2...=value[;key3...=value;...]"',
2074 "--skip-charm-build",
2077 help="The charm will not be compiled, it is assumed to already exist",
2084 help="adds guest-epa parameters to all VDU",
2087 "--override-nonepa",
2091 help="removes all guest-epa parameters from all VDU",
2094 "--override-paravirt",
2098 help="overrides all VDU interfaces to PARAVIRT",
2100 @click.option("--repo", default
=None, help="[repository]: Repository name")
2101 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2105 help="[repository]: filter by version. Default: latest",
2120 """creates a new VNFD/VNFpkg
2122 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2123 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2124 If FILENAME is an NF Package folder, it is built and then onboarded.
2130 overwrite
=overwrite
,
2131 skip_charm_build
=skip_charm_build
,
2132 override_epa
=override_epa
,
2133 override_nonepa
=override_nonepa
,
2134 override_paravirt
=override_paravirt
,
2141 @cli_osm.command(name
="vnfpkg-create", short_help
="creates a new VNFD/VNFpkg")
2142 @click.argument("filename")
2146 default
=None, # hidden=True,
2147 help="Deprecated. Use override",
2153 help="overrides fields in descriptor, format: "
2154 '"key1.key2...=value[;key3...=value;...]"',
2157 "--skip-charm-build",
2160 help="The charm will not be compiled, it is assumed to already exist",
2167 help="adds guest-epa parameters to all VDU",
2170 "--override-nonepa",
2174 help="removes all guest-epa parameters from all VDU",
2177 "--override-paravirt",
2181 help="overrides all VDU interfaces to PARAVIRT",
2183 @click.option("--repo", default
=None, help="[repository]: Repository name")
2184 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2188 help="[repository]: filter by version. Default: latest",
2203 """creates a new VNFD/VNFpkg
2205 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2206 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2207 If FILENAME is an NF Package folder, it is built and then onboarded.
2213 overwrite
=overwrite
,
2214 skip_charm_build
=skip_charm_build
,
2215 override_epa
=override_epa
,
2216 override_nonepa
=override_nonepa
,
2217 override_paravirt
=override_paravirt
,
2224 @cli_osm.command(name
="nfpkg-create", short_help
="creates a new NFpkg")
2225 @click.argument("filename")
2229 default
=None, # hidden=True,
2230 help="Deprecated. Use override",
2236 help="overrides fields in descriptor, format: "
2237 '"key1.key2...=value[;key3...=value;...]"',
2240 "--skip-charm-build",
2243 help="The charm will not be compiled, it is assumed to already exist",
2250 help="adds guest-epa parameters to all VDU",
2253 "--override-nonepa",
2257 help="removes all guest-epa parameters from all VDU",
2260 "--override-paravirt",
2264 help="overrides all VDU interfaces to PARAVIRT",
2266 @click.option("--repo", default
=None, help="[repository]: Repository name")
2267 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2271 help="[repository]: filter by version. Default: latest",
2286 """creates a new NFpkg
2289 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2290 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2291 If FILENAME is an NF Package folder, it is built and then onboarded.
2297 overwrite
=overwrite
,
2298 skip_charm_build
=skip_charm_build
,
2299 override_epa
=override_epa
,
2300 override_nonepa
=override_nonepa
,
2301 override_paravirt
=override_paravirt
,
2308 @cli_osm.command(name
="ns-create", short_help
="creates a new Network Service instance")
2309 @click.option("--ns_name", prompt
=True, help="name of the NS instance")
2310 @click.option("--nsd_name", prompt
=True, help="name of the NS descriptor")
2314 help="default VIM account id or name for the deployment",
2316 @click.option("--admin_status", default
="ENABLED", help="administration status")
2320 help="comma separated list of public key files to inject to vnfs",
2322 @click.option("--config", default
=None, help="ns specific yaml configuration")
2323 @click.option("--config_file", default
=None, help="ns specific yaml configuration file")
2329 help="do not return the control immediately, but keep it "
2330 "until the operation is completed, or timeout",
2344 """creates a new NS instance"""
2348 check_client_version(ctx
.obj
, "--config_file")
2350 raise ClientException(
2351 '"--config" option is incompatible with "--config_file" option'
2353 with
open(config_file
, "r") as cf
:
2360 account
=vim_account
,
2363 # except ClientException as e:
2368 def nst_create(ctx
, filename
, overwrite
):
2371 check_client_version(ctx
.obj
, ctx
.command
.name
)
2372 ctx
.obj
.nst
.create(filename
, overwrite
)
2373 # except ClientException as e:
2379 name
="nst-create", short_help
="creates a new Network Slice Template (NST)"
2381 @click.argument("filename")
2385 default
=None, # hidden=True,
2386 help="Deprecated. Use override",
2392 help="overrides fields in descriptor, format: "
2393 '"key1.key2...=value[;key3...=value;...]"',
2396 def nst_create1(ctx
, filename
, overwrite
):
2397 """creates a new Network Slice Template (NST)
2399 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
2402 nst_create(ctx
, filename
, overwrite
)
2406 name
="netslice-template-create",
2407 short_help
="creates a new Network Slice Template (NST)",
2409 @click.argument("filename")
2413 default
=None, # hidden=True,
2414 help="Deprecated. Use override",
2420 help="overrides fields in descriptor, format: "
2421 '"key1.key2...=value[;key3...=value;...]"',
2424 def nst_create2(ctx
, filename
, overwrite
):
2425 """creates a new Network Slice Template (NST)
2427 FILENAME: NST yaml file or NSTpkg tar.gz file
2430 nst_create(ctx
, filename
, overwrite
)
2434 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
2436 """creates a new Network Slice Instance (NSI)"""
2439 check_client_version(ctx
.obj
, ctx
.command
.name
)
2442 raise ClientException(
2443 '"--config" option is incompatible with "--config_file" option'
2445 with
open(config_file
, "r") as cf
:
2452 account
=vim_account
,
2455 # except ClientException as e:
2460 @cli_osm.command(name
="nsi-create", short_help
="creates a new Network Slice Instance")
2461 @click.option("--nsi_name", prompt
=True, help="name of the Network Slice Instance")
2462 @click.option("--nst_name", prompt
=True, help="name of the Network Slice Template")
2466 help="default VIM account id or name for the deployment",
2469 "--ssh_keys", default
=None, help="comma separated list of keys to inject to vnfs"
2474 help="Netslice specific yaml configuration:\n"
2475 "netslice_subnet: [\n"
2476 "id: TEXT, vim_account: TEXT,\n"
2477 "vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n"
2478 "vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n"
2479 "additionalParamsForNsi: {param: value, ...}\n"
2480 "additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n"
2482 "netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]",
2485 "--config_file", default
=None, help="nsi specific yaml configuration file"
2492 help="do not return the control immediately, but keep it "
2493 "until the operation is completed, or timeout",
2497 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
2499 """creates a new Network Slice Instance (NSI)"""
2502 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
2507 name
="netslice-instance-create", short_help
="creates a new Network Slice Instance"
2509 @click.option("--nsi_name", prompt
=True, help="name of the Network Slice Instance")
2510 @click.option("--nst_name", prompt
=True, help="name of the Network Slice Template")
2514 help="default VIM account id or name for the deployment",
2517 "--ssh_keys", default
=None, help="comma separated list of keys to inject to vnfs"
2522 help="Netslice specific yaml configuration:\n"
2523 "netslice_subnet: [\n"
2524 "id: TEXT, vim_account: TEXT,\n"
2525 "vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n"
2526 "vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]"
2528 "netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]",
2531 "--config_file", default
=None, help="nsi specific yaml configuration file"
2538 help="do not return the control immediately, but keep it "
2539 "until the operation is completed, or timeout",
2543 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
2545 """creates a new Network Slice Instance (NSI)"""
2548 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
2553 name
="pdu-create", short_help
="adds a new Physical Deployment Unit to the catalog"
2555 @click.option("--name", help="name of the Physical Deployment Unit")
2556 @click.option("--pdu_type", help="type of PDU (e.g. router, firewall, FW001)")
2559 help="interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>"
2560 + "[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]",
2563 @click.option("--description", help="human readable description")
2566 help="list of VIM accounts (in the same VIM) that can reach this PDU",
2570 "--descriptor_file",
2572 help="PDU descriptor file (as an alternative to using the other arguments",
2576 ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
2578 """creates a new Physical Deployment Unit (PDU)"""
2581 check_client_version(ctx
.obj
, ctx
.command
.name
)
2583 if not descriptor_file
:
2585 raise ClientException(
2586 'in absence of descriptor file, option "--name" is mandatory'
2589 raise ClientException(
2590 'in absence of descriptor file, option "--pdu_type" is mandatory'
2593 raise ClientException(
2594 'in absence of descriptor file, option "--interface" is mandatory (at least once)'
2597 raise ClientException(
2598 'in absence of descriptor file, option "--vim_account" is mandatory (at least once)'
2601 with
open(descriptor_file
, "r") as df
:
2602 pdu
= yaml
.safe_load(df
.read())
2606 pdu
["type"] = pdu_type
2608 pdu
["description"] = description
2610 pdu
["vim_accounts"] = vim_account
2613 for iface
in interface
:
2614 new_iface
= {k
: v
for k
, v
in [i
.split("=") for i
in iface
.split(",")]}
2615 new_iface
["mgmt"] = new_iface
.get("mgmt", "false").lower() == "true"
2616 ifaces_list
.append(new_iface
)
2617 pdu
["interfaces"] = ifaces_list
2618 ctx
.obj
.pdu
.create(pdu
)
2619 # except ClientException as e:
2624 ####################
2626 ####################
2629 def nsd_update(ctx
, name
, content
):
2632 check_client_version(ctx
.obj
, ctx
.command
.name
)
2633 ctx
.obj
.nsd
.update(name
, content
)
2634 # except ClientException as e:
2639 @cli_osm.command(name
="nsd-update", short_help
="updates a NSD/NSpkg")
2640 @click.argument("name")
2644 help="filename with the NSD/NSpkg replacing the current one",
2647 def nsd_update1(ctx
, name
, content
):
2648 """updates a NSD/NSpkg
2650 NAME: name or ID of the NSD/NSpkg
2653 nsd_update(ctx
, name
, content
)
2656 @cli_osm.command(name
="nspkg-update", short_help
="updates a NSD/NSpkg")
2657 @click.argument("name")
2661 help="filename with the NSD/NSpkg replacing the current one",
2664 def nsd_update2(ctx
, name
, content
):
2665 """updates a NSD/NSpkg
2667 NAME: name or ID of the NSD/NSpkg
2670 nsd_update(ctx
, name
, content
)
2673 def vnfd_update(ctx
, name
, content
):
2676 check_client_version(ctx
.obj
, ctx
.command
.name
)
2677 ctx
.obj
.vnfd
.update(name
, content
)
2678 # except ClientException as e:
2683 @cli_osm.command(name
="vnfd-update", short_help
="updates a new VNFD/VNFpkg")
2684 @click.argument("name")
2688 help="filename with the VNFD/VNFpkg replacing the current one",
2691 def vnfd_update1(ctx
, name
, content
):
2692 """updates a VNFD/VNFpkg
2694 NAME: name or ID of the VNFD/VNFpkg
2697 vnfd_update(ctx
, name
, content
)
2700 @cli_osm.command(name
="vnfpkg-update", short_help
="updates a VNFD/VNFpkg")
2701 @click.argument("name")
2705 help="filename with the VNFD/VNFpkg replacing the current one",
2708 def vnfd_update2(ctx
, name
, content
):
2709 """updates a VNFD/VNFpkg
2711 NAME: VNFD yaml file or VNFpkg tar.gz file
2714 vnfd_update(ctx
, name
, content
)
2717 @cli_osm.command(name
="nfpkg-update", short_help
="updates a NFpkg")
2718 @click.argument("name")
2720 "--content", default
=None, help="filename with the NFpkg replacing the current one"
2723 def nfpkg_update(ctx
, name
, content
):
2726 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2729 vnfd_update(ctx
, name
, content
)
2732 def nst_update(ctx
, name
, content
):
2735 check_client_version(ctx
.obj
, ctx
.command
.name
)
2736 ctx
.obj
.nst
.update(name
, content
)
2737 # except ClientException as e:
2742 @cli_osm.command(name
="nst-update", short_help
="updates a Network Slice Template (NST)")
2743 @click.argument("name")
2747 help="filename with the NST/NSTpkg replacing the current one",
2750 def nst_update1(ctx
, name
, content
):
2751 """updates a Network Slice Template (NST)
2753 NAME: name or ID of the NSD/NSpkg
2756 nst_update(ctx
, name
, content
)
2760 name
="netslice-template-update", short_help
="updates a Network Slice Template (NST)"
2762 @click.argument("name")
2766 help="filename with the NST/NSTpkg replacing the current one",
2769 def nst_update2(ctx
, name
, content
):
2770 """updates a Network Slice Template (NST)
2772 NAME: name or ID of the NSD/NSpkg
2775 nst_update(ctx
, name
, content
)
2778 ####################
2780 ####################
2783 def nsd_delete(ctx
, name
, force
):
2787 ctx
.obj
.nsd
.delete(name
)
2789 check_client_version(ctx
.obj
, "--force")
2790 ctx
.obj
.nsd
.delete(name
, force
)
2791 # except ClientException as e:
2796 @cli_osm.command(name
="nsd-delete", short_help
="deletes a NSD/NSpkg")
2797 @click.argument("name")
2799 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2802 def nsd_delete1(ctx
, name
, force
):
2803 """deletes a NSD/NSpkg
2805 NAME: name or ID of the NSD/NSpkg to be deleted
2808 nsd_delete(ctx
, name
, force
)
2811 @cli_osm.command(name
="nspkg-delete", short_help
="deletes a NSD/NSpkg")
2812 @click.argument("name")
2814 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2817 def nsd_delete2(ctx
, name
, force
):
2818 """deletes a NSD/NSpkg
2820 NAME: name or ID of the NSD/NSpkg to be deleted
2823 nsd_delete(ctx
, name
, force
)
2826 def vnfd_delete(ctx
, name
, force
):
2830 ctx
.obj
.vnfd
.delete(name
)
2832 check_client_version(ctx
.obj
, "--force")
2833 ctx
.obj
.vnfd
.delete(name
, force
)
2834 # except ClientException as e:
2839 @cli_osm.command(name
="vnfd-delete", short_help
="deletes a VNFD/VNFpkg")
2840 @click.argument("name")
2842 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2845 def vnfd_delete1(ctx
, name
, force
):
2846 """deletes a VNFD/VNFpkg
2848 NAME: name or ID of the VNFD/VNFpkg to be deleted
2851 vnfd_delete(ctx
, name
, force
)
2854 @cli_osm.command(name
="vnfpkg-delete", short_help
="deletes a VNFD/VNFpkg")
2855 @click.argument("name")
2857 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2860 def vnfd_delete2(ctx
, name
, force
):
2861 """deletes a VNFD/VNFpkg
2863 NAME: name or ID of the VNFD/VNFpkg to be deleted
2866 vnfd_delete(ctx
, name
, force
)
2869 @cli_osm.command(name
="nfpkg-delete", short_help
="deletes a NFpkg")
2870 @click.argument("name")
2872 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2875 def nfpkg_delete(ctx
, name
, force
):
2878 NAME: name or ID of the NFpkg to be deleted
2881 vnfd_delete(ctx
, name
, force
)
2884 @cli_osm.command(name
="ns-delete", short_help
="deletes a NS instance")
2885 @click.argument("name")
2887 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2892 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2893 "600, skip_terminate_primitives: True}'",
2900 help="do not return the control immediately, but keep it "
2901 "until the operation is completed, or timeout",
2904 def ns_delete(ctx
, name
, force
, config
, wait
):
2905 """deletes a NS instance
2907 NAME: name or ID of the NS instance to be deleted
2912 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2914 check_client_version(ctx
.obj
, "--force")
2915 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2916 # except ClientException as e:
2921 def nst_delete(ctx
, name
, force
):
2924 check_client_version(ctx
.obj
, ctx
.command
.name
)
2925 ctx
.obj
.nst
.delete(name
, force
)
2926 # except ClientException as e:
2931 @cli_osm.command(name
="nst-delete", short_help
="deletes a Network Slice Template (NST)")
2932 @click.argument("name")
2934 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2937 def nst_delete1(ctx
, name
, force
):
2938 """deletes a Network Slice Template (NST)
2940 NAME: name or ID of the NST/NSTpkg to be deleted
2943 nst_delete(ctx
, name
, force
)
2947 name
="netslice-template-delete", short_help
="deletes a Network Slice Template (NST)"
2949 @click.argument("name")
2951 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2954 def nst_delete2(ctx
, name
, force
):
2955 """deletes a Network Slice Template (NST)
2957 NAME: name or ID of the NST/NSTpkg to be deleted
2960 nst_delete(ctx
, name
, force
)
2963 def nsi_delete(ctx
, name
, force
, wait
):
2966 check_client_version(ctx
.obj
, ctx
.command
.name
)
2967 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2968 # except ClientException as e:
2973 @cli_osm.command(name
="nsi-delete", short_help
="deletes a Network Slice Instance (NSI)")
2974 @click.argument("name")
2976 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2983 help="do not return the control immediately, but keep it "
2984 "until the operation is completed, or timeout",
2987 def nsi_delete1(ctx
, name
, force
, wait
):
2988 """deletes a Network Slice Instance (NSI)
2990 NAME: name or ID of the Network Slice instance to be deleted
2993 nsi_delete(ctx
, name
, force
, wait
=wait
)
2997 name
="netslice-instance-delete", short_help
="deletes a Network Slice Instance (NSI)"
2999 @click.argument("name")
3001 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3004 def nsi_delete2(ctx
, name
, force
, wait
):
3005 """deletes a Network Slice Instance (NSI)
3007 NAME: name or ID of the Network Slice instance to be deleted
3010 nsi_delete(ctx
, name
, force
, wait
=wait
)
3014 name
="pdu-delete", short_help
="deletes a Physical Deployment Unit (PDU)"
3016 @click.argument("name")
3018 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3021 def pdu_delete(ctx
, name
, force
):
3022 """deletes a Physical Deployment Unit (PDU)
3024 NAME: name or ID of the PDU to be deleted
3028 check_client_version(ctx
.obj
, ctx
.command
.name
)
3029 ctx
.obj
.pdu
.delete(name
, force
)
3030 # except ClientException as e:
3040 @cli_osm.command(name
="vim-create", short_help
="creates a new VIM account")
3041 @click.option("--name", prompt
=True, help="Name to create datacenter")
3042 @click.option("--user", prompt
=True, help="VIM username")
3047 confirmation_prompt
=True,
3048 help="VIM password",
3050 @click.option("--auth_url", prompt
=True, help="VIM url")
3051 @click.option("--tenant", prompt
=True, help="VIM tenant name")
3052 @click.option("--config", default
=None, help="VIM specific config parameters")
3053 @click.option("--account_type", default
="openstack", help="VIM type")
3054 @click.option("--description", default
=None, help="human readable description")
3058 help="Name or id of the SDN controller associated to this VIM account",
3061 "--sdn_port_mapping",
3063 help="File describing the port mapping between compute nodes' ports and switch ports",
3070 help="do not return the control immediately, but keep it "
3071 "until the operation is completed, or timeout",
3088 """creates a new VIM account"""
3092 check_client_version(ctx
.obj
, "--sdn_controller")
3093 if sdn_port_mapping
:
3094 check_client_version(ctx
.obj
, "--sdn_port_mapping")
3096 vim
["vim-username"] = user
3097 vim
["vim-password"] = password
3098 vim
["vim-url"] = auth_url
3099 vim
["vim-tenant-name"] = tenant
3100 vim
["vim-type"] = account_type
3101 vim
["description"] = description
3102 vim
["config"] = config
3103 if sdn_controller
or sdn_port_mapping
:
3104 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
3106 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
3107 # except ClientException as e:
3112 @cli_osm.command(name
="vim-update", short_help
="updates a VIM account")
3113 @click.argument("name")
3114 @click.option("--newname", help="New name for the VIM account")
3115 @click.option("--user", help="VIM username")
3116 @click.option("--password", help="VIM password")
3117 @click.option("--auth_url", help="VIM url")
3118 @click.option("--tenant", help="VIM tenant name")
3119 @click.option("--config", help="VIM specific config parameters")
3120 @click.option("--account_type", help="VIM type")
3121 @click.option("--description", help="human readable description")
3125 help="Name or id of the SDN controller to be associated with this VIM"
3126 "account. Use empty string to disassociate",
3129 "--sdn_port_mapping",
3131 help="File describing the port mapping between compute nodes' ports and switch ports",
3138 help="do not return the control immediately, but keep it "
3139 "until the operation is completed, or timeout",
3157 """updates a VIM account
3159 NAME: name or ID of the VIM account
3163 check_client_version(ctx
.obj
, ctx
.command
.name
)
3166 vim
["name"] = newname
3168 vim
["vim_user"] = user
3170 vim
["vim_password"] = password
3172 vim
["vim_url"] = auth_url
3174 vim
["vim-tenant-name"] = tenant
3176 vim
["vim_type"] = account_type
3178 vim
["description"] = description
3180 vim
["config"] = config
3181 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
3182 # except ClientException as e:
3187 @cli_osm.command(name
="vim-delete", short_help
="deletes a VIM account")
3188 @click.argument("name")
3190 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3197 help="do not return the control immediately, but keep it "
3198 "until the operation is completed, or timeout",
3201 def vim_delete(ctx
, name
, force
, wait
):
3202 """deletes a VIM account
3204 NAME: name or ID of the VIM account to be deleted
3209 ctx
.obj
.vim
.delete(name
, wait
=wait
)
3211 check_client_version(ctx
.obj
, "--force")
3212 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
3213 # except ClientException as e:
3218 @cli_osm.command(name
="vim-list", short_help
="list all VIM accounts")
3219 # @click.option('--ro_update/--no_ro_update',
3221 # help='update list from RO')
3226 help="restricts the list to the VIM accounts matching the filter",
3231 help="get more details of the NS (project, vim, deployment status, configuration status.",
3234 def vim_list(ctx
, filter, long):
3235 """list all VIM accounts"""
3238 filter = "&".join(filter)
3239 check_client_version(ctx
.obj
, "--filter")
3241 # check_client_version(ctx.obj, '--ro_update', 'v1')
3242 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3243 if fullclassname
== "osmclient.sol005.client.Client":
3244 resp
= ctx
.obj
.vim
.list(filter)
3246 # resp = ctx.obj.vim.list(ro_update)
3248 table
= PrettyTable(
3249 ["vim name", "uuid", "project", "operational state", "error details"]
3251 project_list
= ctx
.obj
.project
.list()
3253 table
= PrettyTable(["vim name", "uuid", "operational state"])
3256 if "vim_password" in vim
:
3257 vim
["vim_password"] = "********"
3258 logger
.debug("VIM details: {}".format(yaml
.safe_dump(vim
)))
3259 vim_state
= vim
["_admin"].get("operationalState", "-")
3260 error_details
= "N/A"
3261 if vim_state
== "ERROR":
3262 error_details
= vim
["_admin"].get("detailed-status", "Not found")
3263 project_id
, project_name
= get_project(project_list
, vim
)
3264 # project_info = '{} ({})'.format(project_name, project_id)
3265 project_info
= project_name
3272 wrap_text(text
=error_details
, width
=80),
3277 [vim
["name"], vim
["uuid"], vim
["_admin"].get("operationalState", "-")]
3283 @cli_osm.command(name
="vim-show", short_help
="shows the details of a VIM account")
3284 @click.argument("name")
3288 help="restricts the information to the fields in the filter",
3291 def vim_show(ctx
, name
, filter):
3292 """shows the details of a VIM account
3294 NAME: name or ID of the VIM account
3298 resp
= ctx
.obj
.vim
.get(name
)
3299 if "vim_password" in resp
:
3300 resp
["vim_password"] = "********"
3301 # except ClientException as e:
3305 table
= PrettyTable(["key", "attribute"])
3306 for k
, v
in list(resp
.items()):
3307 if not filter or k
in filter:
3308 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
3313 ####################
3315 ####################
3318 @cli_osm.command(name
="wim-create", short_help
="creates a new WIM account")
3319 @click.option("--name", prompt
=True, help="Name for the WIM account")
3320 @click.option("--user", help="WIM username")
3321 @click.option("--password", help="WIM password")
3322 @click.option("--url", prompt
=True, help="WIM url")
3323 # @click.option('--tenant',
3324 # help='wIM tenant name')
3325 @click.option("--config", default
=None, help="WIM specific config parameters")
3326 @click.option("--wim_type", help="WIM type")
3327 @click.option("--description", default
=None, help="human readable description")
3329 "--wim_port_mapping",
3331 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
3332 "(WAN service endpoint id and info)",
3339 help="do not return the control immediately, but keep it "
3340 "until the operation is completed, or timeout",
3356 """creates a new WIM account"""
3359 check_client_version(ctx
.obj
, ctx
.command
.name
)
3360 # if sdn_controller:
3361 # check_client_version(ctx.obj, '--sdn_controller')
3362 # if sdn_port_mapping:
3363 # check_client_version(ctx.obj, '--sdn_port_mapping')
3368 wim
["password"] = password
3370 wim
["wim_url"] = url
3371 # if tenant: wim['tenant'] = tenant
3372 wim
["wim_type"] = wim_type
3374 wim
["description"] = description
3376 wim
["config"] = config
3377 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
3378 # except ClientException as e:
3383 @cli_osm.command(name
="wim-update", short_help
="updates a WIM account")
3384 @click.argument("name")
3385 @click.option("--newname", help="New name for the WIM account")
3386 @click.option("--user", help="WIM username")
3387 @click.option("--password", help="WIM password")
3388 @click.option("--url", help="WIM url")
3389 @click.option("--config", help="WIM specific config parameters")
3390 @click.option("--wim_type", help="WIM type")
3391 @click.option("--description", help="human readable description")
3393 "--wim_port_mapping",
3395 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
3396 "(WAN service endpoint id and info)",
3403 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3419 """updates a WIM account
3421 NAME: name or ID of the WIM account
3425 check_client_version(ctx
.obj
, ctx
.command
.name
)
3428 wim
["name"] = newname
3432 wim
["password"] = password
3435 # if tenant: wim['tenant'] = tenant
3437 wim
["wim_type"] = wim_type
3439 wim
["description"] = description
3441 wim
["config"] = config
3442 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
3443 # except ClientException as e:
3448 @cli_osm.command(name
="wim-delete", short_help
="deletes a WIM account")
3449 @click.argument("name")
3451 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3458 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3461 def wim_delete(ctx
, name
, force
, wait
):
3462 """deletes a WIM account
3464 NAME: name or ID of the WIM account to be deleted
3468 check_client_version(ctx
.obj
, ctx
.command
.name
)
3469 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
3470 # except ClientException as e:
3475 @cli_osm.command(name
="wim-list", short_help
="list all WIM accounts")
3480 help="restricts the list to the WIM accounts matching the filter",
3483 def wim_list(ctx
, filter):
3484 """list all WIM accounts"""
3487 check_client_version(ctx
.obj
, ctx
.command
.name
)
3489 filter = "&".join(filter)
3490 resp
= ctx
.obj
.wim
.list(filter)
3491 table
= PrettyTable(["wim name", "uuid"])
3493 table
.add_row([wim
["name"], wim
["uuid"]])
3496 # except ClientException as e:
3501 @cli_osm.command(name
="wim-show", short_help
="shows the details of a WIM account")
3502 @click.argument("name")
3504 def wim_show(ctx
, name
):
3505 """shows the details of a WIM account
3507 NAME: name or ID of the WIM account
3511 check_client_version(ctx
.obj
, ctx
.command
.name
)
3512 resp
= ctx
.obj
.wim
.get(name
)
3513 if "password" in resp
:
3514 resp
["wim_password"] = "********"
3515 # except ClientException as e:
3519 table
= PrettyTable(["key", "attribute"])
3520 for k
, v
in list(resp
.items()):
3521 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3526 ####################
3527 # SDN controller operations
3528 ####################
3531 @cli_osm.command(name
="sdnc-create", short_help
="creates a new SDN controller")
3532 @click.option("--name", prompt
=True, help="Name to create sdn controller")
3533 @click.option("--type", prompt
=True, help="SDN controller type")
3535 "--sdn_controller_version", # hidden=True,
3536 help="Deprecated. Use --config {version: sdn_controller_version}",
3538 @click.option("--url", help="URL in format http[s]://HOST:IP/")
3539 @click.option("--ip_address", help="Deprecated. Use --url") # hidden=True,
3540 @click.option("--port", help="Deprecated. Use --url") # hidden=True,
3542 "--switch_dpid", help="Deprecated. Use --config {switch_id: DPID}" # hidden=True,
3546 help="Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: "
3547 "Openflow Datapath ID), version: version}",
3549 @click.option("--user", help="SDN controller username")
3553 confirmation_prompt
=True,
3554 help="SDN controller password",
3556 @click.option("--description", default
=None, help="human readable description")
3562 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3565 def sdnc_create(ctx
, **kwargs
):
3566 """creates a new SDN controller"""
3571 if kwargs
[x
] and x
not in ("wait", "ip_address", "port", "switch_dpid")
3573 if kwargs
.get("port"):
3574 print("option '--port' is deprecated, use '--url' instead")
3575 sdncontroller
["port"] = int(kwargs
["port"])
3576 if kwargs
.get("ip_address"):
3577 print("option '--ip_address' is deprecated, use '--url' instead")
3578 sdncontroller
["ip"] = kwargs
["ip_address"]
3579 if kwargs
.get("switch_dpid"):
3581 "option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead"
3583 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
3584 if kwargs
.get("sdn_controller_version"):
3586 "option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
3590 check_client_version(ctx
.obj
, ctx
.command
.name
)
3591 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
3592 # except ClientException as e:
3597 @cli_osm.command(name
="sdnc-update", short_help
="updates an SDN controller")
3598 @click.argument("name")
3599 @click.option("--newname", help="New name for the SDN controller")
3600 @click.option("--description", default
=None, help="human readable description")
3601 @click.option("--type", help="SDN controller type")
3602 @click.option("--url", help="URL in format http[s]://HOST:IP/")
3605 help="Extra information for SDN in yaml format, as "
3606 "{switch_id: identity used for the plugin (e.g. DPID: "
3607 "Openflow Datapath ID), version: version}",
3609 @click.option("--user", help="SDN controller username")
3610 @click.option("--password", help="SDN controller password")
3611 @click.option("--ip_address", help="Deprecated. Use --url") # hidden=True
3612 @click.option("--port", help="Deprecated. Use --url") # hidden=True
3614 "--switch_dpid", help="Deprecated. Use --config {switch_dpid: DPID}"
3617 "--sdn_controller_version", help="Deprecated. Use --config {version: VERSION}"
3624 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3627 def sdnc_update(ctx
, **kwargs
):
3628 """updates an SDN controller
3630 NAME: name or ID of the SDN controller
3637 and x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")
3639 if kwargs
.get("newname"):
3640 sdncontroller
["name"] = kwargs
["newname"]
3641 if kwargs
.get("port"):
3642 print("option '--port' is deprecated, use '--url' instead")
3643 sdncontroller
["port"] = int(kwargs
["port"])
3644 if kwargs
.get("ip_address"):
3645 print("option '--ip_address' is deprecated, use '--url' instead")
3646 sdncontroller
["ip"] = kwargs
["ip_address"]
3647 if kwargs
.get("switch_dpid"):
3649 "option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead"
3651 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
3652 if kwargs
.get("sdn_controller_version"):
3654 "option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
3659 check_client_version(ctx
.obj
, ctx
.command
.name
)
3660 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
3661 # except ClientException as e:
3666 @cli_osm.command(name
="sdnc-delete", short_help
="deletes an SDN controller")
3667 @click.argument("name")
3669 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3676 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3679 def sdnc_delete(ctx
, name
, force
, wait
):
3680 """deletes an SDN controller
3682 NAME: name or ID of the SDN controller to be deleted
3686 check_client_version(ctx
.obj
, ctx
.command
.name
)
3687 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
3688 # except ClientException as e:
3693 @cli_osm.command(name
="sdnc-list", short_help
="list all SDN controllers")
3698 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'",
3701 def sdnc_list(ctx
, filter):
3702 """list all SDN controllers"""
3705 check_client_version(ctx
.obj
, ctx
.command
.name
)
3707 filter = "&".join(filter)
3708 resp
= ctx
.obj
.sdnc
.list(filter)
3709 # except ClientException as e:
3712 table
= PrettyTable(["sdnc name", "id"])
3714 table
.add_row([sdnc
["name"], sdnc
["_id"]])
3719 @cli_osm.command(name
="sdnc-show", short_help
="shows the details of an SDN controller")
3720 @click.argument("name")
3722 def sdnc_show(ctx
, name
):
3723 """shows the details of an SDN controller
3725 NAME: name or ID of the SDN controller
3729 check_client_version(ctx
.obj
, ctx
.command
.name
)
3730 resp
= ctx
.obj
.sdnc
.get(name
)
3731 # except ClientException as e:
3735 table
= PrettyTable(["key", "attribute"])
3736 for k
, v
in list(resp
.items()):
3737 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3742 ###########################
3743 # K8s cluster operations
3744 ###########################
3747 @cli_osm.command(name
="k8scluster-add", short_help
="adds a K8s cluster to OSM")
3748 @click.argument("name")
3750 "--creds", prompt
=True, help="credentials file, i.e. a valid `.kube/config` file"
3752 @click.option("--version", prompt
=True, help="Kubernetes version")
3754 "--vim", prompt
=True, help="VIM target, the VIM where the cluster resides"
3759 help='''list of VIM networks, in JSON inline format, where the cluster is
3760 accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''',
3762 @click.option("--description", default
=None, help="human readable description")
3765 default
="kube-system",
3766 help="namespace to be used for its operation, defaults to `kube-system`",
3771 help="list of CNI plugins, in JSON inline format, used in the cluster",
3773 # @click.option('--skip-init',
3775 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3776 # @click.option('--wait',
3778 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3781 ctx
, name
, creds
, version
, vim
, k8s_nets
, description
, namespace
, cni
3783 """adds a K8s cluster to OSM
3785 NAME: name of the K8s cluster
3788 check_client_version(ctx
.obj
, ctx
.command
.name
)
3790 cluster
["name"] = name
3791 with
open(creds
, "r") as cf
:
3792 cluster
["credentials"] = yaml
.safe_load(cf
.read())
3793 cluster
["k8s_version"] = version
3794 cluster
["vim_account"] = vim
3795 cluster
["nets"] = yaml
.safe_load(k8s_nets
)
3797 cluster
["description"] = description
3799 cluster
["namespace"] = namespace
3801 cluster
["cni"] = yaml
.safe_load(cni
)
3802 ctx
.obj
.k8scluster
.create(name
, cluster
)
3803 # except ClientException as e:
3808 @cli_osm.command(name
="k8scluster-update", short_help
="updates a K8s cluster")
3809 @click.argument("name")
3810 @click.option("--newname", help="New name for the K8s cluster")
3811 @click.option("--creds", help="credentials file, i.e. a valid `.kube/config` file")
3812 @click.option("--version", help="Kubernetes version")
3813 @click.option("--vim", help="VIM target, the VIM where the cluster resides")
3816 help='''list of VIM networks, in JSON inline format, where the cluster is accessible
3817 via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''',
3819 @click.option("--description", help="human readable description")
3822 help="namespace to be used for its operation, defaults to `kube-system`",
3825 "--cni", help="list of CNI plugins, in JSON inline format, used in the cluster"
3828 def k8scluster_update(
3829 ctx
, name
, newname
, creds
, version
, vim
, k8s_nets
, description
, namespace
, cni
3831 """updates a K8s cluster
3833 NAME: name or ID of the K8s cluster
3836 check_client_version(ctx
.obj
, ctx
.command
.name
)
3839 cluster
["name"] = newname
3841 with
open(creds
, "r") as cf
:
3842 cluster
["credentials"] = yaml
.safe_load(cf
.read())
3844 cluster
["k8s_version"] = version
3846 cluster
["vim_account"] = vim
3848 cluster
["nets"] = yaml
.safe_load(k8s_nets
)
3850 cluster
["description"] = description
3852 cluster
["namespace"] = namespace
3854 cluster
["cni"] = yaml
.safe_load(cni
)
3855 ctx
.obj
.k8scluster
.update(name
, cluster
)
3856 # except ClientException as e:
3861 @cli_osm.command(name
="k8scluster-delete", short_help
="deletes a K8s cluster")
3862 @click.argument("name")
3864 "--force", is_flag
=True, help="forces the deletion from the DB (not recommended)"
3866 # @click.option('--wait',
3868 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3870 def k8scluster_delete(ctx
, name
, force
):
3871 """deletes a K8s cluster
3873 NAME: name or ID of the K8s cluster to be deleted
3876 check_client_version(ctx
.obj
, ctx
.command
.name
)
3877 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3878 # except ClientException as e:
3883 @cli_osm.command(name
="k8scluster-list")
3888 help="restricts the list to the K8s clusters matching the filter",
3890 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
3891 @click.option("--long", is_flag
=True, help="get more details")
3893 def k8scluster_list(ctx
, filter, literal
, long):
3894 """list all K8s clusters"""
3896 check_client_version(ctx
.obj
, ctx
.command
.name
)
3898 filter = "&".join(filter)
3899 resp
= ctx
.obj
.k8scluster
.list(filter)
3901 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3904 table
= PrettyTable(
3912 "Operational State",
3913 "Op. state (details)",
3918 project_list
= ctx
.obj
.project
.list()
3920 table
= PrettyTable(
3921 ["Name", "Id", "VIM", "Operational State", "Op. state details"]
3924 vim_list
= ctx
.obj
.vim
.list()
3927 for cluster
in resp
:
3928 logger
.debug("Cluster details: {}".format(yaml
.safe_dump(cluster
)))
3929 vim_name
= get_vim_name(vim_list
, cluster
["vim_account"])
3930 # vim_info = '{} ({})'.format(vim_name,cluster['vim_account'])
3932 op_state_details
= "Helm: {}\nJuju: {}".format(
3933 cluster
["_admin"].get("helm-chart", {}).get("operationalState", "-"),
3934 cluster
["_admin"].get("juju-bundle", {}).get("operationalState", "-"),
3937 project_id
, project_name
= get_project(project_list
, cluster
)
3938 # project_info = '{} ({})'.format(project_name, project_id)
3939 project_info
= project_name
3940 detailed_status
= cluster
["_admin"].get("detailed-status", "-")
3946 cluster
["k8s_version"],
3948 json
.dumps(cluster
["nets"]),
3949 cluster
["_admin"]["operationalState"],
3951 trunc_text(cluster
.get("description") or "", 40),
3952 wrap_text(text
=detailed_status
, width
=40),
3961 cluster
["_admin"]["operationalState"],
3967 # except ClientException as e:
3973 name
="k8scluster-show", short_help
="shows the details of a K8s cluster"
3975 @click.argument("name")
3976 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
3978 def k8scluster_show(ctx
, name
, literal
):
3979 """shows the details of a K8s cluster
3981 NAME: name or ID of the K8s cluster
3984 resp
= ctx
.obj
.k8scluster
.get(name
)
3986 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3988 table
= PrettyTable(["key", "attribute"])
3989 for k
, v
in list(resp
.items()):
3990 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
3993 # except ClientException as e:
3998 ###########################
4000 ###########################
4003 @cli_osm.command(name
="repo-add", short_help
="adds a repo to OSM")
4004 @click.argument("name")
4005 @click.argument("uri")
4008 type=click
.Choice(["helm-chart", "juju-bundle", "osm"]),
4010 help="type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)",
4012 @click.option("--description", default
=None, help="human readable description")
4014 "--user", default
=None, help="OSM repository: The username of the OSM repository"
4019 help="OSM repository: The password of the OSM repository",
4021 # @click.option('--wait',
4023 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4025 def repo_add(ctx
, **kwargs
):
4026 """adds a repo to OSM
4028 NAME: name of the repo
4029 URI: URI of the repo
4032 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
4034 repo
["url"] = repo
.pop("uri")
4035 if repo
["type"] in ["helm-chart", "juju-bundle"]:
4036 ctx
.obj
.repo
.create(repo
["name"], repo
)
4038 ctx
.obj
.osmrepo
.create(repo
["name"], repo
)
4039 # except ClientException as e:
4044 @cli_osm.command(name
="repo-update", short_help
="updates a repo in OSM")
4045 @click.argument("name")
4046 @click.option("--newname", help="New name for the repo")
4047 @click.option("--uri", help="URI of the repo")
4048 @click.option("--description", help="human readable description")
4049 # @click.option('--wait',
4051 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4053 def repo_update(ctx
, name
, newname
, uri
, description
):
4054 """updates a repo in OSM
4056 NAME: name of the repo
4059 check_client_version(ctx
.obj
, ctx
.command
.name
)
4062 repo
["name"] = newname
4066 repo
["description"] = description
4068 ctx
.obj
.repo
.update(name
, repo
)
4070 ctx
.obj
.osmrepo
.update(name
, repo
)
4072 # except ClientException as e:
4078 name
="repo-index", short_help
="Index a repository from a folder with artifacts"
4081 "--origin", default
=".", help="origin path where the artifacts are located"
4084 "--destination", default
=".", help="destination path where the index is deployed"
4087 def repo_index(ctx
, origin
, destination
):
4088 """Index a repository
4090 NAME: name or ID of the repo to be deleted
4092 check_client_version(ctx
.obj
, ctx
.command
.name
)
4093 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
4096 @cli_osm.command(name
="repo-delete", short_help
="deletes a repo")
4097 @click.argument("name")
4099 "--force", is_flag
=True, help="forces the deletion from the DB (not recommended)"
4101 # @click.option('--wait',
4103 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4105 def repo_delete(ctx
, name
, force
):
4108 NAME: name or ID of the repo to be deleted
4112 ctx
.obj
.repo
.delete(name
, force
=force
)
4114 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
4115 # except ClientException as e:
4120 @cli_osm.command(name
="repo-list")
4125 help="restricts the list to the repos matching the filter",
4127 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4129 def repo_list(ctx
, filter, literal
):
4130 """list all repos"""
4133 check_client_version(ctx
.obj
, ctx
.command
.name
)
4135 filter = "&".join(filter)
4136 resp
= ctx
.obj
.repo
.list(filter)
4137 resp
+= ctx
.obj
.osmrepo
.list(filter)
4139 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4141 table
= PrettyTable(["Name", "Id", "Type", "URI", "Description"])
4143 # cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
4150 trunc_text(repo
.get("description") or "", 40),
4156 # except ClientException as e:
4161 @cli_osm.command(name
="repo-show", short_help
="shows the details of a repo")
4162 @click.argument("name")
4163 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4165 def repo_show(ctx
, name
, literal
):
4166 """shows the details of a repo
4168 NAME: name or ID of the repo
4171 resp
= ctx
.obj
.repo
.get(name
)
4173 resp
= ctx
.obj
.osmrepo
.get(name
)
4177 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4179 table
= PrettyTable(["key", "attribute"])
4181 for k
, v
in list(resp
.items()):
4182 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4186 # except ClientException as e:
4191 ####################
4192 # Project mgmt operations
4193 ####################
4196 @cli_osm.command(name
="project-create", short_help
="creates a new project")
4197 @click.argument("name")
4198 # @click.option('--description',
4199 # default='no description',
4200 # help='human readable description')
4201 @click.option("--domain-name", "domain_name", default
=None, help="assign to a domain")
4207 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
4208 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos",
4211 def project_create(ctx
, name
, domain_name
, quotas
):
4212 """Creates a new project
4214 NAME: name of the project
4215 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
4216 QUOTAS: set quotas for the project
4219 project
= {"name": name
}
4221 project
["domain_name"] = domain_name
4222 quotas_dict
= _process_project_quotas(quotas
)
4224 project
["quotas"] = quotas_dict
4227 check_client_version(ctx
.obj
, ctx
.command
.name
)
4228 ctx
.obj
.project
.create(name
, project
)
4229 # except ClientException as e:
4234 def _process_project_quotas(quota_list
):
4239 for quota
in quota_list
:
4240 for single_quota
in quota
.split(","):
4241 k
, v
= single_quota
.split("=")
4242 quotas_dict
[k
] = None if v
in ("None", "null", "") else int(v
)
4243 except (ValueError, TypeError):
4244 raise ClientException(
4245 "invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null"
4250 @cli_osm.command(name
="project-delete", short_help
="deletes a project")
4251 @click.argument("name")
4252 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4254 def project_delete(ctx
, name
):
4255 """deletes a project
4257 NAME: name or ID of the project to be deleted
4261 check_client_version(ctx
.obj
, ctx
.command
.name
)
4262 ctx
.obj
.project
.delete(name
)
4263 # except ClientException as e:
4268 @cli_osm.command(name
="project-list", short_help
="list all projects")
4273 help="restricts the list to the projects matching the filter",
4276 def project_list(ctx
, filter):
4277 """list all projects"""
4280 check_client_version(ctx
.obj
, ctx
.command
.name
)
4282 filter = "&".join(filter)
4283 resp
= ctx
.obj
.project
.list(filter)
4284 # except ClientException as e:
4287 table
= PrettyTable(["name", "id"])
4289 table
.add_row([proj
["name"], proj
["_id"]])
4294 @cli_osm.command(name
="project-show", short_help
="shows the details of a project")
4295 @click.argument("name")
4297 def project_show(ctx
, name
):
4298 """shows the details of a project
4300 NAME: name or ID of the project
4304 check_client_version(ctx
.obj
, ctx
.command
.name
)
4305 resp
= ctx
.obj
.project
.get(name
)
4306 # except ClientException as e:
4310 table
= PrettyTable(["key", "attribute"])
4311 for k
, v
in resp
.items():
4312 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4318 name
="project-update", short_help
="updates a project (only the name can be updated)"
4320 @click.argument("project")
4321 @click.option("--name", default
=None, help="new name for the project")
4327 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
4328 "(use empty to reset quota to default",
4331 def project_update(ctx
, project
, name
, quotas
):
4333 Update a project name
4336 :param project: id or name of the project to modify
4337 :param name: new name for the project
4338 :param quotas: change quotas of the project
4342 project_changes
= {}
4344 project_changes
["name"] = name
4345 quotas_dict
= _process_project_quotas(quotas
)
4347 project_changes
["quotas"] = quotas_dict
4350 check_client_version(ctx
.obj
, ctx
.command
.name
)
4351 ctx
.obj
.project
.update(project
, project_changes
)
4352 # except ClientException as e:
4356 ####################
4357 # User mgmt operations
4358 ####################
4361 @cli_osm.command(name
="user-create", short_help
="creates a new user")
4362 @click.argument("username")
4367 confirmation_prompt
=True,
4368 help="user password",
4372 # prompt="Comma separate list of projects",
4374 callback
=lambda ctx
, param
, value
: "".join(value
).split(",")
4375 if all(len(x
) == 1 for x
in value
)
4377 help="list of project ids that the user belongs to",
4380 "--project-role-mappings",
4381 "project_role_mappings",
4384 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4386 @click.option("--domain-name", "domain_name", default
=None, help="assign to a domain")
4388 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
4389 """Creates a new user
4392 USERNAME: name of the user
4393 PASSWORD: password of the user
4394 PROJECTS: projects assigned to user (internal only)
4395 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
4396 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
4400 user
["username"] = username
4401 user
["password"] = password
4402 user
["projects"] = projects
4403 user
["project_role_mappings"] = project_role_mappings
4405 user
["domain_name"] = domain_name
4408 check_client_version(ctx
.obj
, ctx
.command
.name
)
4409 ctx
.obj
.user
.create(username
, user
)
4410 # except ClientException as e:
4415 @cli_osm.command(name
="user-update", short_help
="updates user information")
4416 @click.argument("username")
4421 # confirmation_prompt=True,
4422 help="user password",
4424 @click.option("--set-username", "set_username", default
=None, help="change username")
4430 help="create/replace the roles for this project: 'project,role1[,role2,...]'",
4437 help="removes project from user: 'project'",
4440 "--add-project-role",
4444 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4447 "--remove-project-role",
4448 "remove_project_role",
4451 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4462 remove_project_role
,
4464 """Update a user information
4467 USERNAME: name of the user
4468 PASSWORD: new password
4469 SET_USERNAME: new username
4470 SET_PROJECT: creating mappings for project/role(s)
4471 REMOVE_PROJECT: deleting mappings for project/role(s)
4472 ADD_PROJECT_ROLE: adding mappings for project/role(s)
4473 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
4477 user
["password"] = password
4478 user
["username"] = set_username
4479 user
["set-project"] = set_project
4480 user
["remove-project"] = remove_project
4481 user
["add-project-role"] = add_project_role
4482 user
["remove-project-role"] = remove_project_role
4485 check_client_version(ctx
.obj
, ctx
.command
.name
)
4486 ctx
.obj
.user
.update(username
, user
)
4487 # except ClientException as e:
4492 @cli_osm.command(name
="user-delete", short_help
="deletes a user")
4493 @click.argument("name")
4494 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4496 def user_delete(ctx
, name
):
4500 NAME: name or ID of the user to be deleted
4504 check_client_version(ctx
.obj
, ctx
.command
.name
)
4505 ctx
.obj
.user
.delete(name
)
4506 # except ClientException as e:
4511 @cli_osm.command(name
="user-list", short_help
="list all users")
4516 help="restricts the list to the users matching the filter",
4519 def user_list(ctx
, filter):
4520 """list all users"""
4522 check_client_version(ctx
.obj
, ctx
.command
.name
)
4524 filter = "&".join(filter)
4525 resp
= ctx
.obj
.user
.list(filter)
4526 # except ClientException as e:
4529 table
= PrettyTable(["name", "id"])
4531 table
.add_row([user
["username"], user
["_id"]])
4536 @cli_osm.command(name
="user-show", short_help
="shows the details of a user")
4537 @click.argument("name")
4539 def user_show(ctx
, name
):
4540 """shows the details of a user
4542 NAME: name or ID of the user
4546 check_client_version(ctx
.obj
, ctx
.command
.name
)
4547 resp
= ctx
.obj
.user
.get(name
)
4548 if "password" in resp
:
4549 resp
["password"] = "********"
4550 # except ClientException as e:
4554 table
= PrettyTable(["key", "attribute"])
4555 for k
, v
in resp
.items():
4556 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4561 ####################
4562 # Fault Management operations
4563 ####################
4566 @cli_osm.command(name
="ns-alarm-create")
4567 @click.argument("name")
4568 @click.option("--ns", prompt
=True, help="NS instance id or name")
4570 "--vnf", prompt
=True, help="VNF name (VNF member index as declared in the NSD)"
4572 @click.option("--vdu", prompt
=True, help="VDU name (VDU name as declared in the VNFD)")
4573 @click.option("--metric", prompt
=True, help="Name of the metric (e.g. cpu_utilization)")
4577 help="severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)",
4580 "--threshold_value",
4582 help="threshold value that, when crossed, an alarm is triggered",
4585 "--threshold_operator",
4587 help="threshold operator describing the comparison (GE, LE, GT, LT, EQ)",
4592 help="statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)",
4595 def ns_alarm_create(
4607 """creates a new alarm for a NS instance"""
4608 # TODO: Check how to validate threshold_value.
4609 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
4612 ns_instance
= ctx
.obj
.ns
.get(ns
)
4614 alarm
["alarm_name"] = name
4615 alarm
["ns_id"] = ns_instance
["_id"]
4616 alarm
["correlation_id"] = ns_instance
["_id"]
4617 alarm
["vnf_member_index"] = vnf
4618 alarm
["vdu_name"] = vdu
4619 alarm
["metric_name"] = metric
4620 alarm
["severity"] = severity
4621 alarm
["threshold_value"] = int(threshold_value
)
4622 alarm
["operation"] = threshold_operator
4623 alarm
["statistic"] = statistic
4624 check_client_version(ctx
.obj
, ctx
.command
.name
)
4625 ctx
.obj
.ns
.create_alarm(alarm
)
4626 # except ClientException as e:
4631 # @cli_osm.command(name='ns-alarm-delete')
4632 # @click.argument('name')
4633 # @click.pass_context
4634 # def ns_alarm_delete(ctx, name):
4635 # """deletes an alarm
4637 # NAME: name of the alarm to be deleted
4640 # check_client_version(ctx.obj, ctx.command.name)
4641 # ctx.obj.ns.delete_alarm(name)
4642 # except ClientException as e:
4647 ####################
4648 # Performance Management operations
4649 ####################
4653 name
="ns-metric-export",
4654 short_help
="exports a metric to the internal OSM bus, which can be read by other apps",
4656 @click.option("--ns", prompt
=True, help="NS instance id or name")
4658 "--vnf", prompt
=True, help="VNF name (VNF member index as declared in the NSD)"
4660 @click.option("--vdu", prompt
=True, help="VDU name (VDU name as declared in the VNFD)")
4661 @click.option("--metric", prompt
=True, help="name of the metric (e.g. cpu_utilization)")
4662 # @click.option('--period', default='1w',
4663 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
4665 "--interval", help="periodic interval (seconds) to export metrics continuously"
4668 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
4669 """exports a metric to the internal OSM bus, which can be read by other apps"""
4670 # TODO: Check how to validate interval.
4671 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
4674 ns_instance
= ctx
.obj
.ns
.get(ns
)
4676 metric_data
["ns_id"] = ns_instance
["_id"]
4677 metric_data
["correlation_id"] = ns_instance
["_id"]
4678 metric_data
["vnf_member_index"] = vnf
4679 metric_data
["vdu_name"] = vdu
4680 metric_data
["metric_name"] = metric
4681 metric_data
["collection_unit"] = "WEEK"
4682 metric_data
["collection_period"] = 1
4683 check_client_version(ctx
.obj
, ctx
.command
.name
)
4685 print("{}".format(ctx
.obj
.ns
.export_metric(metric_data
)))
4689 print("{} {}".format(ctx
.obj
.ns
.export_metric(metric_data
), i
))
4690 time
.sleep(int(interval
))
4692 # except ClientException as e:
4697 ####################
4699 ####################
4702 @cli_osm.command(name
="version", short_help
="shows client and server versions")
4704 def get_version(ctx
):
4705 """shows client and server versions"""
4707 check_client_version(ctx
.obj
, "version")
4708 print("Server version: {}".format(ctx
.obj
.get_version()))
4710 "Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
)
4712 # except ClientException as e:
4718 name
="upload-package", short_help
="uploads a VNF package or NS package"
4720 @click.argument("filename")
4722 "--skip-charm-build",
4725 help="the charm will not be compiled, it is assumed to already exist",
4728 def upload_package(ctx
, filename
, skip_charm_build
):
4729 """uploads a vnf package or ns package
4731 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
4735 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
4736 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
4737 if fullclassname
!= "osmclient.sol005.client.Client":
4738 ctx
.obj
.package
.wait_for_upload(filename
)
4739 # except ClientException as e:
4744 # @cli_osm.command(name='ns-scaling-show')
4745 # @click.argument('ns_name')
4746 # @click.pass_context
4747 # def show_ns_scaling(ctx, ns_name):
4748 # """shows the status of a NS scaling operation
4750 # NS_NAME: name of the NS instance being scaled
4753 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4754 # resp = ctx.obj.ns.list()
4755 # except ClientException as e:
4759 # table = PrettyTable(
4762 # 'operational status',
4767 # if ns_name == ns['name']:
4768 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
4769 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
4770 # for record in scaling_records:
4771 # if 'instance' in record:
4772 # instances = record['instance']
4773 # for inst in instances:
4775 # [record['scaling-group-name-ref'],
4776 # inst['instance-id'],
4777 # inst['op-status'],
4778 # time.strftime('%Y-%m-%d %H:%M:%S',
4780 # inst['create-time'])),
4786 # @cli_osm.command(name='ns-scale')
4787 # @click.argument('ns_name')
4788 # @click.option('--ns_scale_group', prompt=True)
4789 # @click.option('--index', prompt=True)
4790 # @click.option('--wait',
4794 # help='do not return the control immediately, but keep it \
4795 # until the operation is completed, or timeout')
4796 # @click.pass_context
4797 # def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
4800 # NS_NAME: name of the NS instance to be scaled
4803 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4804 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
4805 # except ClientException as e:
4810 # @cli_osm.command(name='config-agent-list')
4811 # @click.pass_context
4812 # def config_agent_list(ctx):
4813 # """list config agents"""
4815 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4816 # except ClientException as e:
4819 # table = PrettyTable(['name', 'account-type', 'details'])
4820 # for account in ctx.obj.vca.list():
4823 # account['account-type'],
4829 # @cli_osm.command(name='config-agent-delete')
4830 # @click.argument('name')
4831 # @click.pass_context
4832 # def config_agent_delete(ctx, name):
4833 # """deletes a config agent
4835 # NAME: name of the config agent to be deleted
4838 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4839 # ctx.obj.vca.delete(name)
4840 # except ClientException as e:
4845 # @cli_osm.command(name='config-agent-add')
4846 # @click.option('--name',
4848 # @click.option('--account_type',
4850 # @click.option('--server',
4852 # @click.option('--user',
4854 # @click.option('--secret',
4857 # confirmation_prompt=True)
4858 # @click.pass_context
4859 # def config_agent_add(ctx, name, account_type, server, user, secret):
4860 # """adds a config agent"""
4862 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4863 # ctx.obj.vca.create(name, account_type, server, user, secret)
4864 # except ClientException as e:
4869 # @cli_osm.command(name='ro-dump')
4870 # @click.pass_context
4872 # """shows RO agent information"""
4873 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4874 # resp = ctx.obj.vim.get_resource_orchestrator()
4875 # table = PrettyTable(['key', 'attribute'])
4876 # for k, v in list(resp.items()):
4877 # table.add_row([k, json.dumps(v, indent=2)])
4882 # @cli_osm.command(name='vcs-list')
4883 # @click.pass_context
4884 # def vcs_list(ctx):
4885 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4886 # resp = ctx.obj.utils.get_vcs_info()
4887 # table = PrettyTable(['component name', 'state'])
4888 # for component in resp:
4889 # table.add_row([component['component_name'], component['state']])
4895 name
="ns-action", short_help
="executes an action/primitive over a NS instance"
4897 @click.argument("ns_name")
4901 help="member-vnf-index if the target is a vnf instead of a ns)",
4903 @click.option("--kdu_name", default
=None, help="kdu-name if the target is a kdu)")
4904 @click.option("--vdu_id", default
=None, help="vdu-id if the target is a vdu")
4906 "--vdu_count", default
=None, type=int, help="number of vdu instance of this vdu_id"
4908 @click.option("--action_name", prompt
=True, help="action name")
4909 @click.option("--params", default
=None, help="action params in YAML/JSON inline string")
4910 @click.option("--params_file", default
=None, help="YAML/JSON file with action params")
4912 "--timeout", required
=False, default
=None, type=int, help="timeout in seconds"
4919 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
4935 """executes an action/primitive over a NS instance
4937 NS_NAME: name or ID of the NS instance
4941 check_client_version(ctx
.obj
, ctx
.command
.name
)
4944 op_data
["member_vnf_index"] = vnf_name
4946 op_data
["kdu_name"] = kdu_name
4948 op_data
["vdu_id"] = vdu_id
4949 if vdu_count
is not None:
4950 op_data
["vdu_count_index"] = vdu_count
4952 op_data
["timeout_ns_action"] = timeout
4953 op_data
["primitive"] = action_name
4955 with
open(params_file
, "r") as pf
:
4958 op_data
["primitive_params"] = yaml
.safe_load(params
)
4960 op_data
["primitive_params"] = {}
4961 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
="action", op_data
=op_data
, wait
=wait
))
4963 # except ClientException as e:
4969 name
="vnf-scale", short_help
="executes a VNF scale (adding/removing VDUs)"
4971 @click.argument("ns_name")
4972 @click.argument("vnf_name")
4974 "--scaling-group", prompt
=True, help="scaling-group-descriptor name to use"
4977 "--scale-in", default
=False, is_flag
=True, help="performs a scale in operation"
4983 help="performs a scale out operation (by default)",
4986 "--timeout", required
=False, default
=None, type=int, help="timeout in seconds"
4993 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
4997 ctx
, ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, timeout
, wait
5000 Executes a VNF scale (adding/removing VDUs)
5003 NS_NAME: name or ID of the NS instance.
5004 VNF_NAME: member-vnf-index in the NS to be scaled.
5008 check_client_version(ctx
.obj
, ctx
.command
.name
)
5009 if not scale_in
and not scale_out
:
5011 ctx
.obj
.ns
.scale_vnf(
5012 ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
5014 # except ClientException as e:
5019 ##############################
5020 # Role Management Operations #
5021 ##############################
5024 @cli_osm.command(name
="role-create", short_help
="creates a new role")
5025 @click.argument("name")
5026 @click.option("--permissions", default
=None, help="role permissions using a dictionary")
5028 def role_create(ctx
, name
, permissions
):
5033 NAME: Name or ID of the role.
5034 DEFINITION: Definition of grant/denial of access to resources.
5038 check_client_version(ctx
.obj
, ctx
.command
.name
)
5039 ctx
.obj
.role
.create(name
, permissions
)
5040 # except ClientException as e:
5045 @cli_osm.command(name
="role-update", short_help
="updates a role")
5046 @click.argument("name")
5047 @click.option("--set-name", default
=None, help="change name of rle")
5048 # @click.option('--permissions',
5050 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
5054 help="yaml format dictionary with permission: True/False to access grant/denial",
5056 @click.option("--remove", default
=None, help="yaml format list to remove a permission")
5058 def role_update(ctx
, name
, set_name
, add
, remove
):
5063 NAME: Name or ID of the role.
5064 DEFINITION: Definition overwrites the old definition.
5065 ADD: Grant/denial of access to resource to add.
5066 REMOVE: Grant/denial of access to resource to remove.
5070 check_client_version(ctx
.obj
, ctx
.command
.name
)
5071 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
5072 # except ClientException as e:
5077 @cli_osm.command(name
="role-delete", short_help
="deletes a role")
5078 @click.argument("name")
5079 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
5081 def role_delete(ctx
, name
):
5086 NAME: Name or ID of the role.
5090 check_client_version(ctx
.obj
, ctx
.command
.name
)
5091 ctx
.obj
.role
.delete(name
)
5092 # except ClientException as e:
5097 @cli_osm.command(name
="role-list", short_help
="list all roles")
5102 help="restricts the list to the projects matching the filter",
5105 def role_list(ctx
, filter):
5111 check_client_version(ctx
.obj
, ctx
.command
.name
)
5113 filter = "&".join(filter)
5114 resp
= ctx
.obj
.role
.list(filter)
5115 # except ClientException as e:
5118 table
= PrettyTable(["name", "id"])
5120 table
.add_row([role
["name"], role
["_id"]])
5125 @cli_osm.command(name
="role-show", short_help
="show specific role")
5126 @click.argument("name")
5128 def role_show(ctx
, name
):
5130 Shows the details of a role.
5133 NAME: Name or ID of the role.
5137 check_client_version(ctx
.obj
, ctx
.command
.name
)
5138 resp
= ctx
.obj
.role
.get(name
)
5139 # except ClientException as e:
5143 table
= PrettyTable(["key", "attribute"])
5144 for k
, v
in resp
.items():
5145 table
.add_row([k
, json
.dumps(v
, indent
=2)])
5150 @cli_osm.command(name
="package-create", short_help
="Create empty NS package structure")
5151 @click.argument("package-type")
5152 @click.argument("package-name")
5156 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'),
5160 default
="image-name",
5161 help='(VNF) Set the name of the vdu image. Default "image-name"',
5164 "--vdus", default
=1, help="(VNF) Set the number of vdus in a VNF. Default 1"
5167 "--vcpu", default
=1, help="(VNF) Set the number of virtual CPUs in a vdu. Default 1"
5172 help="(VNF) Set the memory size (MB) of the vdu. Default 1024",
5175 "--storage", default
=10, help="(VNF) Set the disk size (GB) of the vdu. Default 10"
5180 help="(VNF) Set the number of additional interfaces apart from the management interface. Default 0",
5183 "--vendor", default
="OSM", help='(NS/VNF) Set the descriptor vendor. Default "OSM"'
5189 help="(NS/VNF/NST) Flag for overriding the package if exists.",
5195 help="(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options",
5198 "--netslice-subnets", default
=1, help="(NST) Number of netslice subnets. Default 1"
5201 "--netslice-vlds", default
=1, help="(NST) Number of netslice vlds. Default 1"
5222 Creates an OSM NS, VNF, NST package
5225 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
5226 PACKAGE_NAME: Name of the package to create the folder with the content.
5231 check_client_version(ctx
.obj
, ctx
.command
.name
)
5233 "Creating the {} structure: {}/{}".format(
5234 package_type
.upper(), base_directory
, package_name
5237 resp
= ctx
.obj
.package_tool
.create(
5247 interfaces
=interfaces
,
5250 netslice_subnets
=netslice_subnets
,
5251 netslice_vlds
=netslice_vlds
,
5254 # except ClientException as inst:
5255 # print("ERROR: {}".format(inst))
5260 name
="package-validate", short_help
="Validate descriptors given a base directory"
5262 @click.argument("base-directory", default
=".", required
=False)
5264 "--recursive/--no-recursive",
5266 help="The activated recursive option will validate the yaml files"
5267 " within the indicated directory and in its subdirectories",
5273 help="Validates also the descriptors using the previous OSM format (pre SOL006)",
5276 def package_validate(ctx
, base_directory
, recursive
, old
):
5278 Validate descriptors given a base directory.
5281 BASE_DIRECTORY: Base folder for NS, VNF or NST package.
5285 check_client_version(ctx
.obj
, ctx
.command
.name
)
5286 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
, old
)
5287 table
= PrettyTable()
5288 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
5289 # Print the dictionary generated by the validation function
5290 for result
in results
:
5292 [result
["type"], result
["path"], result
["valid"], result
["error"]]
5294 table
.sortby
= "VALID"
5295 table
.align
["PATH"] = "l"
5296 table
.align
["TYPE"] = "l"
5297 table
.align
["ERROR"] = "l"
5299 # except ClientException as inst:
5300 # print("ERROR: {}".format(inst))
5305 name
="package-translate", short_help
="Translate descriptors given a base directory"
5307 @click.argument("base-directory", default
=".", required
=False)
5309 "--recursive/--no-recursive",
5311 help="The activated recursive option will translate the yaml files"
5312 " within the indicated directory and in its subdirectories",
5318 help="Do not translate yet, only make a dry-run to test translation",
5321 def package_translate(ctx
, base_directory
, recursive
, dryrun
):
5323 Translate descriptors given a base directory.
5326 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
5329 check_client_version(ctx
.obj
, ctx
.command
.name
)
5330 results
= ctx
.obj
.package_tool
.translate(base_directory
, recursive
, dryrun
)
5331 table
= PrettyTable()
5332 table
.field_names
= [
5340 # Print the dictionary generated by the validation function
5341 for result
in results
:
5344 result
["current type"],
5348 result
["translated"],
5352 table
.sortby
= "TRANSLATED"
5353 table
.align
["PATH"] = "l"
5354 table
.align
["TYPE"] = "l"
5355 table
.align
["ERROR"] = "l"
5357 # except ClientException as inst:
5358 # print("ERROR: {}".format(inst))
5362 @cli_osm.command(name
="package-build", short_help
="Build the tar.gz of the package")
5363 @click.argument("package-folder")
5365 "--skip-validation", default
=False, is_flag
=True, help="skip package validation"
5368 "--skip-charm-build",
5371 help="the charm will not be compiled, it is assumed to already exist",
5374 def package_build(ctx
, package_folder
, skip_validation
, skip_charm_build
):
5376 Build the package NS, VNF given the package_folder.
5379 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
5383 check_client_version(ctx
.obj
, ctx
.command
.name
)
5384 results
= ctx
.obj
.package_tool
.build(
5386 skip_validation
=skip_validation
,
5387 skip_charm_build
=skip_charm_build
,
5390 # except ClientException as inst:
5391 # print("ERROR: {}".format(inst))
5396 name
="descriptor-translate",
5397 short_help
="Translate input descriptor file from Rel EIGHT OSM descriptors to SOL006 and prints in standard output",
5399 @click.argument("descriptor-file", required
=True)
5401 def descriptor_translate(ctx
, descriptor_file
):
5403 Translate input descriptor.
5406 DESCRIPTOR_FILE: Descriptor file for NS, VNF or Network Slice.
5409 check_client_version(ctx
.obj
, ctx
.command
.name
)
5410 result
= ctx
.obj
.package_tool
.descriptor_translate(descriptor_file
)
5418 except pycurl
.error
as exc
:
5421 'Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified'
5423 except ClientException
as exc
:
5424 print("ERROR: {}".format(exc
))
5425 except (FileNotFoundError
, PermissionError
) as exc
:
5426 print("Cannot open file: {}".format(exc
))
5427 except yaml
.YAMLError
as exc
:
5428 print("Invalid YAML format: {}".format(exc
))
5430 # TODO capture other controlled exceptions here
5431 # TODO remove the ClientException captures from all places, unless they do something different
5434 if __name__
== "__main__":