Feature 10296 Pip Standardization
[osm/osmclient.git] / osmclient / scripts / osm.py
1 # Copyright 2017-2018 Sandvine
2 # Copyright 2018 Telefonica
3 #
4 # All Rights Reserved.
5 #
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
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
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
16 # under the License.
17 """
18 OSM shell/cli
19 """
20
21 import click
22 from osmclient import client
23 from osmclient.common.exceptions import ClientException, NotFound
24 from prettytable import PrettyTable
25 import yaml
26 import json
27 import time
28 import pycurl
29 import os
30 import textwrap
31 import pkg_resources
32 import logging
33 from datetime import datetime
34
35
36 def wrap_text(text, width):
37 wrapper = textwrap.TextWrapper(width=width)
38 lines = text.splitlines()
39 return "\n".join(map(wrapper.fill, lines))
40
41
42 def trunc_text(text, length):
43 if len(text) > length:
44 return text[: (length - 3)] + "..."
45 else:
46 return text
47
48
49 def check_client_version(obj, what, version="sol005"):
50 """
51 Checks the version of the client object and raises error if it not the expected.
52
53 :param obj: the client object
54 :what: the function or command under evaluation (used when an error is raised)
55 :return: -
56 :raises ClientError: if the specified version does not match the client version
57 """
58 logger.debug("")
59 fullclassname = obj.__module__ + "." + obj.__class__.__name__
60 message = 'The following commands or options are only supported with the option "--sol005": {}'.format(
61 what
62 )
63 if version == "v1":
64 message = 'The following commands or options are not supported when using option "--sol005": {}'.format(
65 what
66 )
67 if fullclassname != "osmclient.{}.client.Client".format(version):
68 raise ClientException(message)
69 return
70
71
72 def get_project(project_list, item):
73 # project_list = ctx.obj.project.list()
74 item_project_list = item.get("_admin", {}).get("projects_read")
75 project_id = "None"
76 project_name = "None"
77 if item_project_list:
78 for p1 in item_project_list:
79 project_id = p1
80 for p2 in project_list:
81 if p2["_id"] == project_id:
82 project_name = p2["name"]
83 return project_id, project_name
84 return project_id, project_name
85
86
87 def get_vim_name(vim_list, vim_id):
88 vim_name = "-"
89 for v in vim_list:
90 if v["uuid"] == vim_id:
91 vim_name = v["name"]
92 break
93 return vim_name
94
95
96 @click.group(
97 context_settings=dict(help_option_names=["-h", "--help"], max_content_width=160)
98 )
99 @click.option(
100 "--hostname",
101 default="127.0.0.1",
102 envvar="OSM_HOSTNAME",
103 help="hostname of server. " + "Also can set OSM_HOSTNAME in environment",
104 )
105 # @click.option('--sol005/--no-sol005',
106 # default=True,
107 # envvar='OSM_SOL005',
108 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
109 # 'Also can set OSM_SOL005 in environment')
110 @click.option(
111 "--user",
112 default=None,
113 envvar="OSM_USER",
114 help="user (defaults to admin). " + "Also can set OSM_USER in environment",
115 )
116 @click.option(
117 "--password",
118 default=None,
119 envvar="OSM_PASSWORD",
120 help="password (defaults to admin). " + "Also can set OSM_PASSWORD in environment",
121 )
122 @click.option(
123 "--project",
124 default=None,
125 envvar="OSM_PROJECT",
126 help="project (defaults to admin). " + "Also can set OSM_PROJECT in environment",
127 )
128 @click.option(
129 "-v",
130 "--verbose",
131 count=True,
132 help="increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)",
133 )
134 @click.option("--all-projects", default=None, is_flag=True, help="include all projects")
135 @click.option(
136 "--public/--no-public",
137 default=None,
138 help="flag for public items (packages, instances, VIM accounts, etc.)",
139 )
140 @click.option(
141 "--project-domain-name",
142 "project_domain_name",
143 default=None,
144 envvar="OSM_PROJECT_DOMAIN_NAME",
145 help="project domain name for keystone authentication (default to None). "
146 + "Also can set OSM_PROJECT_DOMAIN_NAME in environment",
147 )
148 @click.option(
149 "--user-domain-name",
150 "user_domain_name",
151 default=None,
152 envvar="OSM_USER_DOMAIN_NAME",
153 help="user domain name for keystone authentication (default to None). "
154 + "Also can set OSM_USER_DOMAIN_NAME in environment",
155 )
156 # @click.option('--so-port',
157 # default=None,
158 # envvar='OSM_SO_PORT',
159 # help='hostname of server. ' +
160 # 'Also can set OSM_SO_PORT in environment')
161 # @click.option('--so-project',
162 # default=None,
163 # envvar='OSM_SO_PROJECT',
164 # help='Project Name in SO. ' +
165 # 'Also can set OSM_SO_PROJECT in environment')
166 # @click.option('--ro-hostname',
167 # default=None,
168 # envvar='OSM_RO_HOSTNAME',
169 # help='hostname of RO server. ' +
170 # 'Also can set OSM_RO_HOSTNAME in environment')
171 # @click.option('--ro-port',
172 # default=None,
173 # envvar='OSM_RO_PORT',
174 # help='hostname of RO server. ' +
175 # 'Also can set OSM_RO_PORT in environment')
176 @click.pass_context
177 def cli_osm(ctx, **kwargs):
178 global logger
179 hostname = kwargs.pop("hostname", None)
180 if hostname is None:
181 print(
182 (
183 "either hostname option or OSM_HOSTNAME "
184 + "environment variable needs to be specified"
185 )
186 )
187 exit(1)
188 # Remove None values
189 kwargs = {k: v for k, v in kwargs.items() if v is not None}
190 # if so_port is not None:
191 # kwargs['so_port']=so_port
192 # if so_project is not None:
193 # kwargs['so_project']=so_project
194 # if ro_hostname is not None:
195 # kwargs['ro_host']=ro_hostname
196 # if ro_port is not None:
197 # kwargs['ro_port']=ro_port
198 sol005 = os.getenv("OSM_SOL005", True)
199 # if user is not None:
200 # kwargs['user']=user
201 # if password is not None:
202 # kwargs['password']=password
203 # if project is not None:
204 # kwargs['project']=project
205 # if all_projects:
206 # kwargs['all_projects']=all_projects
207 # if public is not None:
208 # kwargs['public']=public
209 ctx.obj = client.Client(host=hostname, sol005=sol005, **kwargs)
210 logger = logging.getLogger("osmclient")
211
212
213 ####################
214 # LIST operations
215 ####################
216
217
218 @cli_osm.command(name="ns-list", short_help="list all NS instances")
219 @click.option(
220 "--filter",
221 default=None,
222 multiple=True,
223 help="restricts the list to the NS instances matching the filter.",
224 )
225 @click.option(
226 "--long",
227 is_flag=True,
228 help="get more details of the NS (project, vim, deployment status, configuration status.",
229 )
230 @click.pass_context
231 def ns_list(ctx, filter, long):
232 """list all NS instances
233
234 \b
235 Options:
236 --filter filterExpr Restricts the list to the NS instances matching the filter
237
238 \b
239 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
240 concatenated using the "&" character:
241
242 \b
243 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
244 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
245 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
246 attrName := string
247 value := scalar value
248
249 \b
250 where:
251 * zero or more occurrences
252 ? zero or one occurrence
253 [] grouping of expressions to be used with ? and *
254 "" quotation marks for marking string constants
255 <> name separator
256
257 \b
258 "AttrName" is the name of one attribute in the data type that defines the representation
259 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
260 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
261 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
262 entries, it means that the operator "op" is applied to the attribute addressed by the last
263 <attrName> entry included in the concatenation. All simple filter expressions are combined
264 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
265 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
266 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
267 prefix". If an attribute referenced in an expression is an array, an object that contains a
268 corresponding array shall be considered to match the expression if any of the elements in the
269 array matches all expressions that have the same attribute prefix.
270
271 \b
272 Filter examples:
273 --filter admin-status=ENABLED
274 --filter nsd-ref=<NSD_NAME>
275 --filter nsd.vendor=<VENDOR>
276 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
277 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
278 """
279
280 def summarize_deployment_status(status_dict):
281 # Nets
282 summary = ""
283 if not status_dict:
284 return summary
285 n_nets = 0
286 status_nets = {}
287 net_list = status_dict.get("nets", [])
288 for net in net_list:
289 n_nets += 1
290 if net["status"] not in status_nets:
291 status_nets[net["status"]] = 1
292 else:
293 status_nets[net["status"]] += 1
294 message = "Nets: "
295 for k, v in status_nets.items():
296 message += "{}:{},".format(k, v)
297 message += "TOTAL:{}".format(n_nets)
298 summary += "{}".format(message)
299 # VMs and VNFs
300 n_vms = 0
301 status_vms = {}
302 status_vnfs = {}
303 vnf_list = status_dict["vnfs"]
304 for vnf in vnf_list:
305 member_vnf_index = vnf["member_vnf_index"]
306 if member_vnf_index not in status_vnfs:
307 status_vnfs[member_vnf_index] = {}
308 for vm in vnf["vms"]:
309 n_vms += 1
310 if vm["status"] not in status_vms:
311 status_vms[vm["status"]] = 1
312 else:
313 status_vms[vm["status"]] += 1
314 if vm["status"] not in status_vnfs[member_vnf_index]:
315 status_vnfs[member_vnf_index][vm["status"]] = 1
316 else:
317 status_vnfs[member_vnf_index][vm["status"]] += 1
318 message = "VMs: "
319 for k, v in status_vms.items():
320 message += "{}:{},".format(k, v)
321 message += "TOTAL:{}".format(n_vms)
322 summary += "\n{}".format(message)
323 summary += "\nNFs:"
324 for k, v in status_vnfs.items():
325 total = 0
326 message = "\n {} VMs: ".format(k)
327 for k2, v2 in v.items():
328 message += "{}:{},".format(k2, v2)
329 total += v2
330 message += "TOTAL:{}".format(total)
331 summary += message
332 return summary
333
334 def summarize_config_status(ee_list):
335 summary = ""
336 if not ee_list:
337 return summary
338 n_ee = 0
339 status_ee = {}
340 for ee in ee_list:
341 n_ee += 1
342 if ee["elementType"] not in status_ee:
343 status_ee[ee["elementType"]] = {}
344 status_ee[ee["elementType"]][ee["status"]] = 1
345 continue
346 if ee["status"] in status_ee[ee["elementType"]]:
347 status_ee[ee["elementType"]][ee["status"]] += 1
348 else:
349 status_ee[ee["elementType"]][ee["status"]] = 1
350 for elementType in ["KDU", "VDU", "PDU", "VNF", "NS"]:
351 if elementType in status_ee:
352 message = ""
353 total = 0
354 for k, v in status_ee[elementType].items():
355 message += "{}:{},".format(k, v)
356 total += v
357 message += "TOTAL:{}\n".format(total)
358 summary += "{}: {}".format(elementType, message)
359 summary += "TOTAL Exec. Env.: {}".format(n_ee)
360 return summary
361
362 logger.debug("")
363 if filter:
364 check_client_version(ctx.obj, "--filter")
365 filter = "&".join(filter)
366 resp = ctx.obj.ns.list(filter)
367 else:
368 resp = ctx.obj.ns.list()
369 if long:
370 table = PrettyTable(
371 [
372 "ns instance name",
373 "id",
374 "date",
375 "ns state",
376 "current operation",
377 "error details",
378 "project",
379 "vim (inst param)",
380 "deployment status",
381 "configuration status",
382 ]
383 )
384 project_list = ctx.obj.project.list()
385 try:
386 vim_list = ctx.obj.vim.list()
387 except Exception:
388 vim_list = []
389 else:
390 table = PrettyTable(
391 [
392 "ns instance name",
393 "id",
394 "date",
395 "ns state",
396 "current operation",
397 "error details",
398 ]
399 )
400 for ns in resp:
401 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
402 if fullclassname == "osmclient.sol005.client.Client":
403 nsr = ns
404 logger.debug("NS info: {}".format(nsr))
405 nsr_name = nsr["name"]
406 nsr_id = nsr["_id"]
407 date = datetime.fromtimestamp(nsr["create-time"]).strftime(
408 "%Y-%m-%dT%H:%M:%S"
409 )
410 ns_state = nsr.get("nsState", nsr["_admin"]["nsState"])
411 if long:
412 deployment_status = summarize_deployment_status(
413 nsr.get("deploymentStatus")
414 )
415 config_status = summarize_config_status(nsr.get("configurationStatus"))
416 project_id, project_name = get_project(project_list, nsr)
417 # project = '{} ({})'.format(project_name, project_id)
418 project = project_name
419 vim_id = nsr.get("datacenter")
420 vim_name = get_vim_name(vim_list, vim_id)
421
422 # vim = '{} ({})'.format(vim_name, vim_id)
423 vim = vim_name
424 if "currentOperation" in nsr:
425 current_operation = "{} ({})".format(
426 nsr["currentOperation"], nsr["currentOperationID"]
427 )
428 else:
429 current_operation = "{} ({})".format(
430 nsr["_admin"].get("current-operation", "-"),
431 nsr["_admin"]["nslcmop"],
432 )
433 error_details = "N/A"
434 if (
435 ns_state == "BROKEN"
436 or ns_state == "DEGRADED"
437 or ("currentOperation" not in nsr and nsr.get("errorDescription"))
438 ):
439 error_details = "{}\nDetail: {}".format(
440 nsr["errorDescription"], nsr["errorDetail"]
441 )
442 else:
443 nsopdata = ctx.obj.ns.get_opdata(ns["id"])
444 nsr = nsopdata["nsr:nsr"]
445 nsr_name = nsr["name-ref"]
446 nsr_id = nsr["ns-instance-config-ref"]
447 date = "-"
448 project = "-"
449 deployment_status = (
450 nsr["operational-status"]
451 if "operational-status" in nsr
452 else "Not found"
453 )
454 ns_state = deployment_status
455 config_status = nsr.get("config-status", "Not found")
456 current_operation = "Unknown"
457 error_details = nsr.get("detailed-status", "Not found")
458 if config_status == "config_not_needed":
459 config_status = "configured (no charms)"
460
461 if long:
462 table.add_row(
463 [
464 nsr_name,
465 nsr_id,
466 date,
467 ns_state,
468 current_operation,
469 wrap_text(text=error_details, width=40),
470 project,
471 vim,
472 deployment_status,
473 config_status,
474 ]
475 )
476 else:
477 table.add_row(
478 [
479 nsr_name,
480 nsr_id,
481 date,
482 ns_state,
483 current_operation,
484 wrap_text(text=error_details, width=40),
485 ]
486 )
487 table.align = "l"
488 print(table)
489 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
490 print(
491 'For more details on the current operation, run "osm ns-op-show OPERATION_ID"'
492 )
493
494
495 def nsd_list(ctx, filter, long):
496 logger.debug("")
497 if filter:
498 check_client_version(ctx.obj, "--filter")
499 filter = "&".join(filter)
500 resp = ctx.obj.nsd.list(filter)
501 else:
502 resp = ctx.obj.nsd.list()
503 # print(yaml.safe_dump(resp))
504 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
505 if fullclassname == "osmclient.sol005.client.Client":
506 if long:
507 table = PrettyTable(
508 [
509 "nsd name",
510 "id",
511 "onboarding state",
512 "operational state",
513 "usage state",
514 "date",
515 "last update",
516 ]
517 )
518 else:
519 table = PrettyTable(["nsd name", "id"])
520 for nsd in resp:
521 name = nsd.get("id", "-")
522 if long:
523 onb_state = nsd["_admin"].get("onboardingState", "-")
524 op_state = nsd["_admin"].get("operationalState", "-")
525 usage_state = nsd["_admin"].get("usageState", "-")
526 date = datetime.fromtimestamp(nsd["_admin"]["created"]).strftime(
527 "%Y-%m-%dT%H:%M:%S"
528 )
529 last_update = datetime.fromtimestamp(
530 nsd["_admin"]["modified"]
531 ).strftime("%Y-%m-%dT%H:%M:%S")
532 table.add_row(
533 [
534 name,
535 nsd["_id"],
536 onb_state,
537 op_state,
538 usage_state,
539 date,
540 last_update,
541 ]
542 )
543 else:
544 table.add_row([name, nsd["_id"]])
545 else:
546 table = PrettyTable(["nsd name", "id"])
547 for nsd in resp:
548 table.add_row([nsd["name"], nsd["id"]])
549 table.align = "l"
550 print(table)
551
552
553 @cli_osm.command(name="nsd-list", short_help="list all NS packages")
554 @click.option(
555 "--filter",
556 default=None,
557 multiple=True,
558 help="restricts the list to the NSD/NSpkg matching the filter",
559 )
560 @click.option("--long", is_flag=True, help="get more details")
561 @click.pass_context
562 def nsd_list1(ctx, filter, long):
563 """list all NSD/NS pkg in the system"""
564 logger.debug("")
565 nsd_list(ctx, filter, long)
566
567
568 @cli_osm.command(name="nspkg-list", short_help="list all NS packages")
569 @click.option(
570 "--filter",
571 default=None,
572 multiple=True,
573 help="restricts the list to the NSD/NSpkg matching the filter",
574 )
575 @click.option("--long", is_flag=True, help="get more details")
576 @click.pass_context
577 def nsd_list2(ctx, filter, long):
578 """list all NS packages"""
579 logger.debug("")
580 nsd_list(ctx, filter, long)
581
582
583 def pkg_repo_list(ctx, pkgtype, filter, repo, long):
584 resp = ctx.obj.osmrepo.pkg_list(pkgtype, filter, repo)
585 if long:
586 table = PrettyTable(
587 ["nfpkg name", "vendor", "version", "latest", "description", "repository"]
588 )
589 else:
590 table = PrettyTable(["nfpkg name", "repository"])
591 for vnfd in resp:
592 name = vnfd.get("id", vnfd.get("name", "-"))
593 repository = vnfd.get("repository")
594 if long:
595 vendor = vnfd.get("provider", vnfd.get("vendor"))
596 version = vnfd.get("version")
597 description = vnfd.get("description")
598 latest = vnfd.get("latest")
599 table.add_row([name, vendor, version, latest, description, repository])
600 else:
601 table.add_row([name, repository])
602 table.align = "l"
603 print(table)
604
605
606 def vnfd_list(ctx, nf_type, filter, long):
607 logger.debug("")
608 if nf_type:
609 check_client_version(ctx.obj, "--nf_type")
610 elif filter:
611 check_client_version(ctx.obj, "--filter")
612 if filter:
613 filter = "&".join(filter)
614 if nf_type:
615 if nf_type == "vnf":
616 nf_filter = "_admin.type=vnfd"
617 elif nf_type == "pnf":
618 nf_filter = "_admin.type=pnfd"
619 elif nf_type == "hnf":
620 nf_filter = "_admin.type=hnfd"
621 else:
622 raise ClientException(
623 'wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf'
624 )
625 if filter:
626 filter = "{}&{}".format(nf_filter, filter)
627 else:
628 filter = nf_filter
629 if filter:
630 resp = ctx.obj.vnfd.list(filter)
631 else:
632 resp = ctx.obj.vnfd.list()
633 # print(yaml.safe_dump(resp))
634 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
635 if fullclassname == "osmclient.sol005.client.Client":
636 if long:
637 table = PrettyTable(
638 [
639 "nfpkg name",
640 "id",
641 "desc type",
642 "vendor",
643 "version",
644 "onboarding state",
645 "operational state",
646 "usage state",
647 "date",
648 "last update",
649 ]
650 )
651 else:
652 table = PrettyTable(["nfpkg name", "id", "desc type"])
653 for vnfd in resp:
654 name = vnfd.get("id", vnfd.get("name", "-"))
655 descriptor_type = "sol006" if "product-name" in vnfd else "rel8"
656 if long:
657 onb_state = vnfd["_admin"].get("onboardingState", "-")
658 op_state = vnfd["_admin"].get("operationalState", "-")
659 vendor = vnfd.get("provider", vnfd.get("vendor"))
660 version = vnfd.get("version")
661 usage_state = vnfd["_admin"].get("usageState", "-")
662 date = datetime.fromtimestamp(vnfd["_admin"]["created"]).strftime(
663 "%Y-%m-%dT%H:%M:%S"
664 )
665 last_update = datetime.fromtimestamp(
666 vnfd["_admin"]["modified"]
667 ).strftime("%Y-%m-%dT%H:%M:%S")
668 table.add_row(
669 [
670 name,
671 vnfd["_id"],
672 descriptor_type,
673 vendor,
674 version,
675 onb_state,
676 op_state,
677 usage_state,
678 date,
679 last_update,
680 ]
681 )
682 else:
683 table.add_row([name, vnfd["_id"], descriptor_type])
684 else:
685 table = PrettyTable(["nfpkg name", "id"])
686 for vnfd in resp:
687 table.add_row([vnfd["name"], vnfd["id"]])
688 table.align = "l"
689 print(table)
690
691
692 @cli_osm.command(name="vnfd-list", short_help="list all xNF packages (VNF, HNF, PNF)")
693 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
694 @click.option(
695 "--filter",
696 default=None,
697 multiple=True,
698 help="restricts the list to the NF pkg matching the filter",
699 )
700 @click.option("--long", is_flag=True, help="get more details")
701 @click.pass_context
702 def vnfd_list1(ctx, nf_type, filter, long):
703 """list all xNF packages (VNF, HNF, PNF)"""
704 logger.debug("")
705 vnfd_list(ctx, nf_type, filter, long)
706
707
708 @cli_osm.command(name="vnfpkg-list", short_help="list all xNF packages (VNF, HNF, PNF)")
709 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
710 @click.option(
711 "--filter",
712 default=None,
713 multiple=True,
714 help="restricts the list to the NFpkg matching the filter",
715 )
716 @click.option("--long", is_flag=True, help="get more details")
717 @click.pass_context
718 def vnfd_list2(ctx, nf_type, filter, long):
719 """list all xNF packages (VNF, HNF, PNF)"""
720 logger.debug("")
721 vnfd_list(ctx, nf_type, filter, long)
722
723
724 @cli_osm.command(name="nfpkg-list", short_help="list all xNF packages (VNF, HNF, PNF)")
725 @click.option("--nf_type", help="type of NF (vnf, pnf, hnf)")
726 @click.option(
727 "--filter",
728 default=None,
729 multiple=True,
730 help="restricts the list to the NFpkg matching the filter",
731 )
732 @click.option("--long", is_flag=True, help="get more details")
733 @click.pass_context
734 def nfpkg_list(ctx, nf_type, filter, long):
735 """list all xNF packages (VNF, HNF, PNF)"""
736 logger.debug("")
737 # try:
738 check_client_version(ctx.obj, ctx.command.name)
739 vnfd_list(ctx, nf_type, filter, long)
740 # except ClientException as e:
741 # print(str(e))
742 # exit(1)
743
744
745 @cli_osm.command(
746 name="vnfpkg-repo-list", short_help="list all xNF from OSM repositories"
747 )
748 @click.option(
749 "--filter",
750 default=None,
751 multiple=True,
752 help="restricts the list to the NFpkg matching the filter",
753 )
754 @click.option(
755 "--repo", default=None, help="restricts the list to a particular OSM repository"
756 )
757 @click.option("--long", is_flag=True, help="get more details")
758 @click.pass_context
759 def nfpkg_repo_list1(ctx, filter, repo, long):
760 """list xNF packages from OSM repositories"""
761 pkgtype = "vnf"
762 pkg_repo_list(ctx, pkgtype, filter, repo, long)
763
764
765 @cli_osm.command(
766 name="nfpkg-repo-list", short_help="list all xNF from OSM repositories"
767 )
768 @click.option(
769 "--filter",
770 default=None,
771 multiple=True,
772 help="restricts the list to the NFpkg matching the filter",
773 )
774 @click.option(
775 "--repo", default=None, help="restricts the list to a particular OSM repository"
776 )
777 @click.option("--long", is_flag=True, help="get more details")
778 @click.pass_context
779 def nfpkg_repo_list2(ctx, filter, repo, long):
780 """list xNF packages from OSM repositories"""
781 pkgtype = "vnf"
782 pkg_repo_list(ctx, pkgtype, filter, repo, long)
783
784
785 def vnf_list(ctx, ns, filter, long):
786 # try:
787 if ns or filter:
788 if ns:
789 check_client_version(ctx.obj, "--ns")
790 if filter:
791 filter = "&".join(filter)
792 check_client_version(ctx.obj, "--filter")
793 resp = ctx.obj.vnf.list(ns, filter)
794 else:
795 resp = ctx.obj.vnf.list()
796 # except ClientException as e:
797 # print(str(e))
798 # exit(1)
799 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
800 if fullclassname == "osmclient.sol005.client.Client":
801 field_names = [
802 "vnf id",
803 "name",
804 "ns id",
805 "vnf member index",
806 "vnfd name",
807 "vim account id",
808 "ip address",
809 ]
810 if long:
811 field_names = [
812 "vnf id",
813 "name",
814 "ns id",
815 "vnf member index",
816 "vnfd name",
817 "vim account id",
818 "ip address",
819 "date",
820 "last update",
821 ]
822 table = PrettyTable(field_names)
823 for vnfr in resp:
824 name = vnfr["name"] if "name" in vnfr else "-"
825 new_row = [
826 vnfr["_id"],
827 name,
828 vnfr["nsr-id-ref"],
829 vnfr["member-vnf-index-ref"],
830 vnfr["vnfd-ref"],
831 vnfr["vim-account-id"],
832 vnfr["ip-address"],
833 ]
834 if long:
835 date = datetime.fromtimestamp(vnfr["_admin"]["created"]).strftime(
836 "%Y-%m-%dT%H:%M:%S"
837 )
838 last_update = datetime.fromtimestamp(
839 vnfr["_admin"]["modified"]
840 ).strftime("%Y-%m-%dT%H:%M:%S")
841 new_row.extend([date, last_update])
842 table.add_row(new_row)
843 else:
844 table = PrettyTable(["vnf name", "id", "operational status", "config status"])
845 for vnfr in resp:
846 if "mgmt-interface" not in vnfr:
847 vnfr["mgmt-interface"] = {}
848 vnfr["mgmt-interface"]["ip-address"] = None
849 table.add_row(
850 [
851 vnfr["name"],
852 vnfr["id"],
853 vnfr["operational-status"],
854 vnfr["config-status"],
855 ]
856 )
857 table.align = "l"
858 print(table)
859
860
861 @cli_osm.command(name="vnf-list", short_help="list all NF instances")
862 @click.option(
863 "--ns", default=None, help="NS instance id or name to restrict the NF list"
864 )
865 @click.option(
866 "--filter",
867 default=None,
868 multiple=True,
869 help="restricts the list to the NF instances matching the filter.",
870 )
871 @click.option("--long", is_flag=True, help="get more details")
872 @click.pass_context
873 def vnf_list1(ctx, ns, filter, long):
874 """list all NF instances"""
875 logger.debug("")
876 vnf_list(ctx, ns, filter, long)
877
878
879 @cli_osm.command(name="nsd-repo-list", short_help="list all NS from OSM repositories")
880 @click.option(
881 "--filter",
882 default=None,
883 multiple=True,
884 help="restricts the list to the NS matching the filter",
885 )
886 @click.option(
887 "--repo", default=None, help="restricts the list to a particular OSM repository"
888 )
889 @click.option("--long", is_flag=True, help="get more details")
890 @click.pass_context
891 def nspkg_repo_list(ctx, filter, repo, long):
892 """list xNF packages from OSM repositories"""
893 pkgtype = "ns"
894 pkg_repo_list(ctx, pkgtype, filter, repo, long)
895
896
897 @cli_osm.command(name="nspkg-repo-list", short_help="list all NS from OSM repositories")
898 @click.option(
899 "--filter",
900 default=None,
901 multiple=True,
902 help="restricts the list to the NS matching the filter",
903 )
904 @click.option(
905 "--repo", default=None, help="restricts the list to a particular OSM repository"
906 )
907 @click.option("--long", is_flag=True, help="get more details")
908 @click.pass_context
909 def nspkg_repo_list2(ctx, filter, repo, long):
910 """list xNF packages from OSM repositories"""
911 pkgtype = "ns"
912 pkg_repo_list(ctx, pkgtype, filter, repo, long)
913
914
915 @cli_osm.command(name="nf-list", short_help="list all NF instances")
916 @click.option(
917 "--ns", default=None, help="NS instance id or name to restrict the NF list"
918 )
919 @click.option(
920 "--filter",
921 default=None,
922 multiple=True,
923 help="restricts the list to the NF instances matching the filter.",
924 )
925 @click.option("--long", is_flag=True, help="get more details")
926 @click.pass_context
927 def nf_list(ctx, ns, filter, long):
928 """list all NF instances
929
930 \b
931 Options:
932 --ns TEXT NS instance id or name to restrict the VNF list
933 --filter filterExpr Restricts the list to the VNF instances matching the filter
934
935 \b
936 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
937 concatenated using the "&" character:
938
939 \b
940 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
941 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
942 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
943 attrName := string
944 value := scalar value
945
946 \b
947 where:
948 * zero or more occurrences
949 ? zero or one occurrence
950 [] grouping of expressions to be used with ? and *
951 "" quotation marks for marking string constants
952 <> name separator
953
954 \b
955 "AttrName" is the name of one attribute in the data type that defines the representation
956 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
957 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
958 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
959 entries, it means that the operator "op" is applied to the attribute addressed by the last
960 <attrName> entry included in the concatenation. All simple filter expressions are combined
961 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
962 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
963 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
964 prefix". If an attribute referenced in an expression is an array, an object that contains a
965 corresponding array shall be considered to match the expression if any of the elements in the
966 array matches all expressions that have the same attribute prefix.
967
968 \b
969 Filter examples:
970 --filter vim-account-id=<VIM_ACCOUNT_ID>
971 --filter vnfd-ref=<VNFD_NAME>
972 --filter vdur.ip-address=<IP_ADDRESS>
973 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
974 """
975 logger.debug("")
976 vnf_list(ctx, ns, filter, long)
977
978
979 @cli_osm.command(
980 name="ns-op-list", short_help="shows the history of operations over a NS instance"
981 )
982 @click.argument("name")
983 @click.option(
984 "--long", is_flag=True, help="get more details of the NS operation (date, )."
985 )
986 @click.pass_context
987 def ns_op_list(ctx, name, long):
988 """shows the history of operations over a NS instance
989
990 NAME: name or ID of the NS instance
991 """
992
993 def formatParams(params):
994 if params["lcmOperationType"] == "instantiate":
995 params.pop("nsDescription")
996 params.pop("nsName")
997 params.pop("nsdId")
998 params.pop("nsr_id")
999 elif params["lcmOperationType"] == "action":
1000 params.pop("primitive")
1001 params.pop("lcmOperationType")
1002 params.pop("nsInstanceId")
1003 return params
1004
1005 logger.debug("")
1006 # try:
1007 check_client_version(ctx.obj, ctx.command.name)
1008 resp = ctx.obj.ns.list_op(name)
1009 # except ClientException as e:
1010 # print(str(e))
1011 # exit(1)
1012
1013 if long:
1014 table = PrettyTable(
1015 [
1016 "id",
1017 "operation",
1018 "action_name",
1019 "operation_params",
1020 "status",
1021 "date",
1022 "last update",
1023 "detail",
1024 ]
1025 )
1026 else:
1027 table = PrettyTable(
1028 ["id", "operation", "action_name", "status", "date", "detail"]
1029 )
1030
1031 # print(yaml.safe_dump(resp))
1032 for op in resp:
1033 action_name = "N/A"
1034 if op["lcmOperationType"] == "action":
1035 action_name = op["operationParams"]["primitive"]
1036 detail = "-"
1037 if op["operationState"] == "PROCESSING":
1038 if op["queuePosition"] is not None and op["queuePosition"] > 0:
1039 detail = "In queue. Current position: {}".format(op["queuePosition"])
1040 elif op["lcmOperationType"] in ("instantiate", "terminate"):
1041 if op["stage"]:
1042 detail = op["stage"]
1043 elif op["operationState"] in ("FAILED", "FAILED_TEMP"):
1044 detail = op.get("errorMessage", "-")
1045 date = datetime.fromtimestamp(op["startTime"]).strftime("%Y-%m-%dT%H:%M:%S")
1046 last_update = datetime.fromtimestamp(op["statusEnteredTime"]).strftime(
1047 "%Y-%m-%dT%H:%M:%S"
1048 )
1049 if long:
1050 table.add_row(
1051 [
1052 op["id"],
1053 op["lcmOperationType"],
1054 action_name,
1055 wrap_text(
1056 text=json.dumps(formatParams(op["operationParams"]), indent=2),
1057 width=50,
1058 ),
1059 op["operationState"],
1060 date,
1061 last_update,
1062 wrap_text(text=detail, width=50),
1063 ]
1064 )
1065 else:
1066 table.add_row(
1067 [
1068 op["id"],
1069 op["lcmOperationType"],
1070 action_name,
1071 op["operationState"],
1072 date,
1073 wrap_text(text=detail or "", width=50),
1074 ]
1075 )
1076 table.align = "l"
1077 print(table)
1078
1079
1080 def nsi_list(ctx, filter):
1081 """list all Network Slice Instances"""
1082 logger.debug("")
1083 # try:
1084 check_client_version(ctx.obj, ctx.command.name)
1085 if filter:
1086 filter = "&".join(filter)
1087 resp = ctx.obj.nsi.list(filter)
1088 # except ClientException as e:
1089 # print(str(e))
1090 # exit(1)
1091 table = PrettyTable(
1092 [
1093 "netslice instance name",
1094 "id",
1095 "operational status",
1096 "config status",
1097 "detailed status",
1098 ]
1099 )
1100 for nsi in resp:
1101 nsi_name = nsi["name"]
1102 nsi_id = nsi["_id"]
1103 opstatus = (
1104 nsi["operational-status"] if "operational-status" in nsi else "Not found"
1105 )
1106 configstatus = nsi["config-status"] if "config-status" in nsi else "Not found"
1107 detailed_status = (
1108 nsi["detailed-status"] if "detailed-status" in nsi else "Not found"
1109 )
1110 if configstatus == "config_not_needed":
1111 configstatus = "configured (no charms)"
1112 table.add_row([nsi_name, nsi_id, opstatus, configstatus, detailed_status])
1113 table.align = "l"
1114 print(table)
1115
1116
1117 @cli_osm.command(name="nsi-list", short_help="list all Network Slice Instances (NSI)")
1118 @click.option(
1119 "--filter",
1120 default=None,
1121 multiple=True,
1122 help="restricts the list to the Network Slice Instances matching the filter",
1123 )
1124 @click.pass_context
1125 def nsi_list1(ctx, filter):
1126 """list all Network Slice Instances (NSI)"""
1127 logger.debug("")
1128 nsi_list(ctx, filter)
1129
1130
1131 @cli_osm.command(
1132 name="netslice-instance-list", short_help="list all Network Slice Instances (NSI)"
1133 )
1134 @click.option(
1135 "--filter",
1136 default=None,
1137 multiple=True,
1138 help="restricts the list to the Network Slice Instances matching the filter",
1139 )
1140 @click.pass_context
1141 def nsi_list2(ctx, filter):
1142 """list all Network Slice Instances (NSI)"""
1143 logger.debug("")
1144 nsi_list(ctx, filter)
1145
1146
1147 def nst_list(ctx, filter):
1148 logger.debug("")
1149 # try:
1150 check_client_version(ctx.obj, ctx.command.name)
1151 if filter:
1152 filter = "&".join(filter)
1153 resp = ctx.obj.nst.list(filter)
1154 # except ClientException as e:
1155 # print(str(e))
1156 # exit(1)
1157 # print(yaml.safe_dump(resp))
1158 table = PrettyTable(["nst name", "id"])
1159 for nst in resp:
1160 name = nst["name"] if "name" in nst else "-"
1161 table.add_row([name, nst["_id"]])
1162 table.align = "l"
1163 print(table)
1164
1165
1166 @cli_osm.command(name="nst-list", short_help="list all Network Slice Templates (NST)")
1167 @click.option(
1168 "--filter",
1169 default=None,
1170 multiple=True,
1171 help="restricts the list to the NST matching the filter",
1172 )
1173 @click.pass_context
1174 def nst_list1(ctx, filter):
1175 """list all Network Slice Templates (NST) in the system"""
1176 logger.debug("")
1177 nst_list(ctx, filter)
1178
1179
1180 @cli_osm.command(
1181 name="netslice-template-list", short_help="list all Network Slice Templates (NST)"
1182 )
1183 @click.option(
1184 "--filter",
1185 default=None,
1186 multiple=True,
1187 help="restricts the list to the NST matching the filter",
1188 )
1189 @click.pass_context
1190 def nst_list2(ctx, filter):
1191 """list all Network Slice Templates (NST) in the system"""
1192 logger.debug("")
1193 nst_list(ctx, filter)
1194
1195
1196 def nsi_op_list(ctx, name):
1197 logger.debug("")
1198 # try:
1199 check_client_version(ctx.obj, ctx.command.name)
1200 resp = ctx.obj.nsi.list_op(name)
1201 # except ClientException as e:
1202 # print(str(e))
1203 # exit(1)
1204 table = PrettyTable(["id", "operation", "status"])
1205 for op in resp:
1206 table.add_row([op["id"], op["lcmOperationType"], op["operationState"]])
1207 table.align = "l"
1208 print(table)
1209
1210
1211 @cli_osm.command(
1212 name="nsi-op-list",
1213 short_help="shows the history of operations over a Network Slice Instance (NSI)",
1214 )
1215 @click.argument("name")
1216 @click.pass_context
1217 def nsi_op_list1(ctx, name):
1218 """shows the history of operations over a Network Slice Instance (NSI)
1219
1220 NAME: name or ID of the Network Slice Instance
1221 """
1222 logger.debug("")
1223 nsi_op_list(ctx, name)
1224
1225
1226 @cli_osm.command(
1227 name="netslice-instance-op-list",
1228 short_help="shows the history of operations over a Network Slice Instance (NSI)",
1229 )
1230 @click.argument("name")
1231 @click.pass_context
1232 def nsi_op_list2(ctx, name):
1233 """shows the history of operations over a Network Slice Instance (NSI)
1234
1235 NAME: name or ID of the Network Slice Instance
1236 """
1237 logger.debug("")
1238 nsi_op_list(ctx, name)
1239
1240
1241 @cli_osm.command(name="pdu-list", short_help="list all Physical Deployment Units (PDU)")
1242 @click.option(
1243 "--filter",
1244 default=None,
1245 multiple=True,
1246 help="restricts the list to the Physical Deployment Units matching the filter",
1247 )
1248 @click.pass_context
1249 def pdu_list(ctx, filter):
1250 """list all Physical Deployment Units (PDU)"""
1251 logger.debug("")
1252 # try:
1253 check_client_version(ctx.obj, ctx.command.name)
1254 if filter:
1255 filter = "&".join(filter)
1256 resp = ctx.obj.pdu.list(filter)
1257 # except ClientException as e:
1258 # print(str(e))
1259 # exit(1)
1260 table = PrettyTable(["pdu name", "id", "type", "mgmt ip address"])
1261 for pdu in resp:
1262 pdu_name = pdu["name"]
1263 pdu_id = pdu["_id"]
1264 pdu_type = pdu["type"]
1265 pdu_ipaddress = "None"
1266 for iface in pdu["interfaces"]:
1267 if iface["mgmt"]:
1268 pdu_ipaddress = iface["ip-address"]
1269 break
1270 table.add_row([pdu_name, pdu_id, pdu_type, pdu_ipaddress])
1271 table.align = "l"
1272 print(table)
1273
1274
1275 ####################
1276 # SHOW operations
1277 ####################
1278
1279
1280 def nsd_show(ctx, name, literal):
1281 logger.debug("")
1282 # try:
1283 resp = ctx.obj.nsd.get(name)
1284 # resp = ctx.obj.nsd.get_individual(name)
1285 # except ClientException as e:
1286 # print(str(e))
1287 # exit(1)
1288
1289 if literal:
1290 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
1291 return
1292
1293 table = PrettyTable(["field", "value"])
1294 for k, v in list(resp.items()):
1295 table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)])
1296 table.align = "l"
1297 print(table)
1298
1299
1300 @cli_osm.command(name="nsd-show", short_help="shows the details of a NS package")
1301 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1302 @click.argument("name")
1303 @click.pass_context
1304 def nsd_show1(ctx, name, literal):
1305 """shows the content of a NSD
1306
1307 NAME: name or ID of the NSD/NSpkg
1308 """
1309 logger.debug("")
1310 nsd_show(ctx, name, literal)
1311
1312
1313 @cli_osm.command(name="nspkg-show", short_help="shows the details of a NS package")
1314 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1315 @click.argument("name")
1316 @click.pass_context
1317 def nsd_show2(ctx, name, literal):
1318 """shows the content of a NSD
1319
1320 NAME: name or ID of the NSD/NSpkg
1321 """
1322 logger.debug("")
1323 nsd_show(ctx, name, literal)
1324
1325
1326 def vnfd_show(ctx, name, literal):
1327 logger.debug("")
1328 # try:
1329 resp = ctx.obj.vnfd.get(name)
1330 # resp = ctx.obj.vnfd.get_individual(name)
1331 # except ClientException as e:
1332 # print(str(e))
1333 # exit(1)
1334
1335 if literal:
1336 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
1337 return
1338
1339 table = PrettyTable(["field", "value"])
1340 for k, v in list(resp.items()):
1341 table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)])
1342 table.align = "l"
1343 print(table)
1344
1345
1346 def pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal):
1347 logger.debug("")
1348 if filter:
1349 filter = "&".join(filter)
1350 # try:
1351 resp = ctx.obj.osmrepo.pkg_get(pkgtype, name, repo, version, filter)
1352
1353 if literal:
1354 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
1355 return
1356 pkgtype += "d"
1357 catalog = pkgtype + "-catalog"
1358 full_catalog = pkgtype + ":" + catalog
1359 if resp.get(catalog):
1360 resp = resp.pop(catalog)[pkgtype][0]
1361 elif resp.get(full_catalog):
1362 resp = resp.pop(full_catalog)[pkgtype][0]
1363
1364 table = PrettyTable(["field", "value"])
1365 for k, v in list(resp.items()):
1366 table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)])
1367 table.align = "l"
1368 print(table)
1369
1370
1371 @cli_osm.command(name="vnfd-show", short_help="shows the details of a NF package")
1372 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1373 @click.argument("name")
1374 @click.pass_context
1375 def vnfd_show1(ctx, name, literal):
1376 """shows the content of a VNFD
1377
1378 NAME: name or ID of the VNFD/VNFpkg
1379 """
1380 logger.debug("")
1381 vnfd_show(ctx, name, literal)
1382
1383
1384 @cli_osm.command(name="vnfpkg-show", short_help="shows the details of a NF package")
1385 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1386 @click.argument("name")
1387 @click.pass_context
1388 def vnfd_show2(ctx, name, literal):
1389 """shows the content of a VNFD
1390
1391 NAME: name or ID of the VNFD/VNFpkg
1392 """
1393 logger.debug("")
1394 vnfd_show(ctx, name, literal)
1395
1396
1397 @cli_osm.command(
1398 name="vnfpkg-repo-show",
1399 short_help="shows the details of a NF package in an OSM repository",
1400 )
1401 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1402 @click.option("--repo", required=True, help="Repository name")
1403 @click.argument("name")
1404 @click.option("--filter", default=None, multiple=True, help="filter by fields")
1405 @click.option("--version", default="latest", help="package version")
1406 @click.pass_context
1407 def vnfd_show3(ctx, name, repo, version, literal=None, filter=None):
1408 """shows the content of a VNFD in a repository
1409
1410 NAME: name or ID of the VNFD/VNFpkg
1411 """
1412 pkgtype = "vnf"
1413 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
1414
1415
1416 @cli_osm.command(
1417 name="nsd-repo-show",
1418 short_help="shows the details of a NS package in an OSM repository",
1419 )
1420 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1421 @click.option("--repo", required=True, help="Repository name")
1422 @click.argument("name")
1423 @click.option("--filter", default=None, multiple=True, help="filter by fields")
1424 @click.option("--version", default="latest", help="package version")
1425 @click.pass_context
1426 def nsd_repo_show(ctx, name, repo, version, literal=None, filter=None):
1427 """shows the content of a VNFD in a repository
1428
1429 NAME: name or ID of the VNFD/VNFpkg
1430 """
1431 pkgtype = "ns"
1432 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
1433
1434
1435 @cli_osm.command(
1436 name="nspkg-repo-show",
1437 short_help="shows the details of a NS package in an OSM repository",
1438 )
1439 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1440 @click.option("--repo", required=True, help="Repository name")
1441 @click.argument("name")
1442 @click.option("--filter", default=None, multiple=True, help="filter by fields")
1443 @click.option("--version", default="latest", help="package version")
1444 @click.pass_context
1445 def nsd_repo_show2(ctx, name, repo, version, literal=None, filter=None):
1446 """shows the content of a VNFD in a repository
1447
1448 NAME: name or ID of the VNFD/VNFpkg
1449 """
1450 pkgtype = "ns"
1451 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
1452
1453
1454 @cli_osm.command(name="nfpkg-show", short_help="shows the details of a NF package")
1455 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1456 @click.argument("name")
1457 @click.pass_context
1458 def nfpkg_show(ctx, name, literal):
1459 """shows the content of a NF Descriptor
1460
1461 NAME: name or ID of the NFpkg
1462 """
1463 logger.debug("")
1464 vnfd_show(ctx, name, literal)
1465
1466
1467 @cli_osm.command(
1468 name="nfpkg-repo-show",
1469 short_help="shows the details of a NF package in an OSM repository",
1470 )
1471 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1472 @click.option("--repo", required=True, help="Repository name")
1473 @click.argument("name")
1474 @click.option("--filter", default=None, multiple=True, help="filter by fields")
1475 @click.option("--version", default="latest", help="package version")
1476 @click.pass_context
1477 def vnfd_show4(ctx, name, repo, version, literal=None, filter=None):
1478 """shows the content of a VNFD in a repository
1479
1480 NAME: name or ID of the VNFD/VNFpkg
1481 """
1482 pkgtype = "vnf"
1483 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
1484
1485
1486 @cli_osm.command(name="ns-show", short_help="shows the info of a NS instance")
1487 @click.argument("name")
1488 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1489 @click.option(
1490 "--filter",
1491 multiple=True,
1492 help="restricts the information to the fields in the filter",
1493 )
1494 @click.pass_context
1495 def ns_show(ctx, name, literal, filter):
1496 """shows the info of a NS instance
1497
1498 NAME: name or ID of the NS instance
1499 """
1500 logger.debug("")
1501 # try:
1502 ns = ctx.obj.ns.get(name)
1503 # except ClientException as e:
1504 # print(str(e))
1505 # exit(1)
1506
1507 if literal:
1508 print(yaml.safe_dump(ns, indent=4, default_flow_style=False))
1509 return
1510
1511 table = PrettyTable(["field", "value"])
1512
1513 for k, v in list(ns.items()):
1514 if not filter or k in filter:
1515 table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)])
1516
1517 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1518 if fullclassname != "osmclient.sol005.client.Client":
1519 nsopdata = ctx.obj.ns.get_opdata(ns["id"])
1520 nsr_optdata = nsopdata["nsr:nsr"]
1521 for k, v in list(nsr_optdata.items()):
1522 if not filter or k in filter:
1523 table.add_row([k, wrap_text(json.dumps(v, indent=2), width=100)])
1524 table.align = "l"
1525 print(table)
1526
1527
1528 @cli_osm.command(name="vnf-show", short_help="shows the info of a VNF instance")
1529 @click.argument("name")
1530 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1531 @click.option(
1532 "--filter",
1533 multiple=True,
1534 help="restricts the information to the fields in the filter",
1535 )
1536 @click.option("--kdu", default=None, help="KDU name (whose status will be shown)")
1537 @click.pass_context
1538 def vnf_show(ctx, name, literal, filter, kdu):
1539 """shows the info of a VNF instance
1540
1541 NAME: name or ID of the VNF instance
1542 """
1543
1544 def print_kdu_status(op_info_status):
1545 """print KDU status properly formatted"""
1546 try:
1547 op_status = yaml.safe_load(op_info_status)
1548 if (
1549 "namespace" in op_status
1550 and "info" in op_status
1551 and "last_deployed" in op_status["info"]
1552 and "status" in op_status["info"]
1553 and "code" in op_status["info"]["status"]
1554 and "resources" in op_status["info"]["status"]
1555 and "seconds" in op_status["info"]["last_deployed"]
1556 ):
1557 last_deployed_time = datetime.fromtimestamp(
1558 op_status["info"]["last_deployed"]["seconds"]
1559 ).strftime("%a %b %d %I:%M:%S %Y")
1560 print("LAST DEPLOYED: {}".format(last_deployed_time))
1561 print("NAMESPACE: {}".format(op_status["namespace"]))
1562 status_code = "UNKNOWN"
1563 if op_status["info"]["status"]["code"] == 1:
1564 status_code = "DEPLOYED"
1565 print("STATUS: {}".format(status_code))
1566 print()
1567 print("RESOURCES:")
1568 print(op_status["info"]["status"]["resources"])
1569 if "notes" in op_status["info"]["status"]:
1570 print("NOTES:")
1571 print(op_status["info"]["status"]["notes"])
1572 else:
1573 print(op_info_status)
1574 except Exception:
1575 print(op_info_status)
1576
1577 logger.debug("")
1578 if kdu:
1579 if literal:
1580 raise ClientException(
1581 '"--literal" option is incompatible with "--kdu" option'
1582 )
1583 if filter:
1584 raise ClientException(
1585 '"--filter" option is incompatible with "--kdu" option'
1586 )
1587
1588 # try:
1589 check_client_version(ctx.obj, ctx.command.name)
1590 resp = ctx.obj.vnf.get(name)
1591
1592 if kdu:
1593 ns_id = resp["nsr-id-ref"]
1594 op_data = {}
1595 op_data["member_vnf_index"] = resp["member-vnf-index-ref"]
1596 op_data["kdu_name"] = kdu
1597 op_data["primitive"] = "status"
1598 op_data["primitive_params"] = {}
1599 op_id = ctx.obj.ns.exec_op(ns_id, op_name="action", op_data=op_data, wait=False)
1600 t = 0
1601 while t < 30:
1602 op_info = ctx.obj.ns.get_op(op_id)
1603 if op_info["operationState"] == "COMPLETED":
1604 print_kdu_status(op_info["detailed-status"])
1605 return
1606 time.sleep(5)
1607 t += 5
1608 print("Could not determine KDU status")
1609 return
1610
1611 if literal:
1612 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
1613 return
1614
1615 table = PrettyTable(["field", "value"])
1616 for k, v in list(resp.items()):
1617 if not filter or k in filter:
1618 table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)])
1619 table.align = "l"
1620 print(table)
1621 # except ClientException as e:
1622 # print(str(e))
1623 # exit(1)
1624
1625
1626 # @cli_osm.command(name='vnf-monitoring-show')
1627 # @click.argument('vnf_name')
1628 # @click.pass_context
1629 # def vnf_monitoring_show(ctx, vnf_name):
1630 # try:
1631 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1632 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1633 # except ClientException as e:
1634 # print(str(e))
1635 # exit(1)
1636 #
1637 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1638 # if resp is not None:
1639 # for monitor in resp:
1640 # table.add_row(
1641 # [vnf_name,
1642 # monitor['name'],
1643 # monitor['value-integer'],
1644 # monitor['units']])
1645 # table.align = 'l'
1646 # print(table)
1647
1648
1649 # @cli_osm.command(name='ns-monitoring-show')
1650 # @click.argument('ns_name')
1651 # @click.pass_context
1652 # def ns_monitoring_show(ctx, ns_name):
1653 # try:
1654 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1655 # resp = ctx.obj.ns.get_monitoring(ns_name)
1656 # except ClientException as e:
1657 # print(str(e))
1658 # exit(1)
1659 #
1660 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1661 # for key, val in list(resp.items()):
1662 # for monitor in val:
1663 # table.add_row(
1664 # [key,
1665 # monitor['name'],
1666 # monitor['value-integer'],
1667 # monitor['units']])
1668 # table.align = 'l'
1669 # print(table)
1670
1671
1672 @cli_osm.command(name="ns-op-show", short_help="shows the info of a NS operation")
1673 @click.argument("id")
1674 @click.option(
1675 "--filter",
1676 multiple=True,
1677 help="restricts the information to the fields in the filter",
1678 )
1679 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1680 @click.pass_context
1681 def ns_op_show(ctx, id, filter, literal):
1682 """shows the detailed info of a NS operation
1683
1684 ID: operation identifier
1685 """
1686 logger.debug("")
1687 # try:
1688 check_client_version(ctx.obj, ctx.command.name)
1689 op_info = ctx.obj.ns.get_op(id)
1690 # except ClientException as e:
1691 # print(str(e))
1692 # exit(1)
1693
1694 if literal:
1695 print(yaml.safe_dump(op_info, indent=4, default_flow_style=False))
1696 return
1697
1698 table = PrettyTable(["field", "value"])
1699 for k, v in list(op_info.items()):
1700 if not filter or k in filter:
1701 table.add_row([k, wrap_text(json.dumps(v, indent=2), 100)])
1702 table.align = "l"
1703 print(table)
1704
1705
1706 def nst_show(ctx, name, literal):
1707 logger.debug("")
1708 # try:
1709 check_client_version(ctx.obj, ctx.command.name)
1710 resp = ctx.obj.nst.get(name)
1711 # resp = ctx.obj.nst.get_individual(name)
1712 # except ClientException as e:
1713 # print(str(e))
1714 # exit(1)
1715
1716 if literal:
1717 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
1718 return
1719
1720 table = PrettyTable(["field", "value"])
1721 for k, v in list(resp.items()):
1722 table.add_row([k, wrap_text(json.dumps(v, indent=2), 100)])
1723 table.align = "l"
1724 print(table)
1725
1726
1727 @cli_osm.command(
1728 name="nst-show", short_help="shows the content of a Network Slice Template (NST)"
1729 )
1730 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1731 @click.argument("name")
1732 @click.pass_context
1733 def nst_show1(ctx, name, literal):
1734 """shows the content of a Network Slice Template (NST)
1735
1736 NAME: name or ID of the NST
1737 """
1738 logger.debug("")
1739 nst_show(ctx, name, literal)
1740
1741
1742 @cli_osm.command(
1743 name="netslice-template-show",
1744 short_help="shows the content of a Network Slice Template (NST)",
1745 )
1746 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1747 @click.argument("name")
1748 @click.pass_context
1749 def nst_show2(ctx, name, literal):
1750 """shows the content of a Network Slice Template (NST)
1751
1752 NAME: name or ID of the NST
1753 """
1754 logger.debug("")
1755 nst_show(ctx, name, literal)
1756
1757
1758 def nsi_show(ctx, name, literal, filter):
1759 logger.debug("")
1760 # try:
1761 check_client_version(ctx.obj, ctx.command.name)
1762 nsi = ctx.obj.nsi.get(name)
1763 # except ClientException as e:
1764 # print(str(e))
1765 # exit(1)
1766
1767 if literal:
1768 print(yaml.safe_dump(nsi, indent=4, default_flow_style=False))
1769 return
1770
1771 table = PrettyTable(["field", "value"])
1772
1773 for k, v in list(nsi.items()):
1774 if not filter or k in filter:
1775 table.add_row([k, json.dumps(v, indent=2)])
1776
1777 table.align = "l"
1778 print(table)
1779
1780
1781 @cli_osm.command(
1782 name="nsi-show", short_help="shows the content of a Network Slice Instance (NSI)"
1783 )
1784 @click.argument("name")
1785 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1786 @click.option(
1787 "--filter",
1788 multiple=True,
1789 help="restricts the information to the fields in the filter",
1790 )
1791 @click.pass_context
1792 def nsi_show1(ctx, name, literal, filter):
1793 """shows the content of a Network Slice Instance (NSI)
1794
1795 NAME: name or ID of the Network Slice Instance
1796 """
1797 logger.debug("")
1798 nsi_show(ctx, name, literal, filter)
1799
1800
1801 @cli_osm.command(
1802 name="netslice-instance-show",
1803 short_help="shows the content of a Network Slice Instance (NSI)",
1804 )
1805 @click.argument("name")
1806 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1807 @click.option(
1808 "--filter",
1809 multiple=True,
1810 help="restricts the information to the fields in the filter",
1811 )
1812 @click.pass_context
1813 def nsi_show2(ctx, name, literal, filter):
1814 """shows the content of a Network Slice Instance (NSI)
1815
1816 NAME: name or ID of the Network Slice Instance
1817 """
1818 logger.debug("")
1819 nsi_show(ctx, name, literal, filter)
1820
1821
1822 def nsi_op_show(ctx, id, filter):
1823 logger.debug("")
1824 # try:
1825 check_client_version(ctx.obj, ctx.command.name)
1826 op_info = ctx.obj.nsi.get_op(id)
1827 # except ClientException as e:
1828 # print(str(e))
1829 # exit(1)
1830
1831 table = PrettyTable(["field", "value"])
1832 for k, v in list(op_info.items()):
1833 if not filter or k in filter:
1834 table.add_row([k, json.dumps(v, indent=2)])
1835 table.align = "l"
1836 print(table)
1837
1838
1839 @cli_osm.command(
1840 name="nsi-op-show",
1841 short_help="shows the info of an operation over a Network Slice Instance(NSI)",
1842 )
1843 @click.argument("id")
1844 @click.option(
1845 "--filter",
1846 multiple=True,
1847 help="restricts the information to the fields in the filter",
1848 )
1849 @click.pass_context
1850 def nsi_op_show1(ctx, id, filter):
1851 """shows the info of an operation over a Network Slice Instance(NSI)
1852
1853 ID: operation identifier
1854 """
1855 logger.debug("")
1856 nsi_op_show(ctx, id, filter)
1857
1858
1859 @cli_osm.command(
1860 name="netslice-instance-op-show",
1861 short_help="shows the info of an operation over a Network Slice Instance(NSI)",
1862 )
1863 @click.argument("id")
1864 @click.option(
1865 "--filter",
1866 multiple=True,
1867 help="restricts the information to the fields in the filter",
1868 )
1869 @click.pass_context
1870 def nsi_op_show2(ctx, id, filter):
1871 """shows the info of an operation over a Network Slice Instance(NSI)
1872
1873 ID: operation identifier
1874 """
1875 logger.debug("")
1876 nsi_op_show(ctx, id, filter)
1877
1878
1879 @cli_osm.command(
1880 name="pdu-show", short_help="shows the content of a Physical Deployment Unit (PDU)"
1881 )
1882 @click.argument("name")
1883 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
1884 @click.option(
1885 "--filter",
1886 multiple=True,
1887 help="restricts the information to the fields in the filter",
1888 )
1889 @click.pass_context
1890 def pdu_show(ctx, name, literal, filter):
1891 """shows the content of a Physical Deployment Unit (PDU)
1892
1893 NAME: name or ID of the PDU
1894 """
1895 logger.debug("")
1896 # try:
1897 check_client_version(ctx.obj, ctx.command.name)
1898 pdu = ctx.obj.pdu.get(name)
1899 # except ClientException as e:
1900 # print(str(e))
1901 # exit(1)
1902
1903 if literal:
1904 print(yaml.safe_dump(pdu, indent=4, default_flow_style=False))
1905 return
1906
1907 table = PrettyTable(["field", "value"])
1908
1909 for k, v in list(pdu.items()):
1910 if not filter or k in filter:
1911 table.add_row([k, json.dumps(v, indent=2)])
1912
1913 table.align = "l"
1914 print(table)
1915
1916
1917 ####################
1918 # CREATE operations
1919 ####################
1920
1921
1922 def nsd_create(ctx, filename, overwrite, skip_charm_build, repo, vendor, version):
1923 logger.debug("")
1924 # try:
1925 check_client_version(ctx.obj, ctx.command.name)
1926 if repo:
1927 filename = ctx.obj.osmrepo.get_pkg("ns", filename, repo, vendor, version)
1928 ctx.obj.nsd.create(filename, overwrite=overwrite, skip_charm_build=skip_charm_build)
1929 # except ClientException as e:
1930 # print(str(e))
1931 # exit(1)
1932
1933
1934 @cli_osm.command(name="nsd-create", short_help="creates a new NSD/NSpkg")
1935 @click.argument("filename")
1936 @click.option(
1937 "--overwrite",
1938 "overwrite",
1939 default=None, # hidden=True,
1940 help="Deprecated. Use override",
1941 )
1942 @click.option(
1943 "--override",
1944 "overwrite",
1945 default=None,
1946 help="overrides fields in descriptor, format: "
1947 '"key1.key2...=value[;key3...=value;...]"',
1948 )
1949 @click.option(
1950 "--skip-charm-build",
1951 default=False,
1952 is_flag=True,
1953 help="The charm will not be compiled, it is assumed to already exist",
1954 )
1955 @click.option("--repo", default=None, help="[repository]: Repository name")
1956 @click.option("--vendor", default=None, help="[repository]: filter by vendor]")
1957 @click.option(
1958 "--version",
1959 default="latest",
1960 help="[repository]: filter by version. Default: latest",
1961 )
1962 @click.pass_context
1963 def nsd_create1(ctx, filename, overwrite, skip_charm_build, repo, vendor, version):
1964 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1965
1966 \b
1967 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1968 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1969 If FILENAME is an NF Package folder, it is built and then onboarded.
1970 """
1971 logger.debug("")
1972 nsd_create(
1973 ctx,
1974 filename,
1975 overwrite=overwrite,
1976 skip_charm_build=skip_charm_build,
1977 repo=repo,
1978 vendor=vendor,
1979 version=version,
1980 )
1981
1982
1983 @cli_osm.command(name="nspkg-create", short_help="creates a new NSD/NSpkg")
1984 @click.argument("filename")
1985 @click.option(
1986 "--overwrite",
1987 "overwrite",
1988 default=None, # hidden=True,
1989 help="Deprecated. Use override",
1990 )
1991 @click.option(
1992 "--override",
1993 "overwrite",
1994 default=None,
1995 help="overrides fields in descriptor, format: "
1996 '"key1.key2...=value[;key3...=value;...]"',
1997 )
1998 @click.option(
1999 "--skip-charm-build",
2000 default=False,
2001 is_flag=True,
2002 help="The charm will not be compiled, it is assumed to already exist",
2003 )
2004 @click.option("--repo", default=None, help="[repository]: Repository name")
2005 @click.option("--vendor", default=None, help="[repository]: filter by vendor]")
2006 @click.option(
2007 "--version",
2008 default="latest",
2009 help="[repository]: filter by version. Default: latest",
2010 )
2011 @click.pass_context
2012 def nsd_pkg_create(ctx, filename, overwrite, skip_charm_build, repo, vendor, version):
2013 """onboards a new NSpkg
2014 \b
2015 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2016 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2017 If FILENAME is an NF Package folder, it is built and then onboarded.
2018 """
2019 logger.debug("")
2020 nsd_create(
2021 ctx,
2022 filename,
2023 overwrite=overwrite,
2024 skip_charm_build=skip_charm_build,
2025 repo=repo,
2026 vendor=vendor,
2027 version=version,
2028 )
2029
2030
2031 def vnfd_create(
2032 ctx,
2033 filename,
2034 overwrite,
2035 skip_charm_build,
2036 override_epa,
2037 override_nonepa,
2038 override_paravirt,
2039 repo,
2040 vendor,
2041 version,
2042 ):
2043 logger.debug("")
2044 # try:
2045 check_client_version(ctx.obj, ctx.command.name)
2046 if repo:
2047 filename = ctx.obj.osmrepo.get_pkg("vnf", filename, repo, vendor, version)
2048 ctx.obj.vnfd.create(
2049 filename,
2050 overwrite=overwrite,
2051 skip_charm_build=skip_charm_build,
2052 override_epa=override_epa,
2053 override_nonepa=override_nonepa,
2054 override_paravirt=override_paravirt,
2055 )
2056 # except ClientException as e:
2057 # print(str(e))
2058 # exit(1)
2059
2060
2061 @cli_osm.command(name="vnfd-create", short_help="creates a new VNFD/VNFpkg")
2062 @click.argument("filename")
2063 @click.option(
2064 "--overwrite", "overwrite", default=None, help="overwrite deprecated, use override"
2065 )
2066 @click.option(
2067 "--override",
2068 "overwrite",
2069 default=None,
2070 help="overrides fields in descriptor, format: "
2071 '"key1.key2...=value[;key3...=value;...]"',
2072 )
2073 @click.option(
2074 "--skip-charm-build",
2075 default=False,
2076 is_flag=True,
2077 help="The charm will not be compiled, it is assumed to already exist",
2078 )
2079 @click.option(
2080 "--override-epa",
2081 required=False,
2082 default=False,
2083 is_flag=True,
2084 help="adds guest-epa parameters to all VDU",
2085 )
2086 @click.option(
2087 "--override-nonepa",
2088 required=False,
2089 default=False,
2090 is_flag=True,
2091 help="removes all guest-epa parameters from all VDU",
2092 )
2093 @click.option(
2094 "--override-paravirt",
2095 required=False,
2096 default=False,
2097 is_flag=True,
2098 help="overrides all VDU interfaces to PARAVIRT",
2099 )
2100 @click.option("--repo", default=None, help="[repository]: Repository name")
2101 @click.option("--vendor", default=None, help="[repository]: filter by vendor]")
2102 @click.option(
2103 "--version",
2104 default="latest",
2105 help="[repository]: filter by version. Default: latest",
2106 )
2107 @click.pass_context
2108 def vnfd_create1(
2109 ctx,
2110 filename,
2111 overwrite,
2112 skip_charm_build,
2113 override_epa,
2114 override_nonepa,
2115 override_paravirt,
2116 repo,
2117 vendor,
2118 version,
2119 ):
2120 """creates a new VNFD/VNFpkg
2121 \b
2122 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2123 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2124 If FILENAME is an NF Package folder, it is built and then onboarded.
2125 """
2126 logger.debug("")
2127 vnfd_create(
2128 ctx,
2129 filename,
2130 overwrite=overwrite,
2131 skip_charm_build=skip_charm_build,
2132 override_epa=override_epa,
2133 override_nonepa=override_nonepa,
2134 override_paravirt=override_paravirt,
2135 repo=repo,
2136 vendor=vendor,
2137 version=version,
2138 )
2139
2140
2141 @cli_osm.command(name="vnfpkg-create", short_help="creates a new VNFD/VNFpkg")
2142 @click.argument("filename")
2143 @click.option(
2144 "--overwrite",
2145 "overwrite",
2146 default=None, # hidden=True,
2147 help="Deprecated. Use override",
2148 )
2149 @click.option(
2150 "--override",
2151 "overwrite",
2152 default=None,
2153 help="overrides fields in descriptor, format: "
2154 '"key1.key2...=value[;key3...=value;...]"',
2155 )
2156 @click.option(
2157 "--skip-charm-build",
2158 default=False,
2159 is_flag=True,
2160 help="The charm will not be compiled, it is assumed to already exist",
2161 )
2162 @click.option(
2163 "--override-epa",
2164 required=False,
2165 default=False,
2166 is_flag=True,
2167 help="adds guest-epa parameters to all VDU",
2168 )
2169 @click.option(
2170 "--override-nonepa",
2171 required=False,
2172 default=False,
2173 is_flag=True,
2174 help="removes all guest-epa parameters from all VDU",
2175 )
2176 @click.option(
2177 "--override-paravirt",
2178 required=False,
2179 default=False,
2180 is_flag=True,
2181 help="overrides all VDU interfaces to PARAVIRT",
2182 )
2183 @click.option("--repo", default=None, help="[repository]: Repository name")
2184 @click.option("--vendor", default=None, help="[repository]: filter by vendor]")
2185 @click.option(
2186 "--version",
2187 default="latest",
2188 help="[repository]: filter by version. Default: latest",
2189 )
2190 @click.pass_context
2191 def vnfd_create2(
2192 ctx,
2193 filename,
2194 overwrite,
2195 skip_charm_build,
2196 override_epa,
2197 override_nonepa,
2198 override_paravirt,
2199 repo,
2200 vendor,
2201 version,
2202 ):
2203 """creates a new VNFD/VNFpkg
2204 \b
2205 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2206 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2207 If FILENAME is an NF Package folder, it is built and then onboarded.
2208 """
2209 logger.debug("")
2210 vnfd_create(
2211 ctx,
2212 filename,
2213 overwrite=overwrite,
2214 skip_charm_build=skip_charm_build,
2215 override_epa=override_epa,
2216 override_nonepa=override_nonepa,
2217 override_paravirt=override_paravirt,
2218 repo=repo,
2219 vendor=vendor,
2220 version=version,
2221 )
2222
2223
2224 @cli_osm.command(name="nfpkg-create", short_help="creates a new NFpkg")
2225 @click.argument("filename")
2226 @click.option(
2227 "--overwrite",
2228 "overwrite",
2229 default=None, # hidden=True,
2230 help="Deprecated. Use override",
2231 )
2232 @click.option(
2233 "--override",
2234 "overwrite",
2235 default=None,
2236 help="overrides fields in descriptor, format: "
2237 '"key1.key2...=value[;key3...=value;...]"',
2238 )
2239 @click.option(
2240 "--skip-charm-build",
2241 default=False,
2242 is_flag=True,
2243 help="The charm will not be compiled, it is assumed to already exist",
2244 )
2245 @click.option(
2246 "--override-epa",
2247 required=False,
2248 default=False,
2249 is_flag=True,
2250 help="adds guest-epa parameters to all VDU",
2251 )
2252 @click.option(
2253 "--override-nonepa",
2254 required=False,
2255 default=False,
2256 is_flag=True,
2257 help="removes all guest-epa parameters from all VDU",
2258 )
2259 @click.option(
2260 "--override-paravirt",
2261 required=False,
2262 default=False,
2263 is_flag=True,
2264 help="overrides all VDU interfaces to PARAVIRT",
2265 )
2266 @click.option("--repo", default=None, help="[repository]: Repository name")
2267 @click.option("--vendor", default=None, help="[repository]: filter by vendor]")
2268 @click.option(
2269 "--version",
2270 default="latest",
2271 help="[repository]: filter by version. Default: latest",
2272 )
2273 @click.pass_context
2274 def nfpkg_create(
2275 ctx,
2276 filename,
2277 overwrite,
2278 skip_charm_build,
2279 override_epa,
2280 override_nonepa,
2281 override_paravirt,
2282 repo,
2283 vendor,
2284 version,
2285 ):
2286 """creates a new NFpkg
2287
2288 \b
2289 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
2290 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
2291 If FILENAME is an NF Package folder, it is built and then onboarded.
2292 """
2293 logger.debug("")
2294 vnfd_create(
2295 ctx,
2296 filename,
2297 overwrite=overwrite,
2298 skip_charm_build=skip_charm_build,
2299 override_epa=override_epa,
2300 override_nonepa=override_nonepa,
2301 override_paravirt=override_paravirt,
2302 repo=repo,
2303 vendor=vendor,
2304 version=version,
2305 )
2306
2307
2308 @cli_osm.command(name="ns-create", short_help="creates a new Network Service instance")
2309 @click.option("--ns_name", prompt=True, help="name of the NS instance")
2310 @click.option("--nsd_name", prompt=True, help="name of the NS descriptor")
2311 @click.option(
2312 "--vim_account",
2313 prompt=True,
2314 help="default VIM account id or name for the deployment",
2315 )
2316 @click.option("--admin_status", default="ENABLED", help="administration status")
2317 @click.option(
2318 "--ssh_keys",
2319 default=None,
2320 help="comma separated list of public key files to inject to vnfs",
2321 )
2322 @click.option("--config", default=None, help="ns specific yaml configuration")
2323 @click.option("--config_file", default=None, help="ns specific yaml configuration file")
2324 @click.option(
2325 "--wait",
2326 required=False,
2327 default=False,
2328 is_flag=True,
2329 help="do not return the control immediately, but keep it "
2330 "until the operation is completed, or timeout",
2331 )
2332 @click.pass_context
2333 def ns_create(
2334 ctx,
2335 nsd_name,
2336 ns_name,
2337 vim_account,
2338 admin_status,
2339 ssh_keys,
2340 config,
2341 config_file,
2342 wait,
2343 ):
2344 """creates a new NS instance"""
2345 logger.debug("")
2346 # try:
2347 if config_file:
2348 check_client_version(ctx.obj, "--config_file")
2349 if config:
2350 raise ClientException(
2351 '"--config" option is incompatible with "--config_file" option'
2352 )
2353 with open(config_file, "r") as cf:
2354 config = cf.read()
2355 ctx.obj.ns.create(
2356 nsd_name,
2357 ns_name,
2358 config=config,
2359 ssh_keys=ssh_keys,
2360 account=vim_account,
2361 wait=wait,
2362 )
2363 # except ClientException as e:
2364 # print(str(e))
2365 # exit(1)
2366
2367
2368 def nst_create(ctx, filename, overwrite):
2369 logger.debug("")
2370 # try:
2371 check_client_version(ctx.obj, ctx.command.name)
2372 ctx.obj.nst.create(filename, overwrite)
2373 # except ClientException as e:
2374 # print(str(e))
2375 # exit(1)
2376
2377
2378 @cli_osm.command(
2379 name="nst-create", short_help="creates a new Network Slice Template (NST)"
2380 )
2381 @click.argument("filename")
2382 @click.option(
2383 "--overwrite",
2384 "overwrite",
2385 default=None, # hidden=True,
2386 help="Deprecated. Use override",
2387 )
2388 @click.option(
2389 "--override",
2390 "overwrite",
2391 default=None,
2392 help="overrides fields in descriptor, format: "
2393 '"key1.key2...=value[;key3...=value;...]"',
2394 )
2395 @click.pass_context
2396 def nst_create1(ctx, filename, overwrite):
2397 """creates a new Network Slice Template (NST)
2398
2399 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
2400 """
2401 logger.debug("")
2402 nst_create(ctx, filename, overwrite)
2403
2404
2405 @cli_osm.command(
2406 name="netslice-template-create",
2407 short_help="creates a new Network Slice Template (NST)",
2408 )
2409 @click.argument("filename")
2410 @click.option(
2411 "--overwrite",
2412 "overwrite",
2413 default=None, # hidden=True,
2414 help="Deprecated. Use override",
2415 )
2416 @click.option(
2417 "--override",
2418 "overwrite",
2419 default=None,
2420 help="overrides fields in descriptor, format: "
2421 '"key1.key2...=value[;key3...=value;...]"',
2422 )
2423 @click.pass_context
2424 def nst_create2(ctx, filename, overwrite):
2425 """creates a new Network Slice Template (NST)
2426
2427 FILENAME: NST yaml file or NSTpkg tar.gz file
2428 """
2429 logger.debug("")
2430 nst_create(ctx, filename, overwrite)
2431
2432
2433 def nsi_create(
2434 ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait
2435 ):
2436 """creates a new Network Slice Instance (NSI)"""
2437 logger.debug("")
2438 # try:
2439 check_client_version(ctx.obj, ctx.command.name)
2440 if config_file:
2441 if config:
2442 raise ClientException(
2443 '"--config" option is incompatible with "--config_file" option'
2444 )
2445 with open(config_file, "r") as cf:
2446 config = cf.read()
2447 ctx.obj.nsi.create(
2448 nst_name,
2449 nsi_name,
2450 config=config,
2451 ssh_keys=ssh_keys,
2452 account=vim_account,
2453 wait=wait,
2454 )
2455 # except ClientException as e:
2456 # print(str(e))
2457 # exit(1)
2458
2459
2460 @cli_osm.command(name="nsi-create", short_help="creates a new Network Slice Instance")
2461 @click.option("--nsi_name", prompt=True, help="name of the Network Slice Instance")
2462 @click.option("--nst_name", prompt=True, help="name of the Network Slice Template")
2463 @click.option(
2464 "--vim_account",
2465 prompt=True,
2466 help="default VIM account id or name for the deployment",
2467 )
2468 @click.option(
2469 "--ssh_keys", default=None, help="comma separated list of keys to inject to vnfs"
2470 )
2471 @click.option(
2472 "--config",
2473 default=None,
2474 help="Netslice specific yaml configuration:\n"
2475 "netslice_subnet: [\n"
2476 "id: TEXT, vim_account: TEXT,\n"
2477 "vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n"
2478 "vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n"
2479 "additionalParamsForNsi: {param: value, ...}\n"
2480 "additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n"
2481 "],\n"
2482 "netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]",
2483 )
2484 @click.option(
2485 "--config_file", default=None, help="nsi specific yaml configuration file"
2486 )
2487 @click.option(
2488 "--wait",
2489 required=False,
2490 default=False,
2491 is_flag=True,
2492 help="do not return the control immediately, but keep it "
2493 "until the operation is completed, or timeout",
2494 )
2495 @click.pass_context
2496 def nsi_create1(
2497 ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait
2498 ):
2499 """creates a new Network Slice Instance (NSI)"""
2500 logger.debug("")
2501 nsi_create(
2502 ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait
2503 )
2504
2505
2506 @cli_osm.command(
2507 name="netslice-instance-create", short_help="creates a new Network Slice Instance"
2508 )
2509 @click.option("--nsi_name", prompt=True, help="name of the Network Slice Instance")
2510 @click.option("--nst_name", prompt=True, help="name of the Network Slice Template")
2511 @click.option(
2512 "--vim_account",
2513 prompt=True,
2514 help="default VIM account id or name for the deployment",
2515 )
2516 @click.option(
2517 "--ssh_keys", default=None, help="comma separated list of keys to inject to vnfs"
2518 )
2519 @click.option(
2520 "--config",
2521 default=None,
2522 help="Netslice specific yaml configuration:\n"
2523 "netslice_subnet: [\n"
2524 "id: TEXT, vim_account: TEXT,\n"
2525 "vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n"
2526 "vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]"
2527 "],\n"
2528 "netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]",
2529 )
2530 @click.option(
2531 "--config_file", default=None, help="nsi specific yaml configuration file"
2532 )
2533 @click.option(
2534 "--wait",
2535 required=False,
2536 default=False,
2537 is_flag=True,
2538 help="do not return the control immediately, but keep it "
2539 "until the operation is completed, or timeout",
2540 )
2541 @click.pass_context
2542 def nsi_create2(
2543 ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait
2544 ):
2545 """creates a new Network Slice Instance (NSI)"""
2546 logger.debug("")
2547 nsi_create(
2548 ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait
2549 )
2550
2551
2552 @cli_osm.command(
2553 name="pdu-create", short_help="adds a new Physical Deployment Unit to the catalog"
2554 )
2555 @click.option("--name", help="name of the Physical Deployment Unit")
2556 @click.option("--pdu_type", help="type of PDU (e.g. router, firewall, FW001)")
2557 @click.option(
2558 "--interface",
2559 help="interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>"
2560 + "[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]",
2561 multiple=True,
2562 )
2563 @click.option("--description", help="human readable description")
2564 @click.option(
2565 "--vim_account",
2566 help="list of VIM accounts (in the same VIM) that can reach this PDU",
2567 multiple=True,
2568 )
2569 @click.option(
2570 "--descriptor_file",
2571 default=None,
2572 help="PDU descriptor file (as an alternative to using the other arguments",
2573 )
2574 @click.pass_context
2575 def pdu_create(
2576 ctx, name, pdu_type, interface, description, vim_account, descriptor_file
2577 ):
2578 """creates a new Physical Deployment Unit (PDU)"""
2579 logger.debug("")
2580 # try:
2581 check_client_version(ctx.obj, ctx.command.name)
2582 pdu = {}
2583 if not descriptor_file:
2584 if not name:
2585 raise ClientException(
2586 'in absence of descriptor file, option "--name" is mandatory'
2587 )
2588 if not pdu_type:
2589 raise ClientException(
2590 'in absence of descriptor file, option "--pdu_type" is mandatory'
2591 )
2592 if not interface:
2593 raise ClientException(
2594 'in absence of descriptor file, option "--interface" is mandatory (at least once)'
2595 )
2596 if not vim_account:
2597 raise ClientException(
2598 'in absence of descriptor file, option "--vim_account" is mandatory (at least once)'
2599 )
2600 else:
2601 with open(descriptor_file, "r") as df:
2602 pdu = yaml.safe_load(df.read())
2603 if name:
2604 pdu["name"] = name
2605 if pdu_type:
2606 pdu["type"] = pdu_type
2607 if description:
2608 pdu["description"] = description
2609 if vim_account:
2610 pdu["vim_accounts"] = vim_account
2611 if interface:
2612 ifaces_list = []
2613 for iface in interface:
2614 new_iface = {k: v for k, v in [i.split("=") for i in iface.split(",")]}
2615 new_iface["mgmt"] = new_iface.get("mgmt", "false").lower() == "true"
2616 ifaces_list.append(new_iface)
2617 pdu["interfaces"] = ifaces_list
2618 ctx.obj.pdu.create(pdu)
2619 # except ClientException as e:
2620 # print(str(e))
2621 # exit(1)
2622
2623
2624 ####################
2625 # UPDATE operations
2626 ####################
2627
2628
2629 def nsd_update(ctx, name, content):
2630 logger.debug("")
2631 # try:
2632 check_client_version(ctx.obj, ctx.command.name)
2633 ctx.obj.nsd.update(name, content)
2634 # except ClientException as e:
2635 # print(str(e))
2636 # exit(1)
2637
2638
2639 @cli_osm.command(name="nsd-update", short_help="updates a NSD/NSpkg")
2640 @click.argument("name")
2641 @click.option(
2642 "--content",
2643 default=None,
2644 help="filename with the NSD/NSpkg replacing the current one",
2645 )
2646 @click.pass_context
2647 def nsd_update1(ctx, name, content):
2648 """updates a NSD/NSpkg
2649
2650 NAME: name or ID of the NSD/NSpkg
2651 """
2652 logger.debug("")
2653 nsd_update(ctx, name, content)
2654
2655
2656 @cli_osm.command(name="nspkg-update", short_help="updates a NSD/NSpkg")
2657 @click.argument("name")
2658 @click.option(
2659 "--content",
2660 default=None,
2661 help="filename with the NSD/NSpkg replacing the current one",
2662 )
2663 @click.pass_context
2664 def nsd_update2(ctx, name, content):
2665 """updates a NSD/NSpkg
2666
2667 NAME: name or ID of the NSD/NSpkg
2668 """
2669 logger.debug("")
2670 nsd_update(ctx, name, content)
2671
2672
2673 def vnfd_update(ctx, name, content):
2674 logger.debug("")
2675 # try:
2676 check_client_version(ctx.obj, ctx.command.name)
2677 ctx.obj.vnfd.update(name, content)
2678 # except ClientException as e:
2679 # print(str(e))
2680 # exit(1)
2681
2682
2683 @cli_osm.command(name="vnfd-update", short_help="updates a new VNFD/VNFpkg")
2684 @click.argument("name")
2685 @click.option(
2686 "--content",
2687 default=None,
2688 help="filename with the VNFD/VNFpkg replacing the current one",
2689 )
2690 @click.pass_context
2691 def vnfd_update1(ctx, name, content):
2692 """updates a VNFD/VNFpkg
2693
2694 NAME: name or ID of the VNFD/VNFpkg
2695 """
2696 logger.debug("")
2697 vnfd_update(ctx, name, content)
2698
2699
2700 @cli_osm.command(name="vnfpkg-update", short_help="updates a VNFD/VNFpkg")
2701 @click.argument("name")
2702 @click.option(
2703 "--content",
2704 default=None,
2705 help="filename with the VNFD/VNFpkg replacing the current one",
2706 )
2707 @click.pass_context
2708 def vnfd_update2(ctx, name, content):
2709 """updates a VNFD/VNFpkg
2710
2711 NAME: VNFD yaml file or VNFpkg tar.gz file
2712 """
2713 logger.debug("")
2714 vnfd_update(ctx, name, content)
2715
2716
2717 @cli_osm.command(name="nfpkg-update", short_help="updates a NFpkg")
2718 @click.argument("name")
2719 @click.option(
2720 "--content", default=None, help="filename with the NFpkg replacing the current one"
2721 )
2722 @click.pass_context
2723 def nfpkg_update(ctx, name, content):
2724 """updates a NFpkg
2725
2726 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2727 """
2728 logger.debug("")
2729 vnfd_update(ctx, name, content)
2730
2731
2732 def nst_update(ctx, name, content):
2733 logger.debug("")
2734 # try:
2735 check_client_version(ctx.obj, ctx.command.name)
2736 ctx.obj.nst.update(name, content)
2737 # except ClientException as e:
2738 # print(str(e))
2739 # exit(1)
2740
2741
2742 @cli_osm.command(name="nst-update", short_help="updates a Network Slice Template (NST)")
2743 @click.argument("name")
2744 @click.option(
2745 "--content",
2746 default=None,
2747 help="filename with the NST/NSTpkg replacing the current one",
2748 )
2749 @click.pass_context
2750 def nst_update1(ctx, name, content):
2751 """updates a Network Slice Template (NST)
2752
2753 NAME: name or ID of the NSD/NSpkg
2754 """
2755 logger.debug("")
2756 nst_update(ctx, name, content)
2757
2758
2759 @cli_osm.command(
2760 name="netslice-template-update", short_help="updates a Network Slice Template (NST)"
2761 )
2762 @click.argument("name")
2763 @click.option(
2764 "--content",
2765 default=None,
2766 help="filename with the NST/NSTpkg replacing the current one",
2767 )
2768 @click.pass_context
2769 def nst_update2(ctx, name, content):
2770 """updates a Network Slice Template (NST)
2771
2772 NAME: name or ID of the NSD/NSpkg
2773 """
2774 logger.debug("")
2775 nst_update(ctx, name, content)
2776
2777
2778 ####################
2779 # DELETE operations
2780 ####################
2781
2782
2783 def nsd_delete(ctx, name, force):
2784 logger.debug("")
2785 # try:
2786 if not force:
2787 ctx.obj.nsd.delete(name)
2788 else:
2789 check_client_version(ctx.obj, "--force")
2790 ctx.obj.nsd.delete(name, force)
2791 # except ClientException as e:
2792 # print(str(e))
2793 # exit(1)
2794
2795
2796 @cli_osm.command(name="nsd-delete", short_help="deletes a NSD/NSpkg")
2797 @click.argument("name")
2798 @click.option(
2799 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
2800 )
2801 @click.pass_context
2802 def nsd_delete1(ctx, name, force):
2803 """deletes a NSD/NSpkg
2804
2805 NAME: name or ID of the NSD/NSpkg to be deleted
2806 """
2807 logger.debug("")
2808 nsd_delete(ctx, name, force)
2809
2810
2811 @cli_osm.command(name="nspkg-delete", short_help="deletes a NSD/NSpkg")
2812 @click.argument("name")
2813 @click.option(
2814 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
2815 )
2816 @click.pass_context
2817 def nsd_delete2(ctx, name, force):
2818 """deletes a NSD/NSpkg
2819
2820 NAME: name or ID of the NSD/NSpkg to be deleted
2821 """
2822 logger.debug("")
2823 nsd_delete(ctx, name, force)
2824
2825
2826 def vnfd_delete(ctx, name, force):
2827 logger.debug("")
2828 # try:
2829 if not force:
2830 ctx.obj.vnfd.delete(name)
2831 else:
2832 check_client_version(ctx.obj, "--force")
2833 ctx.obj.vnfd.delete(name, force)
2834 # except ClientException as e:
2835 # print(str(e))
2836 # exit(1)
2837
2838
2839 @cli_osm.command(name="vnfd-delete", short_help="deletes a VNFD/VNFpkg")
2840 @click.argument("name")
2841 @click.option(
2842 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
2843 )
2844 @click.pass_context
2845 def vnfd_delete1(ctx, name, force):
2846 """deletes a VNFD/VNFpkg
2847
2848 NAME: name or ID of the VNFD/VNFpkg to be deleted
2849 """
2850 logger.debug("")
2851 vnfd_delete(ctx, name, force)
2852
2853
2854 @cli_osm.command(name="vnfpkg-delete", short_help="deletes a VNFD/VNFpkg")
2855 @click.argument("name")
2856 @click.option(
2857 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
2858 )
2859 @click.pass_context
2860 def vnfd_delete2(ctx, name, force):
2861 """deletes a VNFD/VNFpkg
2862
2863 NAME: name or ID of the VNFD/VNFpkg to be deleted
2864 """
2865 logger.debug("")
2866 vnfd_delete(ctx, name, force)
2867
2868
2869 @cli_osm.command(name="nfpkg-delete", short_help="deletes a NFpkg")
2870 @click.argument("name")
2871 @click.option(
2872 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
2873 )
2874 @click.pass_context
2875 def nfpkg_delete(ctx, name, force):
2876 """deletes a NFpkg
2877
2878 NAME: name or ID of the NFpkg to be deleted
2879 """
2880 logger.debug("")
2881 vnfd_delete(ctx, name, force)
2882
2883
2884 @cli_osm.command(name="ns-delete", short_help="deletes a NS instance")
2885 @click.argument("name")
2886 @click.option(
2887 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
2888 )
2889 @click.option(
2890 "--config",
2891 default=None,
2892 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2893 "600, skip_terminate_primitives: True}'",
2894 )
2895 @click.option(
2896 "--wait",
2897 required=False,
2898 default=False,
2899 is_flag=True,
2900 help="do not return the control immediately, but keep it "
2901 "until the operation is completed, or timeout",
2902 )
2903 @click.pass_context
2904 def ns_delete(ctx, name, force, config, wait):
2905 """deletes a NS instance
2906
2907 NAME: name or ID of the NS instance to be deleted
2908 """
2909 logger.debug("")
2910 # try:
2911 if not force:
2912 ctx.obj.ns.delete(name, config=config, wait=wait)
2913 else:
2914 check_client_version(ctx.obj, "--force")
2915 ctx.obj.ns.delete(name, force, config=config, wait=wait)
2916 # except ClientException as e:
2917 # print(str(e))
2918 # exit(1)
2919
2920
2921 def nst_delete(ctx, name, force):
2922 logger.debug("")
2923 # try:
2924 check_client_version(ctx.obj, ctx.command.name)
2925 ctx.obj.nst.delete(name, force)
2926 # except ClientException as e:
2927 # print(str(e))
2928 # exit(1)
2929
2930
2931 @cli_osm.command(name="nst-delete", short_help="deletes a Network Slice Template (NST)")
2932 @click.argument("name")
2933 @click.option(
2934 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
2935 )
2936 @click.pass_context
2937 def nst_delete1(ctx, name, force):
2938 """deletes a Network Slice Template (NST)
2939
2940 NAME: name or ID of the NST/NSTpkg to be deleted
2941 """
2942 logger.debug("")
2943 nst_delete(ctx, name, force)
2944
2945
2946 @cli_osm.command(
2947 name="netslice-template-delete", short_help="deletes a Network Slice Template (NST)"
2948 )
2949 @click.argument("name")
2950 @click.option(
2951 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
2952 )
2953 @click.pass_context
2954 def nst_delete2(ctx, name, force):
2955 """deletes a Network Slice Template (NST)
2956
2957 NAME: name or ID of the NST/NSTpkg to be deleted
2958 """
2959 logger.debug("")
2960 nst_delete(ctx, name, force)
2961
2962
2963 def nsi_delete(ctx, name, force, wait):
2964 logger.debug("")
2965 # try:
2966 check_client_version(ctx.obj, ctx.command.name)
2967 ctx.obj.nsi.delete(name, force, wait=wait)
2968 # except ClientException as e:
2969 # print(str(e))
2970 # exit(1)
2971
2972
2973 @cli_osm.command(name="nsi-delete", short_help="deletes a Network Slice Instance (NSI)")
2974 @click.argument("name")
2975 @click.option(
2976 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
2977 )
2978 @click.option(
2979 "--wait",
2980 required=False,
2981 default=False,
2982 is_flag=True,
2983 help="do not return the control immediately, but keep it "
2984 "until the operation is completed, or timeout",
2985 )
2986 @click.pass_context
2987 def nsi_delete1(ctx, name, force, wait):
2988 """deletes a Network Slice Instance (NSI)
2989
2990 NAME: name or ID of the Network Slice instance to be deleted
2991 """
2992 logger.debug("")
2993 nsi_delete(ctx, name, force, wait=wait)
2994
2995
2996 @cli_osm.command(
2997 name="netslice-instance-delete", short_help="deletes a Network Slice Instance (NSI)"
2998 )
2999 @click.argument("name")
3000 @click.option(
3001 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
3002 )
3003 @click.pass_context
3004 def nsi_delete2(ctx, name, force, wait):
3005 """deletes a Network Slice Instance (NSI)
3006
3007 NAME: name or ID of the Network Slice instance to be deleted
3008 """
3009 logger.debug("")
3010 nsi_delete(ctx, name, force, wait=wait)
3011
3012
3013 @cli_osm.command(
3014 name="pdu-delete", short_help="deletes a Physical Deployment Unit (PDU)"
3015 )
3016 @click.argument("name")
3017 @click.option(
3018 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
3019 )
3020 @click.pass_context
3021 def pdu_delete(ctx, name, force):
3022 """deletes a Physical Deployment Unit (PDU)
3023
3024 NAME: name or ID of the PDU to be deleted
3025 """
3026 logger.debug("")
3027 # try:
3028 check_client_version(ctx.obj, ctx.command.name)
3029 ctx.obj.pdu.delete(name, force)
3030 # except ClientException as e:
3031 # print(str(e))
3032 # exit(1)
3033
3034
3035 #################
3036 # VIM operations
3037 #################
3038
3039
3040 @cli_osm.command(name="vim-create", short_help="creates a new VIM account")
3041 @click.option("--name", prompt=True, help="Name to create datacenter")
3042 @click.option("--user", prompt=True, help="VIM username")
3043 @click.option(
3044 "--password",
3045 prompt=True,
3046 hide_input=True,
3047 confirmation_prompt=True,
3048 help="VIM password",
3049 )
3050 @click.option("--auth_url", prompt=True, help="VIM url")
3051 @click.option("--tenant", prompt=True, help="VIM tenant name")
3052 @click.option("--config", default=None, help="VIM specific config parameters")
3053 @click.option("--account_type", default="openstack", help="VIM type")
3054 @click.option("--description", default=None, help="human readable description")
3055 @click.option(
3056 "--sdn_controller",
3057 default=None,
3058 help="Name or id of the SDN controller associated to this VIM account",
3059 )
3060 @click.option(
3061 "--sdn_port_mapping",
3062 default=None,
3063 help="File describing the port mapping between compute nodes' ports and switch ports",
3064 )
3065 @click.option(
3066 "--wait",
3067 required=False,
3068 default=False,
3069 is_flag=True,
3070 help="do not return the control immediately, but keep it "
3071 "until the operation is completed, or timeout",
3072 )
3073 @click.pass_context
3074 def vim_create(
3075 ctx,
3076 name,
3077 user,
3078 password,
3079 auth_url,
3080 tenant,
3081 config,
3082 account_type,
3083 description,
3084 sdn_controller,
3085 sdn_port_mapping,
3086 wait,
3087 ):
3088 """creates a new VIM account"""
3089 logger.debug("")
3090 # try:
3091 if sdn_controller:
3092 check_client_version(ctx.obj, "--sdn_controller")
3093 if sdn_port_mapping:
3094 check_client_version(ctx.obj, "--sdn_port_mapping")
3095 vim = {}
3096 vim["vim-username"] = user
3097 vim["vim-password"] = password
3098 vim["vim-url"] = auth_url
3099 vim["vim-tenant-name"] = tenant
3100 vim["vim-type"] = account_type
3101 vim["description"] = description
3102 vim["config"] = config
3103 if sdn_controller or sdn_port_mapping:
3104 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
3105 else:
3106 ctx.obj.vim.create(name, vim, wait=wait)
3107 # except ClientException as e:
3108 # print(str(e))
3109 # exit(1)
3110
3111
3112 @cli_osm.command(name="vim-update", short_help="updates a VIM account")
3113 @click.argument("name")
3114 @click.option("--newname", help="New name for the VIM account")
3115 @click.option("--user", help="VIM username")
3116 @click.option("--password", help="VIM password")
3117 @click.option("--auth_url", help="VIM url")
3118 @click.option("--tenant", help="VIM tenant name")
3119 @click.option("--config", help="VIM specific config parameters")
3120 @click.option("--account_type", help="VIM type")
3121 @click.option("--description", help="human readable description")
3122 @click.option(
3123 "--sdn_controller",
3124 default=None,
3125 help="Name or id of the SDN controller to be associated with this VIM"
3126 "account. Use empty string to disassociate",
3127 )
3128 @click.option(
3129 "--sdn_port_mapping",
3130 default=None,
3131 help="File describing the port mapping between compute nodes' ports and switch ports",
3132 )
3133 @click.option(
3134 "--wait",
3135 required=False,
3136 default=False,
3137 is_flag=True,
3138 help="do not return the control immediately, but keep it "
3139 "until the operation is completed, or timeout",
3140 )
3141 @click.pass_context
3142 def vim_update(
3143 ctx,
3144 name,
3145 newname,
3146 user,
3147 password,
3148 auth_url,
3149 tenant,
3150 config,
3151 account_type,
3152 description,
3153 sdn_controller,
3154 sdn_port_mapping,
3155 wait,
3156 ):
3157 """updates a VIM account
3158
3159 NAME: name or ID of the VIM account
3160 """
3161 logger.debug("")
3162 # try:
3163 check_client_version(ctx.obj, ctx.command.name)
3164 vim = {}
3165 if newname:
3166 vim["name"] = newname
3167 if user:
3168 vim["vim_user"] = user
3169 if password:
3170 vim["vim_password"] = password
3171 if auth_url:
3172 vim["vim_url"] = auth_url
3173 if tenant:
3174 vim["vim-tenant-name"] = tenant
3175 if account_type:
3176 vim["vim_type"] = account_type
3177 if description:
3178 vim["description"] = description
3179 if config:
3180 vim["config"] = config
3181 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
3182 # except ClientException as e:
3183 # print(str(e))
3184 # exit(1)
3185
3186
3187 @cli_osm.command(name="vim-delete", short_help="deletes a VIM account")
3188 @click.argument("name")
3189 @click.option(
3190 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
3191 )
3192 @click.option(
3193 "--wait",
3194 required=False,
3195 default=False,
3196 is_flag=True,
3197 help="do not return the control immediately, but keep it "
3198 "until the operation is completed, or timeout",
3199 )
3200 @click.pass_context
3201 def vim_delete(ctx, name, force, wait):
3202 """deletes a VIM account
3203
3204 NAME: name or ID of the VIM account to be deleted
3205 """
3206 logger.debug("")
3207 # try:
3208 if not force:
3209 ctx.obj.vim.delete(name, wait=wait)
3210 else:
3211 check_client_version(ctx.obj, "--force")
3212 ctx.obj.vim.delete(name, force, wait=wait)
3213 # except ClientException as e:
3214 # print(str(e))
3215 # exit(1)
3216
3217
3218 @cli_osm.command(name="vim-list", short_help="list all VIM accounts")
3219 # @click.option('--ro_update/--no_ro_update',
3220 # default=False,
3221 # help='update list from RO')
3222 @click.option(
3223 "--filter",
3224 default=None,
3225 multiple=True,
3226 help="restricts the list to the VIM accounts matching the filter",
3227 )
3228 @click.option(
3229 "--long",
3230 is_flag=True,
3231 help="get more details of the NS (project, vim, deployment status, configuration status.",
3232 )
3233 @click.pass_context
3234 def vim_list(ctx, filter, long):
3235 """list all VIM accounts"""
3236 logger.debug("")
3237 if filter:
3238 filter = "&".join(filter)
3239 check_client_version(ctx.obj, "--filter")
3240 # if ro_update:
3241 # check_client_version(ctx.obj, '--ro_update', 'v1')
3242 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
3243 if fullclassname == "osmclient.sol005.client.Client":
3244 resp = ctx.obj.vim.list(filter)
3245 # else:
3246 # resp = ctx.obj.vim.list(ro_update)
3247 if long:
3248 table = PrettyTable(
3249 ["vim name", "uuid", "project", "operational state", "error details"]
3250 )
3251 project_list = ctx.obj.project.list()
3252 else:
3253 table = PrettyTable(["vim name", "uuid", "operational state"])
3254 for vim in resp:
3255 if long:
3256 if "vim_password" in vim:
3257 vim["vim_password"] = "********"
3258 logger.debug("VIM details: {}".format(yaml.safe_dump(vim)))
3259 vim_state = vim["_admin"].get("operationalState", "-")
3260 error_details = "N/A"
3261 if vim_state == "ERROR":
3262 error_details = vim["_admin"].get("detailed-status", "Not found")
3263 project_id, project_name = get_project(project_list, vim)
3264 # project_info = '{} ({})'.format(project_name, project_id)
3265 project_info = project_name
3266 table.add_row(
3267 [
3268 vim["name"],
3269 vim["uuid"],
3270 project_info,
3271 vim_state,
3272 wrap_text(text=error_details, width=80),
3273 ]
3274 )
3275 else:
3276 table.add_row(
3277 [vim["name"], vim["uuid"], vim["_admin"].get("operationalState", "-")]
3278 )
3279 table.align = "l"
3280 print(table)
3281
3282
3283 @cli_osm.command(name="vim-show", short_help="shows the details of a VIM account")
3284 @click.argument("name")
3285 @click.option(
3286 "--filter",
3287 multiple=True,
3288 help="restricts the information to the fields in the filter",
3289 )
3290 @click.pass_context
3291 def vim_show(ctx, name, filter):
3292 """shows the details of a VIM account
3293
3294 NAME: name or ID of the VIM account
3295 """
3296 logger.debug("")
3297 # try:
3298 resp = ctx.obj.vim.get(name)
3299 if "vim_password" in resp:
3300 resp["vim_password"] = "********"
3301 # except ClientException as e:
3302 # print(str(e))
3303 # exit(1)
3304
3305 table = PrettyTable(["key", "attribute"])
3306 for k, v in list(resp.items()):
3307 if not filter or k in filter:
3308 table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)])
3309 table.align = "l"
3310 print(table)
3311
3312
3313 ####################
3314 # WIM operations
3315 ####################
3316
3317
3318 @cli_osm.command(name="wim-create", short_help="creates a new WIM account")
3319 @click.option("--name", prompt=True, help="Name for the WIM account")
3320 @click.option("--user", help="WIM username")
3321 @click.option("--password", help="WIM password")
3322 @click.option("--url", prompt=True, help="WIM url")
3323 # @click.option('--tenant',
3324 # help='wIM tenant name')
3325 @click.option("--config", default=None, help="WIM specific config parameters")
3326 @click.option("--wim_type", help="WIM type")
3327 @click.option("--description", default=None, help="human readable description")
3328 @click.option(
3329 "--wim_port_mapping",
3330 default=None,
3331 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
3332 "(WAN service endpoint id and info)",
3333 )
3334 @click.option(
3335 "--wait",
3336 required=False,
3337 default=False,
3338 is_flag=True,
3339 help="do not return the control immediately, but keep it "
3340 "until the operation is completed, or timeout",
3341 )
3342 @click.pass_context
3343 def wim_create(
3344 ctx,
3345 name,
3346 user,
3347 password,
3348 url,
3349 # tenant,
3350 config,
3351 wim_type,
3352 description,
3353 wim_port_mapping,
3354 wait,
3355 ):
3356 """creates a new WIM account"""
3357 logger.debug("")
3358 # try:
3359 check_client_version(ctx.obj, ctx.command.name)
3360 # if sdn_controller:
3361 # check_client_version(ctx.obj, '--sdn_controller')
3362 # if sdn_port_mapping:
3363 # check_client_version(ctx.obj, '--sdn_port_mapping')
3364 wim = {}
3365 if user:
3366 wim["user"] = user
3367 if password:
3368 wim["password"] = password
3369 if url:
3370 wim["wim_url"] = url
3371 # if tenant: wim['tenant'] = tenant
3372 wim["wim_type"] = wim_type
3373 if description:
3374 wim["description"] = description
3375 if config:
3376 wim["config"] = config
3377 ctx.obj.wim.create(name, wim, wim_port_mapping, wait=wait)
3378 # except ClientException as e:
3379 # print(str(e))
3380 # exit(1)
3381
3382
3383 @cli_osm.command(name="wim-update", short_help="updates a WIM account")
3384 @click.argument("name")
3385 @click.option("--newname", help="New name for the WIM account")
3386 @click.option("--user", help="WIM username")
3387 @click.option("--password", help="WIM password")
3388 @click.option("--url", help="WIM url")
3389 @click.option("--config", help="WIM specific config parameters")
3390 @click.option("--wim_type", help="WIM type")
3391 @click.option("--description", help="human readable description")
3392 @click.option(
3393 "--wim_port_mapping",
3394 default=None,
3395 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
3396 "(WAN service endpoint id and info)",
3397 )
3398 @click.option(
3399 "--wait",
3400 required=False,
3401 default=False,
3402 is_flag=True,
3403 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3404 )
3405 @click.pass_context
3406 def wim_update(
3407 ctx,
3408 name,
3409 newname,
3410 user,
3411 password,
3412 url,
3413 config,
3414 wim_type,
3415 description,
3416 wim_port_mapping,
3417 wait,
3418 ):
3419 """updates a WIM account
3420
3421 NAME: name or ID of the WIM account
3422 """
3423 logger.debug("")
3424 # try:
3425 check_client_version(ctx.obj, ctx.command.name)
3426 wim = {}
3427 if newname:
3428 wim["name"] = newname
3429 if user:
3430 wim["user"] = user
3431 if password:
3432 wim["password"] = password
3433 if url:
3434 wim["url"] = url
3435 # if tenant: wim['tenant'] = tenant
3436 if wim_type:
3437 wim["wim_type"] = wim_type
3438 if description:
3439 wim["description"] = description
3440 if config:
3441 wim["config"] = config
3442 ctx.obj.wim.update(name, wim, wim_port_mapping, wait=wait)
3443 # except ClientException as e:
3444 # print(str(e))
3445 # exit(1)
3446
3447
3448 @cli_osm.command(name="wim-delete", short_help="deletes a WIM account")
3449 @click.argument("name")
3450 @click.option(
3451 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
3452 )
3453 @click.option(
3454 "--wait",
3455 required=False,
3456 default=False,
3457 is_flag=True,
3458 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3459 )
3460 @click.pass_context
3461 def wim_delete(ctx, name, force, wait):
3462 """deletes a WIM account
3463
3464 NAME: name or ID of the WIM account to be deleted
3465 """
3466 logger.debug("")
3467 # try:
3468 check_client_version(ctx.obj, ctx.command.name)
3469 ctx.obj.wim.delete(name, force, wait=wait)
3470 # except ClientException as e:
3471 # print(str(e))
3472 # exit(1)
3473
3474
3475 @cli_osm.command(name="wim-list", short_help="list all WIM accounts")
3476 @click.option(
3477 "--filter",
3478 default=None,
3479 multiple=True,
3480 help="restricts the list to the WIM accounts matching the filter",
3481 )
3482 @click.pass_context
3483 def wim_list(ctx, filter):
3484 """list all WIM accounts"""
3485 logger.debug("")
3486 # try:
3487 check_client_version(ctx.obj, ctx.command.name)
3488 if filter:
3489 filter = "&".join(filter)
3490 resp = ctx.obj.wim.list(filter)
3491 table = PrettyTable(["wim name", "uuid"])
3492 for wim in resp:
3493 table.add_row([wim["name"], wim["uuid"]])
3494 table.align = "l"
3495 print(table)
3496 # except ClientException as e:
3497 # print(str(e))
3498 # exit(1)
3499
3500
3501 @cli_osm.command(name="wim-show", short_help="shows the details of a WIM account")
3502 @click.argument("name")
3503 @click.pass_context
3504 def wim_show(ctx, name):
3505 """shows the details of a WIM account
3506
3507 NAME: name or ID of the WIM account
3508 """
3509 logger.debug("")
3510 # try:
3511 check_client_version(ctx.obj, ctx.command.name)
3512 resp = ctx.obj.wim.get(name)
3513 if "password" in resp:
3514 resp["wim_password"] = "********"
3515 # except ClientException as e:
3516 # print(str(e))
3517 # exit(1)
3518
3519 table = PrettyTable(["key", "attribute"])
3520 for k, v in list(resp.items()):
3521 table.add_row([k, json.dumps(v, indent=2)])
3522 table.align = "l"
3523 print(table)
3524
3525
3526 ####################
3527 # SDN controller operations
3528 ####################
3529
3530
3531 @cli_osm.command(name="sdnc-create", short_help="creates a new SDN controller")
3532 @click.option("--name", prompt=True, help="Name to create sdn controller")
3533 @click.option("--type", prompt=True, help="SDN controller type")
3534 @click.option(
3535 "--sdn_controller_version", # hidden=True,
3536 help="Deprecated. Use --config {version: sdn_controller_version}",
3537 )
3538 @click.option("--url", help="URL in format http[s]://HOST:IP/")
3539 @click.option("--ip_address", help="Deprecated. Use --url") # hidden=True,
3540 @click.option("--port", help="Deprecated. Use --url") # hidden=True,
3541 @click.option(
3542 "--switch_dpid", help="Deprecated. Use --config {switch_id: DPID}" # hidden=True,
3543 )
3544 @click.option(
3545 "--config",
3546 help="Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: "
3547 "Openflow Datapath ID), version: version}",
3548 )
3549 @click.option("--user", help="SDN controller username")
3550 @click.option(
3551 "--password",
3552 hide_input=True,
3553 confirmation_prompt=True,
3554 help="SDN controller password",
3555 )
3556 @click.option("--description", default=None, help="human readable description")
3557 @click.option(
3558 "--wait",
3559 required=False,
3560 default=False,
3561 is_flag=True,
3562 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3563 )
3564 @click.pass_context
3565 def sdnc_create(ctx, **kwargs):
3566 """creates a new SDN controller"""
3567 logger.debug("")
3568 sdncontroller = {
3569 x: kwargs[x]
3570 for x in kwargs
3571 if kwargs[x] and x not in ("wait", "ip_address", "port", "switch_dpid")
3572 }
3573 if kwargs.get("port"):
3574 print("option '--port' is deprecated, use '--url' instead")
3575 sdncontroller["port"] = int(kwargs["port"])
3576 if kwargs.get("ip_address"):
3577 print("option '--ip_address' is deprecated, use '--url' instead")
3578 sdncontroller["ip"] = kwargs["ip_address"]
3579 if kwargs.get("switch_dpid"):
3580 print(
3581 "option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead"
3582 )
3583 sdncontroller["dpid"] = kwargs["switch_dpid"]
3584 if kwargs.get("sdn_controller_version"):
3585 print(
3586 "option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
3587 " instead"
3588 )
3589 # try:
3590 check_client_version(ctx.obj, ctx.command.name)
3591 ctx.obj.sdnc.create(kwargs["name"], sdncontroller, wait=kwargs["wait"])
3592 # except ClientException as e:
3593 # print(str(e))
3594 # exit(1)
3595
3596
3597 @cli_osm.command(name="sdnc-update", short_help="updates an SDN controller")
3598 @click.argument("name")
3599 @click.option("--newname", help="New name for the SDN controller")
3600 @click.option("--description", default=None, help="human readable description")
3601 @click.option("--type", help="SDN controller type")
3602 @click.option("--url", help="URL in format http[s]://HOST:IP/")
3603 @click.option(
3604 "--config",
3605 help="Extra information for SDN in yaml format, as "
3606 "{switch_id: identity used for the plugin (e.g. DPID: "
3607 "Openflow Datapath ID), version: version}",
3608 )
3609 @click.option("--user", help="SDN controller username")
3610 @click.option("--password", help="SDN controller password")
3611 @click.option("--ip_address", help="Deprecated. Use --url") # hidden=True
3612 @click.option("--port", help="Deprecated. Use --url") # hidden=True
3613 @click.option(
3614 "--switch_dpid", help="Deprecated. Use --config {switch_dpid: DPID}"
3615 ) # hidden=True
3616 @click.option(
3617 "--sdn_controller_version", help="Deprecated. Use --config {version: VERSION}"
3618 ) # hidden=True
3619 @click.option(
3620 "--wait",
3621 required=False,
3622 default=False,
3623 is_flag=True,
3624 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3625 )
3626 @click.pass_context
3627 def sdnc_update(ctx, **kwargs):
3628 """updates an SDN controller
3629
3630 NAME: name or ID of the SDN controller
3631 """
3632 logger.debug("")
3633 sdncontroller = {
3634 x: kwargs[x]
3635 for x in kwargs
3636 if kwargs[x]
3637 and x not in ("wait", "ip_address", "port", "switch_dpid", "new_name")
3638 }
3639 if kwargs.get("newname"):
3640 sdncontroller["name"] = kwargs["newname"]
3641 if kwargs.get("port"):
3642 print("option '--port' is deprecated, use '--url' instead")
3643 sdncontroller["port"] = int(kwargs["port"])
3644 if kwargs.get("ip_address"):
3645 print("option '--ip_address' is deprecated, use '--url' instead")
3646 sdncontroller["ip"] = kwargs["ip_address"]
3647 if kwargs.get("switch_dpid"):
3648 print(
3649 "option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead"
3650 )
3651 sdncontroller["dpid"] = kwargs["switch_dpid"]
3652 if kwargs.get("sdn_controller_version"):
3653 print(
3654 "option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
3655 " instead"
3656 )
3657
3658 # try:
3659 check_client_version(ctx.obj, ctx.command.name)
3660 ctx.obj.sdnc.update(kwargs["name"], sdncontroller, wait=kwargs["wait"])
3661 # except ClientException as e:
3662 # print(str(e))
3663 # exit(1)
3664
3665
3666 @cli_osm.command(name="sdnc-delete", short_help="deletes an SDN controller")
3667 @click.argument("name")
3668 @click.option(
3669 "--force", is_flag=True, help="forces the deletion bypassing pre-conditions"
3670 )
3671 @click.option(
3672 "--wait",
3673 required=False,
3674 default=False,
3675 is_flag=True,
3676 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
3677 )
3678 @click.pass_context
3679 def sdnc_delete(ctx, name, force, wait):
3680 """deletes an SDN controller
3681
3682 NAME: name or ID of the SDN controller to be deleted
3683 """
3684 logger.debug("")
3685 # try:
3686 check_client_version(ctx.obj, ctx.command.name)
3687 ctx.obj.sdnc.delete(name, force, wait=wait)
3688 # except ClientException as e:
3689 # print(str(e))
3690 # exit(1)
3691
3692
3693 @cli_osm.command(name="sdnc-list", short_help="list all SDN controllers")
3694 @click.option(
3695 "--filter",
3696 default=None,
3697 multiple=True,
3698 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'",
3699 )
3700 @click.pass_context
3701 def sdnc_list(ctx, filter):
3702 """list all SDN controllers"""
3703 logger.debug("")
3704 # try:
3705 check_client_version(ctx.obj, ctx.command.name)
3706 if filter:
3707 filter = "&".join(filter)
3708 resp = ctx.obj.sdnc.list(filter)
3709 # except ClientException as e:
3710 # print(str(e))
3711 # exit(1)
3712 table = PrettyTable(["sdnc name", "id"])
3713 for sdnc in resp:
3714 table.add_row([sdnc["name"], sdnc["_id"]])
3715 table.align = "l"
3716 print(table)
3717
3718
3719 @cli_osm.command(name="sdnc-show", short_help="shows the details of an SDN controller")
3720 @click.argument("name")
3721 @click.pass_context
3722 def sdnc_show(ctx, name):
3723 """shows the details of an SDN controller
3724
3725 NAME: name or ID of the SDN controller
3726 """
3727 logger.debug("")
3728 # try:
3729 check_client_version(ctx.obj, ctx.command.name)
3730 resp = ctx.obj.sdnc.get(name)
3731 # except ClientException as e:
3732 # print(str(e))
3733 # exit(1)
3734
3735 table = PrettyTable(["key", "attribute"])
3736 for k, v in list(resp.items()):
3737 table.add_row([k, json.dumps(v, indent=2)])
3738 table.align = "l"
3739 print(table)
3740
3741
3742 ###########################
3743 # K8s cluster operations
3744 ###########################
3745
3746
3747 @cli_osm.command(name="k8scluster-add", short_help="adds a K8s cluster to OSM")
3748 @click.argument("name")
3749 @click.option(
3750 "--creds", prompt=True, help="credentials file, i.e. a valid `.kube/config` file"
3751 )
3752 @click.option("--version", prompt=True, help="Kubernetes version")
3753 @click.option(
3754 "--vim", prompt=True, help="VIM target, the VIM where the cluster resides"
3755 )
3756 @click.option(
3757 "--k8s-nets",
3758 prompt=True,
3759 help='''list of VIM networks, in JSON inline format, where the cluster is
3760 accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''',
3761 )
3762 @click.option("--description", default=None, help="human readable description")
3763 @click.option(
3764 "--namespace",
3765 default="kube-system",
3766 help="namespace to be used for its operation, defaults to `kube-system`",
3767 )
3768 @click.option(
3769 "--cni",
3770 default=None,
3771 help="list of CNI plugins, in JSON inline format, used in the cluster",
3772 )
3773 # @click.option('--skip-init',
3774 # is_flag=True,
3775 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3776 # @click.option('--wait',
3777 # is_flag=True,
3778 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3779 @click.pass_context
3780 def k8scluster_add(
3781 ctx, name, creds, version, vim, k8s_nets, description, namespace, cni
3782 ):
3783 """adds a K8s cluster to OSM
3784
3785 NAME: name of the K8s cluster
3786 """
3787 # try:
3788 check_client_version(ctx.obj, ctx.command.name)
3789 cluster = {}
3790 cluster["name"] = name
3791 with open(creds, "r") as cf:
3792 cluster["credentials"] = yaml.safe_load(cf.read())
3793 cluster["k8s_version"] = version
3794 cluster["vim_account"] = vim
3795 cluster["nets"] = yaml.safe_load(k8s_nets)
3796 if description:
3797 cluster["description"] = description
3798 if namespace:
3799 cluster["namespace"] = namespace
3800 if cni:
3801 cluster["cni"] = yaml.safe_load(cni)
3802 ctx.obj.k8scluster.create(name, cluster)
3803 # except ClientException as e:
3804 # print(str(e))
3805 # exit(1)
3806
3807
3808 @cli_osm.command(name="k8scluster-update", short_help="updates a K8s cluster")
3809 @click.argument("name")
3810 @click.option("--newname", help="New name for the K8s cluster")
3811 @click.option("--creds", help="credentials file, i.e. a valid `.kube/config` file")
3812 @click.option("--version", help="Kubernetes version")
3813 @click.option("--vim", help="VIM target, the VIM where the cluster resides")
3814 @click.option(
3815 "--k8s-nets",
3816 help='''list of VIM networks, in JSON inline format, where the cluster is accessible
3817 via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''',
3818 )
3819 @click.option("--description", help="human readable description")
3820 @click.option(
3821 "--namespace",
3822 help="namespace to be used for its operation, defaults to `kube-system`",
3823 )
3824 @click.option(
3825 "--cni", help="list of CNI plugins, in JSON inline format, used in the cluster"
3826 )
3827 @click.pass_context
3828 def k8scluster_update(
3829 ctx, name, newname, creds, version, vim, k8s_nets, description, namespace, cni
3830 ):
3831 """updates a K8s cluster
3832
3833 NAME: name or ID of the K8s cluster
3834 """
3835 # try:
3836 check_client_version(ctx.obj, ctx.command.name)
3837 cluster = {}
3838 if newname:
3839 cluster["name"] = newname
3840 if creds:
3841 with open(creds, "r") as cf:
3842 cluster["credentials"] = yaml.safe_load(cf.read())
3843 if version:
3844 cluster["k8s_version"] = version
3845 if vim:
3846 cluster["vim_account"] = vim
3847 if k8s_nets:
3848 cluster["nets"] = yaml.safe_load(k8s_nets)
3849 if description:
3850 cluster["description"] = description
3851 if namespace:
3852 cluster["namespace"] = namespace
3853 if cni:
3854 cluster["cni"] = yaml.safe_load(cni)
3855 ctx.obj.k8scluster.update(name, cluster)
3856 # except ClientException as e:
3857 # print(str(e))
3858 # exit(1)
3859
3860
3861 @cli_osm.command(name="k8scluster-delete", short_help="deletes a K8s cluster")
3862 @click.argument("name")
3863 @click.option(
3864 "--force", is_flag=True, help="forces the deletion from the DB (not recommended)"
3865 )
3866 # @click.option('--wait',
3867 # is_flag=True,
3868 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3869 @click.pass_context
3870 def k8scluster_delete(ctx, name, force):
3871 """deletes a K8s cluster
3872
3873 NAME: name or ID of the K8s cluster to be deleted
3874 """
3875 # try:
3876 check_client_version(ctx.obj, ctx.command.name)
3877 ctx.obj.k8scluster.delete(name, force=force)
3878 # except ClientException as e:
3879 # print(str(e))
3880 # exit(1)
3881
3882
3883 @cli_osm.command(name="k8scluster-list")
3884 @click.option(
3885 "--filter",
3886 default=None,
3887 multiple=True,
3888 help="restricts the list to the K8s clusters matching the filter",
3889 )
3890 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
3891 @click.option("--long", is_flag=True, help="get more details")
3892 @click.pass_context
3893 def k8scluster_list(ctx, filter, literal, long):
3894 """list all K8s clusters"""
3895 # try:
3896 check_client_version(ctx.obj, ctx.command.name)
3897 if filter:
3898 filter = "&".join(filter)
3899 resp = ctx.obj.k8scluster.list(filter)
3900 if literal:
3901 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
3902 return
3903 if long:
3904 table = PrettyTable(
3905 [
3906 "Name",
3907 "Id",
3908 "Project",
3909 "Version",
3910 "VIM",
3911 "K8s-nets",
3912 "Operational State",
3913 "Op. state (details)",
3914 "Description",
3915 "Detailed status",
3916 ]
3917 )
3918 project_list = ctx.obj.project.list()
3919 else:
3920 table = PrettyTable(
3921 ["Name", "Id", "VIM", "Operational State", "Op. state details"]
3922 )
3923 try:
3924 vim_list = ctx.obj.vim.list()
3925 except Exception:
3926 vim_list = []
3927 for cluster in resp:
3928 logger.debug("Cluster details: {}".format(yaml.safe_dump(cluster)))
3929 vim_name = get_vim_name(vim_list, cluster["vim_account"])
3930 # vim_info = '{} ({})'.format(vim_name,cluster['vim_account'])
3931 vim_info = vim_name
3932 op_state_details = "Helm: {}\nJuju: {}".format(
3933 cluster["_admin"].get("helm-chart", {}).get("operationalState", "-"),
3934 cluster["_admin"].get("juju-bundle", {}).get("operationalState", "-"),
3935 )
3936 if long:
3937 project_id, project_name = get_project(project_list, cluster)
3938 # project_info = '{} ({})'.format(project_name, project_id)
3939 project_info = project_name
3940 detailed_status = cluster["_admin"].get("detailed-status", "-")
3941 table.add_row(
3942 [
3943 cluster["name"],
3944 cluster["_id"],
3945 project_info,
3946 cluster["k8s_version"],
3947 vim_info,
3948 json.dumps(cluster["nets"]),
3949 cluster["_admin"]["operationalState"],
3950 op_state_details,
3951 trunc_text(cluster.get("description") or "", 40),
3952 wrap_text(text=detailed_status, width=40),
3953 ]
3954 )
3955 else:
3956 table.add_row(
3957 [
3958 cluster["name"],
3959 cluster["_id"],
3960 vim_info,
3961 cluster["_admin"]["operationalState"],
3962 op_state_details,
3963 ]
3964 )
3965 table.align = "l"
3966 print(table)
3967 # except ClientException as e:
3968 # print(str(e))
3969 # exit(1)
3970
3971
3972 @cli_osm.command(
3973 name="k8scluster-show", short_help="shows the details of a K8s cluster"
3974 )
3975 @click.argument("name")
3976 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
3977 @click.pass_context
3978 def k8scluster_show(ctx, name, literal):
3979 """shows the details of a K8s cluster
3980
3981 NAME: name or ID of the K8s cluster
3982 """
3983 # try:
3984 resp = ctx.obj.k8scluster.get(name)
3985 if literal:
3986 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
3987 return
3988 table = PrettyTable(["key", "attribute"])
3989 for k, v in list(resp.items()):
3990 table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)])
3991 table.align = "l"
3992 print(table)
3993 # except ClientException as e:
3994 # print(str(e))
3995 # exit(1)
3996
3997
3998 ###########################
3999 # Repo operations
4000 ###########################
4001
4002
4003 @cli_osm.command(name="repo-add", short_help="adds a repo to OSM")
4004 @click.argument("name")
4005 @click.argument("uri")
4006 @click.option(
4007 "--type",
4008 type=click.Choice(["helm-chart", "juju-bundle", "osm"]),
4009 default="osm",
4010 help="type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)",
4011 )
4012 @click.option("--description", default=None, help="human readable description")
4013 @click.option(
4014 "--user", default=None, help="OSM repository: The username of the OSM repository"
4015 )
4016 @click.option(
4017 "--password",
4018 default=None,
4019 help="OSM repository: The password of the OSM repository",
4020 )
4021 # @click.option('--wait',
4022 # is_flag=True,
4023 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4024 @click.pass_context
4025 def repo_add(ctx, **kwargs):
4026 """adds a repo to OSM
4027
4028 NAME: name of the repo
4029 URI: URI of the repo
4030 """
4031 # try:
4032 kwargs = {k: v for k, v in kwargs.items() if v is not None}
4033 repo = kwargs
4034 repo["url"] = repo.pop("uri")
4035 if repo["type"] in ["helm-chart", "juju-bundle"]:
4036 ctx.obj.repo.create(repo["name"], repo)
4037 else:
4038 ctx.obj.osmrepo.create(repo["name"], repo)
4039 # except ClientException as e:
4040 # print(str(e))
4041 # exit(1)
4042
4043
4044 @cli_osm.command(name="repo-update", short_help="updates a repo in OSM")
4045 @click.argument("name")
4046 @click.option("--newname", help="New name for the repo")
4047 @click.option("--uri", help="URI of the repo")
4048 @click.option("--description", help="human readable description")
4049 # @click.option('--wait',
4050 # is_flag=True,
4051 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4052 @click.pass_context
4053 def repo_update(ctx, name, newname, uri, description):
4054 """updates a repo in OSM
4055
4056 NAME: name of the repo
4057 """
4058 # try:
4059 check_client_version(ctx.obj, ctx.command.name)
4060 repo = {}
4061 if newname:
4062 repo["name"] = newname
4063 if uri:
4064 repo["uri"] = uri
4065 if description:
4066 repo["description"] = description
4067 try:
4068 ctx.obj.repo.update(name, repo)
4069 except NotFound:
4070 ctx.obj.osmrepo.update(name, repo)
4071
4072 # except ClientException as e:
4073 # print(str(e))
4074 # exit(1)
4075
4076
4077 @cli_osm.command(
4078 name="repo-index", short_help="Index a repository from a folder with artifacts"
4079 )
4080 @click.option(
4081 "--origin", default=".", help="origin path where the artifacts are located"
4082 )
4083 @click.option(
4084 "--destination", default=".", help="destination path where the index is deployed"
4085 )
4086 @click.pass_context
4087 def repo_index(ctx, origin, destination):
4088 """Index a repository
4089
4090 NAME: name or ID of the repo to be deleted
4091 """
4092 check_client_version(ctx.obj, ctx.command.name)
4093 ctx.obj.osmrepo.repo_index(origin, destination)
4094
4095
4096 @cli_osm.command(name="repo-delete", short_help="deletes a repo")
4097 @click.argument("name")
4098 @click.option(
4099 "--force", is_flag=True, help="forces the deletion from the DB (not recommended)"
4100 )
4101 # @click.option('--wait',
4102 # is_flag=True,
4103 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4104 @click.pass_context
4105 def repo_delete(ctx, name, force):
4106 """deletes a repo
4107
4108 NAME: name or ID of the repo to be deleted
4109 """
4110 logger.debug("")
4111 try:
4112 ctx.obj.repo.delete(name, force=force)
4113 except NotFound:
4114 ctx.obj.osmrepo.delete(name, force=force)
4115 # except ClientException as e:
4116 # print(str(e))
4117 # exit(1)
4118
4119
4120 @cli_osm.command(name="repo-list")
4121 @click.option(
4122 "--filter",
4123 default=None,
4124 multiple=True,
4125 help="restricts the list to the repos matching the filter",
4126 )
4127 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
4128 @click.pass_context
4129 def repo_list(ctx, filter, literal):
4130 """list all repos"""
4131 # try:
4132 # K8s Repositories
4133 check_client_version(ctx.obj, ctx.command.name)
4134 if filter:
4135 filter = "&".join(filter)
4136 resp = ctx.obj.repo.list(filter)
4137 resp += ctx.obj.osmrepo.list(filter)
4138 if literal:
4139 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
4140 return
4141 table = PrettyTable(["Name", "Id", "Type", "URI", "Description"])
4142 for repo in resp:
4143 # cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
4144 table.add_row(
4145 [
4146 repo["name"],
4147 repo["_id"],
4148 repo["type"],
4149 repo["url"],
4150 trunc_text(repo.get("description") or "", 40),
4151 ]
4152 )
4153 table.align = "l"
4154 print(table)
4155
4156 # except ClientException as e:
4157 # print(str(e))
4158 # exit(1)
4159
4160
4161 @cli_osm.command(name="repo-show", short_help="shows the details of a repo")
4162 @click.argument("name")
4163 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
4164 @click.pass_context
4165 def repo_show(ctx, name, literal):
4166 """shows the details of a repo
4167
4168 NAME: name or ID of the repo
4169 """
4170 try:
4171 resp = ctx.obj.repo.get(name)
4172 except NotFound:
4173 resp = ctx.obj.osmrepo.get(name)
4174
4175 if literal:
4176 if resp:
4177 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
4178 return
4179 table = PrettyTable(["key", "attribute"])
4180 if resp:
4181 for k, v in list(resp.items()):
4182 table.add_row([k, json.dumps(v, indent=2)])
4183
4184 table.align = "l"
4185 print(table)
4186 # except ClientException as e:
4187 # print(str(e))
4188 # exit(1)
4189
4190
4191 ####################
4192 # Project mgmt operations
4193 ####################
4194
4195
4196 @cli_osm.command(name="project-create", short_help="creates a new project")
4197 @click.argument("name")
4198 # @click.option('--description',
4199 # default='no description',
4200 # help='human readable description')
4201 @click.option("--domain-name", "domain_name", default=None, help="assign to a domain")
4202 @click.option(
4203 "--quotas",
4204 "quotas",
4205 multiple=True,
4206 default=None,
4207 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
4208 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos",
4209 )
4210 @click.pass_context
4211 def project_create(ctx, name, domain_name, quotas):
4212 """Creates a new project
4213
4214 NAME: name of the project
4215 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
4216 QUOTAS: set quotas for the project
4217 """
4218 logger.debug("")
4219 project = {"name": name}
4220 if domain_name:
4221 project["domain_name"] = domain_name
4222 quotas_dict = _process_project_quotas(quotas)
4223 if quotas_dict:
4224 project["quotas"] = quotas_dict
4225
4226 # try:
4227 check_client_version(ctx.obj, ctx.command.name)
4228 ctx.obj.project.create(name, project)
4229 # except ClientException as e:
4230 # print(str(e))
4231 # exit(1)
4232
4233
4234 def _process_project_quotas(quota_list):
4235 quotas_dict = {}
4236 if not quota_list:
4237 return quotas_dict
4238 try:
4239 for quota in quota_list:
4240 for single_quota in quota.split(","):
4241 k, v = single_quota.split("=")
4242 quotas_dict[k] = None if v in ("None", "null", "") else int(v)
4243 except (ValueError, TypeError):
4244 raise ClientException(
4245 "invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null"
4246 )
4247 return quotas_dict
4248
4249
4250 @cli_osm.command(name="project-delete", short_help="deletes a project")
4251 @click.argument("name")
4252 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4253 @click.pass_context
4254 def project_delete(ctx, name):
4255 """deletes a project
4256
4257 NAME: name or ID of the project to be deleted
4258 """
4259 logger.debug("")
4260 # try:
4261 check_client_version(ctx.obj, ctx.command.name)
4262 ctx.obj.project.delete(name)
4263 # except ClientException as e:
4264 # print(str(e))
4265 # exit(1)
4266
4267
4268 @cli_osm.command(name="project-list", short_help="list all projects")
4269 @click.option(
4270 "--filter",
4271 default=None,
4272 multiple=True,
4273 help="restricts the list to the projects matching the filter",
4274 )
4275 @click.pass_context
4276 def project_list(ctx, filter):
4277 """list all projects"""
4278 logger.debug("")
4279 # try:
4280 check_client_version(ctx.obj, ctx.command.name)
4281 if filter:
4282 filter = "&".join(filter)
4283 resp = ctx.obj.project.list(filter)
4284 # except ClientException as e:
4285 # print(str(e))
4286 # exit(1)
4287 table = PrettyTable(["name", "id"])
4288 for proj in resp:
4289 table.add_row([proj["name"], proj["_id"]])
4290 table.align = "l"
4291 print(table)
4292
4293
4294 @cli_osm.command(name="project-show", short_help="shows the details of a project")
4295 @click.argument("name")
4296 @click.pass_context
4297 def project_show(ctx, name):
4298 """shows the details of a project
4299
4300 NAME: name or ID of the project
4301 """
4302 logger.debug("")
4303 # try:
4304 check_client_version(ctx.obj, ctx.command.name)
4305 resp = ctx.obj.project.get(name)
4306 # except ClientException as e:
4307 # print(str(e))
4308 # exit(1)
4309
4310 table = PrettyTable(["key", "attribute"])
4311 for k, v in resp.items():
4312 table.add_row([k, json.dumps(v, indent=2)])
4313 table.align = "l"
4314 print(table)
4315
4316
4317 @cli_osm.command(
4318 name="project-update", short_help="updates a project (only the name can be updated)"
4319 )
4320 @click.argument("project")
4321 @click.option("--name", default=None, help="new name for the project")
4322 @click.option(
4323 "--quotas",
4324 "quotas",
4325 multiple=True,
4326 default=None,
4327 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
4328 "(use empty to reset quota to default",
4329 )
4330 @click.pass_context
4331 def project_update(ctx, project, name, quotas):
4332 """
4333 Update a project name
4334
4335 :param ctx:
4336 :param project: id or name of the project to modify
4337 :param name: new name for the project
4338 :param quotas: change quotas of the project
4339 :return:
4340 """
4341 logger.debug("")
4342 project_changes = {}
4343 if name:
4344 project_changes["name"] = name
4345 quotas_dict = _process_project_quotas(quotas)
4346 if quotas_dict:
4347 project_changes["quotas"] = quotas_dict
4348
4349 # try:
4350 check_client_version(ctx.obj, ctx.command.name)
4351 ctx.obj.project.update(project, project_changes)
4352 # except ClientException as e:
4353 # print(str(e))
4354
4355
4356 ####################
4357 # User mgmt operations
4358 ####################
4359
4360
4361 @cli_osm.command(name="user-create", short_help="creates a new user")
4362 @click.argument("username")
4363 @click.option(
4364 "--password",
4365 prompt=True,
4366 hide_input=True,
4367 confirmation_prompt=True,
4368 help="user password",
4369 )
4370 @click.option(
4371 "--projects",
4372 # prompt="Comma separate list of projects",
4373 multiple=True,
4374 callback=lambda ctx, param, value: "".join(value).split(",")
4375 if all(len(x) == 1 for x in value)
4376 else value,
4377 help="list of project ids that the user belongs to",
4378 )
4379 @click.option(
4380 "--project-role-mappings",
4381 "project_role_mappings",
4382 default=None,
4383 multiple=True,
4384 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4385 )
4386 @click.option("--domain-name", "domain_name", default=None, help="assign to a domain")
4387 @click.pass_context
4388 def user_create(ctx, username, password, projects, project_role_mappings, domain_name):
4389 """Creates a new user
4390
4391 \b
4392 USERNAME: name of the user
4393 PASSWORD: password of the user
4394 PROJECTS: projects assigned to user (internal only)
4395 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
4396 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
4397 """
4398 logger.debug("")
4399 user = {}
4400 user["username"] = username
4401 user["password"] = password
4402 user["projects"] = projects
4403 user["project_role_mappings"] = project_role_mappings
4404 if domain_name:
4405 user["domain_name"] = domain_name
4406
4407 # try:
4408 check_client_version(ctx.obj, ctx.command.name)
4409 ctx.obj.user.create(username, user)
4410 # except ClientException as e:
4411 # print(str(e))
4412 # exit(1)
4413
4414
4415 @cli_osm.command(name="user-update", short_help="updates user information")
4416 @click.argument("username")
4417 @click.option(
4418 "--password",
4419 # prompt=True,
4420 # hide_input=True,
4421 # confirmation_prompt=True,
4422 help="user password",
4423 )
4424 @click.option("--set-username", "set_username", default=None, help="change username")
4425 @click.option(
4426 "--set-project",
4427 "set_project",
4428 default=None,
4429 multiple=True,
4430 help="create/replace the roles for this project: 'project,role1[,role2,...]'",
4431 )
4432 @click.option(
4433 "--remove-project",
4434 "remove_project",
4435 default=None,
4436 multiple=True,
4437 help="removes project from user: 'project'",
4438 )
4439 @click.option(
4440 "--add-project-role",
4441 "add_project_role",
4442 default=None,
4443 multiple=True,
4444 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4445 )
4446 @click.option(
4447 "--remove-project-role",
4448 "remove_project_role",
4449 default=None,
4450 multiple=True,
4451 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
4452 )
4453 @click.pass_context
4454 def user_update(
4455 ctx,
4456 username,
4457 password,
4458 set_username,
4459 set_project,
4460 remove_project,
4461 add_project_role,
4462 remove_project_role,
4463 ):
4464 """Update a user information
4465
4466 \b
4467 USERNAME: name of the user
4468 PASSWORD: new password
4469 SET_USERNAME: new username
4470 SET_PROJECT: creating mappings for project/role(s)
4471 REMOVE_PROJECT: deleting mappings for project/role(s)
4472 ADD_PROJECT_ROLE: adding mappings for project/role(s)
4473 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
4474 """
4475 logger.debug("")
4476 user = {}
4477 user["password"] = password
4478 user["username"] = set_username
4479 user["set-project"] = set_project
4480 user["remove-project"] = remove_project
4481 user["add-project-role"] = add_project_role
4482 user["remove-project-role"] = remove_project_role
4483
4484 # try:
4485 check_client_version(ctx.obj, ctx.command.name)
4486 ctx.obj.user.update(username, user)
4487 # except ClientException as e:
4488 # print(str(e))
4489 # exit(1)
4490
4491
4492 @cli_osm.command(name="user-delete", short_help="deletes a user")
4493 @click.argument("name")
4494 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4495 @click.pass_context
4496 def user_delete(ctx, name):
4497 """deletes a user
4498
4499 \b
4500 NAME: name or ID of the user to be deleted
4501 """
4502 logger.debug("")
4503 # try:
4504 check_client_version(ctx.obj, ctx.command.name)
4505 ctx.obj.user.delete(name)
4506 # except ClientException as e:
4507 # print(str(e))
4508 # exit(1)
4509
4510
4511 @cli_osm.command(name="user-list", short_help="list all users")
4512 @click.option(
4513 "--filter",
4514 default=None,
4515 multiple=True,
4516 help="restricts the list to the users matching the filter",
4517 )
4518 @click.pass_context
4519 def user_list(ctx, filter):
4520 """list all users"""
4521 # try:
4522 check_client_version(ctx.obj, ctx.command.name)
4523 if filter:
4524 filter = "&".join(filter)
4525 resp = ctx.obj.user.list(filter)
4526 # except ClientException as e:
4527 # print(str(e))
4528 # exit(1)
4529 table = PrettyTable(["name", "id"])
4530 for user in resp:
4531 table.add_row([user["username"], user["_id"]])
4532 table.align = "l"
4533 print(table)
4534
4535
4536 @cli_osm.command(name="user-show", short_help="shows the details of a user")
4537 @click.argument("name")
4538 @click.pass_context
4539 def user_show(ctx, name):
4540 """shows the details of a user
4541
4542 NAME: name or ID of the user
4543 """
4544 logger.debug("")
4545 # try:
4546 check_client_version(ctx.obj, ctx.command.name)
4547 resp = ctx.obj.user.get(name)
4548 if "password" in resp:
4549 resp["password"] = "********"
4550 # except ClientException as e:
4551 # print(str(e))
4552 # exit(1)
4553
4554 table = PrettyTable(["key", "attribute"])
4555 for k, v in resp.items():
4556 table.add_row([k, json.dumps(v, indent=2)])
4557 table.align = "l"
4558 print(table)
4559
4560
4561 ####################
4562 # Fault Management operations
4563 ####################
4564
4565
4566 @cli_osm.command(name="ns-alarm-create")
4567 @click.argument("name")
4568 @click.option("--ns", prompt=True, help="NS instance id or name")
4569 @click.option(
4570 "--vnf", prompt=True, help="VNF name (VNF member index as declared in the NSD)"
4571 )
4572 @click.option("--vdu", prompt=True, help="VDU name (VDU name as declared in the VNFD)")
4573 @click.option("--metric", prompt=True, help="Name of the metric (e.g. cpu_utilization)")
4574 @click.option(
4575 "--severity",
4576 default="WARNING",
4577 help="severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)",
4578 )
4579 @click.option(
4580 "--threshold_value",
4581 prompt=True,
4582 help="threshold value that, when crossed, an alarm is triggered",
4583 )
4584 @click.option(
4585 "--threshold_operator",
4586 prompt=True,
4587 help="threshold operator describing the comparison (GE, LE, GT, LT, EQ)",
4588 )
4589 @click.option(
4590 "--statistic",
4591 default="AVERAGE",
4592 help="statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)",
4593 )
4594 @click.pass_context
4595 def ns_alarm_create(
4596 ctx,
4597 name,
4598 ns,
4599 vnf,
4600 vdu,
4601 metric,
4602 severity,
4603 threshold_value,
4604 threshold_operator,
4605 statistic,
4606 ):
4607 """creates a new alarm for a NS instance"""
4608 # TODO: Check how to validate threshold_value.
4609 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
4610 logger.debug("")
4611 # try:
4612 ns_instance = ctx.obj.ns.get(ns)
4613 alarm = {}
4614 alarm["alarm_name"] = name
4615 alarm["ns_id"] = ns_instance["_id"]
4616 alarm["correlation_id"] = ns_instance["_id"]
4617 alarm["vnf_member_index"] = vnf
4618 alarm["vdu_name"] = vdu
4619 alarm["metric_name"] = metric
4620 alarm["severity"] = severity
4621 alarm["threshold_value"] = int(threshold_value)
4622 alarm["operation"] = threshold_operator
4623 alarm["statistic"] = statistic
4624 check_client_version(ctx.obj, ctx.command.name)
4625 ctx.obj.ns.create_alarm(alarm)
4626 # except ClientException as e:
4627 # print(str(e))
4628 # exit(1)
4629
4630
4631 # @cli_osm.command(name='ns-alarm-delete')
4632 # @click.argument('name')
4633 # @click.pass_context
4634 # def ns_alarm_delete(ctx, name):
4635 # """deletes an alarm
4636 #
4637 # NAME: name of the alarm to be deleted
4638 # """
4639 # try:
4640 # check_client_version(ctx.obj, ctx.command.name)
4641 # ctx.obj.ns.delete_alarm(name)
4642 # except ClientException as e:
4643 # print(str(e))
4644 # exit(1)
4645
4646
4647 ####################
4648 # Performance Management operations
4649 ####################
4650
4651
4652 @cli_osm.command(
4653 name="ns-metric-export",
4654 short_help="exports a metric to the internal OSM bus, which can be read by other apps",
4655 )
4656 @click.option("--ns", prompt=True, help="NS instance id or name")
4657 @click.option(
4658 "--vnf", prompt=True, help="VNF name (VNF member index as declared in the NSD)"
4659 )
4660 @click.option("--vdu", prompt=True, help="VDU name (VDU name as declared in the VNFD)")
4661 @click.option("--metric", prompt=True, help="name of the metric (e.g. cpu_utilization)")
4662 # @click.option('--period', default='1w',
4663 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
4664 @click.option(
4665 "--interval", help="periodic interval (seconds) to export metrics continuously"
4666 )
4667 @click.pass_context
4668 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
4669 """exports a metric to the internal OSM bus, which can be read by other apps"""
4670 # TODO: Check how to validate interval.
4671 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
4672 logger.debug("")
4673 # try:
4674 ns_instance = ctx.obj.ns.get(ns)
4675 metric_data = {}
4676 metric_data["ns_id"] = ns_instance["_id"]
4677 metric_data["correlation_id"] = ns_instance["_id"]
4678 metric_data["vnf_member_index"] = vnf
4679 metric_data["vdu_name"] = vdu
4680 metric_data["metric_name"] = metric
4681 metric_data["collection_unit"] = "WEEK"
4682 metric_data["collection_period"] = 1
4683 check_client_version(ctx.obj, ctx.command.name)
4684 if not interval:
4685 print("{}".format(ctx.obj.ns.export_metric(metric_data)))
4686 else:
4687 i = 1
4688 while True:
4689 print("{} {}".format(ctx.obj.ns.export_metric(metric_data), i))
4690 time.sleep(int(interval))
4691 i += 1
4692 # except ClientException as e:
4693 # print(str(e))
4694 # exit(1)
4695
4696
4697 ####################
4698 # Other operations
4699 ####################
4700
4701
4702 @cli_osm.command(name="version", short_help="shows client and server versions")
4703 @click.pass_context
4704 def get_version(ctx):
4705 """shows client and server versions"""
4706 # try:
4707 check_client_version(ctx.obj, "version")
4708 print("Server version: {}".format(ctx.obj.get_version()))
4709 print(
4710 "Client version: {}".format(pkg_resources.get_distribution("osmclient").version)
4711 )
4712 # except ClientException as e:
4713 # print(str(e))
4714 # exit(1)
4715
4716
4717 @cli_osm.command(
4718 name="upload-package", short_help="uploads a VNF package or NS package"
4719 )
4720 @click.argument("filename")
4721 @click.option(
4722 "--skip-charm-build",
4723 default=False,
4724 is_flag=True,
4725 help="the charm will not be compiled, it is assumed to already exist",
4726 )
4727 @click.pass_context
4728 def upload_package(ctx, filename, skip_charm_build):
4729 """uploads a vnf package or ns package
4730
4731 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
4732 """
4733 logger.debug("")
4734 # try:
4735 ctx.obj.package.upload(filename, skip_charm_build=skip_charm_build)
4736 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
4737 if fullclassname != "osmclient.sol005.client.Client":
4738 ctx.obj.package.wait_for_upload(filename)
4739 # except ClientException as e:
4740 # print(str(e))
4741 # exit(1)
4742
4743
4744 # @cli_osm.command(name='ns-scaling-show')
4745 # @click.argument('ns_name')
4746 # @click.pass_context
4747 # def show_ns_scaling(ctx, ns_name):
4748 # """shows the status of a NS scaling operation
4749 #
4750 # NS_NAME: name of the NS instance being scaled
4751 # """
4752 # try:
4753 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4754 # resp = ctx.obj.ns.list()
4755 # except ClientException as e:
4756 # print(str(e))
4757 # exit(1)
4758 #
4759 # table = PrettyTable(
4760 # ['group-name',
4761 # 'instance-id',
4762 # 'operational status',
4763 # 'create-time',
4764 # 'vnfr ids'])
4765 #
4766 # for ns in resp:
4767 # if ns_name == ns['name']:
4768 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
4769 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
4770 # for record in scaling_records:
4771 # if 'instance' in record:
4772 # instances = record['instance']
4773 # for inst in instances:
4774 # table.add_row(
4775 # [record['scaling-group-name-ref'],
4776 # inst['instance-id'],
4777 # inst['op-status'],
4778 # time.strftime('%Y-%m-%d %H:%M:%S',
4779 # time.localtime(
4780 # inst['create-time'])),
4781 # inst['vnfrs']])
4782 # table.align = 'l'
4783 # print(table)
4784
4785
4786 # @cli_osm.command(name='ns-scale')
4787 # @click.argument('ns_name')
4788 # @click.option('--ns_scale_group', prompt=True)
4789 # @click.option('--index', prompt=True)
4790 # @click.option('--wait',
4791 # required=False,
4792 # default=False,
4793 # is_flag=True,
4794 # help='do not return the control immediately, but keep it \
4795 # until the operation is completed, or timeout')
4796 # @click.pass_context
4797 # def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
4798 # """scales NS
4799 #
4800 # NS_NAME: name of the NS instance to be scaled
4801 # """
4802 # try:
4803 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4804 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
4805 # except ClientException as e:
4806 # print(str(e))
4807 # exit(1)
4808
4809
4810 # @cli_osm.command(name='config-agent-list')
4811 # @click.pass_context
4812 # def config_agent_list(ctx):
4813 # """list config agents"""
4814 # try:
4815 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4816 # except ClientException as e:
4817 # print(str(e))
4818 # exit(1)
4819 # table = PrettyTable(['name', 'account-type', 'details'])
4820 # for account in ctx.obj.vca.list():
4821 # table.add_row(
4822 # [account['name'],
4823 # account['account-type'],
4824 # account['juju']])
4825 # table.align = 'l'
4826 # print(table)
4827
4828
4829 # @cli_osm.command(name='config-agent-delete')
4830 # @click.argument('name')
4831 # @click.pass_context
4832 # def config_agent_delete(ctx, name):
4833 # """deletes a config agent
4834 #
4835 # NAME: name of the config agent to be deleted
4836 # """
4837 # try:
4838 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4839 # ctx.obj.vca.delete(name)
4840 # except ClientException as e:
4841 # print(str(e))
4842 # exit(1)
4843
4844
4845 # @cli_osm.command(name='config-agent-add')
4846 # @click.option('--name',
4847 # prompt=True)
4848 # @click.option('--account_type',
4849 # prompt=True)
4850 # @click.option('--server',
4851 # prompt=True)
4852 # @click.option('--user',
4853 # prompt=True)
4854 # @click.option('--secret',
4855 # prompt=True,
4856 # hide_input=True,
4857 # confirmation_prompt=True)
4858 # @click.pass_context
4859 # def config_agent_add(ctx, name, account_type, server, user, secret):
4860 # """adds a config agent"""
4861 # try:
4862 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4863 # ctx.obj.vca.create(name, account_type, server, user, secret)
4864 # except ClientException as e:
4865 # print(str(e))
4866 # exit(1)
4867
4868
4869 # @cli_osm.command(name='ro-dump')
4870 # @click.pass_context
4871 # def ro_dump(ctx):
4872 # """shows RO agent information"""
4873 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4874 # resp = ctx.obj.vim.get_resource_orchestrator()
4875 # table = PrettyTable(['key', 'attribute'])
4876 # for k, v in list(resp.items()):
4877 # table.add_row([k, json.dumps(v, indent=2)])
4878 # table.align = 'l'
4879 # print(table)
4880
4881
4882 # @cli_osm.command(name='vcs-list')
4883 # @click.pass_context
4884 # def vcs_list(ctx):
4885 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4886 # resp = ctx.obj.utils.get_vcs_info()
4887 # table = PrettyTable(['component name', 'state'])
4888 # for component in resp:
4889 # table.add_row([component['component_name'], component['state']])
4890 # table.align = 'l'
4891 # print(table)
4892
4893
4894 @cli_osm.command(
4895 name="ns-action", short_help="executes an action/primitive over a NS instance"
4896 )
4897 @click.argument("ns_name")
4898 @click.option(
4899 "--vnf_name",
4900 default=None,
4901 help="member-vnf-index if the target is a vnf instead of a ns)",
4902 )
4903 @click.option("--kdu_name", default=None, help="kdu-name if the target is a kdu)")
4904 @click.option("--vdu_id", default=None, help="vdu-id if the target is a vdu")
4905 @click.option(
4906 "--vdu_count", default=None, type=int, help="number of vdu instance of this vdu_id"
4907 )
4908 @click.option("--action_name", prompt=True, help="action name")
4909 @click.option("--params", default=None, help="action params in YAML/JSON inline string")
4910 @click.option("--params_file", default=None, help="YAML/JSON file with action params")
4911 @click.option(
4912 "--timeout", required=False, default=None, type=int, help="timeout in seconds"
4913 )
4914 @click.option(
4915 "--wait",
4916 required=False,
4917 default=False,
4918 is_flag=True,
4919 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
4920 )
4921 @click.pass_context
4922 def ns_action(
4923 ctx,
4924 ns_name,
4925 vnf_name,
4926 kdu_name,
4927 vdu_id,
4928 vdu_count,
4929 action_name,
4930 params,
4931 params_file,
4932 timeout,
4933 wait,
4934 ):
4935 """executes an action/primitive over a NS instance
4936
4937 NS_NAME: name or ID of the NS instance
4938 """
4939 logger.debug("")
4940 # try:
4941 check_client_version(ctx.obj, ctx.command.name)
4942 op_data = {}
4943 if vnf_name:
4944 op_data["member_vnf_index"] = vnf_name
4945 if kdu_name:
4946 op_data["kdu_name"] = kdu_name
4947 if vdu_id:
4948 op_data["vdu_id"] = vdu_id
4949 if vdu_count is not None:
4950 op_data["vdu_count_index"] = vdu_count
4951 if timeout:
4952 op_data["timeout_ns_action"] = timeout
4953 op_data["primitive"] = action_name
4954 if params_file:
4955 with open(params_file, "r") as pf:
4956 params = pf.read()
4957 if params:
4958 op_data["primitive_params"] = yaml.safe_load(params)
4959 else:
4960 op_data["primitive_params"] = {}
4961 print(ctx.obj.ns.exec_op(ns_name, op_name="action", op_data=op_data, wait=wait))
4962
4963 # except ClientException as e:
4964 # print(str(e))
4965 # exit(1)
4966
4967
4968 @cli_osm.command(
4969 name="vnf-scale", short_help="executes a VNF scale (adding/removing VDUs)"
4970 )
4971 @click.argument("ns_name")
4972 @click.argument("vnf_name")
4973 @click.option(
4974 "--scaling-group", prompt=True, help="scaling-group-descriptor name to use"
4975 )
4976 @click.option(
4977 "--scale-in", default=False, is_flag=True, help="performs a scale in operation"
4978 )
4979 @click.option(
4980 "--scale-out",
4981 default=False,
4982 is_flag=True,
4983 help="performs a scale out operation (by default)",
4984 )
4985 @click.option(
4986 "--timeout", required=False, default=None, type=int, help="timeout in seconds"
4987 )
4988 @click.option(
4989 "--wait",
4990 required=False,
4991 default=False,
4992 is_flag=True,
4993 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
4994 )
4995 @click.pass_context
4996 def vnf_scale(
4997 ctx, ns_name, vnf_name, scaling_group, scale_in, scale_out, timeout, wait
4998 ):
4999 """
5000 Executes a VNF scale (adding/removing VDUs)
5001
5002 \b
5003 NS_NAME: name or ID of the NS instance.
5004 VNF_NAME: member-vnf-index in the NS to be scaled.
5005 """
5006 logger.debug("")
5007 # try:
5008 check_client_version(ctx.obj, ctx.command.name)
5009 if not scale_in and not scale_out:
5010 scale_out = True
5011 ctx.obj.ns.scale_vnf(
5012 ns_name, vnf_name, scaling_group, scale_in, scale_out, wait, timeout
5013 )
5014 # except ClientException as e:
5015 # print(str(e))
5016 # exit(1)
5017
5018
5019 ##############################
5020 # Role Management Operations #
5021 ##############################
5022
5023
5024 @cli_osm.command(name="role-create", short_help="creates a new role")
5025 @click.argument("name")
5026 @click.option("--permissions", default=None, help="role permissions using a dictionary")
5027 @click.pass_context
5028 def role_create(ctx, name, permissions):
5029 """
5030 Creates a new role.
5031
5032 \b
5033 NAME: Name or ID of the role.
5034 DEFINITION: Definition of grant/denial of access to resources.
5035 """
5036 logger.debug("")
5037 # try:
5038 check_client_version(ctx.obj, ctx.command.name)
5039 ctx.obj.role.create(name, permissions)
5040 # except ClientException as e:
5041 # print(str(e))
5042 # exit(1)
5043
5044
5045 @cli_osm.command(name="role-update", short_help="updates a role")
5046 @click.argument("name")
5047 @click.option("--set-name", default=None, help="change name of rle")
5048 # @click.option('--permissions',
5049 # default=None,
5050 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
5051 @click.option(
5052 "--add",
5053 default=None,
5054 help="yaml format dictionary with permission: True/False to access grant/denial",
5055 )
5056 @click.option("--remove", default=None, help="yaml format list to remove a permission")
5057 @click.pass_context
5058 def role_update(ctx, name, set_name, add, remove):
5059 """
5060 Updates a role.
5061
5062 \b
5063 NAME: Name or ID of the role.
5064 DEFINITION: Definition overwrites the old definition.
5065 ADD: Grant/denial of access to resource to add.
5066 REMOVE: Grant/denial of access to resource to remove.
5067 """
5068 logger.debug("")
5069 # try:
5070 check_client_version(ctx.obj, ctx.command.name)
5071 ctx.obj.role.update(name, set_name, None, add, remove)
5072 # except ClientException as e:
5073 # print(str(e))
5074 # exit(1)
5075
5076
5077 @cli_osm.command(name="role-delete", short_help="deletes a role")
5078 @click.argument("name")
5079 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
5080 @click.pass_context
5081 def role_delete(ctx, name):
5082 """
5083 Deletes a role.
5084
5085 \b
5086 NAME: Name or ID of the role.
5087 """
5088 logger.debug("")
5089 # try:
5090 check_client_version(ctx.obj, ctx.command.name)
5091 ctx.obj.role.delete(name)
5092 # except ClientException as e:
5093 # print(str(e))
5094 # exit(1)
5095
5096
5097 @cli_osm.command(name="role-list", short_help="list all roles")
5098 @click.option(
5099 "--filter",
5100 default=None,
5101 multiple=True,
5102 help="restricts the list to the projects matching the filter",
5103 )
5104 @click.pass_context
5105 def role_list(ctx, filter):
5106 """
5107 List all roles.
5108 """
5109 logger.debug("")
5110 # try:
5111 check_client_version(ctx.obj, ctx.command.name)
5112 if filter:
5113 filter = "&".join(filter)
5114 resp = ctx.obj.role.list(filter)
5115 # except ClientException as e:
5116 # print(str(e))
5117 # exit(1)
5118 table = PrettyTable(["name", "id"])
5119 for role in resp:
5120 table.add_row([role["name"], role["_id"]])
5121 table.align = "l"
5122 print(table)
5123
5124
5125 @cli_osm.command(name="role-show", short_help="show specific role")
5126 @click.argument("name")
5127 @click.pass_context
5128 def role_show(ctx, name):
5129 """
5130 Shows the details of a role.
5131
5132 \b
5133 NAME: Name or ID of the role.
5134 """
5135 logger.debug("")
5136 # try:
5137 check_client_version(ctx.obj, ctx.command.name)
5138 resp = ctx.obj.role.get(name)
5139 # except ClientException as e:
5140 # print(str(e))
5141 # exit(1)
5142
5143 table = PrettyTable(["key", "attribute"])
5144 for k, v in resp.items():
5145 table.add_row([k, json.dumps(v, indent=2)])
5146 table.align = "l"
5147 print(table)
5148
5149
5150 @cli_osm.command(name="package-create", short_help="Create empty NS package structure")
5151 @click.argument("package-type")
5152 @click.argument("package-name")
5153 @click.option(
5154 "--base-directory",
5155 default=".",
5156 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'),
5157 )
5158 @click.option(
5159 "--image",
5160 default="image-name",
5161 help='(VNF) Set the name of the vdu image. Default "image-name"',
5162 )
5163 @click.option(
5164 "--vdus", default=1, help="(VNF) Set the number of vdus in a VNF. Default 1"
5165 )
5166 @click.option(
5167 "--vcpu", default=1, help="(VNF) Set the number of virtual CPUs in a vdu. Default 1"
5168 )
5169 @click.option(
5170 "--memory",
5171 default=1024,
5172 help="(VNF) Set the memory size (MB) of the vdu. Default 1024",
5173 )
5174 @click.option(
5175 "--storage", default=10, help="(VNF) Set the disk size (GB) of the vdu. Default 10"
5176 )
5177 @click.option(
5178 "--interfaces",
5179 default=0,
5180 help="(VNF) Set the number of additional interfaces apart from the management interface. Default 0",
5181 )
5182 @click.option(
5183 "--vendor", default="OSM", help='(NS/VNF) Set the descriptor vendor. Default "OSM"'
5184 )
5185 @click.option(
5186 "--override",
5187 default=False,
5188 is_flag=True,
5189 help="(NS/VNF/NST) Flag for overriding the package if exists.",
5190 )
5191 @click.option(
5192 "--detailed",
5193 is_flag=True,
5194 default=False,
5195 help="(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options",
5196 )
5197 @click.option(
5198 "--netslice-subnets", default=1, help="(NST) Number of netslice subnets. Default 1"
5199 )
5200 @click.option(
5201 "--netslice-vlds", default=1, help="(NST) Number of netslice vlds. Default 1"
5202 )
5203 @click.pass_context
5204 def package_create(
5205 ctx,
5206 package_type,
5207 base_directory,
5208 package_name,
5209 override,
5210 image,
5211 vdus,
5212 vcpu,
5213 memory,
5214 storage,
5215 interfaces,
5216 vendor,
5217 detailed,
5218 netslice_subnets,
5219 netslice_vlds,
5220 ):
5221 """
5222 Creates an OSM NS, VNF, NST package
5223
5224 \b
5225 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
5226 PACKAGE_NAME: Name of the package to create the folder with the content.
5227 """
5228
5229 # try:
5230 logger.debug("")
5231 check_client_version(ctx.obj, ctx.command.name)
5232 print(
5233 "Creating the {} structure: {}/{}".format(
5234 package_type.upper(), base_directory, package_name
5235 )
5236 )
5237 resp = ctx.obj.package_tool.create(
5238 package_type,
5239 base_directory,
5240 package_name,
5241 override=override,
5242 image=image,
5243 vdus=vdus,
5244 vcpu=vcpu,
5245 memory=memory,
5246 storage=storage,
5247 interfaces=interfaces,
5248 vendor=vendor,
5249 detailed=detailed,
5250 netslice_subnets=netslice_subnets,
5251 netslice_vlds=netslice_vlds,
5252 )
5253 print(resp)
5254 # except ClientException as inst:
5255 # print("ERROR: {}".format(inst))
5256 # exit(1)
5257
5258
5259 @cli_osm.command(
5260 name="package-validate", short_help="Validate descriptors given a base directory"
5261 )
5262 @click.argument("base-directory", default=".", required=False)
5263 @click.option(
5264 "--recursive/--no-recursive",
5265 default=True,
5266 help="The activated recursive option will validate the yaml files"
5267 " within the indicated directory and in its subdirectories",
5268 )
5269 @click.option(
5270 "--old",
5271 is_flag=True,
5272 default=False,
5273 help="Validates also the descriptors using the previous OSM format (pre SOL006)",
5274 )
5275 @click.pass_context
5276 def package_validate(ctx, base_directory, recursive, old):
5277 """
5278 Validate descriptors given a base directory.
5279
5280 \b
5281 BASE_DIRECTORY: Base folder for NS, VNF or NST package.
5282 """
5283 # try:
5284 logger.debug("")
5285 check_client_version(ctx.obj, ctx.command.name)
5286 results = ctx.obj.package_tool.validate(base_directory, recursive, old)
5287 table = PrettyTable()
5288 table.field_names = ["TYPE", "PATH", "VALID", "ERROR"]
5289 # Print the dictionary generated by the validation function
5290 for result in results:
5291 table.add_row(
5292 [result["type"], result["path"], result["valid"], result["error"]]
5293 )
5294 table.sortby = "VALID"
5295 table.align["PATH"] = "l"
5296 table.align["TYPE"] = "l"
5297 table.align["ERROR"] = "l"
5298 print(table)
5299 # except ClientException as inst:
5300 # print("ERROR: {}".format(inst))
5301 # exit(1)
5302
5303
5304 @cli_osm.command(
5305 name="package-translate", short_help="Translate descriptors given a base directory"
5306 )
5307 @click.argument("base-directory", default=".", required=False)
5308 @click.option(
5309 "--recursive/--no-recursive",
5310 default=True,
5311 help="The activated recursive option will translate the yaml files"
5312 " within the indicated directory and in its subdirectories",
5313 )
5314 @click.option(
5315 "--dryrun",
5316 is_flag=True,
5317 default=False,
5318 help="Do not translate yet, only make a dry-run to test translation",
5319 )
5320 @click.pass_context
5321 def package_translate(ctx, base_directory, recursive, dryrun):
5322 """
5323 Translate descriptors given a base directory.
5324
5325 \b
5326 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
5327 """
5328 logger.debug("")
5329 check_client_version(ctx.obj, ctx.command.name)
5330 results = ctx.obj.package_tool.translate(base_directory, recursive, dryrun)
5331 table = PrettyTable()
5332 table.field_names = [
5333 "CURRENT TYPE",
5334 "NEW TYPE",
5335 "PATH",
5336 "VALID",
5337 "TRANSLATED",
5338 "ERROR",
5339 ]
5340 # Print the dictionary generated by the validation function
5341 for result in results:
5342 table.add_row(
5343 [
5344 result["current type"],
5345 result["new type"],
5346 result["path"],
5347 result["valid"],
5348 result["translated"],
5349 result["error"],
5350 ]
5351 )
5352 table.sortby = "TRANSLATED"
5353 table.align["PATH"] = "l"
5354 table.align["TYPE"] = "l"
5355 table.align["ERROR"] = "l"
5356 print(table)
5357 # except ClientException as inst:
5358 # print("ERROR: {}".format(inst))
5359 # exit(1)
5360
5361
5362 @cli_osm.command(name="package-build", short_help="Build the tar.gz of the package")
5363 @click.argument("package-folder")
5364 @click.option(
5365 "--skip-validation", default=False, is_flag=True, help="skip package validation"
5366 )
5367 @click.option(
5368 "--skip-charm-build",
5369 default=False,
5370 is_flag=True,
5371 help="the charm will not be compiled, it is assumed to already exist",
5372 )
5373 @click.pass_context
5374 def package_build(ctx, package_folder, skip_validation, skip_charm_build):
5375 """
5376 Build the package NS, VNF given the package_folder.
5377
5378 \b
5379 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
5380 """
5381 # try:
5382 logger.debug("")
5383 check_client_version(ctx.obj, ctx.command.name)
5384 results = ctx.obj.package_tool.build(
5385 package_folder,
5386 skip_validation=skip_validation,
5387 skip_charm_build=skip_charm_build,
5388 )
5389 print(results)
5390 # except ClientException as inst:
5391 # print("ERROR: {}".format(inst))
5392 # exit(1)
5393
5394
5395 @cli_osm.command(
5396 name="descriptor-translate",
5397 short_help="Translate input descriptor file from Rel EIGHT OSM descriptors to SOL006 and prints in standard output",
5398 )
5399 @click.argument("descriptor-file", required=True)
5400 @click.pass_context
5401 def descriptor_translate(ctx, descriptor_file):
5402 """
5403 Translate input descriptor.
5404
5405 \b
5406 DESCRIPTOR_FILE: Descriptor file for NS, VNF or Network Slice.
5407 """
5408 logger.debug("")
5409 check_client_version(ctx.obj, ctx.command.name)
5410 result = ctx.obj.package_tool.descriptor_translate(descriptor_file)
5411 print(result)
5412
5413
5414 def cli():
5415 try:
5416 cli_osm()
5417 exit(0)
5418 except pycurl.error as exc:
5419 print(exc)
5420 print(
5421 'Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified'
5422 )
5423 except ClientException as exc:
5424 print("ERROR: {}".format(exc))
5425 except (FileNotFoundError, PermissionError) as exc:
5426 print("Cannot open file: {}".format(exc))
5427 except yaml.YAMLError as exc:
5428 print("Invalid YAML format: {}".format(exc))
5429 exit(1)
5430 # TODO capture other controlled exceptions here
5431 # TODO remove the ClientException captures from all places, unless they do something different
5432
5433
5434 if __name__ == "__main__":
5435 cli()