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