1 # Copyright 2017-2018 Sandvine
2 # Copyright 2018 Telefonica
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
22 from osmclient
import client
23 from osmclient
.common
.exceptions
import ClientException
, NotFound
24 from prettytable
import PrettyTable
33 from datetime
import datetime
34 from typing
import Any
, Dict
37 def wrap_text(text
, width
):
38 wrapper
= textwrap
.TextWrapper(width
=width
)
39 lines
= text
.splitlines()
40 return "\n".join(map(wrapper
.fill
, lines
))
43 def trunc_text(text
, length
):
44 if len(text
) > length
:
45 return text
[: (length
- 3)] + "..."
50 def check_client_version(obj
, what
, version
="sol005"):
52 Checks the version of the client object and raises error if it not the expected.
54 :param obj: the client object
55 :what: the function or command under evaluation (used when an error is raised)
57 :raises ClientError: if the specified version does not match the client version
60 fullclassname
= obj
.__module
__ + "." + obj
.__class
__.__name
__
61 message
= 'The following commands or options are only supported with the option "--sol005": {}'.format(
65 message
= 'The following commands or options are not supported when using option "--sol005": {}'.format(
68 if fullclassname
!= "osmclient.{}.client.Client".format(version
):
69 raise ClientException(message
)
73 def get_project(project_list
, item
):
74 # project_list = ctx.obj.project.list()
75 item_project_list
= item
.get("_admin", {}).get("projects_read")
79 for p1
in item_project_list
:
81 for p2
in project_list
:
82 if p2
["_id"] == project_id
:
83 project_name
= p2
["name"]
84 return project_id
, project_name
85 return project_id
, project_name
88 def get_vim_name(vim_list
, vim_id
):
91 if v
["uuid"] == vim_id
:
98 context_settings
=dict(help_option_names
=["-h", "--help"], max_content_width
=160)
103 envvar
="OSM_HOSTNAME",
104 help="hostname of server. " + "Also can set OSM_HOSTNAME in environment",
106 # @click.option('--sol005/--no-sol005',
108 # envvar='OSM_SOL005',
109 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
110 # 'Also can set OSM_SOL005 in environment')
115 help="user (defaults to admin). " + "Also can set OSM_USER in environment",
120 envvar
="OSM_PASSWORD",
121 help="password (defaults to admin). " + "Also can set OSM_PASSWORD in environment",
126 envvar
="OSM_PROJECT",
127 help="project (defaults to admin). " + "Also can set OSM_PROJECT in environment",
133 help="increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)",
135 @click.option("--all-projects", default
=None, is_flag
=True, help="include all projects")
137 "--public/--no-public",
139 help="flag for public items (packages, instances, VIM accounts, etc.)",
142 "--project-domain-name",
143 "project_domain_name",
145 envvar
="OSM_PROJECT_DOMAIN_NAME",
146 help="project domain name for keystone authentication (default to None). "
147 + "Also can set OSM_PROJECT_DOMAIN_NAME in environment",
150 "--user-domain-name",
153 envvar
="OSM_USER_DOMAIN_NAME",
154 help="user domain name for keystone authentication (default to None). "
155 + "Also can set OSM_USER_DOMAIN_NAME in environment",
157 # @click.option('--so-port',
159 # envvar='OSM_SO_PORT',
160 # help='hostname of server. ' +
161 # 'Also can set OSM_SO_PORT in environment')
162 # @click.option('--so-project',
164 # envvar='OSM_SO_PROJECT',
165 # help='Project Name in SO. ' +
166 # 'Also can set OSM_SO_PROJECT in environment')
167 # @click.option('--ro-hostname',
169 # envvar='OSM_RO_HOSTNAME',
170 # help='hostname of RO server. ' +
171 # 'Also can set OSM_RO_HOSTNAME in environment')
172 # @click.option('--ro-port',
174 # envvar='OSM_RO_PORT',
175 # help='hostname of RO server. ' +
176 # 'Also can set OSM_RO_PORT in environment')
178 def cli_osm(ctx
, **kwargs
):
180 hostname
= kwargs
.pop("hostname", None)
184 "either hostname option or OSM_HOSTNAME "
185 + "environment variable needs to be specified"
190 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
191 # if so_port is not None:
192 # kwargs['so_port']=so_port
193 # if so_project is not None:
194 # kwargs['so_project']=so_project
195 # if ro_hostname is not None:
196 # kwargs['ro_host']=ro_hostname
197 # if ro_port is not None:
198 # kwargs['ro_port']=ro_port
199 sol005
= os
.getenv("OSM_SOL005", True)
200 # if user is not None:
201 # kwargs['user']=user
202 # if password is not None:
203 # kwargs['password']=password
204 # if project is not None:
205 # kwargs['project']=project
207 # kwargs['all_projects']=all_projects
208 # if public is not None:
209 # kwargs['public']=public
210 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
211 logger
= logging
.getLogger("osmclient")
219 @cli_osm.command(name
="ns-list", short_help
="list all NS instances")
224 help="restricts the list to the NS instances matching the filter.",
229 help="get more details of the NS (project, vim, deployment status, configuration status.",
232 def ns_list(ctx
, filter, long):
233 """list all NS instances
237 --filter filterExpr Restricts the list to the NS instances matching the filter
240 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
241 concatenated using the "&" character:
244 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
245 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
246 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
248 value := scalar value
252 * zero or more occurrences
253 ? zero or one occurrence
254 [] grouping of expressions to be used with ? and *
255 "" quotation marks for marking string constants
259 "AttrName" is the name of one attribute in the data type that defines the representation
260 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
261 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
262 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
263 entries, it means that the operator "op" is applied to the attribute addressed by the last
264 <attrName> entry included in the concatenation. All simple filter expressions are combined
265 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
266 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
267 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
268 prefix". If an attribute referenced in an expression is an array, an object that contains a
269 corresponding array shall be considered to match the expression if any of the elements in the
270 array matches all expressions that have the same attribute prefix.
274 --filter admin-status=ENABLED
275 --filter nsd-ref=<NSD_NAME>
276 --filter nsd.vendor=<VENDOR>
277 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
278 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
281 def summarize_deployment_status(status_dict
):
288 net_list
= status_dict
.get("nets", [])
291 if net
["status"] not in status_nets
:
292 status_nets
[net
["status"]] = 1
294 status_nets
[net
["status"]] += 1
296 for k
, v
in status_nets
.items():
297 message
+= "{}:{},".format(k
, v
)
298 message
+= "TOTAL:{}".format(n_nets
)
299 summary
+= "{}".format(message
)
304 vnf_list
= status_dict
["vnfs"]
306 member_vnf_index
= vnf
["member_vnf_index"]
307 if member_vnf_index
not in status_vnfs
:
308 status_vnfs
[member_vnf_index
] = {}
309 for vm
in vnf
["vms"]:
311 if vm
["status"] not in status_vms
:
312 status_vms
[vm
["status"]] = 1
314 status_vms
[vm
["status"]] += 1
315 if vm
["status"] not in status_vnfs
[member_vnf_index
]:
316 status_vnfs
[member_vnf_index
][vm
["status"]] = 1
318 status_vnfs
[member_vnf_index
][vm
["status"]] += 1
320 for k
, v
in status_vms
.items():
321 message
+= "{}:{},".format(k
, v
)
322 message
+= "TOTAL:{}".format(n_vms
)
323 summary
+= "\n{}".format(message
)
325 for k
, v
in status_vnfs
.items():
327 message
= "\n {} VMs: ".format(k
)
328 for k2
, v2
in v
.items():
329 message
+= "{}:{},".format(k2
, v2
)
331 message
+= "TOTAL:{}".format(total
)
335 def summarize_config_status(ee_list
):
343 if ee
["elementType"] not in status_ee
:
344 status_ee
[ee
["elementType"]] = {}
345 status_ee
[ee
["elementType"]][ee
["status"]] = 1
347 if ee
["status"] in status_ee
[ee
["elementType"]]:
348 status_ee
[ee
["elementType"]][ee
["status"]] += 1
350 status_ee
[ee
["elementType"]][ee
["status"]] = 1
351 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
352 if elementType
in status_ee
:
355 for k
, v
in status_ee
[elementType
].items():
356 message
+= "{}:{},".format(k
, v
)
358 message
+= "TOTAL:{}\n".format(total
)
359 summary
+= "{}: {}".format(elementType
, message
)
360 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
365 check_client_version(ctx
.obj
, "--filter")
366 filter = "&".join(filter)
367 resp
= ctx
.obj
.ns
.list(filter)
369 resp
= ctx
.obj
.ns
.list()
382 "configuration status",
385 project_list
= ctx
.obj
.project
.list()
387 vim_list
= ctx
.obj
.vim
.list()
402 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
403 if fullclassname
== "osmclient.sol005.client.Client":
405 logger
.debug("NS info: {}".format(nsr
))
406 nsr_name
= nsr
["name"]
408 date
= datetime
.fromtimestamp(nsr
["create-time"]).strftime(
411 ns_state
= nsr
.get("nsState", nsr
["_admin"]["nsState"])
413 deployment_status
= summarize_deployment_status(
414 nsr
.get("deploymentStatus")
416 config_status
= summarize_config_status(nsr
.get("configurationStatus"))
417 project_id
, project_name
= get_project(project_list
, nsr
)
418 # project = '{} ({})'.format(project_name, project_id)
419 project
= project_name
420 vim_id
= nsr
.get("datacenter")
421 vim_name
= get_vim_name(vim_list
, vim_id
)
423 # vim = '{} ({})'.format(vim_name, vim_id)
425 if "currentOperation" in nsr
:
426 current_operation
= "{} ({})".format(
427 nsr
["currentOperation"], nsr
["currentOperationID"]
430 current_operation
= "{} ({})".format(
431 nsr
["_admin"].get("current-operation", "-"),
432 nsr
["_admin"]["nslcmop"],
434 error_details
= "N/A"
437 or ns_state
== "DEGRADED"
438 or ("currentOperation" not in nsr
and nsr
.get("errorDescription"))
440 error_details
= "{}\nDetail: {}".format(
441 nsr
["errorDescription"], nsr
["errorDetail"]
444 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
["id"])
445 nsr
= nsopdata
["nsr:nsr"]
446 nsr_name
= nsr
["name-ref"]
447 nsr_id
= nsr
["ns-instance-config-ref"]
450 deployment_status
= (
451 nsr
["operational-status"]
452 if "operational-status" in nsr
455 ns_state
= deployment_status
456 config_status
= nsr
.get("config-status", "Not found")
457 current_operation
= "Unknown"
458 error_details
= nsr
.get("detailed-status", "Not found")
459 if config_status
== "config_not_needed":
460 config_status
= "configured (no charms)"
470 wrap_text(text
=error_details
, width
=40),
485 wrap_text(text
=error_details
, width
=40),
490 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
492 'For more details on the current operation, run "osm ns-op-show OPERATION_ID"'
496 def nsd_list(ctx
, filter, long):
499 check_client_version(ctx
.obj
, "--filter")
500 filter = "&".join(filter)
501 resp
= ctx
.obj
.nsd
.list(filter)
503 resp
= ctx
.obj
.nsd
.list()
504 # print(yaml.safe_dump(resp))
505 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
506 if fullclassname
== "osmclient.sol005.client.Client":
520 table
= PrettyTable(["nsd name", "id"])
522 name
= nsd
.get("id", "-")
524 onb_state
= nsd
["_admin"].get("onboardingState", "-")
525 op_state
= nsd
["_admin"].get("operationalState", "-")
526 usage_state
= nsd
["_admin"].get("usageState", "-")
527 date
= datetime
.fromtimestamp(nsd
["_admin"]["created"]).strftime(
530 last_update
= datetime
.fromtimestamp(
531 nsd
["_admin"]["modified"]
532 ).strftime("%Y-%m-%dT%H:%M:%S")
545 table
.add_row([name
, nsd
["_id"]])
547 table
= PrettyTable(["nsd name", "id"])
549 table
.add_row([nsd
["name"], nsd
["id"]])
554 @cli_osm.command(name
="nsd-list", short_help
="list all NS packages")
559 help="restricts the list to the NSD/NSpkg matching the filter",
561 @click.option("--long", is_flag
=True, help="get more details")
563 def nsd_list1(ctx
, filter, long):
564 """list all NSD/NS pkg in the system"""
566 nsd_list(ctx
, filter, long)
569 @cli_osm.command(name
="nspkg-list", short_help
="list all NS packages")
574 help="restricts the list to the NSD/NSpkg matching the filter",
576 @click.option("--long", is_flag
=True, help="get more details")
578 def nsd_list2(ctx
, filter, long):
579 """list all NS packages"""
581 nsd_list(ctx
, filter, long)
584 def pkg_repo_list(ctx
, pkgtype
, filter, repo
, long):
585 resp
= ctx
.obj
.osmrepo
.pkg_list(pkgtype
, filter, repo
)
588 ["nfpkg name", "vendor", "version", "latest", "description", "repository"]
591 table
= PrettyTable(["nfpkg name", "repository"])
593 name
= vnfd
.get("id", vnfd
.get("name", "-"))
594 repository
= vnfd
.get("repository")
596 vendor
= vnfd
.get("provider", vnfd
.get("vendor"))
597 version
= vnfd
.get("version")
598 description
= vnfd
.get("description")
599 latest
= vnfd
.get("latest")
600 table
.add_row([name
, vendor
, version
, latest
, description
, repository
])
602 table
.add_row([name
, repository
])
607 def vnfd_list(ctx
, nf_type
, filter, long):
610 check_client_version(ctx
.obj
, "--nf_type")
612 check_client_version(ctx
.obj
, "--filter")
614 filter = "&".join(filter)
617 nf_filter
= "_admin.type=vnfd"
618 elif nf_type
== "pnf":
619 nf_filter
= "_admin.type=pnfd"
620 elif nf_type
== "hnf":
621 nf_filter
= "_admin.type=hnfd"
623 raise ClientException(
624 'wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf'
627 filter = "{}&{}".format(nf_filter
, filter)
631 resp
= ctx
.obj
.vnfd
.list(filter)
633 resp
= ctx
.obj
.vnfd
.list()
634 # print(yaml.safe_dump(resp))
635 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
636 if fullclassname
== "osmclient.sol005.client.Client":
653 table
= PrettyTable(["nfpkg name", "id", "desc type"])
655 name
= vnfd
.get("id", vnfd
.get("name", "-"))
656 descriptor_type
= "sol006" if "product-name" in vnfd
else "rel8"
658 onb_state
= vnfd
["_admin"].get("onboardingState", "-")
659 op_state
= vnfd
["_admin"].get("operationalState", "-")
660 vendor
= vnfd
.get("provider", vnfd
.get("vendor"))
661 version
= vnfd
.get("version")
662 usage_state
= vnfd
["_admin"].get("usageState", "-")
663 date
= datetime
.fromtimestamp(vnfd
["_admin"]["created"]).strftime(
666 last_update
= datetime
.fromtimestamp(
667 vnfd
["_admin"]["modified"]
668 ).strftime("%Y-%m-%dT%H:%M:%S")
684 table
.add_row([name
, vnfd
["_id"], descriptor_type
])
686 table
= PrettyTable(["nfpkg name", "id"])
688 table
.add_row([vnfd
["name"], vnfd
["id"]])
693 @cli_osm.command(name
="vnfd-list", short_help
="list all xNF packages (VNF, HNF, PNF)")
694 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
699 help="restricts the list to the NF pkg matching the filter",
701 @click.option("--long", is_flag
=True, help="get more details")
703 def vnfd_list1(ctx
, nf_type
, filter, long):
704 """list all xNF packages (VNF, HNF, PNF)"""
706 vnfd_list(ctx
, nf_type
, filter, long)
709 @cli_osm.command(name
="vnfpkg-list", short_help
="list all xNF packages (VNF, HNF, PNF)")
710 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
715 help="restricts the list to the NFpkg matching the filter",
717 @click.option("--long", is_flag
=True, help="get more details")
719 def vnfd_list2(ctx
, nf_type
, filter, long):
720 """list all xNF packages (VNF, HNF, PNF)"""
722 vnfd_list(ctx
, nf_type
, filter, long)
725 @cli_osm.command(name
="nfpkg-list", short_help
="list all xNF packages (VNF, HNF, PNF)")
726 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
731 help="restricts the list to the NFpkg matching the filter",
733 @click.option("--long", is_flag
=True, help="get more details")
735 def nfpkg_list(ctx
, nf_type
, filter, long):
736 """list all xNF packages (VNF, HNF, PNF)"""
739 check_client_version(ctx
.obj
, ctx
.command
.name
)
740 vnfd_list(ctx
, nf_type
, filter, long)
741 # except ClientException as e:
747 name
="vnfpkg-repo-list", short_help
="list all xNF from OSM repositories"
753 help="restricts the list to the NFpkg matching the filter",
756 "--repo", default
=None, help="restricts the list to a particular OSM repository"
758 @click.option("--long", is_flag
=True, help="get more details")
760 def nfpkg_repo_list1(ctx
, filter, repo
, long):
761 """list xNF packages from OSM repositories"""
763 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
767 name
="nfpkg-repo-list", short_help
="list all xNF from OSM repositories"
773 help="restricts the list to the NFpkg matching the filter",
776 "--repo", default
=None, help="restricts the list to a particular OSM repository"
778 @click.option("--long", is_flag
=True, help="get more details")
780 def nfpkg_repo_list2(ctx
, filter, repo
, long):
781 """list xNF packages from OSM repositories"""
783 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
786 def vnf_list(ctx
, ns
, filter, long):
790 check_client_version(ctx
.obj
, "--ns")
792 filter = "&".join(filter)
793 check_client_version(ctx
.obj
, "--filter")
794 resp
= ctx
.obj
.vnf
.list(ns
, filter)
796 resp
= ctx
.obj
.vnf
.list()
797 # except ClientException as e:
800 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
801 if fullclassname
== "osmclient.sol005.client.Client":
823 table
= PrettyTable(field_names
)
825 name
= vnfr
["name"] if "name" in vnfr
else "-"
830 vnfr
["member-vnf-index-ref"],
832 vnfr
["vim-account-id"],
836 date
= datetime
.fromtimestamp(vnfr
["_admin"]["created"]).strftime(
839 last_update
= datetime
.fromtimestamp(
840 vnfr
["_admin"]["modified"]
841 ).strftime("%Y-%m-%dT%H:%M:%S")
842 new_row
.extend([date
, last_update
])
843 table
.add_row(new_row
)
845 table
= PrettyTable(["vnf name", "id", "operational status", "config status"])
847 if "mgmt-interface" not in vnfr
:
848 vnfr
["mgmt-interface"] = {}
849 vnfr
["mgmt-interface"]["ip-address"] = None
854 vnfr
["operational-status"],
855 vnfr
["config-status"],
862 @cli_osm.command(name
="vnf-list", short_help
="list all NF instances")
864 "--ns", default
=None, help="NS instance id or name to restrict the NF list"
870 help="restricts the list to the NF instances matching the filter.",
872 @click.option("--long", is_flag
=True, help="get more details")
874 def vnf_list1(ctx
, ns
, filter, long):
875 """list all NF instances"""
877 vnf_list(ctx
, ns
, filter, long)
880 @cli_osm.command(name
="nsd-repo-list", short_help
="list all NS from OSM repositories")
885 help="restricts the list to the NS matching the filter",
888 "--repo", default
=None, help="restricts the list to a particular OSM repository"
890 @click.option("--long", is_flag
=True, help="get more details")
892 def nspkg_repo_list(ctx
, filter, repo
, long):
893 """list xNF packages from OSM repositories"""
895 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
898 @cli_osm.command(name
="nspkg-repo-list", short_help
="list all NS from OSM repositories")
903 help="restricts the list to the NS matching the filter",
906 "--repo", default
=None, help="restricts the list to a particular OSM repository"
908 @click.option("--long", is_flag
=True, help="get more details")
910 def nspkg_repo_list2(ctx
, filter, repo
, long):
911 """list xNF packages from OSM repositories"""
913 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
916 @cli_osm.command(name
="nf-list", short_help
="list all NF instances")
918 "--ns", default
=None, help="NS instance id or name to restrict the NF list"
924 help="restricts the list to the NF instances matching the filter.",
926 @click.option("--long", is_flag
=True, help="get more details")
928 def nf_list(ctx
, ns
, filter, long):
929 """list all NF instances
933 --ns TEXT NS instance id or name to restrict the VNF list
934 --filter filterExpr Restricts the list to the VNF instances matching the filter
937 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
938 concatenated using the "&" character:
941 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
942 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
943 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
945 value := scalar value
949 * zero or more occurrences
950 ? zero or one occurrence
951 [] grouping of expressions to be used with ? and *
952 "" quotation marks for marking string constants
956 "AttrName" is the name of one attribute in the data type that defines the representation
957 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
958 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
959 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
960 entries, it means that the operator "op" is applied to the attribute addressed by the last
961 <attrName> entry included in the concatenation. All simple filter expressions are combined
962 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
963 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
964 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
965 prefix". If an attribute referenced in an expression is an array, an object that contains a
966 corresponding array shall be considered to match the expression if any of the elements in the
967 array matches all expressions that have the same attribute prefix.
971 --filter vim-account-id=<VIM_ACCOUNT_ID>
972 --filter vnfd-ref=<VNFD_NAME>
973 --filter vdur.ip-address=<IP_ADDRESS>
974 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
977 vnf_list(ctx
, ns
, filter, long)
981 name
="ns-op-list", short_help
="shows the history of operations over a NS instance"
983 @click.argument("name")
985 "--long", is_flag
=True, help="get more details of the NS operation (date, )."
988 def ns_op_list(ctx
, name
, long):
989 """shows the history of operations over a NS instance
991 NAME: name or ID of the NS instance
994 def formatParams(params
):
995 if params
["lcmOperationType"] == "instantiate":
996 params
.pop("nsDescription")
1000 elif params
["lcmOperationType"] == "action":
1001 params
.pop("primitive")
1002 params
.pop("lcmOperationType")
1003 params
.pop("nsInstanceId")
1008 check_client_version(ctx
.obj
, ctx
.command
.name
)
1009 resp
= ctx
.obj
.ns
.list_op(name
)
1010 # except ClientException as e:
1015 table
= PrettyTable(
1028 table
= PrettyTable(
1029 ["id", "operation", "action_name", "status", "date", "detail"]
1032 # print(yaml.safe_dump(resp))
1035 if op
["lcmOperationType"] == "action":
1036 action_name
= op
["operationParams"]["primitive"]
1038 if op
["operationState"] == "PROCESSING":
1039 if op
["queuePosition"] is not None and op
["queuePosition"] > 0:
1040 detail
= "In queue. Current position: {}".format(op
["queuePosition"])
1041 elif op
["lcmOperationType"] in ("instantiate", "terminate"):
1043 detail
= op
["stage"]
1044 elif op
["operationState"] in ("FAILED", "FAILED_TEMP"):
1045 detail
= op
.get("errorMessage", "-")
1046 date
= datetime
.fromtimestamp(op
["startTime"]).strftime("%Y-%m-%dT%H:%M:%S")
1047 last_update
= datetime
.fromtimestamp(op
["statusEnteredTime"]).strftime(
1054 op
["lcmOperationType"],
1057 text
=json
.dumps(formatParams(op
["operationParams"]), indent
=2),
1060 op
["operationState"],
1063 wrap_text(text
=detail
, width
=50),
1070 op
["lcmOperationType"],
1072 op
["operationState"],
1074 wrap_text(text
=detail
or "", width
=50),
1081 def nsi_list(ctx
, filter):
1082 """list all Network Slice Instances"""
1085 check_client_version(ctx
.obj
, ctx
.command
.name
)
1087 filter = "&".join(filter)
1088 resp
= ctx
.obj
.nsi
.list(filter)
1089 # except ClientException as e:
1092 table
= PrettyTable(
1094 "netslice instance name",
1096 "operational status",
1102 nsi_name
= nsi
["name"]
1105 nsi
["operational-status"] if "operational-status" in nsi
else "Not found"
1107 configstatus
= nsi
["config-status"] if "config-status" in nsi
else "Not found"
1109 nsi
["detailed-status"] if "detailed-status" in nsi
else "Not found"
1111 if configstatus
== "config_not_needed":
1112 configstatus
= "configured (no charms)"
1113 table
.add_row([nsi_name
, nsi_id
, opstatus
, configstatus
, detailed_status
])
1118 @cli_osm.command(name
="nsi-list", short_help
="list all Network Slice Instances (NSI)")
1123 help="restricts the list to the Network Slice Instances matching the filter",
1126 def nsi_list1(ctx
, filter):
1127 """list all Network Slice Instances (NSI)"""
1129 nsi_list(ctx
, filter)
1133 name
="netslice-instance-list", short_help
="list all Network Slice Instances (NSI)"
1139 help="restricts the list to the Network Slice Instances matching the filter",
1142 def nsi_list2(ctx
, filter):
1143 """list all Network Slice Instances (NSI)"""
1145 nsi_list(ctx
, filter)
1148 def nst_list(ctx
, filter):
1151 check_client_version(ctx
.obj
, ctx
.command
.name
)
1153 filter = "&".join(filter)
1154 resp
= ctx
.obj
.nst
.list(filter)
1155 # except ClientException as e:
1158 # print(yaml.safe_dump(resp))
1159 table
= PrettyTable(["nst name", "id"])
1161 name
= nst
["name"] if "name" in nst
else "-"
1162 table
.add_row([name
, nst
["_id"]])
1167 @cli_osm.command(name
="nst-list", short_help
="list all Network Slice Templates (NST)")
1172 help="restricts the list to the NST matching the filter",
1175 def nst_list1(ctx
, filter):
1176 """list all Network Slice Templates (NST) in the system"""
1178 nst_list(ctx
, filter)
1182 name
="netslice-template-list", short_help
="list all Network Slice Templates (NST)"
1188 help="restricts the list to the NST matching the filter",
1191 def nst_list2(ctx
, filter):
1192 """list all Network Slice Templates (NST) in the system"""
1194 nst_list(ctx
, filter)
1197 def nsi_op_list(ctx
, name
):
1200 check_client_version(ctx
.obj
, ctx
.command
.name
)
1201 resp
= ctx
.obj
.nsi
.list_op(name
)
1202 # except ClientException as e:
1205 table
= PrettyTable(["id", "operation", "status"])
1207 table
.add_row([op
["id"], op
["lcmOperationType"], op
["operationState"]])
1214 short_help
="shows the history of operations over a Network Slice Instance (NSI)",
1216 @click.argument("name")
1218 def nsi_op_list1(ctx
, name
):
1219 """shows the history of operations over a Network Slice Instance (NSI)
1221 NAME: name or ID of the Network Slice Instance
1224 nsi_op_list(ctx
, name
)
1228 name
="netslice-instance-op-list",
1229 short_help
="shows the history of operations over a Network Slice Instance (NSI)",
1231 @click.argument("name")
1233 def nsi_op_list2(ctx
, name
):
1234 """shows the history of operations over a Network Slice Instance (NSI)
1236 NAME: name or ID of the Network Slice Instance
1239 nsi_op_list(ctx
, name
)
1242 @cli_osm.command(name
="pdu-list", short_help
="list all Physical Deployment Units (PDU)")
1247 help="restricts the list to the Physical Deployment Units matching the filter",
1250 def pdu_list(ctx
, filter):
1251 """list all Physical Deployment Units (PDU)"""
1254 check_client_version(ctx
.obj
, ctx
.command
.name
)
1256 filter = "&".join(filter)
1257 resp
= ctx
.obj
.pdu
.list(filter)
1258 # except ClientException as e:
1261 table
= PrettyTable(["pdu name", "id", "type", "mgmt ip address"])
1263 pdu_name
= pdu
["name"]
1265 pdu_type
= pdu
["type"]
1266 pdu_ipaddress
= "None"
1267 for iface
in pdu
["interfaces"]:
1269 pdu_ipaddress
= iface
["ip-address"]
1271 table
.add_row([pdu_name
, pdu_id
, pdu_type
, pdu_ipaddress
])
1276 ####################
1278 ####################
1281 def nsd_show(ctx
, name
, literal
):
1284 resp
= ctx
.obj
.nsd
.get(name
)
1285 # resp = ctx.obj.nsd.get_individual(name)
1286 # except ClientException as e:
1291 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1294 table
= PrettyTable(["field", "value"])
1295 for k
, v
in list(resp
.items()):
1296 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1301 @cli_osm.command(name
="nsd-show", short_help
="shows the details of a NS package")
1302 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1303 @click.argument("name")
1305 def nsd_show1(ctx
, name
, literal
):
1306 """shows the content of a NSD
1308 NAME: name or ID of the NSD/NSpkg
1311 nsd_show(ctx
, name
, literal
)
1314 @cli_osm.command(name
="nspkg-show", short_help
="shows the details of a NS package")
1315 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1316 @click.argument("name")
1318 def nsd_show2(ctx
, name
, literal
):
1319 """shows the content of a NSD
1321 NAME: name or ID of the NSD/NSpkg
1324 nsd_show(ctx
, name
, literal
)
1327 def vnfd_show(ctx
, name
, literal
):
1330 resp
= ctx
.obj
.vnfd
.get(name
)
1331 # resp = ctx.obj.vnfd.get_individual(name)
1332 # except ClientException as e:
1337 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1340 table
= PrettyTable(["field", "value"])
1341 for k
, v
in list(resp
.items()):
1342 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1347 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1350 filter = "&".join(filter)
1352 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1355 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1358 catalog
= pkgtype
+ "-catalog"
1359 full_catalog
= pkgtype
+ ":" + catalog
1360 if resp
.get(catalog
):
1361 resp
= resp
.pop(catalog
)[pkgtype
][0]
1362 elif resp
.get(full_catalog
):
1363 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1365 table
= PrettyTable(["field", "value"])
1366 for k
, v
in list(resp
.items()):
1367 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1372 @cli_osm.command(name
="vnfd-show", short_help
="shows the details of a NF package")
1373 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1374 @click.argument("name")
1376 def vnfd_show1(ctx
, name
, literal
):
1377 """shows the content of a VNFD
1379 NAME: name or ID of the VNFD/VNFpkg
1382 vnfd_show(ctx
, name
, literal
)
1385 @cli_osm.command(name
="vnfpkg-show", short_help
="shows the details of a NF package")
1386 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1387 @click.argument("name")
1389 def vnfd_show2(ctx
, name
, literal
):
1390 """shows the content of a VNFD
1392 NAME: name or ID of the VNFD/VNFpkg
1395 vnfd_show(ctx
, name
, literal
)
1399 name
="vnfpkg-repo-show",
1400 short_help
="shows the details of a NF package in an OSM repository",
1402 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1403 @click.option("--repo", required
=True, help="Repository name")
1404 @click.argument("name")
1405 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1406 @click.option("--version", default
="latest", help="package version")
1408 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1409 """shows the content of a VNFD in a repository
1411 NAME: name or ID of the VNFD/VNFpkg
1414 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1418 name
="nsd-repo-show",
1419 short_help
="shows the details of a NS package in an OSM repository",
1421 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1422 @click.option("--repo", required
=True, help="Repository name")
1423 @click.argument("name")
1424 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1425 @click.option("--version", default
="latest", help="package version")
1427 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1428 """shows the content of a VNFD in a repository
1430 NAME: name or ID of the VNFD/VNFpkg
1433 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1437 name
="nspkg-repo-show",
1438 short_help
="shows the details of a NS package in an OSM repository",
1440 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1441 @click.option("--repo", required
=True, help="Repository name")
1442 @click.argument("name")
1443 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1444 @click.option("--version", default
="latest", help="package version")
1446 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1447 """shows the content of a VNFD in a repository
1449 NAME: name or ID of the VNFD/VNFpkg
1452 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1455 @cli_osm.command(name
="nfpkg-show", short_help
="shows the details of a NF package")
1456 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1457 @click.argument("name")
1459 def nfpkg_show(ctx
, name
, literal
):
1460 """shows the content of a NF Descriptor
1462 NAME: name or ID of the NFpkg
1465 vnfd_show(ctx
, name
, literal
)
1469 name
="nfpkg-repo-show",
1470 short_help
="shows the details of a NF package in an OSM repository",
1472 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1473 @click.option("--repo", required
=True, help="Repository name")
1474 @click.argument("name")
1475 @click.option("--filter", default
=None, multiple
=True, help="filter by fields")
1476 @click.option("--version", default
="latest", help="package version")
1478 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1479 """shows the content of a VNFD in a repository
1481 NAME: name or ID of the VNFD/VNFpkg
1484 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1487 @cli_osm.command(name
="ns-show", short_help
="shows the info of a NS instance")
1488 @click.argument("name")
1489 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1493 help="restricts the information to the fields in the filter",
1496 def ns_show(ctx
, name
, literal
, filter):
1497 """shows the info of a NS instance
1499 NAME: name or ID of the NS instance
1503 ns
= ctx
.obj
.ns
.get(name
)
1504 # except ClientException as e:
1509 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1512 table
= PrettyTable(["field", "value"])
1514 for k
, v
in list(ns
.items()):
1515 if not filter or k
in filter:
1516 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1518 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1519 if fullclassname
!= "osmclient.sol005.client.Client":
1520 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
["id"])
1521 nsr_optdata
= nsopdata
["nsr:nsr"]
1522 for k
, v
in list(nsr_optdata
.items()):
1523 if not filter or k
in filter:
1524 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), width
=100)])
1529 @cli_osm.command(name
="vnf-show", short_help
="shows the info of a VNF instance")
1530 @click.argument("name")
1531 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1535 help="restricts the information to the fields in the filter",
1537 @click.option("--kdu", default
=None, help="KDU name (whose status will be shown)")
1539 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1540 """shows the info of a VNF instance
1542 NAME: name or ID of the VNF instance
1545 def print_kdu_status(op_info_status
):
1546 """print KDU status properly formatted"""
1548 op_status
= yaml
.safe_load(op_info_status
)
1550 "namespace" in op_status
1551 and "info" in op_status
1552 and "last_deployed" in op_status
["info"]
1553 and "status" in op_status
["info"]
1554 and "code" in op_status
["info"]["status"]
1555 and "resources" in op_status
["info"]["status"]
1556 and "seconds" in op_status
["info"]["last_deployed"]
1558 last_deployed_time
= datetime
.fromtimestamp(
1559 op_status
["info"]["last_deployed"]["seconds"]
1560 ).strftime("%a %b %d %I:%M:%S %Y")
1561 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1562 print("NAMESPACE: {}".format(op_status
["namespace"]))
1563 status_code
= "UNKNOWN"
1564 if op_status
["info"]["status"]["code"] == 1:
1565 status_code
= "DEPLOYED"
1566 print("STATUS: {}".format(status_code
))
1569 print(op_status
["info"]["status"]["resources"])
1570 if "notes" in op_status
["info"]["status"]:
1572 print(op_status
["info"]["status"]["notes"])
1574 print(op_info_status
)
1576 print(op_info_status
)
1581 raise ClientException(
1582 '"--literal" option is incompatible with "--kdu" option'
1585 raise ClientException(
1586 '"--filter" option is incompatible with "--kdu" option'
1590 check_client_version(ctx
.obj
, ctx
.command
.name
)
1591 resp
= ctx
.obj
.vnf
.get(name
)
1594 ns_id
= resp
["nsr-id-ref"]
1596 op_data
["member_vnf_index"] = resp
["member-vnf-index-ref"]
1597 op_data
["kdu_name"] = kdu
1598 op_data
["primitive"] = "status"
1599 op_data
["primitive_params"] = {}
1600 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
="action", op_data
=op_data
, wait
=False)
1603 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1604 if op_info
["operationState"] == "COMPLETED":
1605 print_kdu_status(op_info
["detailed-status"])
1609 print("Could not determine KDU status")
1613 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1616 table
= PrettyTable(["field", "value"])
1617 for k
, v
in list(resp
.items()):
1618 if not filter or k
in filter:
1619 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1622 # except ClientException as e:
1627 # @cli_osm.command(name='vnf-monitoring-show')
1628 # @click.argument('vnf_name')
1629 # @click.pass_context
1630 # def vnf_monitoring_show(ctx, vnf_name):
1632 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1633 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1634 # except ClientException as e:
1638 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1639 # if resp is not None:
1640 # for monitor in resp:
1644 # monitor['value-integer'],
1645 # monitor['units']])
1650 # @cli_osm.command(name='ns-monitoring-show')
1651 # @click.argument('ns_name')
1652 # @click.pass_context
1653 # def ns_monitoring_show(ctx, ns_name):
1655 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1656 # resp = ctx.obj.ns.get_monitoring(ns_name)
1657 # except ClientException as e:
1661 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1662 # for key, val in list(resp.items()):
1663 # for monitor in val:
1667 # monitor['value-integer'],
1668 # monitor['units']])
1673 @cli_osm.command(name
="ns-op-show", short_help
="shows the info of a NS operation")
1674 @click.argument("id")
1678 help="restricts the information to the fields in the filter",
1680 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1682 def ns_op_show(ctx
, id, filter, literal
):
1683 """shows the detailed info of a NS operation
1685 ID: operation identifier
1689 check_client_version(ctx
.obj
, ctx
.command
.name
)
1690 op_info
= ctx
.obj
.ns
.get_op(id)
1691 # except ClientException as e:
1696 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1699 table
= PrettyTable(["field", "value"])
1700 for k
, v
in list(op_info
.items()):
1701 if not filter or k
in filter:
1702 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1707 def nst_show(ctx
, name
, literal
):
1710 check_client_version(ctx
.obj
, ctx
.command
.name
)
1711 resp
= ctx
.obj
.nst
.get(name
)
1712 # resp = ctx.obj.nst.get_individual(name)
1713 # except ClientException as e:
1718 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1721 table
= PrettyTable(["field", "value"])
1722 for k
, v
in list(resp
.items()):
1723 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1729 name
="nst-show", short_help
="shows the content of a Network Slice Template (NST)"
1731 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1732 @click.argument("name")
1734 def nst_show1(ctx
, name
, literal
):
1735 """shows the content of a Network Slice Template (NST)
1737 NAME: name or ID of the NST
1740 nst_show(ctx
, name
, literal
)
1744 name
="netslice-template-show",
1745 short_help
="shows the content of a Network Slice Template (NST)",
1747 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1748 @click.argument("name")
1750 def nst_show2(ctx
, name
, literal
):
1751 """shows the content of a Network Slice Template (NST)
1753 NAME: name or ID of the NST
1756 nst_show(ctx
, name
, literal
)
1759 def nsi_show(ctx
, name
, literal
, filter):
1762 check_client_version(ctx
.obj
, ctx
.command
.name
)
1763 nsi
= ctx
.obj
.nsi
.get(name
)
1764 # except ClientException as e:
1769 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1772 table
= PrettyTable(["field", "value"])
1774 for k
, v
in list(nsi
.items()):
1775 if not filter or k
in filter:
1776 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1783 name
="nsi-show", short_help
="shows the content of a Network Slice Instance (NSI)"
1785 @click.argument("name")
1786 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1790 help="restricts the information to the fields in the filter",
1793 def nsi_show1(ctx
, name
, literal
, filter):
1794 """shows the content of a Network Slice Instance (NSI)
1796 NAME: name or ID of the Network Slice Instance
1799 nsi_show(ctx
, name
, literal
, filter)
1803 name
="netslice-instance-show",
1804 short_help
="shows the content of a Network Slice Instance (NSI)",
1806 @click.argument("name")
1807 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1811 help="restricts the information to the fields in the filter",
1814 def nsi_show2(ctx
, name
, literal
, filter):
1815 """shows the content of a Network Slice Instance (NSI)
1817 NAME: name or ID of the Network Slice Instance
1820 nsi_show(ctx
, name
, literal
, filter)
1823 def nsi_op_show(ctx
, id, filter):
1826 check_client_version(ctx
.obj
, ctx
.command
.name
)
1827 op_info
= ctx
.obj
.nsi
.get_op(id)
1828 # except ClientException as e:
1832 table
= PrettyTable(["field", "value"])
1833 for k
, v
in list(op_info
.items()):
1834 if not filter or k
in filter:
1835 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1842 short_help
="shows the info of an operation over a Network Slice Instance(NSI)",
1844 @click.argument("id")
1848 help="restricts the information to the fields in the filter",
1851 def nsi_op_show1(ctx
, id, filter):
1852 """shows the info of an operation over a Network Slice Instance(NSI)
1854 ID: operation identifier
1857 nsi_op_show(ctx
, id, filter)
1861 name
="netslice-instance-op-show",
1862 short_help
="shows the info of an operation over a Network Slice Instance(NSI)",
1864 @click.argument("id")
1868 help="restricts the information to the fields in the filter",
1871 def nsi_op_show2(ctx
, id, filter):
1872 """shows the info of an operation over a Network Slice Instance(NSI)
1874 ID: operation identifier
1877 nsi_op_show(ctx
, id, filter)
1881 name
="pdu-show", short_help
="shows the content of a Physical Deployment Unit (PDU)"
1883 @click.argument("name")
1884 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
1888 help="restricts the information to the fields in the filter",
1891 def pdu_show(ctx
, name
, literal
, filter):
1892 """shows the content of a Physical Deployment Unit (PDU)
1894 NAME: name or ID of the PDU
1898 check_client_version(ctx
.obj
, ctx
.command
.name
)
1899 pdu
= ctx
.obj
.pdu
.get(name
)
1900 # except ClientException as e:
1905 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1908 table
= PrettyTable(["field", "value"])
1910 for k
, v
in list(pdu
.items()):
1911 if not filter or k
in filter:
1912 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1918 ####################
1920 ####################
1923 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1926 check_client_version(ctx
.obj
, ctx
.command
.name
)
1928 filename
= ctx
.obj
.osmrepo
.get_pkg("ns", filename
, repo
, vendor
, version
)
1929 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1930 # except ClientException as e:
1935 @cli_osm.command(name
="nsd-create", short_help
="creates a new NSD/NSpkg")
1936 @click.argument("filename")
1940 default
=None, # hidden=True,
1941 help="Deprecated. Use override",
1947 help="overrides fields in descriptor, format: "
1948 '"key1.key2...=value[;key3...=value;...]"',
1951 "--skip-charm-build",
1954 help="The charm will not be compiled, it is assumed to already exist",
1956 @click.option("--repo", default
=None, help="[repository]: Repository name")
1957 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
1961 help="[repository]: filter by version. Default: latest",
1964 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1965 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1968 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1969 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1970 If FILENAME is an NF Package folder, it is built and then onboarded.
1976 overwrite
=overwrite
,
1977 skip_charm_build
=skip_charm_build
,
1984 @cli_osm.command(name
="nspkg-create", short_help
="creates a new NSD/NSpkg")
1985 @click.argument("filename")
1989 default
=None, # hidden=True,
1990 help="Deprecated. Use override",
1996 help="overrides fields in descriptor, format: "
1997 '"key1.key2...=value[;key3...=value;...]"',
2000 "--skip-charm-build",
2003 help="The charm will not be compiled, it is assumed to already exist",
2005 @click.option("--repo", default
=None, help="[repository]: Repository name")
2006 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2010 help="[repository]: filter by version. Default: latest",
2013 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
2014 """onboards a new NSpkg
2016 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2017 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2018 If FILENAME is an NF Package folder, it is built and then onboarded.
2024 overwrite
=overwrite
,
2025 skip_charm_build
=skip_charm_build
,
2046 check_client_version(ctx
.obj
, ctx
.command
.name
)
2048 filename
= ctx
.obj
.osmrepo
.get_pkg("vnf", filename
, repo
, vendor
, version
)
2049 ctx
.obj
.vnfd
.create(
2051 overwrite
=overwrite
,
2052 skip_charm_build
=skip_charm_build
,
2053 override_epa
=override_epa
,
2054 override_nonepa
=override_nonepa
,
2055 override_paravirt
=override_paravirt
,
2057 # except ClientException as e:
2062 @cli_osm.command(name
="vnfd-create", short_help
="creates a new VNFD/VNFpkg")
2063 @click.argument("filename")
2065 "--overwrite", "overwrite", default
=None, help="overwrite deprecated, use override"
2071 help="overrides fields in descriptor, format: "
2072 '"key1.key2...=value[;key3...=value;...]"',
2075 "--skip-charm-build",
2078 help="The charm will not be compiled, it is assumed to already exist",
2085 help="adds guest-epa parameters to all VDU",
2088 "--override-nonepa",
2092 help="removes all guest-epa parameters from all VDU",
2095 "--override-paravirt",
2099 help="overrides all VDU interfaces to PARAVIRT",
2101 @click.option("--repo", default
=None, help="[repository]: Repository name")
2102 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2106 help="[repository]: filter by version. Default: latest",
2121 """creates a new VNFD/VNFpkg
2123 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2124 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2125 If FILENAME is an NF Package folder, it is built and then onboarded.
2131 overwrite
=overwrite
,
2132 skip_charm_build
=skip_charm_build
,
2133 override_epa
=override_epa
,
2134 override_nonepa
=override_nonepa
,
2135 override_paravirt
=override_paravirt
,
2142 @cli_osm.command(name
="vnfpkg-create", short_help
="creates a new VNFD/VNFpkg")
2143 @click.argument("filename")
2147 default
=None, # hidden=True,
2148 help="Deprecated. Use override",
2154 help="overrides fields in descriptor, format: "
2155 '"key1.key2...=value[;key3...=value;...]"',
2158 "--skip-charm-build",
2161 help="The charm will not be compiled, it is assumed to already exist",
2168 help="adds guest-epa parameters to all VDU",
2171 "--override-nonepa",
2175 help="removes all guest-epa parameters from all VDU",
2178 "--override-paravirt",
2182 help="overrides all VDU interfaces to PARAVIRT",
2184 @click.option("--repo", default
=None, help="[repository]: Repository name")
2185 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2189 help="[repository]: filter by version. Default: latest",
2204 """creates a new VNFD/VNFpkg
2206 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2207 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2208 If FILENAME is an NF Package folder, it is built and then onboarded.
2214 overwrite
=overwrite
,
2215 skip_charm_build
=skip_charm_build
,
2216 override_epa
=override_epa
,
2217 override_nonepa
=override_nonepa
,
2218 override_paravirt
=override_paravirt
,
2225 @cli_osm.command(name
="nfpkg-create", short_help
="creates a new NFpkg")
2226 @click.argument("filename")
2230 default
=None, # hidden=True,
2231 help="Deprecated. Use override",
2237 help="overrides fields in descriptor, format: "
2238 '"key1.key2...=value[;key3...=value;...]"',
2241 "--skip-charm-build",
2244 help="The charm will not be compiled, it is assumed to already exist",
2251 help="adds guest-epa parameters to all VDU",
2254 "--override-nonepa",
2258 help="removes all guest-epa parameters from all VDU",
2261 "--override-paravirt",
2265 help="overrides all VDU interfaces to PARAVIRT",
2267 @click.option("--repo", default
=None, help="[repository]: Repository name")
2268 @click.option("--vendor", default
=None, help="[repository]: filter by vendor]")
2272 help="[repository]: filter by version. Default: latest",
2287 """creates a new NFpkg
2290 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2291 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2292 If FILENAME is an NF Package folder, it is built and then onboarded.
2298 overwrite
=overwrite
,
2299 skip_charm_build
=skip_charm_build
,
2300 override_epa
=override_epa
,
2301 override_nonepa
=override_nonepa
,
2302 override_paravirt
=override_paravirt
,
2309 @cli_osm.command(name
="ns-create", short_help
="creates a new Network Service instance")
2310 @click.option("--ns_name", prompt
=True, help="name of the NS instance")
2311 @click.option("--nsd_name", prompt
=True, help="name of the NS descriptor")
2315 help="default VIM account id or name for the deployment",
2317 @click.option("--admin_status", default
="ENABLED", help="administration status")
2321 help="comma separated list of public key files to inject to vnfs",
2323 @click.option("--config", default
=None, help="ns specific yaml configuration")
2324 @click.option("--config_file", default
=None, help="ns specific yaml configuration file")
2330 help="do not return the control immediately, but keep it "
2331 "until the operation is completed, or timeout",
2345 """creates a new NS instance"""
2349 check_client_version(ctx
.obj
, "--config_file")
2351 raise ClientException(
2352 '"--config" option is incompatible with "--config_file" option'
2354 with
open(config_file
, "r") as cf
:
2361 account
=vim_account
,
2364 # except ClientException as e:
2369 def nst_create(ctx
, filename
, overwrite
):
2372 check_client_version(ctx
.obj
, ctx
.command
.name
)
2373 ctx
.obj
.nst
.create(filename
, overwrite
)
2374 # except ClientException as e:
2380 name
="nst-create", short_help
="creates a new Network Slice Template (NST)"
2382 @click.argument("filename")
2386 default
=None, # hidden=True,
2387 help="Deprecated. Use override",
2393 help="overrides fields in descriptor, format: "
2394 '"key1.key2...=value[;key3...=value;...]"',
2397 def nst_create1(ctx
, filename
, overwrite
):
2398 """creates a new Network Slice Template (NST)
2400 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
2403 nst_create(ctx
, filename
, overwrite
)
2407 name
="netslice-template-create",
2408 short_help
="creates a new Network Slice Template (NST)",
2410 @click.argument("filename")
2414 default
=None, # hidden=True,
2415 help="Deprecated. Use override",
2421 help="overrides fields in descriptor, format: "
2422 '"key1.key2...=value[;key3...=value;...]"',
2425 def nst_create2(ctx
, filename
, overwrite
):
2426 """creates a new Network Slice Template (NST)
2428 FILENAME: NST yaml file or NSTpkg tar.gz file
2431 nst_create(ctx
, filename
, overwrite
)
2435 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
2437 """creates a new Network Slice Instance (NSI)"""
2440 check_client_version(ctx
.obj
, ctx
.command
.name
)
2443 raise ClientException(
2444 '"--config" option is incompatible with "--config_file" option'
2446 with
open(config_file
, "r") as cf
:
2453 account
=vim_account
,
2456 # except ClientException as e:
2461 @cli_osm.command(name
="nsi-create", short_help
="creates a new Network Slice Instance")
2462 @click.option("--nsi_name", prompt
=True, help="name of the Network Slice Instance")
2463 @click.option("--nst_name", prompt
=True, help="name of the Network Slice Template")
2467 help="default VIM account id or name for the deployment",
2470 "--ssh_keys", default
=None, help="comma separated list of keys to inject to vnfs"
2475 help="Netslice specific yaml configuration:\n"
2476 "netslice_subnet: [\n"
2477 "id: TEXT, vim_account: TEXT,\n"
2478 "vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n"
2479 "vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n"
2480 "additionalParamsForNsi: {param: value, ...}\n"
2481 "additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n"
2483 "netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]",
2486 "--config_file", default
=None, help="nsi specific yaml configuration file"
2493 help="do not return the control immediately, but keep it "
2494 "until the operation is completed, or timeout",
2498 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
2500 """creates a new Network Slice Instance (NSI)"""
2503 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
2508 name
="netslice-instance-create", short_help
="creates a new Network Slice Instance"
2510 @click.option("--nsi_name", prompt
=True, help="name of the Network Slice Instance")
2511 @click.option("--nst_name", prompt
=True, help="name of the Network Slice Template")
2515 help="default VIM account id or name for the deployment",
2518 "--ssh_keys", default
=None, help="comma separated list of keys to inject to vnfs"
2523 help="Netslice specific yaml configuration:\n"
2524 "netslice_subnet: [\n"
2525 "id: TEXT, vim_account: TEXT,\n"
2526 "vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n"
2527 "vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]"
2529 "netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]",
2532 "--config_file", default
=None, help="nsi specific yaml configuration file"
2539 help="do not return the control immediately, but keep it "
2540 "until the operation is completed, or timeout",
2544 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
2546 """creates a new Network Slice Instance (NSI)"""
2549 ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
2554 name
="pdu-create", short_help
="adds a new Physical Deployment Unit to the catalog"
2556 @click.option("--name", help="name of the Physical Deployment Unit")
2557 @click.option("--pdu_type", help="type of PDU (e.g. router, firewall, FW001)")
2560 help="interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>"
2561 + "[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]",
2564 @click.option("--description", help="human readable description")
2567 help="list of VIM accounts (in the same VIM) that can reach this PDU\n"
2568 + "The format for multiple VIMs is --vim_account <vim_account_id_1> "
2569 + "--vim_account <vim_account_id_2> ... --vim_account <vim_account_id_N>",
2573 "--descriptor_file",
2575 help="PDU descriptor file (as an alternative to using the other arguments)",
2579 ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
2581 """creates a new Physical Deployment Unit (PDU)"""
2584 check_client_version(ctx
.obj
, ctx
.command
.name
)
2586 pdu
= create_pdu_dictionary(name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
)
2587 ctx
.obj
.pdu
.create(pdu
)
2590 ########################
2591 # UPDATE PDU operation #
2592 ########################
2596 name
="pdu-update", short_help
="updates a Physical Deployment Unit to the catalog"
2598 @click.argument("name")
2599 @click.option("--newname", help="New name for the Physical Deployment Unit")
2600 @click.option("--pdu_type", help="type of PDU (e.g. router, firewall, FW001)")
2603 help="interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>"
2604 + "[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]",
2607 @click.option("--description", help="human readable description")
2610 help="list of VIM accounts (in the same VIM) that can reach this PDU\n"
2611 + "The format for multiple VIMs is --vim_account <vim_account_id_1> "
2612 + "--vim_account <vim_account_id_2> ... --vim_account <vim_account_id_N>",
2616 "--descriptor_file",
2618 help="PDU descriptor file (as an alternative to using the other arguments)",
2622 ctx
, name
, newname
, pdu_type
, interface
, description
, vim_account
, descriptor_file
2624 """Updates a new Physical Deployment Unit (PDU)"""
2627 check_client_version(ctx
.obj
, ctx
.command
.name
)
2634 pdu
= create_pdu_dictionary(newname
, pdu_type
, interface
, description
, vim_account
, descriptor_file
, update
)
2635 ctx
.obj
.pdu
.update(name
, pdu
)
2638 def create_pdu_dictionary(name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
, update
=False):
2643 if not descriptor_file
:
2646 raise ClientException(
2647 'in absence of descriptor file, option "--name" is mandatory'
2650 raise ClientException(
2651 'in absence of descriptor file, option "--pdu_type" is mandatory'
2654 raise ClientException(
2655 'in absence of descriptor file, option "--interface" is mandatory (at least once)'
2658 raise ClientException(
2659 'in absence of descriptor file, option "--vim_account" is mandatory (at least once)'
2662 with
open(descriptor_file
, "r") as df
:
2663 pdu
= yaml
.safe_load(df
.read())
2667 pdu
["type"] = pdu_type
2669 pdu
["description"] = description
2671 pdu
["vim_accounts"] = vim_account
2674 for iface
in interface
:
2675 new_iface
= {k
: v
for k
, v
in [i
.split("=") for i
in iface
.split(",")]}
2676 new_iface
["mgmt"] = new_iface
.get("mgmt", "false").lower() == "true"
2677 ifaces_list
.append(new_iface
)
2678 pdu
["interfaces"] = ifaces_list
2681 ####################
2683 ####################
2686 def nsd_update(ctx
, name
, content
):
2689 check_client_version(ctx
.obj
, ctx
.command
.name
)
2690 ctx
.obj
.nsd
.update(name
, content
)
2691 # except ClientException as e:
2696 @cli_osm.command(name
="nsd-update", short_help
="updates a NSD/NSpkg")
2697 @click.argument("name")
2701 help="filename with the NSD/NSpkg replacing the current one",
2704 def nsd_update1(ctx
, name
, content
):
2705 """updates a NSD/NSpkg
2707 NAME: name or ID of the NSD/NSpkg
2710 nsd_update(ctx
, name
, content
)
2713 @cli_osm.command(name
="nspkg-update", short_help
="updates a NSD/NSpkg")
2714 @click.argument("name")
2718 help="filename with the NSD/NSpkg replacing the current one",
2721 def nsd_update2(ctx
, name
, content
):
2722 """updates a NSD/NSpkg
2724 NAME: name or ID of the NSD/NSpkg
2727 nsd_update(ctx
, name
, content
)
2730 def vnfd_update(ctx
, name
, content
):
2733 check_client_version(ctx
.obj
, ctx
.command
.name
)
2734 ctx
.obj
.vnfd
.update(name
, content
)
2735 # except ClientException as e:
2740 @cli_osm.command(name
="vnfd-update", short_help
="updates a new VNFD/VNFpkg")
2741 @click.argument("name")
2745 help="filename with the VNFD/VNFpkg replacing the current one",
2748 def vnfd_update1(ctx
, name
, content
):
2749 """updates a VNFD/VNFpkg
2751 NAME: name or ID of the VNFD/VNFpkg
2754 vnfd_update(ctx
, name
, content
)
2757 @cli_osm.command(name
="vnfpkg-update", short_help
="updates a VNFD/VNFpkg")
2758 @click.argument("name")
2762 help="filename with the VNFD/VNFpkg replacing the current one",
2765 def vnfd_update2(ctx
, name
, content
):
2766 """updates a VNFD/VNFpkg
2768 NAME: VNFD yaml file or VNFpkg tar.gz file
2771 vnfd_update(ctx
, name
, content
)
2774 @cli_osm.command(name
="nfpkg-update", short_help
="updates a NFpkg")
2775 @click.argument("name")
2777 "--content", default
=None, help="filename with the NFpkg replacing the current one"
2780 def nfpkg_update(ctx
, name
, content
):
2783 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2786 vnfd_update(ctx
, name
, content
)
2789 def nst_update(ctx
, name
, content
):
2792 check_client_version(ctx
.obj
, ctx
.command
.name
)
2793 ctx
.obj
.nst
.update(name
, content
)
2794 # except ClientException as e:
2799 @cli_osm.command(name
="nst-update", short_help
="updates a Network Slice Template (NST)")
2800 @click.argument("name")
2804 help="filename with the NST/NSTpkg replacing the current one",
2807 def nst_update1(ctx
, name
, content
):
2808 """updates a Network Slice Template (NST)
2810 NAME: name or ID of the NSD/NSpkg
2813 nst_update(ctx
, name
, content
)
2817 name
="netslice-template-update", short_help
="updates a Network Slice Template (NST)"
2819 @click.argument("name")
2823 help="filename with the NST/NSTpkg replacing the current one",
2826 def nst_update2(ctx
, name
, content
):
2827 """updates a Network Slice Template (NST)
2829 NAME: name or ID of the NSD/NSpkg
2832 nst_update(ctx
, name
, content
)
2835 ####################
2837 ####################
2840 def nsd_delete(ctx
, name
, force
):
2844 ctx
.obj
.nsd
.delete(name
)
2846 check_client_version(ctx
.obj
, "--force")
2847 ctx
.obj
.nsd
.delete(name
, force
)
2848 # except ClientException as e:
2853 @cli_osm.command(name
="nsd-delete", short_help
="deletes a NSD/NSpkg")
2854 @click.argument("name")
2856 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2859 def nsd_delete1(ctx
, name
, force
):
2860 """deletes a NSD/NSpkg
2862 NAME: name or ID of the NSD/NSpkg to be deleted
2865 nsd_delete(ctx
, name
, force
)
2868 @cli_osm.command(name
="nspkg-delete", short_help
="deletes a NSD/NSpkg")
2869 @click.argument("name")
2871 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2874 def nsd_delete2(ctx
, name
, force
):
2875 """deletes a NSD/NSpkg
2877 NAME: name or ID of the NSD/NSpkg to be deleted
2880 nsd_delete(ctx
, name
, force
)
2883 def vnfd_delete(ctx
, name
, force
):
2887 ctx
.obj
.vnfd
.delete(name
)
2889 check_client_version(ctx
.obj
, "--force")
2890 ctx
.obj
.vnfd
.delete(name
, force
)
2891 # except ClientException as e:
2896 @cli_osm.command(name
="vnfd-delete", short_help
="deletes a VNFD/VNFpkg")
2897 @click.argument("name")
2899 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2902 def vnfd_delete1(ctx
, name
, force
):
2903 """deletes a VNFD/VNFpkg
2905 NAME: name or ID of the VNFD/VNFpkg to be deleted
2908 vnfd_delete(ctx
, name
, force
)
2911 @cli_osm.command(name
="vnfpkg-delete", short_help
="deletes a VNFD/VNFpkg")
2912 @click.argument("name")
2914 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2917 def vnfd_delete2(ctx
, name
, force
):
2918 """deletes a VNFD/VNFpkg
2920 NAME: name or ID of the VNFD/VNFpkg to be deleted
2923 vnfd_delete(ctx
, name
, force
)
2926 @cli_osm.command(name
="nfpkg-delete", short_help
="deletes a NFpkg")
2927 @click.argument("name")
2929 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2932 def nfpkg_delete(ctx
, name
, force
):
2935 NAME: name or ID of the NFpkg to be deleted
2938 vnfd_delete(ctx
, name
, force
)
2941 @cli_osm.command(name
="ns-delete", short_help
="deletes a NS instance")
2942 @click.argument("name")
2944 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2949 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2950 "600, skip_terminate_primitives: True}'",
2957 help="do not return the control immediately, but keep it "
2958 "until the operation is completed, or timeout",
2961 def ns_delete(ctx
, name
, force
, config
, wait
):
2962 """deletes a NS instance
2964 NAME: name or ID of the NS instance to be deleted
2969 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2971 check_client_version(ctx
.obj
, "--force")
2972 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2973 # except ClientException as e:
2978 def nst_delete(ctx
, name
, force
):
2981 check_client_version(ctx
.obj
, ctx
.command
.name
)
2982 ctx
.obj
.nst
.delete(name
, force
)
2983 # except ClientException as e:
2988 @cli_osm.command(name
="nst-delete", short_help
="deletes a Network Slice Template (NST)")
2989 @click.argument("name")
2991 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
2994 def nst_delete1(ctx
, name
, force
):
2995 """deletes a Network Slice Template (NST)
2997 NAME: name or ID of the NST/NSTpkg to be deleted
3000 nst_delete(ctx
, name
, force
)
3004 name
="netslice-template-delete", short_help
="deletes a Network Slice Template (NST)"
3006 @click.argument("name")
3008 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3011 def nst_delete2(ctx
, name
, force
):
3012 """deletes a Network Slice Template (NST)
3014 NAME: name or ID of the NST/NSTpkg to be deleted
3017 nst_delete(ctx
, name
, force
)
3020 def nsi_delete(ctx
, name
, force
, wait
):
3023 check_client_version(ctx
.obj
, ctx
.command
.name
)
3024 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
3025 # except ClientException as e:
3030 @cli_osm.command(name
="nsi-delete", short_help
="deletes a Network Slice Instance (NSI)")
3031 @click.argument("name")
3033 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3040 help="do not return the control immediately, but keep it "
3041 "until the operation is completed, or timeout",
3044 def nsi_delete1(ctx
, name
, force
, wait
):
3045 """deletes a Network Slice Instance (NSI)
3047 NAME: name or ID of the Network Slice instance to be deleted
3050 nsi_delete(ctx
, name
, force
, wait
=wait
)
3054 name
="netslice-instance-delete", short_help
="deletes a Network Slice Instance (NSI)"
3056 @click.argument("name")
3058 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3061 def nsi_delete2(ctx
, name
, force
, wait
):
3062 """deletes a Network Slice Instance (NSI)
3064 NAME: name or ID of the Network Slice instance to be deleted
3067 nsi_delete(ctx
, name
, force
, wait
=wait
)
3071 name
="pdu-delete", short_help
="deletes a Physical Deployment Unit (PDU)"
3073 @click.argument("name")
3075 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3078 def pdu_delete(ctx
, name
, force
):
3079 """deletes a Physical Deployment Unit (PDU)
3081 NAME: name or ID of the PDU to be deleted
3085 check_client_version(ctx
.obj
, ctx
.command
.name
)
3086 ctx
.obj
.pdu
.delete(name
, force
)
3087 # except ClientException as e:
3097 @cli_osm.command(name
="vim-create", short_help
="creates a new VIM account")
3098 @click.option("--name", prompt
=True, help="Name to create datacenter")
3099 @click.option("--user", prompt
=True, help="VIM username")
3104 confirmation_prompt
=True,
3105 help="VIM password",
3107 @click.option("--auth_url", prompt
=True, help="VIM url")
3108 @click.option("--tenant", prompt
=True, help="VIM tenant name")
3109 @click.option("--config", default
=None, help="VIM specific config parameters")
3110 @click.option("--account_type", default
="openstack", help="VIM type")
3111 @click.option("--description", default
=None, help="human readable description")
3115 help="Name or id of the SDN controller associated to this VIM account",
3118 "--sdn_port_mapping",
3120 help="File describing the port mapping between compute nodes' ports and switch ports",
3127 help="do not return the control immediately, but keep it "
3128 "until the operation is completed, or timeout",
3130 @click.option("--vca", default
=None, help="VCA to be used in this VIM account")
3147 """creates a new VIM account"""
3151 check_client_version(ctx
.obj
, "--sdn_controller")
3152 if sdn_port_mapping
:
3153 check_client_version(ctx
.obj
, "--sdn_port_mapping")
3155 vim
["vim-username"] = user
3156 vim
["vim-password"] = password
3157 vim
["vim-url"] = auth_url
3158 vim
["vim-tenant-name"] = tenant
3159 vim
["vim-type"] = account_type
3160 vim
["description"] = description
3161 vim
["config"] = config
3164 if sdn_controller
or sdn_port_mapping
:
3165 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
3167 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
3168 # except ClientException as e:
3173 @cli_osm.command(name
="vim-update", short_help
="updates a VIM account")
3174 @click.argument("name")
3175 @click.option("--newname", help="New name for the VIM account")
3176 @click.option("--user", help="VIM username")
3177 @click.option("--password", help="VIM password")
3178 @click.option("--auth_url", help="VIM url")
3179 @click.option("--tenant", help="VIM tenant name")
3180 @click.option("--config", help="VIM specific config parameters")
3181 @click.option("--account_type", help="VIM type")
3182 @click.option("--description", help="human readable description")
3186 help="Name or id of the SDN controller to be associated with this VIM"
3187 "account. Use empty string to disassociate",
3190 "--sdn_port_mapping",
3192 help="File describing the port mapping between compute nodes' ports and switch ports",
3199 help="do not return the control immediately, but keep it "
3200 "until the operation is completed, or timeout",
3218 """updates a VIM account
3220 NAME: name or ID of the VIM account
3224 check_client_version(ctx
.obj
, ctx
.command
.name
)
3227 vim
["name"] = newname
3229 vim
["vim_user"] = user
3231 vim
["vim_password"] = password
3233 vim
["vim_url"] = auth_url
3235 vim
["vim-tenant-name"] = tenant
3237 vim
["vim_type"] = account_type
3239 vim
["description"] = description
3241 vim
["config"] = config
3242 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
3243 # except ClientException as e:
3248 @cli_osm.command(name
="vim-delete", short_help
="deletes a VIM account")
3249 @click.argument("name")
3251 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3258 help="do not return the control immediately, but keep it "
3259 "until the operation is completed, or timeout",
3262 def vim_delete(ctx
, name
, force
, wait
):
3263 """deletes a VIM account
3265 NAME: name or ID of the VIM account to be deleted
3270 ctx
.obj
.vim
.delete(name
, wait
=wait
)
3272 check_client_version(ctx
.obj
, "--force")
3273 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
3274 # except ClientException as e:
3279 @cli_osm.command(name
="vim-list", short_help
="list all VIM accounts")
3280 # @click.option('--ro_update/--no_ro_update',
3282 # help='update list from RO')
3287 help="restricts the list to the VIM accounts matching the filter",
3292 help="get more details of the NS (project, vim, deployment status, configuration status.",
3295 def vim_list(ctx
, filter, long):
3296 """list all VIM accounts"""
3299 filter = "&".join(filter)
3300 check_client_version(ctx
.obj
, "--filter")
3302 # check_client_version(ctx.obj, '--ro_update', 'v1')
3303 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3304 if fullclassname
== "osmclient.sol005.client.Client":
3305 resp
= ctx
.obj
.vim
.list(filter)
3307 # resp = ctx.obj.vim.list(ro_update)
3309 table
= PrettyTable(
3310 ["vim name", "uuid", "project", "operational state", "error details"]
3312 project_list
= ctx
.obj
.project
.list()
3314 table
= PrettyTable(["vim name", "uuid", "operational state"])
3317 if "vim_password" in vim
:
3318 vim
["vim_password"] = "********"
3319 logger
.debug("VIM details: {}".format(yaml
.safe_dump(vim
)))
3320 vim_state
= vim
["_admin"].get("operationalState", "-")
3321 error_details
= "N/A"
3322 if vim_state
== "ERROR":
3323 error_details
= vim
["_admin"].get("detailed-status", "Not found")
3324 project_id
, project_name
= get_project(project_list
, vim
)
3325 # project_info = '{} ({})'.format(project_name, project_id)
3326 project_info
= project_name
3333 wrap_text(text
=error_details
, width
=80),
3338 [vim
["name"], vim
["uuid"], vim
["_admin"].get("operationalState", "-")]
3344 @cli_osm.command(name
="vim-show", short_help
="shows the details of a VIM account")
3345 @click.argument("name")
3349 help="restricts the information to the fields in the filter",
3352 def vim_show(ctx
, name
, filter):
3353 """shows the details of a VIM account
3355 NAME: name or ID of the VIM account
3359 resp
= ctx
.obj
.vim
.get(name
)
3360 if "vim_password" in resp
:
3361 resp
["vim_password"] = "********"
3362 # except ClientException as e:
3366 table
= PrettyTable(["key", "attribute"])
3367 for k
, v
in list(resp
.items()):
3368 if not filter or k
in filter:
3369 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
3374 ####################
3376 ####################
3379 @cli_osm.command(name
="wim-create", short_help
="creates a new WIM account")
3380 @click.option("--name", prompt
=True, help="Name for the WIM account")
3381 @click.option("--user", help="WIM username")
3382 @click.option("--password", help="WIM password")
3383 @click.option("--url", prompt
=True, help="WIM url")
3384 # @click.option('--tenant',
3385 # help='wIM tenant name')
3386 @click.option("--config", default
=None, help="WIM specific config parameters")
3387 @click.option("--wim_type", help="WIM type")
3388 @click.option("--description", default
=None, help="human readable description")
3390 "--wim_port_mapping",
3392 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
3393 "(WAN service endpoint id and info)",
3400 help="do not return the control immediately, but keep it "
3401 "until the operation is completed, or timeout",
3417 """creates a new WIM account"""
3420 check_client_version(ctx
.obj
, ctx
.command
.name
)
3421 # if sdn_controller:
3422 # check_client_version(ctx.obj, '--sdn_controller')
3423 # if sdn_port_mapping:
3424 # check_client_version(ctx.obj, '--sdn_port_mapping')
3429 wim
["password"] = password
3431 wim
["wim_url"] = url
3432 # if tenant: wim['tenant'] = tenant
3433 wim
["wim_type"] = wim_type
3435 wim
["description"] = description
3437 wim
["config"] = config
3438 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
3439 # except ClientException as e:
3444 @cli_osm.command(name
="wim-update", short_help
="updates a WIM account")
3445 @click.argument("name")
3446 @click.option("--newname", help="New name for the WIM account")
3447 @click.option("--user", help="WIM username")
3448 @click.option("--password", help="WIM password")
3449 @click.option("--url", help="WIM url")
3450 @click.option("--config", help="WIM specific config parameters")
3451 @click.option("--wim_type", help="WIM type")
3452 @click.option("--description", help="human readable description")
3454 "--wim_port_mapping",
3456 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
3457 "(WAN service endpoint id and info)",
3464 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3480 """updates a WIM account
3482 NAME: name or ID of the WIM account
3486 check_client_version(ctx
.obj
, ctx
.command
.name
)
3489 wim
["name"] = newname
3493 wim
["password"] = password
3496 # if tenant: wim['tenant'] = tenant
3498 wim
["wim_type"] = wim_type
3500 wim
["description"] = description
3502 wim
["config"] = config
3503 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
3504 # except ClientException as e:
3509 @cli_osm.command(name
="wim-delete", short_help
="deletes a WIM account")
3510 @click.argument("name")
3512 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3519 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3522 def wim_delete(ctx
, name
, force
, wait
):
3523 """deletes a WIM account
3525 NAME: name or ID of the WIM account to be deleted
3529 check_client_version(ctx
.obj
, ctx
.command
.name
)
3530 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
3531 # except ClientException as e:
3536 @cli_osm.command(name
="wim-list", short_help
="list all WIM accounts")
3541 help="restricts the list to the WIM accounts matching the filter",
3544 def wim_list(ctx
, filter):
3545 """list all WIM accounts"""
3548 check_client_version(ctx
.obj
, ctx
.command
.name
)
3550 filter = "&".join(filter)
3551 resp
= ctx
.obj
.wim
.list(filter)
3552 table
= PrettyTable(["wim name", "uuid"])
3554 table
.add_row([wim
["name"], wim
["uuid"]])
3557 # except ClientException as e:
3562 @cli_osm.command(name
="wim-show", short_help
="shows the details of a WIM account")
3563 @click.argument("name")
3565 def wim_show(ctx
, name
):
3566 """shows the details of a WIM account
3568 NAME: name or ID of the WIM account
3572 check_client_version(ctx
.obj
, ctx
.command
.name
)
3573 resp
= ctx
.obj
.wim
.get(name
)
3574 if "password" in resp
:
3575 resp
["password"] = "********"
3576 # except ClientException as e:
3580 table
= PrettyTable(["key", "attribute"])
3581 for k
, v
in list(resp
.items()):
3582 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3587 ####################
3588 # SDN controller operations
3589 ####################
3592 @cli_osm.command(name
="sdnc-create", short_help
="creates a new SDN controller")
3593 @click.option("--name", prompt
=True, help="Name to create sdn controller")
3594 @click.option("--type", prompt
=True, help="SDN controller type")
3596 "--sdn_controller_version", # hidden=True,
3597 help="Deprecated. Use --config {version: sdn_controller_version}",
3599 @click.option("--url", help="URL in format http[s]://HOST:IP/")
3600 @click.option("--ip_address", help="Deprecated. Use --url") # hidden=True,
3601 @click.option("--port", help="Deprecated. Use --url") # hidden=True,
3603 "--switch_dpid", help="Deprecated. Use --config {switch_id: DPID}" # hidden=True,
3607 help="Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: "
3608 "Openflow Datapath ID), version: version}",
3610 @click.option("--user", help="SDN controller username")
3614 confirmation_prompt
=True,
3615 help="SDN controller password",
3617 @click.option("--description", default
=None, help="human readable description")
3623 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3626 def sdnc_create(ctx
, **kwargs
):
3627 """creates a new SDN controller"""
3632 if kwargs
[x
] and x
not in ("wait", "ip_address", "port", "switch_dpid")
3634 if kwargs
.get("port"):
3635 print("option '--port' is deprecated, use '--url' instead")
3636 sdncontroller
["port"] = int(kwargs
["port"])
3637 if kwargs
.get("ip_address"):
3638 print("option '--ip_address' is deprecated, use '--url' instead")
3639 sdncontroller
["ip"] = kwargs
["ip_address"]
3640 if kwargs
.get("switch_dpid"):
3642 "option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead"
3644 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
3645 if kwargs
.get("sdn_controller_version"):
3647 "option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
3651 check_client_version(ctx
.obj
, ctx
.command
.name
)
3652 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
3653 # except ClientException as e:
3658 @cli_osm.command(name
="sdnc-update", short_help
="updates an SDN controller")
3659 @click.argument("name")
3660 @click.option("--newname", help="New name for the SDN controller")
3661 @click.option("--description", default
=None, help="human readable description")
3662 @click.option("--type", help="SDN controller type")
3663 @click.option("--url", help="URL in format http[s]://HOST:IP/")
3666 help="Extra information for SDN in yaml format, as "
3667 "{switch_id: identity used for the plugin (e.g. DPID: "
3668 "Openflow Datapath ID), version: version}",
3670 @click.option("--user", help="SDN controller username")
3671 @click.option("--password", help="SDN controller password")
3672 @click.option("--ip_address", help="Deprecated. Use --url") # hidden=True
3673 @click.option("--port", help="Deprecated. Use --url") # hidden=True
3675 "--switch_dpid", help="Deprecated. Use --config {switch_dpid: DPID}"
3678 "--sdn_controller_version", help="Deprecated. Use --config {version: VERSION}"
3685 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3688 def sdnc_update(ctx
, **kwargs
):
3689 """updates an SDN controller
3691 NAME: name or ID of the SDN controller
3698 and x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")
3700 if kwargs
.get("newname"):
3701 sdncontroller
["name"] = kwargs
["newname"]
3702 if kwargs
.get("port"):
3703 print("option '--port' is deprecated, use '--url' instead")
3704 sdncontroller
["port"] = int(kwargs
["port"])
3705 if kwargs
.get("ip_address"):
3706 print("option '--ip_address' is deprecated, use '--url' instead")
3707 sdncontroller
["ip"] = kwargs
["ip_address"]
3708 if kwargs
.get("switch_dpid"):
3710 "option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead"
3712 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
3713 if kwargs
.get("sdn_controller_version"):
3715 "option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
3720 check_client_version(ctx
.obj
, ctx
.command
.name
)
3721 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
3722 # except ClientException as e:
3727 @cli_osm.command(name
="sdnc-delete", short_help
="deletes an SDN controller")
3728 @click.argument("name")
3730 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
3737 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3740 def sdnc_delete(ctx
, name
, force
, wait
):
3741 """deletes an SDN controller
3743 NAME: name or ID of the SDN controller to be deleted
3747 check_client_version(ctx
.obj
, ctx
.command
.name
)
3748 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
3749 # except ClientException as e:
3754 @cli_osm.command(name
="sdnc-list", short_help
="list all SDN controllers")
3759 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'",
3762 def sdnc_list(ctx
, filter):
3763 """list all SDN controllers"""
3766 check_client_version(ctx
.obj
, ctx
.command
.name
)
3768 filter = "&".join(filter)
3769 resp
= ctx
.obj
.sdnc
.list(filter)
3770 # except ClientException as e:
3773 table
= PrettyTable(["sdnc name", "id"])
3775 table
.add_row([sdnc
["name"], sdnc
["_id"]])
3780 @cli_osm.command(name
="sdnc-show", short_help
="shows the details of an SDN controller")
3781 @click.argument("name")
3783 def sdnc_show(ctx
, name
):
3784 """shows the details of an SDN controller
3786 NAME: name or ID of the SDN controller
3790 check_client_version(ctx
.obj
, ctx
.command
.name
)
3791 resp
= ctx
.obj
.sdnc
.get(name
)
3792 # except ClientException as e:
3796 table
= PrettyTable(["key", "attribute"])
3797 for k
, v
in list(resp
.items()):
3798 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3803 ###########################
3804 # K8s cluster operations
3805 ###########################
3808 @cli_osm.command(name
="k8scluster-add", short_help
="adds a K8s cluster to OSM")
3809 @click.argument("name")
3811 "--creds", prompt
=True, help="credentials file, i.e. a valid `.kube/config` file"
3813 @click.option("--version", prompt
=True, help="Kubernetes version")
3815 "--vim", prompt
=True, help="VIM target, the VIM where the cluster resides"
3820 help='''list of VIM networks, in JSON inline format, where the cluster is
3821 accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''',
3823 @click.option("--description", default
=None, help="human readable description")
3826 default
="kube-system",
3827 help="namespace to be used for its operation, defaults to `kube-system`",
3834 help="do not return the control immediately, but keep it "
3835 "until the operation is completed, or timeout",
3840 help="list of CNI plugins, in JSON inline format, used in the cluster",
3842 # @click.option('--skip-init',
3844 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3845 # @click.option('--wait',
3847 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3850 ctx
, name
, creds
, version
, vim
, k8s_nets
, description
, namespace
, wait
, cni
3852 """adds a K8s cluster to OSM
3854 NAME: name of the K8s cluster
3857 check_client_version(ctx
.obj
, ctx
.command
.name
)
3859 cluster
["name"] = name
3860 with
open(creds
, "r") as cf
:
3861 cluster
["credentials"] = yaml
.safe_load(cf
.read())
3862 cluster
["k8s_version"] = version
3863 cluster
["vim_account"] = vim
3864 cluster
["nets"] = yaml
.safe_load(k8s_nets
)
3866 cluster
["description"] = description
3868 cluster
["namespace"] = namespace
3870 cluster
["cni"] = yaml
.safe_load(cni
)
3871 ctx
.obj
.k8scluster
.create(name
, cluster
, wait
)
3872 # except ClientException as e:
3877 @cli_osm.command(name
="k8scluster-update", short_help
="updates a K8s cluster")
3878 @click.argument("name")
3879 @click.option("--newname", help="New name for the K8s cluster")
3880 @click.option("--creds", help="credentials file, i.e. a valid `.kube/config` file")
3881 @click.option("--version", help="Kubernetes version")
3882 @click.option("--vim", help="VIM target, the VIM where the cluster resides")
3885 help='''list of VIM networks, in JSON inline format, where the cluster is accessible
3886 via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''',
3888 @click.option("--description", help="human readable description")
3891 help="namespace to be used for its operation, defaults to `kube-system`",
3898 help="do not return the control immediately, but keep it "
3899 "until the operation is completed, or timeout",
3902 "--cni", help="list of CNI plugins, in JSON inline format, used in the cluster"
3905 def k8scluster_update(
3906 ctx
, name
, newname
, creds
, version
, vim
, k8s_nets
, description
, namespace
, wait
, cni
3908 """updates a K8s cluster
3910 NAME: name or ID of the K8s cluster
3913 check_client_version(ctx
.obj
, ctx
.command
.name
)
3916 cluster
["name"] = newname
3918 with
open(creds
, "r") as cf
:
3919 cluster
["credentials"] = yaml
.safe_load(cf
.read())
3921 cluster
["k8s_version"] = version
3923 cluster
["vim_account"] = vim
3925 cluster
["nets"] = yaml
.safe_load(k8s_nets
)
3927 cluster
["description"] = description
3929 cluster
["namespace"] = namespace
3931 cluster
["cni"] = yaml
.safe_load(cni
)
3932 ctx
.obj
.k8scluster
.update(name
, cluster
, wait
)
3933 # except ClientException as e:
3938 @cli_osm.command(name
="k8scluster-delete", short_help
="deletes a K8s cluster")
3939 @click.argument("name")
3941 "--force", is_flag
=True, help="forces the deletion from the DB (not recommended)"
3948 help="do not return the control immediately, but keep it "
3949 "until the operation is completed, or timeout",
3952 def k8scluster_delete(ctx
, name
, force
, wait
):
3953 """deletes a K8s cluster
3955 NAME: name or ID of the K8s cluster to be deleted
3958 check_client_version(ctx
.obj
, ctx
.command
.name
)
3959 ctx
.obj
.k8scluster
.delete(name
, force
, wait
)
3960 # except ClientException as e:
3965 @cli_osm.command(name
="k8scluster-list")
3970 help="restricts the list to the K8s clusters matching the filter",
3972 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
3973 @click.option("--long", is_flag
=True, help="get more details")
3975 def k8scluster_list(ctx
, filter, literal
, long):
3976 """list all K8s clusters"""
3978 check_client_version(ctx
.obj
, ctx
.command
.name
)
3980 filter = "&".join(filter)
3981 resp
= ctx
.obj
.k8scluster
.list(filter)
3983 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3986 table
= PrettyTable(
3994 "Operational State",
3995 "Op. state (details)",
4000 project_list
= ctx
.obj
.project
.list()
4002 table
= PrettyTable(
4003 ["Name", "Id", "VIM", "Operational State", "Op. state details"]
4006 vim_list
= ctx
.obj
.vim
.list()
4009 for cluster
in resp
:
4010 logger
.debug("Cluster details: {}".format(yaml
.safe_dump(cluster
)))
4011 vim_name
= get_vim_name(vim_list
, cluster
["vim_account"])
4012 # vim_info = '{} ({})'.format(vim_name,cluster['vim_account'])
4014 op_state_details
= "Helm: {}\nJuju: {}".format(
4015 cluster
["_admin"].get("helm-chart", {}).get("operationalState", "-"),
4016 cluster
["_admin"].get("juju-bundle", {}).get("operationalState", "-"),
4019 project_id
, project_name
= get_project(project_list
, cluster
)
4020 # project_info = '{} ({})'.format(project_name, project_id)
4021 project_info
= project_name
4022 detailed_status
= cluster
["_admin"].get("detailed-status", "-")
4028 cluster
["k8s_version"],
4030 json
.dumps(cluster
["nets"]),
4031 cluster
["_admin"]["operationalState"],
4033 trunc_text(cluster
.get("description") or "", 40),
4034 wrap_text(text
=detailed_status
, width
=40),
4043 cluster
["_admin"]["operationalState"],
4049 # except ClientException as e:
4055 name
="k8scluster-show", short_help
="shows the details of a K8s cluster"
4057 @click.argument("name")
4058 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4060 def k8scluster_show(ctx
, name
, literal
):
4061 """shows the details of a K8s cluster
4063 NAME: name or ID of the K8s cluster
4066 resp
= ctx
.obj
.k8scluster
.get(name
)
4068 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4070 table
= PrettyTable(["key", "attribute"])
4071 for k
, v
in list(resp
.items()):
4072 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
4075 # except ClientException as e:
4080 ###########################
4082 ###########################
4085 @cli_osm.command(name
="vca-add", short_help
="adds a VCA (Juju controller) to OSM")
4086 @click.argument("name")
4090 help="Comma-separated list of IP or hostnames of the Juju controller",
4092 @click.option("--user", prompt
=True, help="Username with admin priviledges")
4093 @click.option("--secret", prompt
=True, help="Password of the specified username")
4094 @click.option("--cacert", prompt
=True, help="CA certificate")
4098 help="Name of the cloud that will be used for LXD containers (LXD proxy charms)",
4101 "--lxd-credentials",
4103 help="Name of the cloud credentialsto be used for the LXD cloud",
4108 help="Name of the cloud that will be used for K8s containers (K8s proxy charms)",
4111 "--k8s-credentials",
4113 help="Name of the cloud credentialsto be used for the K8s cloud",
4118 help="Configuration options for the models",
4120 @click.option("--description", default
=None, help="human readable description")
4136 """adds a VCA to OSM
4138 NAME: name of the VCA
4140 check_client_version(ctx
.obj
, ctx
.command
.name
)
4143 vca
["endpoints"] = endpoints
.split(",")
4145 vca
["secret"] = secret
4146 vca
["cacert"] = cacert
4147 vca
["lxd-cloud"] = lxd_cloud
4148 vca
["lxd-credentials"] = lxd_credentials
4149 vca
["k8s-cloud"] = k8s_cloud
4150 vca
["k8s-credentials"] = k8s_credentials
4152 vca
["description"] = description
4154 model_config
= load(model_config
)
4155 vca
["model-config"] = model_config
4156 ctx
.obj
.vca
.create(name
, vca
)
4159 def load(data
: Any
):
4160 if os
.path
.isfile(data
):
4161 return load_file(data
)
4164 return json
.loads(data
)
4165 except ValueError as e
:
4166 raise ClientException(e
)
4169 def load_file(file_path
: str) -> Dict
:
4171 with
open(file_path
, "r") as f
:
4174 return yaml
.safe_load(content
)
4175 except yaml
.scanner
.ScannerError
:
4178 return json
.loads(content
)
4181 raise ClientException(f
"{file_path} must be a valid yaml or json file")
4184 @cli_osm.command(name
="vca-update", short_help
="updates a K8s cluster")
4185 @click.argument("name")
4187 "--endpoints", help="Comma-separated list of IP or hostnames of the Juju controller"
4189 @click.option("--user", help="Username with admin priviledges")
4190 @click.option("--secret", help="Password of the specified username")
4191 @click.option("--cacert", help="CA certificate")
4194 help="Name of the cloud that will be used for LXD containers (LXD proxy charms)",
4197 "--lxd-credentials",
4198 help="Name of the cloud credentialsto be used for the LXD cloud",
4202 help="Name of the cloud that will be used for K8s containers (K8s proxy charms)",
4205 "--k8s-credentials",
4206 help="Name of the cloud credentialsto be used for the K8s cloud",
4210 help="Configuration options for the models",
4212 @click.option("--description", default
=None, help="human readable description")
4228 """updates a K8s cluster
4230 NAME: name or ID of the K8s cluster
4232 check_client_version(ctx
.obj
, ctx
.command
.name
)
4236 vca
["endpoints"] = endpoints
.split(",")
4240 vca
["secret"] = secret
4242 vca
["cacert"] = cacert
4244 vca
["lxd-cloud"] = lxd_cloud
4246 vca
["lxd-credentials"] = lxd_credentials
4248 vca
["k8s-cloud"] = k8s_cloud
4250 vca
["k8s-credentials"] = k8s_credentials
4252 vca
["description"] = description
4254 model_config
= load(model_config
)
4255 vca
["model-config"] = model_config
4256 ctx
.obj
.vca
.update(name
, vca
)
4259 @cli_osm.command(name
="vca-delete", short_help
="deletes a K8s cluster")
4260 @click.argument("name")
4262 "--force", is_flag
=True, help="forces the deletion from the DB (not recommended)"
4265 def vca_delete(ctx
, name
, force
):
4266 """deletes a K8s cluster
4268 NAME: name or ID of the K8s cluster to be deleted
4270 check_client_version(ctx
.obj
, ctx
.command
.name
)
4271 ctx
.obj
.vca
.delete(name
, force
=force
)
4274 @cli_osm.command(name
="vca-list")
4279 help="restricts the list to the VCAs matching the filter",
4281 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4282 @click.option("--long", is_flag
=True, help="get more details")
4284 def vca_list(ctx
, filter, literal
, long):
4286 check_client_version(ctx
.obj
, ctx
.command
.name
)
4288 filter = "&".join(filter)
4289 resp
= ctx
.obj
.vca
.list(filter)
4291 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4294 table
= PrettyTable(
4295 ["Name", "Id", "Project", "Operational State", "Detailed Status"]
4297 project_list
= ctx
.obj
.project
.list()
4299 table
= PrettyTable(["Name", "Id", "Operational State"])
4301 logger
.debug("VCA details: {}".format(yaml
.safe_dump(vca
)))
4303 project_id
, project_name
= get_project(project_list
, vca
)
4304 detailed_status
= vca
.get("_admin", {}).get("detailed-status", "-")
4310 vca
.get("_admin", {}).get("operationalState", "-"),
4311 wrap_text(text
=detailed_status
, width
=40),
4319 vca
.get("_admin", {}).get("operationalState", "-"),
4326 @cli_osm.command(name
="vca-show", short_help
="shows the details of a K8s cluster")
4327 @click.argument("name")
4328 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4330 def vca_show(ctx
, name
, literal
):
4331 """shows the details of a K8s cluster
4333 NAME: name or ID of the K8s cluster
4336 resp
= ctx
.obj
.vca
.get(name
)
4338 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4340 table
= PrettyTable(["key", "attribute"])
4341 for k
, v
in list(resp
.items()):
4342 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
4347 ###########################
4349 ###########################
4352 @cli_osm.command(name
="repo-add", short_help
="adds a repo to OSM")
4353 @click.argument("name")
4354 @click.argument("uri")
4357 type=click
.Choice(["helm-chart", "juju-bundle", "osm"]),
4359 help="type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)",
4361 @click.option("--description", default
=None, help="human readable description")
4363 "--user", default
=None, help="OSM repository: The username of the OSM repository"
4368 help="OSM repository: The password of the OSM repository",
4370 # @click.option('--wait',
4372 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4374 def repo_add(ctx
, **kwargs
):
4375 """adds a repo to OSM
4377 NAME: name of the repo
4378 URI: URI of the repo
4381 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
4383 repo
["url"] = repo
.pop("uri")
4384 if repo
["type"] in ["helm-chart", "juju-bundle"]:
4385 ctx
.obj
.repo
.create(repo
["name"], repo
)
4387 ctx
.obj
.osmrepo
.create(repo
["name"], repo
)
4388 # except ClientException as e:
4393 @cli_osm.command(name
="repo-update", short_help
="updates a repo in OSM")
4394 @click.argument("name")
4395 @click.option("--newname", help="New name for the repo")
4396 @click.option("--uri", help="URI of the repo")
4397 @click.option("--description", help="human readable description")
4398 # @click.option('--wait',
4400 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4402 def repo_update(ctx
, name
, newname
, uri
, description
):
4403 """updates a repo in OSM
4405 NAME: name of the repo
4408 check_client_version(ctx
.obj
, ctx
.command
.name
)
4411 repo
["name"] = newname
4415 repo
["description"] = description
4417 ctx
.obj
.repo
.update(name
, repo
)
4419 ctx
.obj
.osmrepo
.update(name
, repo
)
4421 # except ClientException as e:
4427 name
="repo-index", short_help
="Index a repository from a folder with artifacts"
4430 "--origin", default
=".", help="origin path where the artifacts are located"
4433 "--destination", default
=".", help="destination path where the index is deployed"
4436 def repo_index(ctx
, origin
, destination
):
4437 """Index a repository
4439 NAME: name or ID of the repo to be deleted
4441 check_client_version(ctx
.obj
, ctx
.command
.name
)
4442 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
4445 @cli_osm.command(name
="repo-delete", short_help
="deletes a repo")
4446 @click.argument("name")
4448 "--force", is_flag
=True, help="forces the deletion from the DB (not recommended)"
4450 # @click.option('--wait',
4452 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4454 def repo_delete(ctx
, name
, force
):
4457 NAME: name or ID of the repo to be deleted
4461 ctx
.obj
.repo
.delete(name
, force
=force
)
4463 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
4464 # except ClientException as e:
4469 @cli_osm.command(name
="repo-list")
4474 help="restricts the list to the repos matching the filter",
4476 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4478 def repo_list(ctx
, filter, literal
):
4479 """list all repos"""
4482 check_client_version(ctx
.obj
, ctx
.command
.name
)
4484 filter = "&".join(filter)
4485 resp
= ctx
.obj
.repo
.list(filter)
4486 resp
+= ctx
.obj
.osmrepo
.list(filter)
4488 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4490 table
= PrettyTable(["Name", "Id", "Type", "URI", "Description"])
4492 # cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
4499 trunc_text(repo
.get("description") or "", 40),
4505 # except ClientException as e:
4510 @cli_osm.command(name
="repo-show", short_help
="shows the details of a repo")
4511 @click.argument("name")
4512 @click.option("--literal", is_flag
=True, help="print literally, no pretty table")
4514 def repo_show(ctx
, name
, literal
):
4515 """shows the details of a repo
4517 NAME: name or ID of the repo
4520 resp
= ctx
.obj
.repo
.get(name
)
4522 resp
= ctx
.obj
.osmrepo
.get(name
)
4526 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
4528 table
= PrettyTable(["key", "attribute"])
4530 for k
, v
in list(resp
.items()):
4531 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4535 # except ClientException as e:
4540 ####################
4541 # Project mgmt operations
4542 ####################
4545 @cli_osm.command(name
="project-create", short_help
="creates a new project")
4546 @click.argument("name")
4547 # @click.option('--description',
4548 # default='no description',
4549 # help='human readable description')
4550 @click.option("--domain-name", "domain_name", default
=None, help="assign to a domain")
4556 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
4557 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos",
4560 def project_create(ctx
, name
, domain_name
, quotas
):
4561 """Creates a new project
4563 NAME: name of the project
4564 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
4565 QUOTAS: set quotas for the project
4568 project
= {"name": name
}
4570 project
["domain_name"] = domain_name
4571 quotas_dict
= _process_project_quotas(quotas
)
4573 project
["quotas"] = quotas_dict
4576 check_client_version(ctx
.obj
, ctx
.command
.name
)
4577 ctx
.obj
.project
.create(name
, project
)
4578 # except ClientException as e:
4583 def _process_project_quotas(quota_list
):
4588 for quota
in quota_list
:
4589 for single_quota
in quota
.split(","):
4590 k
, v
= single_quota
.split("=")
4591 quotas_dict
[k
] = None if v
in ("None", "null", "") else int(v
)
4592 except (ValueError, TypeError):
4593 raise ClientException(
4594 "invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null"
4599 @cli_osm.command(name
="project-delete", short_help
="deletes a project")
4600 @click.argument("name")
4601 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4603 def project_delete(ctx
, name
):
4604 """deletes a project
4606 NAME: name or ID of the project to be deleted
4610 check_client_version(ctx
.obj
, ctx
.command
.name
)
4611 ctx
.obj
.project
.delete(name
)
4612 # except ClientException as e:
4617 @cli_osm.command(name
="project-list", short_help
="list all projects")
4622 help="restricts the list to the projects matching the filter",
4625 def project_list(ctx
, filter):
4626 """list all projects"""
4629 check_client_version(ctx
.obj
, ctx
.command
.name
)
4631 filter = "&".join(filter)
4632 resp
= ctx
.obj
.project
.list(filter)
4633 # except ClientException as e:
4636 table
= PrettyTable(["name", "id"])
4638 table
.add_row([proj
["name"], proj
["_id"]])
4643 @cli_osm.command(name
="project-show", short_help
="shows the details of a project")
4644 @click.argument("name")
4646 def project_show(ctx
, name
):
4647 """shows the details of a project
4649 NAME: name or ID of the project
4653 check_client_version(ctx
.obj
, ctx
.command
.name
)
4654 resp
= ctx
.obj
.project
.get(name
)
4655 # except ClientException as e:
4659 table
= PrettyTable(["key", "attribute"])
4660 for k
, v
in resp
.items():
4661 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4667 name
="project-update", short_help
="updates a project (only the name can be updated)"
4669 @click.argument("project")
4670 @click.option("--name", default
=None, help="new name for the project")
4676 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
4677 "(use empty to reset quota to default",
4680 def project_update(ctx
, project
, name
, quotas
):
4682 Update a project name
4685 :param project: id or name of the project to modify
4686 :param name: new name for the project
4687 :param quotas: change quotas of the project
4691 project_changes
= {}
4693 project_changes
["name"] = name
4694 quotas_dict
= _process_project_quotas(quotas
)
4696 project_changes
["quotas"] = quotas_dict
4699 check_client_version(ctx
.obj
, ctx
.command
.name
)
4700 ctx
.obj
.project
.update(project
, project_changes
)
4701 # except ClientException as e:
4705 ####################
4706 # User mgmt operations
4707 ####################
4710 @cli_osm.command(name
="user-create", short_help
="creates a new user")
4711 @click.argument("username")
4716 confirmation_prompt
=True,
4717 help="user password",
4721 # prompt="Comma separate list of projects",
4723 callback
=lambda ctx
, param
, value
: "".join(value
).split(",")
4724 if all(len(x
) == 1 for x
in value
)
4726 help="list of project ids that the user belongs to",
4729 "--project-role-mappings",
4730 "project_role_mappings",
4733 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4735 @click.option("--domain-name", "domain_name", default
=None, help="assign to a domain")
4737 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
4738 """Creates a new user
4741 USERNAME: name of the user
4742 PASSWORD: password of the user
4743 PROJECTS: projects assigned to user (internal only)
4744 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
4745 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
4749 user
["username"] = username
4750 user
["password"] = password
4751 user
["projects"] = projects
4752 user
["project_role_mappings"] = project_role_mappings
4754 user
["domain_name"] = domain_name
4757 check_client_version(ctx
.obj
, ctx
.command
.name
)
4758 ctx
.obj
.user
.create(username
, user
)
4759 # except ClientException as e:
4764 @cli_osm.command(name
="user-update", short_help
="updates user information")
4765 @click.argument("username")
4770 # confirmation_prompt=True,
4771 help="user password",
4773 @click.option("--set-username", "set_username", default
=None, help="change username")
4779 help="create/replace the roles for this project: 'project,role1[,role2,...]'",
4786 help="removes project from user: 'project'",
4789 "--add-project-role",
4793 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4796 "--remove-project-role",
4797 "remove_project_role",
4800 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4811 remove_project_role
,
4813 """Update a user information
4816 USERNAME: name of the user
4817 PASSWORD: new password
4818 SET_USERNAME: new username
4819 SET_PROJECT: creating mappings for project/role(s)
4820 REMOVE_PROJECT: deleting mappings for project/role(s)
4821 ADD_PROJECT_ROLE: adding mappings for project/role(s)
4822 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
4826 user
["password"] = password
4827 user
["username"] = set_username
4828 user
["set-project"] = set_project
4829 user
["remove-project"] = remove_project
4830 user
["add-project-role"] = add_project_role
4831 user
["remove-project-role"] = remove_project_role
4834 check_client_version(ctx
.obj
, ctx
.command
.name
)
4835 ctx
.obj
.user
.update(username
, user
)
4836 # except ClientException as e:
4841 @cli_osm.command(name
="user-delete", short_help
="deletes a user")
4842 @click.argument("name")
4843 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4845 def user_delete(ctx
, name
):
4849 NAME: name or ID of the user to be deleted
4853 check_client_version(ctx
.obj
, ctx
.command
.name
)
4854 ctx
.obj
.user
.delete(name
)
4855 # except ClientException as e:
4860 @cli_osm.command(name
="user-list", short_help
="list all users")
4865 help="restricts the list to the users matching the filter",
4868 def user_list(ctx
, filter):
4869 """list all users"""
4871 check_client_version(ctx
.obj
, ctx
.command
.name
)
4873 filter = "&".join(filter)
4874 resp
= ctx
.obj
.user
.list(filter)
4875 # except ClientException as e:
4878 table
= PrettyTable(["name", "id"])
4880 table
.add_row([user
["username"], user
["_id"]])
4885 @cli_osm.command(name
="user-show", short_help
="shows the details of a user")
4886 @click.argument("name")
4888 def user_show(ctx
, name
):
4889 """shows the details of a user
4891 NAME: name or ID of the user
4895 check_client_version(ctx
.obj
, ctx
.command
.name
)
4896 resp
= ctx
.obj
.user
.get(name
)
4897 if "password" in resp
:
4898 resp
["password"] = "********"
4899 # except ClientException as e:
4903 table
= PrettyTable(["key", "attribute"])
4904 for k
, v
in resp
.items():
4905 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4910 ####################
4911 # Fault Management operations
4912 ####################
4915 @cli_osm.command(name
="ns-alarm-create")
4916 @click.argument("name")
4917 @click.option("--ns", prompt
=True, help="NS instance id or name")
4919 "--vnf", prompt
=True, help="VNF name (VNF member index as declared in the NSD)"
4921 @click.option("--vdu", prompt
=True, help="VDU name (VDU name as declared in the VNFD)")
4922 @click.option("--metric", prompt
=True, help="Name of the metric (e.g. cpu_utilization)")
4926 help="severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)",
4929 "--threshold_value",
4931 help="threshold value that, when crossed, an alarm is triggered",
4934 "--threshold_operator",
4936 help="threshold operator describing the comparison (GE, LE, GT, LT, EQ)",
4941 help="statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)",
4944 def ns_alarm_create(
4956 """creates a new alarm for a NS instance"""
4957 # TODO: Check how to validate threshold_value.
4958 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
4961 ns_instance
= ctx
.obj
.ns
.get(ns
)
4963 alarm
["alarm_name"] = name
4964 alarm
["ns_id"] = ns_instance
["_id"]
4965 alarm
["correlation_id"] = ns_instance
["_id"]
4966 alarm
["vnf_member_index"] = vnf
4967 alarm
["vdu_name"] = vdu
4968 alarm
["metric_name"] = metric
4969 alarm
["severity"] = severity
4970 alarm
["threshold_value"] = int(threshold_value
)
4971 alarm
["operation"] = threshold_operator
4972 alarm
["statistic"] = statistic
4973 check_client_version(ctx
.obj
, ctx
.command
.name
)
4974 ctx
.obj
.ns
.create_alarm(alarm
)
4975 # except ClientException as e:
4980 # @cli_osm.command(name='ns-alarm-delete')
4981 # @click.argument('name')
4982 # @click.pass_context
4983 # def ns_alarm_delete(ctx, name):
4984 # """deletes an alarm
4986 # NAME: name of the alarm to be deleted
4989 # check_client_version(ctx.obj, ctx.command.name)
4990 # ctx.obj.ns.delete_alarm(name)
4991 # except ClientException as e:
4996 ####################
4997 # Performance Management operations
4998 ####################
5002 name
="ns-metric-export",
5003 short_help
="exports a metric to the internal OSM bus, which can be read by other apps",
5005 @click.option("--ns", prompt
=True, help="NS instance id or name")
5007 "--vnf", prompt
=True, help="VNF name (VNF member index as declared in the NSD)"
5009 @click.option("--vdu", prompt
=True, help="VDU name (VDU name as declared in the VNFD)")
5010 @click.option("--metric", prompt
=True, help="name of the metric (e.g. cpu_utilization)")
5011 # @click.option('--period', default='1w',
5012 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
5014 "--interval", help="periodic interval (seconds) to export metrics continuously"
5017 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
5018 """exports a metric to the internal OSM bus, which can be read by other apps"""
5019 # TODO: Check how to validate interval.
5020 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
5023 ns_instance
= ctx
.obj
.ns
.get(ns
)
5025 metric_data
["ns_id"] = ns_instance
["_id"]
5026 metric_data
["correlation_id"] = ns_instance
["_id"]
5027 metric_data
["vnf_member_index"] = vnf
5028 metric_data
["vdu_name"] = vdu
5029 metric_data
["metric_name"] = metric
5030 metric_data
["collection_unit"] = "WEEK"
5031 metric_data
["collection_period"] = 1
5032 check_client_version(ctx
.obj
, ctx
.command
.name
)
5034 print("{}".format(ctx
.obj
.ns
.export_metric(metric_data
)))
5038 print("{} {}".format(ctx
.obj
.ns
.export_metric(metric_data
), i
))
5039 time
.sleep(int(interval
))
5041 # except ClientException as e:
5047 # Subscription operations
5052 name
="subscription-create",
5053 short_help
="creates a new subscription to a specific event",
5057 # type=click.Choice(['ns', 'nspkg', 'vnfpkg'], case_sensitive=False))
5058 type=click
.Choice(["ns"], case_sensitive
=False),
5059 help="event type to be subscribed (for the moment, only ns is supported)",
5061 @click.option("--event", default
=None, help="specific yaml configuration for the event")
5063 "--event_file", default
=None, help="specific yaml configuration file for the event"
5066 def subscription_create(ctx
, event_type
, event
, event_file
):
5067 """creates a new subscription to a specific event"""
5069 check_client_version(ctx
.obj
, ctx
.command
.name
)
5072 raise ClientException(
5073 '"--event" option is incompatible with "--event_file" option'
5075 with
open(event_file
, "r") as cf
:
5077 ctx
.obj
.subscription
.create(event_type
, event
)
5080 @cli_osm.command(name
="subscription-delete", short_help
="deletes a subscription")
5083 # type=click.Choice(['ns', 'nspkg', 'vnfpkg'], case_sensitive=False))
5084 type=click
.Choice(["ns"], case_sensitive
=False),
5085 help="event type to be subscribed (for the moment, only ns is supported)",
5087 @click.argument("subscription_id")
5089 "--force", is_flag
=True, help="forces the deletion bypassing pre-conditions"
5092 def subscription_delete(ctx
, event_type
, subscription_id
, force
):
5093 """deletes a subscription
5095 SUBSCRIPTION_ID: ID of the subscription to be deleted
5098 check_client_version(ctx
.obj
, ctx
.command
.name
)
5099 ctx
.obj
.subscription
.delete(event_type
, subscription_id
, force
)
5102 @cli_osm.command(name
="subscription-list", short_help
="list all subscriptions")
5105 # type=click.Choice(['ns', 'nspkg', 'vnfpkg'], case_sensitive=False))
5106 type=click
.Choice(["ns"], case_sensitive
=False),
5107 help="event type to be subscribed (for the moment, only ns is supported)",
5113 help="restricts the list to the subscriptions matching the filter",
5116 def subscription_list(ctx
, event_type
, filter):
5117 """list all subscriptions"""
5119 check_client_version(ctx
.obj
, ctx
.command
.name
)
5121 filter = "&".join(filter)
5122 resp
= ctx
.obj
.subscription
.list(event_type
, filter)
5123 table
= PrettyTable(["id", "filter", "CallbackUri"])
5128 wrap_text(text
=json
.dumps(sub
["filter"], indent
=2), width
=70),
5137 name
="subscription-show", short_help
="shows the details of a subscription"
5139 @click.argument("subscription_id")
5142 # type=click.Choice(['ns', 'nspkg', 'vnfpkg'], case_sensitive=False))
5143 type=click
.Choice(["ns"], case_sensitive
=False),
5144 help="event type to be subscribed (for the moment, only ns is supported)",
5149 help="restricts the information to the fields in the filter",
5152 def subscription_show(ctx
, event_type
, subscription_id
, filter):
5153 """shows the details of a subscription
5155 SUBSCRIPTION_ID: ID of the subscription
5159 resp
= ctx
.obj
.subscription
.get(subscription_id
)
5160 table
= PrettyTable(["key", "attribute"])
5161 for k
, v
in list(resp
.items()):
5162 if not filter or k
in filter:
5163 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
5168 ####################
5170 ####################
5173 @cli_osm.command(name
="version", short_help
="shows client and server versions")
5175 def get_version(ctx
):
5176 """shows client and server versions"""
5178 check_client_version(ctx
.obj
, "version")
5179 print("Server version: {}".format(ctx
.obj
.get_version()))
5181 "Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
)
5183 # except ClientException as e:
5189 name
="upload-package", short_help
="uploads a VNF package or NS package"
5191 @click.argument("filename")
5193 "--skip-charm-build",
5196 help="the charm will not be compiled, it is assumed to already exist",
5199 def upload_package(ctx
, filename
, skip_charm_build
):
5200 """uploads a vnf package or ns package
5202 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
5206 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
5207 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
5208 if fullclassname
!= "osmclient.sol005.client.Client":
5209 ctx
.obj
.package
.wait_for_upload(filename
)
5210 # except ClientException as e:
5215 # @cli_osm.command(name='ns-scaling-show')
5216 # @click.argument('ns_name')
5217 # @click.pass_context
5218 # def show_ns_scaling(ctx, ns_name):
5219 # """shows the status of a NS scaling operation
5221 # NS_NAME: name of the NS instance being scaled
5224 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5225 # resp = ctx.obj.ns.list()
5226 # except ClientException as e:
5230 # table = PrettyTable(
5233 # 'operational status',
5238 # if ns_name == ns['name']:
5239 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
5240 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
5241 # for record in scaling_records:
5242 # if 'instance' in record:
5243 # instances = record['instance']
5244 # for inst in instances:
5246 # [record['scaling-group-name-ref'],
5247 # inst['instance-id'],
5248 # inst['op-status'],
5249 # time.strftime('%Y-%m-%d %H:%M:%S',
5251 # inst['create-time'])),
5257 # @cli_osm.command(name='ns-scale')
5258 # @click.argument('ns_name')
5259 # @click.option('--ns_scale_group', prompt=True)
5260 # @click.option('--index', prompt=True)
5261 # @click.option('--wait',
5265 # help='do not return the control immediately, but keep it \
5266 # until the operation is completed, or timeout')
5267 # @click.pass_context
5268 # def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
5271 # NS_NAME: name of the NS instance to be scaled
5274 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5275 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
5276 # except ClientException as e:
5281 # @cli_osm.command(name='config-agent-list')
5282 # @click.pass_context
5283 # def config_agent_list(ctx):
5284 # """list config agents"""
5286 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5287 # except ClientException as e:
5290 # table = PrettyTable(['name', 'account-type', 'details'])
5291 # for account in ctx.obj.vca.list():
5294 # account['account-type'],
5300 # @cli_osm.command(name='config-agent-delete')
5301 # @click.argument('name')
5302 # @click.pass_context
5303 # def config_agent_delete(ctx, name):
5304 # """deletes a config agent
5306 # NAME: name of the config agent to be deleted
5309 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5310 # ctx.obj.vca.delete(name)
5311 # except ClientException as e:
5316 # @cli_osm.command(name='config-agent-add')
5317 # @click.option('--name',
5319 # @click.option('--account_type',
5321 # @click.option('--server',
5323 # @click.option('--user',
5325 # @click.option('--secret',
5328 # confirmation_prompt=True)
5329 # @click.pass_context
5330 # def config_agent_add(ctx, name, account_type, server, user, secret):
5331 # """adds a config agent"""
5333 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5334 # ctx.obj.vca.create(name, account_type, server, user, secret)
5335 # except ClientException as e:
5340 # @cli_osm.command(name='ro-dump')
5341 # @click.pass_context
5343 # """shows RO agent information"""
5344 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5345 # resp = ctx.obj.vim.get_resource_orchestrator()
5346 # table = PrettyTable(['key', 'attribute'])
5347 # for k, v in list(resp.items()):
5348 # table.add_row([k, json.dumps(v, indent=2)])
5353 # @cli_osm.command(name='vcs-list')
5354 # @click.pass_context
5355 # def vcs_list(ctx):
5356 # check_client_version(ctx.obj, ctx.command.name, 'v1')
5357 # resp = ctx.obj.utils.get_vcs_info()
5358 # table = PrettyTable(['component name', 'state'])
5359 # for component in resp:
5360 # table.add_row([component['component_name'], component['state']])
5366 name
="ns-action", short_help
="executes an action/primitive over a NS instance"
5368 @click.argument("ns_name")
5372 help="member-vnf-index if the target is a vnf instead of a ns)",
5374 @click.option("--kdu_name", default
=None, help="kdu-name if the target is a kdu)")
5375 @click.option("--vdu_id", default
=None, help="vdu-id if the target is a vdu")
5377 "--vdu_count", default
=None, type=int, help="number of vdu instance of this vdu_id"
5379 @click.option("--action_name", prompt
=True, help="action name")
5380 @click.option("--params", default
=None, help="action params in YAML/JSON inline string")
5381 @click.option("--params_file", default
=None, help="YAML/JSON file with action params")
5383 "--timeout", required
=False, default
=None, type=int, help="timeout in seconds"
5390 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
5406 """executes an action/primitive over a NS instance
5408 NS_NAME: name or ID of the NS instance
5412 check_client_version(ctx
.obj
, ctx
.command
.name
)
5415 op_data
["member_vnf_index"] = vnf_name
5417 op_data
["kdu_name"] = kdu_name
5419 op_data
["vdu_id"] = vdu_id
5420 if vdu_count
is not None:
5421 op_data
["vdu_count_index"] = vdu_count
5423 op_data
["timeout_ns_action"] = timeout
5424 op_data
["primitive"] = action_name
5426 with
open(params_file
, "r") as pf
:
5429 op_data
["primitive_params"] = yaml
.safe_load(params
)
5431 op_data
["primitive_params"] = {}
5432 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
="action", op_data
=op_data
, wait
=wait
))
5434 # except ClientException as e:
5440 name
="vnf-scale", short_help
="executes a VNF scale (adding/removing VDUs)"
5442 @click.argument("ns_name")
5443 @click.argument("vnf_name")
5445 "--scaling-group", prompt
=True, help="scaling-group-descriptor name to use"
5448 "--scale-in", default
=False, is_flag
=True, help="performs a scale in operation"
5454 help="performs a scale out operation (by default)",
5457 "--timeout", required
=False, default
=None, type=int, help="timeout in seconds"
5464 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
5468 ctx
, ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, timeout
, wait
5471 Executes a VNF scale (adding/removing VDUs)
5474 NS_NAME: name or ID of the NS instance.
5475 VNF_NAME: member-vnf-index in the NS to be scaled.
5479 check_client_version(ctx
.obj
, ctx
.command
.name
)
5480 if not scale_in
and not scale_out
:
5482 ctx
.obj
.ns
.scale_vnf(
5483 ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
5485 # except ClientException as e:
5490 @cli_osm.command(name
="alarm-show", short_help
="show alarm details")
5491 @click.argument("uuid")
5493 def alarm_show(ctx
, uuid
):
5494 """Show alarm's detail information"""
5496 check_client_version(ctx
.obj
, ctx
.command
.name
)
5497 resp
= ctx
.obj
.ns
.get_alarm(uuid
=uuid
)
5511 table
= PrettyTable(["key", "attribute"])
5513 # Arrange and return the response data
5514 resp
= resp
.replace("ObjectId", "")
5516 for key
in alarm_filter
:
5518 value
= alarm
.get(key
)
5521 value
= alarm
.get(key
)
5523 elif key
== "ns-id":
5524 value
= alarm
["tags"].get("ns_id")
5525 elif key
== "vdu_name":
5526 value
= alarm
["tags"].get("vdu_name")
5527 elif key
== "status":
5528 value
= alarm
["alarm_status"]
5531 table
.add_row([key
, wrap_text(text
=json
.dumps(value
, indent
=2), width
=100)])
5539 @cli_osm.command(name
="alarm-list", short_help
="list all alarms")
5541 "--ns_id", default
=None, required
=False, help="List out alarm for given ns id"
5544 def alarm_list(ctx
, ns_id
):
5545 """list all alarm"""
5547 check_client_version(ctx
.obj
, ctx
.command
.name
)
5548 project_name
= os
.getenv("OSM_PROJECT", "admin")
5549 resp
= ctx
.obj
.ns
.get_alarm(project_name
=project_name
, ns_id
=ns_id
)
5551 table
= PrettyTable(
5552 ["alarm-id", "metric", "threshold", "operation", "action", "status"]
5555 # return the response data in a table
5556 resp
= resp
.replace("ObjectId", "")
5561 wrap_text(text
=str(alarm
["uuid"]), width
=38),
5565 wrap_text(text
=alarm
["action"], width
=25),
5566 alarm
["alarm_status"],
5574 @cli_osm.command(name
="alarm-update", short_help
="Update a alarm")
5575 @click.argument("uuid")
5576 @click.option("--threshold", default
=None, help="Alarm threshold")
5577 @click.option("--is_enable", default
=None, type=bool, help="enable or disable alarm")
5579 def alarm_update(ctx
, uuid
, threshold
, is_enable
):
5584 if not threshold
and is_enable
is None:
5585 raise ClientException(
5586 "Please provide option to update i.e threshold or is_enable"
5588 ctx
.obj
.ns
.update_alarm(uuid
, threshold
, is_enable
)
5591 ##############################
5592 # Role Management Operations #
5593 ##############################
5596 @cli_osm.command(name
="role-create", short_help
="creates a new role")
5597 @click.argument("name")
5598 @click.option("--permissions", default
=None, help="role permissions using a dictionary")
5600 def role_create(ctx
, name
, permissions
):
5605 NAME: Name or ID of the role.
5606 DEFINITION: Definition of grant/denial of access to resources.
5610 check_client_version(ctx
.obj
, ctx
.command
.name
)
5611 ctx
.obj
.role
.create(name
, permissions
)
5612 # except ClientException as e:
5617 @cli_osm.command(name
="role-update", short_help
="updates a role")
5618 @click.argument("name")
5619 @click.option("--set-name", default
=None, help="change name of rle")
5620 # @click.option('--permissions',
5622 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
5626 help="yaml format dictionary with permission: True/False to access grant/denial",
5628 @click.option("--remove", default
=None, help="yaml format list to remove a permission")
5630 def role_update(ctx
, name
, set_name
, add
, remove
):
5635 NAME: Name or ID of the role.
5636 DEFINITION: Definition overwrites the old definition.
5637 ADD: Grant/denial of access to resource to add.
5638 REMOVE: Grant/denial of access to resource to remove.
5642 check_client_version(ctx
.obj
, ctx
.command
.name
)
5643 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
5644 # except ClientException as e:
5649 @cli_osm.command(name
="role-delete", short_help
="deletes a role")
5650 @click.argument("name")
5651 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
5653 def role_delete(ctx
, name
):
5658 NAME: Name or ID of the role.
5662 check_client_version(ctx
.obj
, ctx
.command
.name
)
5663 ctx
.obj
.role
.delete(name
)
5664 # except ClientException as e:
5669 @cli_osm.command(name
="role-list", short_help
="list all roles")
5674 help="restricts the list to the projects matching the filter",
5677 def role_list(ctx
, filter):
5683 check_client_version(ctx
.obj
, ctx
.command
.name
)
5685 filter = "&".join(filter)
5686 resp
= ctx
.obj
.role
.list(filter)
5687 # except ClientException as e:
5690 table
= PrettyTable(["name", "id"])
5692 table
.add_row([role
["name"], role
["_id"]])
5697 @cli_osm.command(name
="role-show", short_help
="show specific role")
5698 @click.argument("name")
5700 def role_show(ctx
, name
):
5702 Shows the details of a role.
5705 NAME: Name or ID of the role.
5709 check_client_version(ctx
.obj
, ctx
.command
.name
)
5710 resp
= ctx
.obj
.role
.get(name
)
5711 # except ClientException as e:
5715 table
= PrettyTable(["key", "attribute"])
5716 for k
, v
in resp
.items():
5717 table
.add_row([k
, json
.dumps(v
, indent
=2)])
5722 @cli_osm.command(name
="package-create", short_help
="Create empty NS package structure")
5723 @click.argument("package-type")
5724 @click.argument("package-name")
5728 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'),
5732 default
="image-name",
5733 help='(VNF) Set the name of the vdu image. Default "image-name"',
5736 "--vdus", default
=1, help="(VNF) Set the number of vdus in a VNF. Default 1"
5739 "--vcpu", default
=1, help="(VNF) Set the number of virtual CPUs in a vdu. Default 1"
5744 help="(VNF) Set the memory size (MB) of the vdu. Default 1024",
5747 "--storage", default
=10, help="(VNF) Set the disk size (GB) of the vdu. Default 10"
5752 help="(VNF) Set the number of additional interfaces apart from the management interface. Default 0",
5755 "--vendor", default
="OSM", help='(NS/VNF) Set the descriptor vendor. Default "OSM"'
5761 help="(NS/VNF/NST) Flag for overriding the package if exists.",
5767 help="(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options",
5770 "--netslice-subnets", default
=1, help="(NST) Number of netslice subnets. Default 1"
5773 "--netslice-vlds", default
=1, help="(NST) Number of netslice vlds. Default 1"
5776 "--old", default
=False, is_flag
=True, help="Support flag for old versions of the OSM IM (OSM<9)"
5798 Creates an OSM NS, VNF, NST package
5801 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
5802 PACKAGE_NAME: Name of the package to create the folder with the content.
5807 check_client_version(ctx
.obj
, ctx
.command
.name
)
5809 "Creating the {} structure: {}/{}".format(
5810 package_type
.upper(), base_directory
, package_name
5813 resp
= ctx
.obj
.package_tool
.create(
5823 interfaces
=interfaces
,
5826 netslice_subnets
=netslice_subnets
,
5827 netslice_vlds
=netslice_vlds
,
5831 # except ClientException as inst:
5832 # print("ERROR: {}".format(inst))
5837 name
="package-validate", short_help
="Validate descriptors given a base directory"
5839 @click.argument("base-directory", default
=".", required
=False)
5841 "--recursive/--no-recursive",
5843 help="The activated recursive option will validate the yaml files"
5844 " within the indicated directory and in its subdirectories",
5850 help="Validates also the descriptors using the previous OSM format (pre SOL006)",
5853 def package_validate(ctx
, base_directory
, recursive
, old
):
5855 Validate descriptors given a base directory.
5858 BASE_DIRECTORY: Base folder for NS, VNF or NST package.
5862 check_client_version(ctx
.obj
, ctx
.command
.name
)
5863 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
, old
)
5864 table
= PrettyTable()
5865 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
5866 # Print the dictionary generated by the validation function
5867 for result
in results
:
5869 [result
["type"], result
["path"], result
["valid"], result
["error"]]
5871 table
.sortby
= "VALID"
5872 table
.align
["PATH"] = "l"
5873 table
.align
["TYPE"] = "l"
5874 table
.align
["ERROR"] = "l"
5876 # except ClientException as inst:
5877 # print("ERROR: {}".format(inst))
5882 name
="package-translate", short_help
="Translate descriptors given a base directory"
5884 @click.argument("base-directory", default
=".", required
=False)
5886 "--recursive/--no-recursive",
5888 help="The activated recursive option will translate the yaml files"
5889 " within the indicated directory and in its subdirectories",
5895 help="Do not translate yet, only make a dry-run to test translation",
5898 def package_translate(ctx
, base_directory
, recursive
, dryrun
):
5900 Translate descriptors given a base directory.
5903 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
5906 check_client_version(ctx
.obj
, ctx
.command
.name
)
5907 results
= ctx
.obj
.package_tool
.translate(base_directory
, recursive
, dryrun
)
5908 table
= PrettyTable()
5909 table
.field_names
= [
5917 # Print the dictionary generated by the validation function
5918 for result
in results
:
5921 result
["current type"],
5925 result
["translated"],
5929 table
.sortby
= "TRANSLATED"
5930 table
.align
["PATH"] = "l"
5931 table
.align
["TYPE"] = "l"
5932 table
.align
["ERROR"] = "l"
5934 # except ClientException as inst:
5935 # print("ERROR: {}".format(inst))
5939 @cli_osm.command(name
="package-build", short_help
="Build the tar.gz of the package")
5940 @click.argument("package-folder")
5942 "--skip-validation", default
=False, is_flag
=True, help="skip package validation"
5945 "--skip-charm-build",
5948 help="the charm will not be compiled, it is assumed to already exist",
5951 def package_build(ctx
, package_folder
, skip_validation
, skip_charm_build
):
5953 Build the package NS, VNF given the package_folder.
5956 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
5960 check_client_version(ctx
.obj
, ctx
.command
.name
)
5961 results
= ctx
.obj
.package_tool
.build(
5963 skip_validation
=skip_validation
,
5964 skip_charm_build
=skip_charm_build
,
5967 # except ClientException as inst:
5968 # print("ERROR: {}".format(inst))
5973 name
="descriptor-translate",
5974 short_help
="Translate input descriptor file from Rel EIGHT OSM descriptors to SOL006 and prints in standard output",
5976 @click.argument("descriptor-file", required
=True)
5978 def descriptor_translate(ctx
, descriptor_file
):
5980 Translate input descriptor.
5983 DESCRIPTOR_FILE: Descriptor file for NS, VNF or Network Slice.
5986 check_client_version(ctx
.obj
, ctx
.command
.name
)
5987 result
= ctx
.obj
.package_tool
.descriptor_translate(descriptor_file
)
5995 except pycurl
.error
as exc
:
5998 'Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified'
6000 except ClientException
as exc
:
6001 print("ERROR: {}".format(exc
))
6002 except (FileNotFoundError
, PermissionError
) as exc
:
6003 print("Cannot open file: {}".format(exc
))
6004 except yaml
.YAMLError
as exc
:
6005 print("Invalid YAML format: {}".format(exc
))
6007 # TODO capture other controlled exceptions here
6008 # TODO remove the ClientException captures from all places, unless they do something different
6011 if __name__
== "__main__":