remove deprecated hidden option not available for all click versions.
[osm/osmclient.git] / osmclient / scripts / osm.py
1 # Copyright 2017-2018 Sandvine
2 # Copyright 2018 Telefonica
3 #
4 # All Rights Reserved.
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
16 # under the License.
17 """
18 OSM shell/cli
19 """
20
21 import click
22 from osmclient import client
23 from osmclient.common.exceptions import ClientException
24 from prettytable import PrettyTable
25 import yaml
26 import json
27 import time
28 import pycurl
29 import os
30 import textwrap
31 import pkg_resources
32 import logging
33
34
35 # Global variables
36
37 CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'], max_content_width=160)
38
39 def wrap_text(text, width):
40 wrapper = textwrap.TextWrapper(width=width)
41 lines = text.splitlines()
42 return "\n".join(map(wrapper.fill, lines))
43
44
45 def trunc_text(text, length):
46 if len(text) > length:
47 return text[:(length - 3)] + '...'
48 else:
49 return text
50
51
52 def check_client_version(obj, what, version='sol005'):
53 """
54 Checks the version of the client object and raises error if it not the expected.
55
56 :param obj: the client object
57 :what: the function or command under evaluation (used when an error is raised)
58 :return: -
59 :raises ClientError: if the specified version does not match the client version
60 """
61 logger.debug("")
62 fullclassname = obj.__module__ + "." + obj.__class__.__name__
63 message = 'The following commands or options are only supported with the option "--sol005": {}'.format(what)
64 if version == 'v1':
65 message = 'The following commands or options are not supported when using option "--sol005": {}'.format(what)
66 if fullclassname != 'osmclient.{}.client.Client'.format(version):
67 raise ClientException(message)
68 return
69
70
71 @click.group(context_settings=dict(help_option_names=['-h', '--help'], max_content_width=160))
72 @click.option('--hostname',
73 default="127.0.0.1",
74 envvar='OSM_HOSTNAME',
75 help='hostname of server. ' +
76 'Also can set OSM_HOSTNAME in environment')
77 #@click.option('--sol005/--no-sol005',
78 # default=True,
79 # envvar='OSM_SOL005',
80 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
81 # 'Also can set OSM_SOL005 in environment')
82 @click.option('--user',
83 default=None,
84 envvar='OSM_USER',
85 help='user (defaults to admin). ' +
86 'Also can set OSM_USER in environment')
87 @click.option('--password',
88 default=None,
89 envvar='OSM_PASSWORD',
90 help='password (defaults to admin). ' +
91 'Also can set OSM_PASSWORD in environment')
92 @click.option('--project',
93 default=None,
94 envvar='OSM_PROJECT',
95 help='project (defaults to admin). ' +
96 'Also can set OSM_PROJECT in environment')
97 @click.option('-v', '--verbose', count=True,
98 help='increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)')
99 #@click.option('--so-port',
100 # default=None,
101 # envvar='OSM_SO_PORT',
102 # help='hostname of server. ' +
103 # 'Also can set OSM_SO_PORT in environment')
104 #@click.option('--so-project',
105 # default=None,
106 # envvar='OSM_SO_PROJECT',
107 # help='Project Name in SO. ' +
108 # 'Also can set OSM_SO_PROJECT in environment')
109 #@click.option('--ro-hostname',
110 # default=None,
111 # envvar='OSM_RO_HOSTNAME',
112 # help='hostname of RO server. ' +
113 # 'Also can set OSM_RO_HOSTNAME in environment')
114 #@click.option('--ro-port',
115 # default=None,
116 # envvar='OSM_RO_PORT',
117 # help='hostname of RO server. ' +
118 # 'Also can set OSM_RO_PORT in environment')
119 @click.pass_context
120 def cli_osm(ctx, hostname, user, password, project, verbose):
121 global logger
122 if hostname is None:
123 print((
124 "either hostname option or OSM_HOSTNAME " +
125 "environment variable needs to be specified"))
126 exit(1)
127 kwargs = {'verbose': verbose}
128 # if so_port is not None:
129 # kwargs['so_port']=so_port
130 # if so_project is not None:
131 # kwargs['so_project']=so_project
132 # if ro_hostname is not None:
133 # kwargs['ro_host']=ro_hostname
134 # if ro_port is not None:
135 # kwargs['ro_port']=ro_port
136 sol005 = os.getenv('OSM_SOL005', True)
137 if user is not None:
138 kwargs['user']=user
139 if password is not None:
140 kwargs['password']=password
141 if project is not None:
142 kwargs['project']=project
143 ctx.obj = client.Client(host=hostname, sol005=sol005, **kwargs)
144 logger = logging.getLogger('osmclient')
145
146
147 ####################
148 # LIST operations
149 ####################
150
151 @cli_osm.command(name='ns-list', short_help='list all NS instances')
152 @click.option('--filter', default=None,
153 help='restricts the list to the NS instances matching the filter.')
154 @click.pass_context
155 def ns_list(ctx, filter):
156 """list all NS instances
157
158 \b
159 Options:
160 --filter filterExpr Restricts the list to the NS instances matching the filter
161
162 \b
163 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
164 concatenated using the "&" character:
165
166 \b
167 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
168 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
169 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
170 attrName := string
171 value := scalar value
172
173 \b
174 where:
175 * zero or more occurrences
176 ? zero or one occurrence
177 [] grouping of expressions to be used with ? and *
178 "" quotation marks for marking string constants
179 <> name separator
180
181 \b
182 "AttrName" is the name of one attribute in the data type that defines the representation
183 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
184 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
185 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
186 entries, it means that the operator "op" is applied to the attribute addressed by the last
187 <attrName> entry included in the concatenation. All simple filter expressions are combined
188 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
189 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
190 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
191 prefix". If an attribute referenced in an expression is an array, an object that contains a
192 corresponding array shall be considered to match the expression if any of the elements in the
193 array matches all expressions that have the same attribute prefix.
194
195 \b
196 Filter examples:
197 --filter admin-status=ENABLED
198 --filter nsd-ref=<NSD_NAME>
199 --filter nsd.vendor=<VENDOR>
200 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
201 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
202 """
203 logger.debug("")
204 if filter:
205 check_client_version(ctx.obj, '--filter')
206 resp = ctx.obj.ns.list(filter)
207 else:
208 resp = ctx.obj.ns.list()
209 table = PrettyTable(
210 ['ns instance name',
211 'id',
212 'operational status',
213 'config status',
214 'detailed status'])
215 for ns in resp:
216 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
217 if fullclassname == 'osmclient.sol005.client.Client':
218 nsr = ns
219 nsr_name = nsr['name']
220 nsr_id = nsr['_id']
221 else:
222 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
223 nsr = nsopdata['nsr:nsr']
224 nsr_name = nsr['name-ref']
225 nsr_id = nsr['ns-instance-config-ref']
226 opstatus = nsr['operational-status'] if 'operational-status' in nsr else 'Not found'
227 configstatus = nsr['config-status'] if 'config-status' in nsr else 'Not found'
228 detailed_status = nsr['detailed-status'] if 'detailed-status' in nsr else 'Not found'
229 detailed_status = wrap_text(text=detailed_status,width=50)
230 if configstatus == "config_not_needed":
231 configstatus = "configured (no charms)"
232
233 table.add_row(
234 [nsr_name,
235 nsr_id,
236 opstatus,
237 configstatus,
238 detailed_status])
239 table.align = 'l'
240 print(table)
241
242
243 def nsd_list(ctx, filter):
244 logger.debug("")
245 if filter:
246 check_client_version(ctx.obj, '--filter')
247 resp = ctx.obj.nsd.list(filter)
248 else:
249 resp = ctx.obj.nsd.list()
250 # print(yaml.safe_dump(resp))
251 table = PrettyTable(['nsd name', 'id'])
252 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
253 if fullclassname == 'osmclient.sol005.client.Client':
254 for ns in resp:
255 name = ns['name'] if 'name' in ns else '-'
256 table.add_row([name, ns['_id']])
257 else:
258 for ns in resp:
259 table.add_row([ns['name'], ns['id']])
260 table.align = 'l'
261 print(table)
262
263
264 @cli_osm.command(name='nsd-list', short_help='list all NS packages')
265 @click.option('--filter', default=None,
266 help='restricts the list to the NSD/NSpkg matching the filter')
267 @click.pass_context
268 def nsd_list1(ctx, filter):
269 """list all NSD/NS pkg in the system"""
270 logger.debug("")
271 nsd_list(ctx, filter)
272
273
274 @cli_osm.command(name='nspkg-list', short_help='list all NS packages')
275 @click.option('--filter', default=None,
276 help='restricts the list to the NSD/NSpkg matching the filter')
277 @click.pass_context
278 def nsd_list2(ctx, filter):
279 """list all NS packages"""
280 logger.debug("")
281 nsd_list(ctx, filter)
282
283
284 def vnfd_list(ctx, nf_type, filter):
285 logger.debug("")
286 if nf_type:
287 check_client_version(ctx.obj, '--nf_type')
288 elif filter:
289 check_client_version(ctx.obj, '--filter')
290 if nf_type:
291 if nf_type == "vnf":
292 nf_filter = "_admin.type=vnfd"
293 elif nf_type == "pnf":
294 nf_filter = "_admin.type=pnfd"
295 elif nf_type == "hnf":
296 nf_filter = "_admin.type=hnfd"
297 else:
298 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
299 if filter:
300 filter = '{}&{}'.format(nf_filter, filter)
301 else:
302 filter = nf_filter
303 if filter:
304 resp = ctx.obj.vnfd.list(filter)
305 else:
306 resp = ctx.obj.vnfd.list()
307 # print(yaml.safe_dump(resp))
308 table = PrettyTable(['nfpkg name', 'id'])
309 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
310 if fullclassname == 'osmclient.sol005.client.Client':
311 for vnfd in resp:
312 name = vnfd['name'] if 'name' in vnfd else '-'
313 table.add_row([name, vnfd['_id']])
314 else:
315 for vnfd in resp:
316 table.add_row([vnfd['name'], vnfd['id']])
317 table.align = 'l'
318 print(table)
319
320
321 @cli_osm.command(name='vnfd-list', short_help='list all xNF packages (VNF, HNF, PNF)')
322 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
323 @click.option('--filter', default=None,
324 help='restricts the list to the NF pkg matching the filter')
325 @click.pass_context
326 def vnfd_list1(ctx, nf_type, filter):
327 """list all xNF packages (VNF, HNF, PNF)"""
328 logger.debug("")
329 vnfd_list(ctx, nf_type, filter)
330
331
332 @cli_osm.command(name='vnfpkg-list', short_help='list all xNF packages (VNF, HNF, PNF)')
333 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
334 @click.option('--filter', default=None,
335 help='restricts the list to the NFpkg matching the filter')
336 @click.pass_context
337 def vnfd_list2(ctx, nf_type, filter):
338 """list all xNF packages (VNF, HNF, PNF)"""
339 logger.debug("")
340 vnfd_list(ctx, nf_type, filter)
341
342
343 @cli_osm.command(name='nfpkg-list', short_help='list all xNF packages (VNF, HNF, PNF)')
344 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
345 @click.option('--filter', default=None,
346 help='restricts the list to the NFpkg matching the filter')
347 @click.pass_context
348 def nfpkg_list(ctx, nf_type, filter):
349 """list all xNF packages (VNF, HNF, PNF)"""
350 logger.debug("")
351 # try:
352 check_client_version(ctx.obj, ctx.command.name)
353 vnfd_list(ctx, nf_type, filter)
354 # except ClientException as e:
355 # print(str(e))
356 # exit(1)
357
358
359 def vnf_list(ctx, ns, filter):
360 # try:
361 if ns or filter:
362 if ns:
363 check_client_version(ctx.obj, '--ns')
364 if filter:
365 check_client_version(ctx.obj, '--filter')
366 resp = ctx.obj.vnf.list(ns, filter)
367 else:
368 resp = ctx.obj.vnf.list()
369 # except ClientException as e:
370 # print(str(e))
371 # exit(1)
372 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
373 if fullclassname == 'osmclient.sol005.client.Client':
374 table = PrettyTable(
375 ['vnf id',
376 'name',
377 'ns id',
378 'vnf member index',
379 'vnfd name',
380 'vim account id',
381 'ip address'])
382 for vnfr in resp:
383 name = vnfr['name'] if 'name' in vnfr else '-'
384 table.add_row(
385 [vnfr['_id'],
386 name,
387 vnfr['nsr-id-ref'],
388 vnfr['member-vnf-index-ref'],
389 vnfr['vnfd-ref'],
390 vnfr['vim-account-id'],
391 vnfr['ip-address']])
392 else:
393 table = PrettyTable(
394 ['vnf name',
395 'id',
396 'operational status',
397 'config status'])
398 for vnfr in resp:
399 if 'mgmt-interface' not in vnfr:
400 vnfr['mgmt-interface'] = {}
401 vnfr['mgmt-interface']['ip-address'] = None
402 table.add_row(
403 [vnfr['name'],
404 vnfr['id'],
405 vnfr['operational-status'],
406 vnfr['config-status']])
407 table.align = 'l'
408 print(table)
409
410
411 @cli_osm.command(name='vnf-list', short_help='list all NF instances')
412 @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list')
413 @click.option('--filter', default=None,
414 help='restricts the list to the NF instances matching the filter.')
415 @click.pass_context
416 def vnf_list1(ctx, ns, filter):
417 """list all NF instances"""
418 logger.debug("")
419 vnf_list(ctx, ns, filter)
420
421
422 @cli_osm.command(name='nf-list', short_help='list all NF instances')
423 @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list')
424 @click.option('--filter', default=None,
425 help='restricts the list to the NF instances matching the filter.')
426 @click.pass_context
427 def nf_list(ctx, ns, filter):
428 """list all NF instances
429
430 \b
431 Options:
432 --ns TEXT NS instance id or name to restrict the VNF list
433 --filter filterExpr Restricts the list to the VNF instances matching the filter
434
435 \b
436 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
437 concatenated using the "&" character:
438
439 \b
440 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
441 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
442 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
443 attrName := string
444 value := scalar value
445
446 \b
447 where:
448 * zero or more occurrences
449 ? zero or one occurrence
450 [] grouping of expressions to be used with ? and *
451 "" quotation marks for marking string constants
452 <> name separator
453
454 \b
455 "AttrName" is the name of one attribute in the data type that defines the representation
456 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
457 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
458 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
459 entries, it means that the operator "op" is applied to the attribute addressed by the last
460 <attrName> entry included in the concatenation. All simple filter expressions are combined
461 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
462 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
463 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
464 prefix". If an attribute referenced in an expression is an array, an object that contains a
465 corresponding array shall be considered to match the expression if any of the elements in the
466 array matches all expressions that have the same attribute prefix.
467
468 \b
469 Filter examples:
470 --filter vim-account-id=<VIM_ACCOUNT_ID>
471 --filter vnfd-ref=<VNFD_NAME>
472 --filter vdur.ip-address=<IP_ADDRESS>
473 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
474 """
475 logger.debug("")
476 vnf_list(ctx, ns, filter)
477
478
479 @cli_osm.command(name='ns-op-list', short_help='shows the history of operations over a NS instance')
480 @click.argument('name')
481 @click.pass_context
482 def ns_op_list(ctx, name):
483 """shows the history of operations over a NS instance
484
485 NAME: name or ID of the NS instance
486 """
487 logger.debug("")
488 # try:
489 check_client_version(ctx.obj, ctx.command.name)
490 resp = ctx.obj.ns.list_op(name)
491 # except ClientException as e:
492 # print(str(e))
493 # exit(1)
494
495 table = PrettyTable(['id', 'operation', 'action_name', 'status'])
496 #print(yaml.safe_dump(resp))
497 for op in resp:
498 action_name = "N/A"
499 if op['lcmOperationType']=='action':
500 action_name = op['operationParams']['primitive']
501 table.add_row([op['id'], op['lcmOperationType'], action_name,
502 op['operationState']])
503 table.align = 'l'
504 print(table)
505
506
507 def nsi_list(ctx, filter):
508 """list all Network Slice Instances"""
509 logger.debug("")
510 # try:
511 check_client_version(ctx.obj, ctx.command.name)
512 resp = ctx.obj.nsi.list(filter)
513 # except ClientException as e:
514 # print(str(e))
515 # exit(1)
516 table = PrettyTable(
517 ['netslice instance name',
518 'id',
519 'operational status',
520 'config status',
521 'detailed status'])
522 for nsi in resp:
523 nsi_name = nsi['name']
524 nsi_id = nsi['_id']
525 opstatus = nsi['operational-status'] if 'operational-status' in nsi else 'Not found'
526 configstatus = nsi['config-status'] if 'config-status' in nsi else 'Not found'
527 detailed_status = nsi['detailed-status'] if 'detailed-status' in nsi else 'Not found'
528 if configstatus == "config_not_needed":
529 configstatus = "configured (no charms)"
530 table.add_row(
531 [nsi_name,
532 nsi_id,
533 opstatus,
534 configstatus,
535 detailed_status])
536 table.align = 'l'
537 print(table)
538
539
540 @cli_osm.command(name='nsi-list', short_help='list all Network Slice Instances (NSI)')
541 @click.option('--filter', default=None,
542 help='restricts the list to the Network Slice Instances matching the filter')
543 @click.pass_context
544 def nsi_list1(ctx, filter):
545 """list all Network Slice Instances (NSI)"""
546 logger.debug("")
547 nsi_list(ctx, filter)
548
549
550 @cli_osm.command(name='netslice-instance-list', short_help='list all Network Slice Instances (NSI)')
551 @click.option('--filter', default=None,
552 help='restricts the list to the Network Slice Instances matching the filter')
553 @click.pass_context
554 def nsi_list2(ctx, filter):
555 """list all Network Slice Instances (NSI)"""
556 logger.debug("")
557 nsi_list(ctx, filter)
558
559
560 def nst_list(ctx, filter):
561 logger.debug("")
562 # try:
563 check_client_version(ctx.obj, ctx.command.name)
564 resp = ctx.obj.nst.list(filter)
565 # except ClientException as e:
566 # print(str(e))
567 # exit(1)
568 # print(yaml.safe_dump(resp))
569 table = PrettyTable(['nst name', 'id'])
570 for nst in resp:
571 name = nst['name'] if 'name' in nst else '-'
572 table.add_row([name, nst['_id']])
573 table.align = 'l'
574 print(table)
575
576
577 @cli_osm.command(name='nst-list', short_help='list all Network Slice Templates (NST)')
578 @click.option('--filter', default=None,
579 help='restricts the list to the NST matching the filter')
580 @click.pass_context
581 def nst_list1(ctx, filter):
582 """list all Network Slice Templates (NST) in the system"""
583 logger.debug("")
584 nst_list(ctx, filter)
585
586
587 @cli_osm.command(name='netslice-template-list', short_help='list all Network Slice Templates (NST)')
588 @click.option('--filter', default=None,
589 help='restricts the list to the NST matching the filter')
590 @click.pass_context
591 def nst_list2(ctx, filter):
592 """list all Network Slice Templates (NST) in the system"""
593 logger.debug("")
594 nst_list(ctx, filter)
595
596
597 def nsi_op_list(ctx, name):
598 logger.debug("")
599 # try:
600 check_client_version(ctx.obj, ctx.command.name)
601 resp = ctx.obj.nsi.list_op(name)
602 # except ClientException as e:
603 # print(str(e))
604 # exit(1)
605 table = PrettyTable(['id', 'operation', 'status'])
606 for op in resp:
607 table.add_row([op['id'], op['lcmOperationType'],
608 op['operationState']])
609 table.align = 'l'
610 print(table)
611
612
613 @cli_osm.command(name='nsi-op-list', short_help='shows the history of operations over a Network Slice Instance (NSI)')
614 @click.argument('name')
615 @click.pass_context
616 def nsi_op_list1(ctx, name):
617 """shows the history of operations over a Network Slice Instance (NSI)
618
619 NAME: name or ID of the Network Slice Instance
620 """
621 logger.debug("")
622 nsi_op_list(ctx, name)
623
624
625 @cli_osm.command(name='netslice-instance-op-list', short_help='shows the history of operations over a Network Slice Instance (NSI)')
626 @click.argument('name')
627 @click.pass_context
628 def nsi_op_list2(ctx, name):
629 """shows the history of operations over a Network Slice Instance (NSI)
630
631 NAME: name or ID of the Network Slice Instance
632 """
633 logger.debug("")
634 nsi_op_list(ctx, name)
635
636
637 @cli_osm.command(name='pdu-list', short_help='list all Physical Deployment Units (PDU)')
638 @click.option('--filter', default=None,
639 help='restricts the list to the Physical Deployment Units matching the filter')
640 @click.pass_context
641 def pdu_list(ctx, filter):
642 """list all Physical Deployment Units (PDU)"""
643 logger.debug("")
644 # try:
645 check_client_version(ctx.obj, ctx.command.name)
646 resp = ctx.obj.pdu.list(filter)
647 # except ClientException as e:
648 # print(str(e))
649 # exit(1)
650 table = PrettyTable(
651 ['pdu name',
652 'id',
653 'type',
654 'mgmt ip address'])
655 for pdu in resp:
656 pdu_name = pdu['name']
657 pdu_id = pdu['_id']
658 pdu_type = pdu['type']
659 pdu_ipaddress = "None"
660 for iface in pdu['interfaces']:
661 if iface['mgmt']:
662 pdu_ipaddress = iface['ip-address']
663 break
664 table.add_row(
665 [pdu_name,
666 pdu_id,
667 pdu_type,
668 pdu_ipaddress])
669 table.align = 'l'
670 print(table)
671
672
673 ####################
674 # SHOW operations
675 ####################
676
677 def nsd_show(ctx, name, literal):
678 logger.debug("")
679 # try:
680 resp = ctx.obj.nsd.get(name)
681 # resp = ctx.obj.nsd.get_individual(name)
682 # except ClientException as e:
683 # print(str(e))
684 # exit(1)
685
686 if literal:
687 print(yaml.safe_dump(resp))
688 return
689
690 table = PrettyTable(['field', 'value'])
691 for k, v in list(resp.items()):
692 table.add_row([k, json.dumps(v, indent=2)])
693 table.align = 'l'
694 print(table)
695
696
697 @cli_osm.command(name='nsd-show', short_help='shows the content of a NSD')
698 @click.option('--literal', is_flag=True,
699 help='print literally, no pretty table')
700 @click.argument('name')
701 @click.pass_context
702 def nsd_show1(ctx, name, literal):
703 """shows the content of a NSD
704
705 NAME: name or ID of the NSD/NSpkg
706 """
707 logger.debug("")
708 nsd_show(ctx, name, literal)
709
710
711 @cli_osm.command(name='nspkg-show', short_help='shows the content of a NSD')
712 @click.option('--literal', is_flag=True,
713 help='print literally, no pretty table')
714 @click.argument('name')
715 @click.pass_context
716 def nsd_show2(ctx, name, literal):
717 """shows the content of a NSD
718
719 NAME: name or ID of the NSD/NSpkg
720 """
721 logger.debug("")
722 nsd_show(ctx, name, literal)
723
724
725 def vnfd_show(ctx, name, literal):
726 logger.debug("")
727 # try:
728 resp = ctx.obj.vnfd.get(name)
729 # resp = ctx.obj.vnfd.get_individual(name)
730 # except ClientException as e:
731 # print(str(e))
732 # exit(1)
733
734 if literal:
735 print(yaml.safe_dump(resp))
736 return
737
738 table = PrettyTable(['field', 'value'])
739 for k, v in list(resp.items()):
740 table.add_row([k, json.dumps(v, indent=2)])
741 table.align = 'l'
742 print(table)
743
744
745 @cli_osm.command(name='vnfd-show', short_help='shows the content of a VNFD')
746 @click.option('--literal', is_flag=True,
747 help='print literally, no pretty table')
748 @click.argument('name')
749 @click.pass_context
750 def vnfd_show1(ctx, name, literal):
751 """shows the content of a VNFD
752
753 NAME: name or ID of the VNFD/VNFpkg
754 """
755 logger.debug("")
756 vnfd_show(ctx, name, literal)
757
758
759 @cli_osm.command(name='vnfpkg-show', short_help='shows the content of a VNFD')
760 @click.option('--literal', is_flag=True,
761 help='print literally, no pretty table')
762 @click.argument('name')
763 @click.pass_context
764 def vnfd_show2(ctx, name, literal):
765 """shows the content of a VNFD
766
767 NAME: name or ID of the VNFD/VNFpkg
768 """
769 logger.debug("")
770 vnfd_show(ctx, name, literal)
771
772
773 @cli_osm.command(name='nfpkg-show', short_help='shows the content of a NF Descriptor')
774 @click.option('--literal', is_flag=True,
775 help='print literally, no pretty table')
776 @click.argument('name')
777 @click.pass_context
778 def nfpkg_show(ctx, name, literal):
779 """shows the content of a NF Descriptor
780
781 NAME: name or ID of the NFpkg
782 """
783 logger.debug("")
784 vnfd_show(ctx, name, literal)
785
786
787 @cli_osm.command(name='ns-show', short_help='shows the info of a NS instance')
788 @click.argument('name')
789 @click.option('--literal', is_flag=True,
790 help='print literally, no pretty table')
791 @click.option('--filter', default=None)
792 @click.pass_context
793 def ns_show(ctx, name, literal, filter):
794 """shows the info of a NS instance
795
796 NAME: name or ID of the NS instance
797 """
798 logger.debug("")
799 # try:
800 ns = ctx.obj.ns.get(name)
801 # except ClientException as e:
802 # print(str(e))
803 # exit(1)
804
805 if literal:
806 print(yaml.safe_dump(ns))
807 return
808
809 table = PrettyTable(['field', 'value'])
810
811 for k, v in list(ns.items()):
812 if filter is None or filter in k:
813 table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
814
815 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
816 if fullclassname != 'osmclient.sol005.client.Client':
817 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
818 nsr_optdata = nsopdata['nsr:nsr']
819 for k, v in list(nsr_optdata.items()):
820 if filter is None or filter in k:
821 table.add_row([k, wrap_text(json.dumps(v, indent=2),width=100)])
822 table.align = 'l'
823 print(table)
824
825
826 @cli_osm.command(name='vnf-show', short_help='shows the info of a VNF instance')
827 @click.argument('name')
828 @click.option('--literal', is_flag=True,
829 help='print literally, no pretty table')
830 @click.option('--filter', default=None, help='restricts the information to the fields in the filter')
831 @click.option('--kdu', default=None, help='KDU name (whose status will be shown)')
832 @click.pass_context
833 def vnf_show(ctx, name, literal, filter, kdu):
834 """shows the info of a VNF instance
835
836 NAME: name or ID of the VNF instance
837 """
838 logger.debug("")
839 if kdu:
840 if literal:
841 raise ClientException('"--literal" option is incompatible with "--kdu" option')
842 if filter:
843 raise ClientException('"--filter" option is incompatible with "--kdu" option')
844
845 # try:
846 check_client_version(ctx.obj, ctx.command.name)
847 resp = ctx.obj.vnf.get(name)
848
849 if kdu:
850 ns_id = resp['nsr-id-ref']
851 op_data={}
852 op_data['member_vnf_index'] = resp['member-vnf-index-ref']
853 op_data['kdu_name'] = kdu
854 op_data['primitive'] = 'status'
855 op_data['primitive_params'] = {}
856 op_id = ctx.obj.ns.exec_op(ns_id, op_name='action', op_data=op_data, wait=False)
857 t = 0
858 while t<30:
859 op_info = ctx.obj.ns.get_op(op_id)
860 if op_info['operationState'] == 'COMPLETED':
861 print(op_info['detailed-status'])
862 return
863 time.sleep(5)
864 t += 5
865 print ("Could not determine KDU status")
866
867 if literal:
868 print(yaml.safe_dump(resp))
869 return
870
871 table = PrettyTable(['field', 'value'])
872
873 for k, v in list(resp.items()):
874 if filter is None or filter in k:
875 table.add_row([k, wrap_text(text=json.dumps(v,indent=2),width=100)])
876 table.align = 'l'
877 print(table)
878 # except ClientException as e:
879 # print(str(e))
880 # exit(1)
881
882
883 #@cli_osm.command(name='vnf-monitoring-show')
884 #@click.argument('vnf_name')
885 #@click.pass_context
886 #def vnf_monitoring_show(ctx, vnf_name):
887 # try:
888 # check_client_version(ctx.obj, ctx.command.name, 'v1')
889 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
890 # except ClientException as e:
891 # print(str(e))
892 # exit(1)
893 #
894 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
895 # if resp is not None:
896 # for monitor in resp:
897 # table.add_row(
898 # [vnf_name,
899 # monitor['name'],
900 # monitor['value-integer'],
901 # monitor['units']])
902 # table.align = 'l'
903 # print(table)
904
905
906 #@cli_osm.command(name='ns-monitoring-show')
907 #@click.argument('ns_name')
908 #@click.pass_context
909 #def ns_monitoring_show(ctx, ns_name):
910 # try:
911 # check_client_version(ctx.obj, ctx.command.name, 'v1')
912 # resp = ctx.obj.ns.get_monitoring(ns_name)
913 # except ClientException as e:
914 # print(str(e))
915 # exit(1)
916 #
917 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
918 # for key, val in list(resp.items()):
919 # for monitor in val:
920 # table.add_row(
921 # [key,
922 # monitor['name'],
923 # monitor['value-integer'],
924 # monitor['units']])
925 # table.align = 'l'
926 # print(table)
927
928
929 @cli_osm.command(name='ns-op-show', short_help='shows the info of a NS operation')
930 @click.argument('id')
931 @click.option('--filter', default=None)
932 @click.option('--literal', is_flag=True,
933 help='print literally, no pretty table')
934 @click.pass_context
935 def ns_op_show(ctx, id, filter, literal):
936 """shows the detailed info of a NS operation
937
938 ID: operation identifier
939 """
940 logger.debug("")
941 # try:
942 check_client_version(ctx.obj, ctx.command.name)
943 op_info = ctx.obj.ns.get_op(id)
944 # except ClientException as e:
945 # print(str(e))
946 # exit(1)
947
948 if literal:
949 print(yaml.safe_dump(op_info))
950 return
951
952 table = PrettyTable(['field', 'value'])
953 for k, v in list(op_info.items()):
954 if filter is None or filter in k:
955 table.add_row([k, wrap_text(json.dumps(v, indent=2), 100)])
956 table.align = 'l'
957 print(table)
958
959
960 def nst_show(ctx, name, literal):
961 logger.debug("")
962 # try:
963 check_client_version(ctx.obj, ctx.command.name)
964 resp = ctx.obj.nst.get(name)
965 #resp = ctx.obj.nst.get_individual(name)
966 # except ClientException as e:
967 # print(str(e))
968 # exit(1)
969
970 if literal:
971 print(yaml.safe_dump(resp))
972 return
973
974 table = PrettyTable(['field', 'value'])
975 for k, v in list(resp.items()):
976 table.add_row([k, wrap_text(json.dumps(v, indent=2), 100)])
977 table.align = 'l'
978 print(table)
979
980
981 @cli_osm.command(name='nst-show', short_help='shows the content of a Network Slice Template (NST)')
982 @click.option('--literal', is_flag=True,
983 help='print literally, no pretty table')
984 @click.argument('name')
985 @click.pass_context
986 def nst_show1(ctx, name, literal):
987 """shows the content of a Network Slice Template (NST)
988
989 NAME: name or ID of the NST
990 """
991 logger.debug("")
992 nst_show(ctx, name, literal)
993
994
995 @cli_osm.command(name='netslice-template-show', short_help='shows the content of a Network Slice Template (NST)')
996 @click.option('--literal', is_flag=True,
997 help='print literally, no pretty table')
998 @click.argument('name')
999 @click.pass_context
1000 def nst_show2(ctx, name, literal):
1001 """shows the content of a Network Slice Template (NST)
1002
1003 NAME: name or ID of the NST
1004 """
1005 logger.debug("")
1006 nst_show(ctx, name, literal)
1007
1008
1009 def nsi_show(ctx, name, literal, filter):
1010 logger.debug("")
1011 # try:
1012 check_client_version(ctx.obj, ctx.command.name)
1013 nsi = ctx.obj.nsi.get(name)
1014 # except ClientException as e:
1015 # print(str(e))
1016 # exit(1)
1017
1018 if literal:
1019 print(yaml.safe_dump(nsi))
1020 return
1021
1022 table = PrettyTable(['field', 'value'])
1023
1024 for k, v in list(nsi.items()):
1025 if filter is None or filter in k:
1026 table.add_row([k, json.dumps(v, indent=2)])
1027
1028 table.align = 'l'
1029 print(table)
1030
1031
1032 @cli_osm.command(name='nsi-show', short_help='shows the content of a Network Slice Instance (NSI)')
1033 @click.argument('name')
1034 @click.option('--literal', is_flag=True,
1035 help='print literally, no pretty table')
1036 @click.option('--filter', default=None)
1037 @click.pass_context
1038 def nsi_show1(ctx, name, literal, filter):
1039 """shows the content of a Network Slice Instance (NSI)
1040
1041 NAME: name or ID of the Network Slice Instance
1042 """
1043 logger.debug("")
1044 nsi_show(ctx, name, literal, filter)
1045
1046
1047 @cli_osm.command(name='netslice-instance-show', short_help='shows the content of a Network Slice Instance (NSI)')
1048 @click.argument('name')
1049 @click.option('--literal', is_flag=True,
1050 help='print literally, no pretty table')
1051 @click.option('--filter', default=None)
1052 @click.pass_context
1053 def nsi_show2(ctx, name, literal, filter):
1054 """shows the content of a Network Slice Instance (NSI)
1055
1056 NAME: name or ID of the Network Slice Instance
1057 """
1058 logger.debug("")
1059 nsi_show(ctx, name, literal, filter)
1060
1061
1062 def nsi_op_show(ctx, id, filter):
1063 logger.debug("")
1064 # try:
1065 check_client_version(ctx.obj, ctx.command.name)
1066 op_info = ctx.obj.nsi.get_op(id)
1067 # except ClientException as e:
1068 # print(str(e))
1069 # exit(1)
1070
1071 table = PrettyTable(['field', 'value'])
1072 for k, v in list(op_info.items()):
1073 if filter is None or filter in k:
1074 table.add_row([k, json.dumps(v, indent=2)])
1075 table.align = 'l'
1076 print(table)
1077
1078
1079 @cli_osm.command(name='nsi-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
1080 @click.argument('id')
1081 @click.option('--filter', default=None)
1082 @click.pass_context
1083 def nsi_op_show1(ctx, id, filter):
1084 """shows the info of an operation over a Network Slice Instance(NSI)
1085
1086 ID: operation identifier
1087 """
1088 logger.debug("")
1089 nsi_op_show(ctx, id, filter)
1090
1091
1092 @cli_osm.command(name='netslice-instance-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
1093 @click.argument('id')
1094 @click.option('--filter', default=None)
1095 @click.pass_context
1096 def nsi_op_show2(ctx, id, filter):
1097 """shows the info of an operation over a Network Slice Instance(NSI)
1098
1099 ID: operation identifier
1100 """
1101 logger.debug("")
1102 nsi_op_show(ctx, id, filter)
1103
1104
1105 @cli_osm.command(name='pdu-show', short_help='shows the content of a Physical Deployment Unit (PDU)')
1106 @click.argument('name')
1107 @click.option('--literal', is_flag=True,
1108 help='print literally, no pretty table')
1109 @click.option('--filter', default=None)
1110 @click.pass_context
1111 def pdu_show(ctx, name, literal, filter):
1112 """shows the content of a Physical Deployment Unit (PDU)
1113
1114 NAME: name or ID of the PDU
1115 """
1116 logger.debug("")
1117 # try:
1118 check_client_version(ctx.obj, ctx.command.name)
1119 pdu = ctx.obj.pdu.get(name)
1120 # except ClientException as e:
1121 # print(str(e))
1122 # exit(1)
1123
1124 if literal:
1125 print(yaml.safe_dump(pdu))
1126 return
1127
1128 table = PrettyTable(['field', 'value'])
1129
1130 for k, v in list(pdu.items()):
1131 if filter is None or filter in k:
1132 table.add_row([k, json.dumps(v, indent=2)])
1133
1134 table.align = 'l'
1135 print(table)
1136
1137
1138 ####################
1139 # CREATE operations
1140 ####################
1141
1142 def nsd_create(ctx, filename, overwrite):
1143 logger.debug("")
1144 # try:
1145 check_client_version(ctx.obj, ctx.command.name)
1146 ctx.obj.nsd.create(filename, overwrite)
1147 # except ClientException as e:
1148 # print(str(e))
1149 # exit(1)
1150
1151
1152 @cli_osm.command(name='nsd-create', short_help='creates a new NSD/NSpkg')
1153 @click.argument('filename')
1154 @click.option('--overwrite', 'overwrite', default=None, # hidden=True,
1155 help='Deprecated. Use override')
1156 @click.option('--override', 'overwrite', default=None,
1157 help='overrides fields in descriptor, format: '
1158 '"key1.key2...=value[;key3...=value;...]"')
1159 @click.pass_context
1160 def nsd_create1(ctx, filename, overwrite):
1161 """creates a new NSD/NSpkg
1162
1163 FILENAME: NSD yaml file or NSpkg tar.gz file
1164 """
1165 logger.debug("")
1166 nsd_create(ctx, filename, overwrite)
1167
1168
1169 @cli_osm.command(name='nspkg-create', short_help='creates a new NSD/NSpkg')
1170 @click.argument('filename')
1171 @click.option('--overwrite', 'overwrite', default=None, # hidden=True,
1172 help='Deprecated. Use override')
1173 @click.option('--override', 'overwrite', default=None,
1174 help='overrides fields in descriptor, format: '
1175 '"key1.key2...=value[;key3...=value;...]"')
1176 @click.pass_context
1177 def nsd_create2(ctx, filename, overwrite):
1178 """creates a new NSD/NSpkg
1179
1180 FILENAME: NSD yaml file or NSpkg tar.gz file
1181 """
1182 logger.debug("")
1183 nsd_create(ctx, filename, overwrite)
1184
1185
1186 def vnfd_create(ctx, filename, overwrite):
1187 logger.debug("")
1188 # try:
1189 check_client_version(ctx.obj, ctx.command.name)
1190 ctx.obj.vnfd.create(filename, overwrite)
1191 # except ClientException as e:
1192 # print(str(e))
1193 # exit(1)
1194
1195
1196 @cli_osm.command(name='vnfd-create', short_help='creates a new VNFD/VNFpkg')
1197 @click.argument('filename')
1198 @click.option('--overwrite', 'overwrite', default=None,
1199 help='overwrite deprecated, use override')
1200 @click.option('--override', 'overwrite', default=None,
1201 help='overrides fields in descriptor, format: '
1202 '"key1.key2...=value[;key3...=value;...]"')
1203 @click.pass_context
1204 def vnfd_create1(ctx, filename, overwrite):
1205 """creates a new VNFD/VNFpkg
1206
1207 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1208 """
1209 logger.debug("")
1210 vnfd_create(ctx, filename, overwrite)
1211
1212
1213 @cli_osm.command(name='vnfpkg-create', short_help='creates a new VNFD/VNFpkg')
1214 @click.argument('filename')
1215 @click.option('--overwrite', 'overwrite', default=None, # hidden=True,
1216 help='Deprecated. Use override')
1217 @click.option('--override', 'overwrite', default=None,
1218 help='overrides fields in descriptor, format: '
1219 '"key1.key2...=value[;key3...=value;...]"')
1220 @click.pass_context
1221 def vnfd_create2(ctx, filename, overwrite):
1222 """creates a new VNFD/VNFpkg
1223
1224 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1225 """
1226 logger.debug("")
1227 vnfd_create(ctx, filename, overwrite)
1228
1229
1230 @cli_osm.command(name='nfpkg-create', short_help='creates a new NFpkg')
1231 @click.argument('filename')
1232 @click.option('--overwrite', 'overwrite', default=None, # hidden=True,
1233 help='Deprecated. Use override')
1234 @click.option('--override', 'overwrite', default=None,
1235 help='overrides fields in descriptor, format: '
1236 '"key1.key2...=value[;key3...=value;...]"')
1237 @click.pass_context
1238 def nfpkg_create(ctx, filename, overwrite):
1239 """creates a new NFpkg
1240
1241 FILENAME: NF Descriptor yaml file or NFpkg tar.gz file
1242 """
1243 logger.debug("")
1244 vnfd_create(ctx, filename, overwrite)
1245
1246
1247 @cli_osm.command(name='ns-create', short_help='creates a new Network Service instance')
1248 @click.option('--ns_name',
1249 prompt=True, help='name of the NS instance')
1250 @click.option('--nsd_name',
1251 prompt=True, help='name of the NS descriptor')
1252 @click.option('--vim_account',
1253 prompt=True, help='default VIM account id or name for the deployment')
1254 @click.option('--admin_status',
1255 default='ENABLED',
1256 help='administration status')
1257 @click.option('--ssh_keys',
1258 default=None,
1259 help='comma separated list of public key files to inject to vnfs')
1260 @click.option('--config',
1261 default=None,
1262 help='ns specific yaml configuration')
1263 @click.option('--config_file',
1264 default=None,
1265 help='ns specific yaml configuration file')
1266 @click.option('--wait',
1267 required=False,
1268 default=False,
1269 is_flag=True,
1270 help='do not return the control immediately, but keep it '
1271 'until the operation is completed, or timeout')
1272 @click.pass_context
1273 def ns_create(ctx,
1274 nsd_name,
1275 ns_name,
1276 vim_account,
1277 admin_status,
1278 ssh_keys,
1279 config,
1280 config_file,
1281 wait):
1282 """creates a new NS instance"""
1283 logger.debug("")
1284 # try:
1285 if config_file:
1286 check_client_version(ctx.obj, '--config_file')
1287 if config:
1288 raise ClientException('"--config" option is incompatible with "--config_file" option')
1289 with open(config_file, 'r') as cf:
1290 config=cf.read()
1291 ctx.obj.ns.create(
1292 nsd_name,
1293 ns_name,
1294 config=config,
1295 ssh_keys=ssh_keys,
1296 account=vim_account,
1297 wait=wait)
1298 # except ClientException as e:
1299 # print(str(e))
1300 # exit(1)
1301
1302
1303 def nst_create(ctx, filename, overwrite):
1304 logger.debug("")
1305 # try:
1306 check_client_version(ctx.obj, ctx.command.name)
1307 ctx.obj.nst.create(filename, overwrite)
1308 # except ClientException as e:
1309 # print(str(e))
1310 # exit(1)
1311
1312
1313 @cli_osm.command(name='nst-create', short_help='creates a new Network Slice Template (NST)')
1314 @click.argument('filename')
1315 @click.option('--overwrite', 'overwrite', default=None, # hidden=True,
1316 help='Deprecated. Use override')
1317 @click.option('--override', 'overwrite', default=None,
1318 help='overrides fields in descriptor, format: '
1319 '"key1.key2...=value[;key3...=value;...]"')
1320 @click.pass_context
1321 def nst_create1(ctx, filename, overwrite):
1322 """creates a new Network Slice Template (NST)
1323
1324 FILENAME: NST yaml file or NSTpkg tar.gz file
1325 """
1326 logger.debug("")
1327 nst_create(ctx, filename, overwrite)
1328
1329
1330 @cli_osm.command(name='netslice-template-create', short_help='creates a new Network Slice Template (NST)')
1331 @click.argument('filename')
1332 @click.option('--overwrite', 'overwrite', default=None, # hidden=True,
1333 help='Deprecated. Use override')
1334 @click.option('--override', 'overwrite', default=None,
1335 help='overrides fields in descriptor, format: '
1336 '"key1.key2...=value[;key3...=value;...]"')
1337 @click.pass_context
1338 def nst_create2(ctx, filename, overwrite):
1339 """creates a new Network Slice Template (NST)
1340
1341 FILENAME: NST yaml file or NSTpkg tar.gz file
1342 """
1343 logger.debug("")
1344 nst_create(ctx, filename, overwrite)
1345
1346
1347 def nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1348 """creates a new Network Slice Instance (NSI)"""
1349 logger.debug("")
1350 # try:
1351 check_client_version(ctx.obj, ctx.command.name)
1352 if config_file:
1353 if config:
1354 raise ClientException('"--config" option is incompatible with "--config_file" option')
1355 with open(config_file, 'r') as cf:
1356 config=cf.read()
1357 ctx.obj.nsi.create(nst_name, nsi_name, config=config, ssh_keys=ssh_keys,
1358 account=vim_account, wait=wait)
1359 # except ClientException as e:
1360 # print(str(e))
1361 # exit(1)
1362
1363
1364 @cli_osm.command(name='nsi-create', short_help='creates a new Network Slice Instance')
1365 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1366 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1367 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1368 @click.option('--ssh_keys', default=None,
1369 help='comma separated list of keys to inject to vnfs')
1370 @click.option('--config', default=None,
1371 help='Netslice specific yaml configuration:\n'
1372 'netslice_subnet: [\n'
1373 'id: TEXT, vim_account: TEXT,\n'
1374 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1375 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1376 'additionalParamsForNsi: {param: value, ...}\n'
1377 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1378 '],\n'
1379 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1380 )
1381 @click.option('--config_file',
1382 default=None,
1383 help='nsi specific yaml configuration file')
1384 @click.option('--wait',
1385 required=False,
1386 default=False,
1387 is_flag=True,
1388 help='do not return the control immediately, but keep it '
1389 'until the operation is completed, or timeout')
1390 @click.pass_context
1391 def nsi_create1(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1392 """creates a new Network Slice Instance (NSI)"""
1393 logger.debug("")
1394 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1395
1396
1397 @cli_osm.command(name='netslice-instance-create', short_help='creates a new Network Slice Instance')
1398 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1399 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1400 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1401 @click.option('--ssh_keys', default=None,
1402 help='comma separated list of keys to inject to vnfs')
1403 @click.option('--config', default=None,
1404 help='Netslice specific yaml configuration:\n'
1405 'netslice_subnet: [\n'
1406 'id: TEXT, vim_account: TEXT,\n'
1407 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1408 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1409 '],\n'
1410 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1411 )
1412 @click.option('--config_file',
1413 default=None,
1414 help='nsi specific yaml configuration file')
1415 @click.option('--wait',
1416 required=False,
1417 default=False,
1418 is_flag=True,
1419 help='do not return the control immediately, but keep it '
1420 'until the operation is completed, or timeout')
1421 @click.pass_context
1422 def nsi_create2(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1423 """creates a new Network Slice Instance (NSI)"""
1424 logger.debug("")
1425 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1426
1427
1428 @cli_osm.command(name='pdu-create', short_help='adds a new Physical Deployment Unit to the catalog')
1429 @click.option('--name', help='name of the Physical Deployment Unit')
1430 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1431 @click.option('--interface',
1432 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1433 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1434 multiple=True)
1435 @click.option('--description', help='human readable description')
1436 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple=True)
1437 @click.option('--descriptor_file', default=None,
1438 help='PDU descriptor file (as an alternative to using the other arguments')
1439 @click.pass_context
1440 def pdu_create(ctx, name, pdu_type, interface, description, vim_account, descriptor_file):
1441 """creates a new Physical Deployment Unit (PDU)"""
1442 logger.debug("")
1443 # try:
1444 check_client_version(ctx.obj, ctx.command.name)
1445 pdu = {}
1446 if not descriptor_file:
1447 if not name:
1448 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1449 if not pdu_type:
1450 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1451 if not interface:
1452 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1453 if not vim_account:
1454 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1455 else:
1456 with open(descriptor_file, 'r') as df:
1457 pdu = yaml.safe_load(df.read())
1458 if name: pdu["name"] = name
1459 if pdu_type: pdu["type"] = pdu_type
1460 if description: pdu["description"] = description
1461 if vim_account: pdu["vim_accounts"] = vim_account
1462 if interface:
1463 ifaces_list = []
1464 for iface in interface:
1465 new_iface={k:v for k,v in [i.split('=') for i in iface.split(',')]}
1466 new_iface["mgmt"] = (new_iface.get("mgmt","false").lower() == "true")
1467 ifaces_list.append(new_iface)
1468 pdu["interfaces"] = ifaces_list
1469 ctx.obj.pdu.create(pdu)
1470 # except ClientException as e:
1471 # print(str(e))
1472 # exit(1)
1473
1474
1475 ####################
1476 # UPDATE operations
1477 ####################
1478
1479 def nsd_update(ctx, name, content):
1480 logger.debug("")
1481 # try:
1482 check_client_version(ctx.obj, ctx.command.name)
1483 ctx.obj.nsd.update(name, content)
1484 # except ClientException as e:
1485 # print(str(e))
1486 # exit(1)
1487
1488
1489 @cli_osm.command(name='nsd-update', short_help='updates a NSD/NSpkg')
1490 @click.argument('name')
1491 @click.option('--content', default=None,
1492 help='filename with the NSD/NSpkg replacing the current one')
1493 @click.pass_context
1494 def nsd_update1(ctx, name, content):
1495 """updates a NSD/NSpkg
1496
1497 NAME: name or ID of the NSD/NSpkg
1498 """
1499 logger.debug("")
1500 nsd_update(ctx, name, content)
1501
1502
1503 @cli_osm.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
1504 @click.argument('name')
1505 @click.option('--content', default=None,
1506 help='filename with the NSD/NSpkg replacing the current one')
1507 @click.pass_context
1508 def nsd_update2(ctx, name, content):
1509 """updates a NSD/NSpkg
1510
1511 NAME: name or ID of the NSD/NSpkg
1512 """
1513 logger.debug("")
1514 nsd_update(ctx, name, content)
1515
1516
1517 def vnfd_update(ctx, name, content):
1518 logger.debug("")
1519 # try:
1520 check_client_version(ctx.obj, ctx.command.name)
1521 ctx.obj.vnfd.update(name, content)
1522 # except ClientException as e:
1523 # print(str(e))
1524 # exit(1)
1525
1526
1527 @cli_osm.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
1528 @click.argument('name')
1529 @click.option('--content', default=None,
1530 help='filename with the VNFD/VNFpkg replacing the current one')
1531 @click.pass_context
1532 def vnfd_update1(ctx, name, content):
1533 """updates a VNFD/VNFpkg
1534
1535 NAME: name or ID of the VNFD/VNFpkg
1536 """
1537 logger.debug("")
1538 vnfd_update(ctx, name, content)
1539
1540
1541 @cli_osm.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
1542 @click.argument('name')
1543 @click.option('--content', default=None,
1544 help='filename with the VNFD/VNFpkg replacing the current one')
1545 @click.pass_context
1546 def vnfd_update2(ctx, name, content):
1547 """updates a VNFD/VNFpkg
1548
1549 NAME: VNFD yaml file or VNFpkg tar.gz file
1550 """
1551 logger.debug("")
1552 vnfd_update(ctx, name, content)
1553
1554
1555 @cli_osm.command(name='nfpkg-update', short_help='updates a NFpkg')
1556 @click.argument('name')
1557 @click.option('--content', default=None,
1558 help='filename with the NFpkg replacing the current one')
1559 @click.pass_context
1560 def nfpkg_update(ctx, name, content):
1561 """updates a NFpkg
1562
1563 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1564 """
1565 logger.debug("")
1566 vnfd_update(ctx, name, content)
1567
1568
1569 def nst_update(ctx, name, content):
1570 logger.debug("")
1571 # try:
1572 check_client_version(ctx.obj, ctx.command.name)
1573 ctx.obj.nst.update(name, content)
1574 # except ClientException as e:
1575 # print(str(e))
1576 # exit(1)
1577
1578
1579 @cli_osm.command(name='nst-update', short_help='updates a Network Slice Template (NST)')
1580 @click.argument('name')
1581 @click.option('--content', default=None,
1582 help='filename with the NST/NSTpkg replacing the current one')
1583 @click.pass_context
1584 def nst_update1(ctx, name, content):
1585 """updates a Network Slice Template (NST)
1586
1587 NAME: name or ID of the NSD/NSpkg
1588 """
1589 logger.debug("")
1590 nst_update(ctx, name, content)
1591
1592
1593 @cli_osm.command(name='netslice-template-update', short_help='updates a Network Slice Template (NST)')
1594 @click.argument('name')
1595 @click.option('--content', default=None,
1596 help='filename with the NST/NSTpkg replacing the current one')
1597 @click.pass_context
1598 def nst_update2(ctx, name, content):
1599 """updates a Network Slice Template (NST)
1600
1601 NAME: name or ID of the NSD/NSpkg
1602 """
1603 logger.debug("")
1604 nst_update(ctx, name, content)
1605
1606
1607 ####################
1608 # DELETE operations
1609 ####################
1610
1611 def nsd_delete(ctx, name, force):
1612 logger.debug("")
1613 # try:
1614 if not force:
1615 ctx.obj.nsd.delete(name)
1616 else:
1617 check_client_version(ctx.obj, '--force')
1618 ctx.obj.nsd.delete(name, force)
1619 # except ClientException as e:
1620 # print(str(e))
1621 # exit(1)
1622
1623
1624 @cli_osm.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
1625 @click.argument('name')
1626 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1627 @click.pass_context
1628 def nsd_delete1(ctx, name, force):
1629 """deletes a NSD/NSpkg
1630
1631 NAME: name or ID of the NSD/NSpkg to be deleted
1632 """
1633 logger.debug("")
1634 nsd_delete(ctx, name, force)
1635
1636
1637 @cli_osm.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
1638 @click.argument('name')
1639 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1640 @click.pass_context
1641 def nsd_delete2(ctx, name, force):
1642 """deletes a NSD/NSpkg
1643
1644 NAME: name or ID of the NSD/NSpkg to be deleted
1645 """
1646 logger.debug("")
1647 nsd_delete(ctx, name, force)
1648
1649
1650 def vnfd_delete(ctx, name, force):
1651 logger.debug("")
1652 # try:
1653 if not force:
1654 ctx.obj.vnfd.delete(name)
1655 else:
1656 check_client_version(ctx.obj, '--force')
1657 ctx.obj.vnfd.delete(name, force)
1658 # except ClientException as e:
1659 # print(str(e))
1660 # exit(1)
1661
1662
1663 @cli_osm.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
1664 @click.argument('name')
1665 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1666 @click.pass_context
1667 def vnfd_delete1(ctx, name, force):
1668 """deletes a VNFD/VNFpkg
1669
1670 NAME: name or ID of the VNFD/VNFpkg to be deleted
1671 """
1672 logger.debug("")
1673 vnfd_delete(ctx, name, force)
1674
1675
1676 @cli_osm.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
1677 @click.argument('name')
1678 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1679 @click.pass_context
1680 def vnfd_delete2(ctx, name, force):
1681 """deletes a VNFD/VNFpkg
1682
1683 NAME: name or ID of the VNFD/VNFpkg to be deleted
1684 """
1685 logger.debug("")
1686 vnfd_delete(ctx, name, force)
1687
1688
1689 @cli_osm.command(name='nfpkg-delete', short_help='deletes a NFpkg')
1690 @click.argument('name')
1691 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1692 @click.pass_context
1693 def nfpkg_delete(ctx, name, force):
1694 """deletes a NFpkg
1695
1696 NAME: name or ID of the NFpkg to be deleted
1697 """
1698 logger.debug("")
1699 vnfd_delete(ctx, name, force)
1700
1701
1702 @cli_osm.command(name='ns-delete', short_help='deletes a NS instance')
1703 @click.argument('name')
1704 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1705 @click.option('--wait',
1706 required=False,
1707 default=False,
1708 is_flag=True,
1709 help='do not return the control immediately, but keep it '
1710 'until the operation is completed, or timeout')
1711 @click.pass_context
1712 def ns_delete(ctx, name, force, wait):
1713 """deletes a NS instance
1714
1715 NAME: name or ID of the NS instance to be deleted
1716 """
1717 logger.debug("")
1718 # try:
1719 if not force:
1720 ctx.obj.ns.delete(name, wait=wait)
1721 else:
1722 check_client_version(ctx.obj, '--force')
1723 ctx.obj.ns.delete(name, force, wait=wait)
1724 # except ClientException as e:
1725 # print(str(e))
1726 # exit(1)
1727
1728
1729 def nst_delete(ctx, name, force):
1730 logger.debug("")
1731 # try:
1732 check_client_version(ctx.obj, ctx.command.name)
1733 ctx.obj.nst.delete(name, force)
1734 # except ClientException as e:
1735 # print(str(e))
1736 # exit(1)
1737
1738
1739 @cli_osm.command(name='nst-delete', short_help='deletes a Network Slice Template (NST)')
1740 @click.argument('name')
1741 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1742 @click.pass_context
1743 def nst_delete1(ctx, name, force):
1744 """deletes a Network Slice Template (NST)
1745
1746 NAME: name or ID of the NST/NSTpkg to be deleted
1747 """
1748 logger.debug("")
1749 nst_delete(ctx, name, force)
1750
1751
1752 @cli_osm.command(name='netslice-template-delete', short_help='deletes a Network Slice Template (NST)')
1753 @click.argument('name')
1754 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1755 @click.pass_context
1756 def nst_delete2(ctx, name, force):
1757 """deletes a Network Slice Template (NST)
1758
1759 NAME: name or ID of the NST/NSTpkg to be deleted
1760 """
1761 logger.debug("")
1762 nst_delete(ctx, name, force)
1763
1764
1765 def nsi_delete(ctx, name, force, wait):
1766 logger.debug("")
1767 # try:
1768 check_client_version(ctx.obj, ctx.command.name)
1769 ctx.obj.nsi.delete(name, force, wait=wait)
1770 # except ClientException as e:
1771 # print(str(e))
1772 # exit(1)
1773
1774
1775 @cli_osm.command(name='nsi-delete', short_help='deletes a Network Slice Instance (NSI)')
1776 @click.argument('name')
1777 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1778 @click.option('--wait',
1779 required=False,
1780 default=False,
1781 is_flag=True,
1782 help='do not return the control immediately, but keep it '
1783 'until the operation is completed, or timeout')
1784 @click.pass_context
1785 def nsi_delete1(ctx, name, force, wait):
1786 """deletes a Network Slice Instance (NSI)
1787
1788 NAME: name or ID of the Network Slice instance to be deleted
1789 """
1790 logger.debug("")
1791 nsi_delete(ctx, name, force, wait=wait)
1792
1793
1794 @cli_osm.command(name='netslice-instance-delete', short_help='deletes a Network Slice Instance (NSI)')
1795 @click.argument('name')
1796 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1797 @click.pass_context
1798 def nsi_delete2(ctx, name, force, wait):
1799 """deletes a Network Slice Instance (NSI)
1800
1801 NAME: name or ID of the Network Slice instance to be deleted
1802 """
1803 logger.debug("")
1804 nsi_delete(ctx, name, force, wait=wait)
1805
1806
1807 @cli_osm.command(name='pdu-delete', short_help='deletes a Physical Deployment Unit (PDU)')
1808 @click.argument('name')
1809 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1810 @click.pass_context
1811 def pdu_delete(ctx, name, force):
1812 """deletes a Physical Deployment Unit (PDU)
1813
1814 NAME: name or ID of the PDU to be deleted
1815 """
1816 logger.debug("")
1817 # try:
1818 check_client_version(ctx.obj, ctx.command.name)
1819 ctx.obj.pdu.delete(name, force)
1820 # except ClientException as e:
1821 # print(str(e))
1822 # exit(1)
1823
1824
1825 #################
1826 # VIM operations
1827 #################
1828
1829 @cli_osm.command(name='vim-create', short_help='creates a new VIM account')
1830 @click.option('--name',
1831 prompt=True,
1832 help='Name to create datacenter')
1833 @click.option('--user',
1834 prompt=True,
1835 help='VIM username')
1836 @click.option('--password',
1837 prompt=True,
1838 hide_input=True,
1839 confirmation_prompt=True,
1840 help='VIM password')
1841 @click.option('--auth_url',
1842 prompt=True,
1843 help='VIM url')
1844 @click.option('--tenant',
1845 prompt=True,
1846 help='VIM tenant name')
1847 @click.option('--config',
1848 default=None,
1849 help='VIM specific config parameters')
1850 @click.option('--account_type',
1851 default='openstack',
1852 help='VIM type')
1853 @click.option('--description',
1854 default='no description',
1855 help='human readable description')
1856 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1857 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1858 @click.option('--wait',
1859 required=False,
1860 default=False,
1861 is_flag=True,
1862 help='do not return the control immediately, but keep it '
1863 'until the operation is completed, or timeout')
1864 @click.pass_context
1865 def vim_create(ctx,
1866 name,
1867 user,
1868 password,
1869 auth_url,
1870 tenant,
1871 config,
1872 account_type,
1873 description,
1874 sdn_controller,
1875 sdn_port_mapping,
1876 wait):
1877 """creates a new VIM account"""
1878 logger.debug("")
1879 # try:
1880 if sdn_controller:
1881 check_client_version(ctx.obj, '--sdn_controller')
1882 if sdn_port_mapping:
1883 check_client_version(ctx.obj, '--sdn_port_mapping')
1884 vim = {}
1885 vim['vim-username'] = user
1886 vim['vim-password'] = password
1887 vim['vim-url'] = auth_url
1888 vim['vim-tenant-name'] = tenant
1889 vim['vim-type'] = account_type
1890 vim['description'] = description
1891 vim['config'] = config
1892 if sdn_controller or sdn_port_mapping:
1893 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1894 else:
1895 ctx.obj.vim.create(name, vim, wait=wait)
1896 # except ClientException as e:
1897 # print(str(e))
1898 # exit(1)
1899
1900
1901 @cli_osm.command(name='vim-update', short_help='updates a VIM account')
1902 @click.argument('name')
1903 @click.option('--newname', help='New name for the VIM account')
1904 @click.option('--user', help='VIM username')
1905 @click.option('--password', help='VIM password')
1906 @click.option('--auth_url', help='VIM url')
1907 @click.option('--tenant', help='VIM tenant name')
1908 @click.option('--config', help='VIM specific config parameters')
1909 @click.option('--account_type', help='VIM type')
1910 @click.option('--description', help='human readable description')
1911 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1912 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1913 @click.option('--wait',
1914 required=False,
1915 default=False,
1916 is_flag=True,
1917 help='do not return the control immediately, but keep it '
1918 'until the operation is completed, or timeout')
1919 @click.pass_context
1920 def vim_update(ctx,
1921 name,
1922 newname,
1923 user,
1924 password,
1925 auth_url,
1926 tenant,
1927 config,
1928 account_type,
1929 description,
1930 sdn_controller,
1931 sdn_port_mapping,
1932 wait):
1933 """updates a VIM account
1934
1935 NAME: name or ID of the VIM account
1936 """
1937 logger.debug("")
1938 # try:
1939 check_client_version(ctx.obj, ctx.command.name)
1940 vim = {}
1941 if newname: vim['name'] = newname
1942 if user: vim['vim_user'] = user
1943 if password: vim['vim_password'] = password
1944 if auth_url: vim['vim_url'] = auth_url
1945 if tenant: vim['vim-tenant-name'] = tenant
1946 if account_type: vim['vim_type'] = account_type
1947 if description: vim['description'] = description
1948 if config: vim['config'] = config
1949 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1950 # except ClientException as e:
1951 # print(str(e))
1952 # exit(1)
1953
1954
1955 @cli_osm.command(name='vim-delete', short_help='deletes a VIM account')
1956 @click.argument('name')
1957 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1958 @click.option('--wait',
1959 required=False,
1960 default=False,
1961 is_flag=True,
1962 help='do not return the control immediately, but keep it '
1963 'until the operation is completed, or timeout')
1964 @click.pass_context
1965 def vim_delete(ctx, name, force, wait):
1966 """deletes a VIM account
1967
1968 NAME: name or ID of the VIM account to be deleted
1969 """
1970 logger.debug("")
1971 # try:
1972 if not force:
1973 ctx.obj.vim.delete(name, wait=wait)
1974 else:
1975 check_client_version(ctx.obj, '--force')
1976 ctx.obj.vim.delete(name, force, wait=wait)
1977 # except ClientException as e:
1978 # print(str(e))
1979 # exit(1)
1980
1981
1982 @cli_osm.command(name='vim-list', short_help='list all VIM accounts')
1983 #@click.option('--ro_update/--no_ro_update',
1984 # default=False,
1985 # help='update list from RO')
1986 @click.option('--filter', default=None,
1987 help='restricts the list to the VIM accounts matching the filter')
1988 @click.pass_context
1989 def vim_list(ctx, filter):
1990 """list all VIM accounts"""
1991 logger.debug("")
1992 if filter:
1993 check_client_version(ctx.obj, '--filter')
1994 # if ro_update:
1995 # check_client_version(ctx.obj, '--ro_update', 'v1')
1996 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1997 if fullclassname == 'osmclient.sol005.client.Client':
1998 resp = ctx.obj.vim.list(filter)
1999 # else:
2000 # resp = ctx.obj.vim.list(ro_update)
2001 table = PrettyTable(['vim name', 'uuid'])
2002 for vim in resp:
2003 table.add_row([vim['name'], vim['uuid']])
2004 table.align = 'l'
2005 print(table)
2006
2007
2008 @cli_osm.command(name='vim-show', short_help='shows the details of a VIM account')
2009 @click.argument('name')
2010 @click.pass_context
2011 def vim_show(ctx, name):
2012 """shows the details of a VIM account
2013
2014 NAME: name or ID of the VIM account
2015 """
2016 logger.debug("")
2017 # try:
2018 resp = ctx.obj.vim.get(name)
2019 if 'vim_password' in resp:
2020 resp['vim_password']='********'
2021 # except ClientException as e:
2022 # print(str(e))
2023 # exit(1)
2024
2025 table = PrettyTable(['key', 'attribute'])
2026 for k, v in list(resp.items()):
2027 table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
2028 table.align = 'l'
2029 print(table)
2030
2031
2032 ####################
2033 # WIM operations
2034 ####################
2035
2036 @cli_osm.command(name='wim-create', short_help='creates a new WIM account')
2037 @click.option('--name',
2038 prompt=True,
2039 help='Name for the WIM account')
2040 @click.option('--user',
2041 help='WIM username')
2042 @click.option('--password',
2043 help='WIM password')
2044 @click.option('--url',
2045 prompt=True,
2046 help='WIM url')
2047 # @click.option('--tenant',
2048 # help='wIM tenant name')
2049 @click.option('--config',
2050 default=None,
2051 help='WIM specific config parameters')
2052 @click.option('--wim_type',
2053 help='WIM type')
2054 @click.option('--description',
2055 default='no description',
2056 help='human readable description')
2057 @click.option('--wim_port_mapping', default=None,
2058 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2059 "(WAN service endpoint id and info)")
2060 @click.option('--wait',
2061 required=False,
2062 default=False,
2063 is_flag=True,
2064 help='do not return the control immediately, but keep it '
2065 'until the operation is completed, or timeout')
2066 @click.pass_context
2067 def wim_create(ctx,
2068 name,
2069 user,
2070 password,
2071 url,
2072 # tenant,
2073 config,
2074 wim_type,
2075 description,
2076 wim_port_mapping,
2077 wait):
2078 """creates a new WIM account"""
2079 logger.debug("")
2080 # try:
2081 check_client_version(ctx.obj, ctx.command.name)
2082 # if sdn_controller:
2083 # check_client_version(ctx.obj, '--sdn_controller')
2084 # if sdn_port_mapping:
2085 # check_client_version(ctx.obj, '--sdn_port_mapping')
2086 wim = {}
2087 if user: wim['user'] = user
2088 if password: wim['password'] = password
2089 if url: wim['wim_url'] = url
2090 # if tenant: wim['tenant'] = tenant
2091 wim['wim_type'] = wim_type
2092 if description: wim['description'] = description
2093 if config: wim['config'] = config
2094 ctx.obj.wim.create(name, wim, wim_port_mapping, wait=wait)
2095 # except ClientException as e:
2096 # print(str(e))
2097 # exit(1)
2098
2099
2100 @cli_osm.command(name='wim-update', short_help='updates a WIM account')
2101 @click.argument('name')
2102 @click.option('--newname', help='New name for the WIM account')
2103 @click.option('--user', help='WIM username')
2104 @click.option('--password', help='WIM password')
2105 @click.option('--url', help='WIM url')
2106 @click.option('--config', help='WIM specific config parameters')
2107 @click.option('--wim_type', help='WIM type')
2108 @click.option('--description', help='human readable description')
2109 @click.option('--wim_port_mapping', default=None,
2110 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2111 "(WAN service endpoint id and info)")
2112 @click.option('--wait',
2113 required=False,
2114 default=False,
2115 is_flag=True,
2116 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2117 @click.pass_context
2118 def wim_update(ctx,
2119 name,
2120 newname,
2121 user,
2122 password,
2123 url,
2124 config,
2125 wim_type,
2126 description,
2127 wim_port_mapping,
2128 wait):
2129 """updates a WIM account
2130
2131 NAME: name or ID of the WIM account
2132 """
2133 logger.debug("")
2134 # try:
2135 check_client_version(ctx.obj, ctx.command.name)
2136 wim = {}
2137 if newname: wim['name'] = newname
2138 if user: wim['user'] = user
2139 if password: wim['password'] = password
2140 if url: wim['url'] = url
2141 # if tenant: wim['tenant'] = tenant
2142 if wim_type: wim['wim_type'] = wim_type
2143 if description: wim['description'] = description
2144 if config: wim['config'] = config
2145 ctx.obj.wim.update(name, wim, wim_port_mapping, wait=wait)
2146 # except ClientException as e:
2147 # print(str(e))
2148 # exit(1)
2149
2150
2151 @cli_osm.command(name='wim-delete', short_help='deletes a WIM account')
2152 @click.argument('name')
2153 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2154 @click.option('--wait',
2155 required=False,
2156 default=False,
2157 is_flag=True,
2158 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2159 @click.pass_context
2160 def wim_delete(ctx, name, force, wait):
2161 """deletes a WIM account
2162
2163 NAME: name or ID of the WIM account to be deleted
2164 """
2165 logger.debug("")
2166 # try:
2167 check_client_version(ctx.obj, ctx.command.name)
2168 ctx.obj.wim.delete(name, force, wait=wait)
2169 # except ClientException as e:
2170 # print(str(e))
2171 # exit(1)
2172
2173
2174 @cli_osm.command(name='wim-list', short_help='list all WIM accounts')
2175 @click.option('--filter', default=None,
2176 help='restricts the list to the WIM accounts matching the filter')
2177 @click.pass_context
2178 def wim_list(ctx, filter):
2179 """list all WIM accounts"""
2180 logger.debug("")
2181 # try:
2182 check_client_version(ctx.obj, ctx.command.name)
2183 resp = ctx.obj.wim.list(filter)
2184 table = PrettyTable(['wim name', 'uuid'])
2185 for wim in resp:
2186 table.add_row([wim['name'], wim['uuid']])
2187 table.align = 'l'
2188 print(table)
2189 # except ClientException as e:
2190 # print(str(e))
2191 # exit(1)
2192
2193
2194 @cli_osm.command(name='wim-show', short_help='shows the details of a WIM account')
2195 @click.argument('name')
2196 @click.pass_context
2197 def wim_show(ctx, name):
2198 """shows the details of a WIM account
2199
2200 NAME: name or ID of the WIM account
2201 """
2202 logger.debug("")
2203 # try:
2204 check_client_version(ctx.obj, ctx.command.name)
2205 resp = ctx.obj.wim.get(name)
2206 if 'password' in resp:
2207 resp['wim_password']='********'
2208 # except ClientException as e:
2209 # print(str(e))
2210 # exit(1)
2211
2212 table = PrettyTable(['key', 'attribute'])
2213 for k, v in list(resp.items()):
2214 table.add_row([k, json.dumps(v, indent=2)])
2215 table.align = 'l'
2216 print(table)
2217
2218
2219 ####################
2220 # SDN controller operations
2221 ####################
2222
2223 @cli_osm.command(name='sdnc-create', short_help='creates a new SDN controller')
2224 @click.option('--name',
2225 prompt=True,
2226 help='Name to create sdn controller')
2227 @click.option('--type',
2228 prompt=True,
2229 help='SDN controller type')
2230 @click.option('--sdn_controller_version', # hidden=True,
2231 help='Deprecated. Use --config {version: sdn_controller_version}')
2232 @click.option('--url',
2233 help='URL in format http[s]://HOST:IP/')
2234 @click.option('--ip_address', # hidden=True,
2235 help='Deprecated. Use --url')
2236 @click.option('--port', # hidden=True,
2237 help='Deprecated. Use --url')
2238 @click.option('--switch_dpid', # hidden=True,
2239 help='Deprecated. Use --config {dpid: DPID}')
2240 @click.option('--config',
2241 help='Extra information for SDN in yaml format, as {dpid: (Openflow Datapath ID), version: version}')
2242 @click.option('--user',
2243 help='SDN controller username')
2244 @click.option('--password',
2245 hide_input=True,
2246 confirmation_prompt=True,
2247 help='SDN controller password')
2248 @click.option('--description', default=None, help='human readable description')
2249 @click.option('--wait',
2250 required=False,
2251 default=False,
2252 is_flag=True,
2253 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2254 @click.pass_context
2255 def sdnc_create(ctx, **kwargs):
2256 """creates a new SDN controller"""
2257 logger.debug("")
2258 sdncontroller = {x: kwargs[x] for x in kwargs if kwargs[x] and
2259 x not in ("wait", "ip_address", "port", "switch_dpid")}
2260 if kwargs.get("port"):
2261 print("option '--port' is deprecated, use '-url' instead")
2262 sdncontroller["port"] = int(kwargs["port"])
2263 if kwargs.get("ip_address"):
2264 print("option '--ip_address' is deprecated, use '-url' instead")
2265 sdncontroller["ip"] = kwargs["ip_address"]
2266 if kwargs.get("switch_dpid"):
2267 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2268 sdncontroller["dpid"] = kwargs["switch_dpid"]
2269 if kwargs.get("sdn_controller_version"):
2270 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2271 " instead")
2272 # try:
2273 check_client_version(ctx.obj, ctx.command.name)
2274 ctx.obj.sdnc.create(kwargs["name"], sdncontroller, wait=kwargs["wait"])
2275 # except ClientException as e:
2276 # print(str(e))
2277 # exit(1)
2278
2279 @cli_osm.command(name='sdnc-update', short_help='updates an SDN controller')
2280 @click.argument('name')
2281 @click.option('--newname', help='New name for the SDN controller')
2282 @click.option('--description', default=None, help='human readable description')
2283 @click.option('--type', help='SDN controller type')
2284 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2285 @click.option('--config', help='Extra information for SDN in yaml format, as '
2286 '{dpid: (Openflow Datapath ID), version: version}')
2287 @click.option('--user', help='SDN controller username')
2288 @click.option('--password', help='SDN controller password')
2289 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2290 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2291 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2292 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2293 @click.option('--wait', required=False, default=False, is_flag=True,
2294 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2295 @click.pass_context
2296 def sdnc_update(ctx, **kwargs):
2297 """updates an SDN controller
2298
2299 NAME: name or ID of the SDN controller
2300 """
2301 logger.debug("")
2302 sdncontroller = {x: kwargs[x] for x in kwargs if kwargs[x] and
2303 x not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2304 if kwargs.get("newname"):
2305 sdncontroller["name"] = kwargs["newname"]
2306 if kwargs.get("port"):
2307 print("option '--port' is deprecated, use '-url' instead")
2308 sdncontroller["port"] = int(kwargs["port"])
2309 if kwargs.get("ip_address"):
2310 print("option '--ip_address' is deprecated, use '-url' instead")
2311 sdncontroller["ip"] = kwargs["ip_address"]
2312 if kwargs.get("switch_dpid"):
2313 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2314 sdncontroller["dpid"] = kwargs["switch_dpid"]
2315 if kwargs.get("sdn_controller_version"):
2316 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2317 " instead")
2318
2319 # try:
2320 check_client_version(ctx.obj, ctx.command.name)
2321 ctx.obj.sdnc.update(kwargs["name"], sdncontroller, wait=kwargs["wait"])
2322 # except ClientException as e:
2323 # print(str(e))
2324 # exit(1)
2325
2326
2327 @cli_osm.command(name='sdnc-delete', short_help='deletes an SDN controller')
2328 @click.argument('name')
2329 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2330 @click.option('--wait', required=False, default=False, is_flag=True,
2331 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2332 @click.pass_context
2333 def sdnc_delete(ctx, name, force, wait):
2334 """deletes an SDN controller
2335
2336 NAME: name or ID of the SDN controller to be deleted
2337 """
2338 logger.debug("")
2339 # try:
2340 check_client_version(ctx.obj, ctx.command.name)
2341 ctx.obj.sdnc.delete(name, force, wait=wait)
2342 # except ClientException as e:
2343 # print(str(e))
2344 # exit(1)
2345
2346
2347 @cli_osm.command(name='sdnc-list', short_help='list all SDN controllers')
2348 @click.option('--filter', default=None,
2349 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2350 @click.pass_context
2351 def sdnc_list(ctx, filter):
2352 """list all SDN controllers"""
2353 logger.debug("")
2354 # try:
2355 check_client_version(ctx.obj, ctx.command.name)
2356 resp = ctx.obj.sdnc.list(filter)
2357 # except ClientException as e:
2358 # print(str(e))
2359 # exit(1)
2360 table = PrettyTable(['sdnc name', 'id'])
2361 for sdnc in resp:
2362 table.add_row([sdnc['name'], sdnc['_id']])
2363 table.align = 'l'
2364 print(table)
2365
2366
2367 @cli_osm.command(name='sdnc-show', short_help='shows the details of an SDN controller')
2368 @click.argument('name')
2369 @click.pass_context
2370 def sdnc_show(ctx, name):
2371 """shows the details of an SDN controller
2372
2373 NAME: name or ID of the SDN controller
2374 """
2375 logger.debug("")
2376 # try:
2377 check_client_version(ctx.obj, ctx.command.name)
2378 resp = ctx.obj.sdnc.get(name)
2379 # except ClientException as e:
2380 # print(str(e))
2381 # exit(1)
2382
2383 table = PrettyTable(['key', 'attribute'])
2384 for k, v in list(resp.items()):
2385 table.add_row([k, json.dumps(v, indent=2)])
2386 table.align = 'l'
2387 print(table)
2388
2389
2390 ###########################
2391 # K8s cluster operations
2392 ###########################
2393
2394 @cli_osm.command(name='k8scluster-add')
2395 @click.argument('name')
2396 @click.option('--creds',
2397 prompt=True,
2398 help='credentials file, i.e. a valid `.kube/config` file')
2399 @click.option('--version',
2400 prompt=True,
2401 help='Kubernetes version')
2402 @click.option('--vim',
2403 prompt=True,
2404 help='VIM target, the VIM where the cluster resides')
2405 @click.option('--k8s-nets',
2406 prompt=True,
2407 help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"')
2408 @click.option('--description',
2409 default='',
2410 help='human readable description')
2411 @click.option('--namespace',
2412 default='kube-system',
2413 help='namespace to be used for its operation, defaults to `kube-system`')
2414 @click.option('--cni',
2415 default=None,
2416 help='list of CNI plugins, in JSON inline format, used in the cluster')
2417 #@click.option('--skip-init',
2418 # is_flag=True,
2419 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2420 #@click.option('--wait',
2421 # is_flag=True,
2422 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2423 @click.pass_context
2424 def k8scluster_add(ctx,
2425 name,
2426 creds,
2427 version,
2428 vim,
2429 k8s_nets,
2430 description,
2431 namespace,
2432 cni):
2433 """adds a K8s cluster to OSM
2434
2435 NAME: name of the K8s cluster
2436 """
2437 # try:
2438 check_client_version(ctx.obj, ctx.command.name)
2439 cluster = {}
2440 cluster['name'] = name
2441 with open(creds, 'r') as cf:
2442 cluster['credentials'] = yaml.safe_load(cf.read())
2443 cluster['k8s_version'] = version
2444 cluster['vim_account'] = vim
2445 cluster['nets'] = yaml.safe_load(k8s_nets)
2446 cluster['description'] = description
2447 if namespace: cluster['namespace'] = namespace
2448 if cni: cluster['cni'] = yaml.safe_load(cni)
2449 ctx.obj.k8scluster.create(name, cluster)
2450 # except ClientException as e:
2451 # print(str(e))
2452 # exit(1)
2453
2454
2455 @cli_osm.command(name='k8scluster-update', short_help='updates a K8s cluster')
2456 @click.argument('name')
2457 @click.option('--newname', help='New name for the K8s cluster')
2458 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
2459 @click.option('--version', help='Kubernetes version')
2460 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
2461 @click.option('--k8s-nets', help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"')
2462 @click.option('--description', help='human readable description')
2463 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
2464 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
2465 @click.pass_context
2466 def k8scluster_update(ctx,
2467 name,
2468 newname,
2469 creds,
2470 version,
2471 vim,
2472 k8s_nets,
2473 description,
2474 namespace,
2475 cni):
2476 """updates a K8s cluster
2477
2478 NAME: name or ID of the K8s cluster
2479 """
2480 # try:
2481 check_client_version(ctx.obj, ctx.command.name)
2482 cluster = {}
2483 if newname: cluster['name'] = newname
2484 if creds:
2485 with open(creds, 'r') as cf:
2486 cluster['credentials'] = yaml.safe_load(cf.read())
2487 if version: cluster['k8s_version'] = version
2488 if vim: cluster['vim_account'] = vim
2489 if k8s_nets: cluster['nets'] = yaml.safe_load(k8s_nets)
2490 if description: cluster['description'] = description
2491 if namespace: cluster['namespace'] = namespace
2492 if cni: cluster['cni'] = yaml.safe_load(cni)
2493 ctx.obj.k8scluster.update(name, cluster)
2494 # except ClientException as e:
2495 # print(str(e))
2496 # exit(1)
2497
2498
2499 @cli_osm.command(name='k8scluster-delete')
2500 @click.argument('name')
2501 @click.option('--force', is_flag=True, help='forces the deletion from the DB (not recommended)')
2502 #@click.option('--wait',
2503 # is_flag=True,
2504 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2505 @click.pass_context
2506 def k8scluster_delete(ctx, name, force):
2507 """deletes a K8s cluster
2508
2509 NAME: name or ID of the K8s cluster to be deleted
2510 """
2511 # try:
2512 check_client_version(ctx.obj, ctx.command.name)
2513 ctx.obj.k8scluster.delete(name, force=force)
2514 # except ClientException as e:
2515 # print(str(e))
2516 # exit(1)
2517
2518
2519 @cli_osm.command(name='k8scluster-list')
2520 @click.option('--filter', default=None,
2521 help='restricts the list to the K8s clusters matching the filter')
2522 @click.option('--literal', is_flag=True,
2523 help='print literally, no pretty table')
2524 @click.pass_context
2525 def k8scluster_list(ctx, filter, literal):
2526 """list all K8s clusters"""
2527 # try:
2528 check_client_version(ctx.obj, ctx.command.name)
2529 resp = ctx.obj.k8scluster.list(filter)
2530 if literal:
2531 print(yaml.safe_dump(resp))
2532 return
2533 table = PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
2534 for cluster in resp:
2535 table.add_row([cluster['name'], cluster['_id'], cluster['k8s_version'], cluster['vim_account'],
2536 json.dumps(cluster['nets']), cluster["_admin"]["operationalState"],
2537 trunc_text(cluster.get('description',''),40)])
2538 table.align = 'l'
2539 print(table)
2540 # except ClientException as e:
2541 # print(str(e))
2542 # exit(1)
2543
2544
2545 @cli_osm.command(name='k8scluster-show')
2546 @click.argument('name')
2547 @click.option('--literal', is_flag=True,
2548 help='print literally, no pretty table')
2549 @click.pass_context
2550 def k8scluster_show(ctx, name, literal):
2551 """shows the details of a K8s cluster
2552
2553 NAME: name or ID of the K8s cluster
2554 """
2555 # try:
2556 resp = ctx.obj.k8scluster.get(name)
2557 if literal:
2558 print(yaml.safe_dump(resp))
2559 return
2560 table = PrettyTable(['key', 'attribute'])
2561 for k, v in list(resp.items()):
2562 table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
2563 table.align = 'l'
2564 print(table)
2565 # except ClientException as e:
2566 # print(str(e))
2567 # exit(1)
2568
2569
2570
2571 ###########################
2572 # Repo operations
2573 ###########################
2574
2575 @cli_osm.command(name='repo-add')
2576 @click.argument('name')
2577 @click.argument('uri')
2578 @click.option('--type',
2579 type=click.Choice(['helm-chart', 'juju-bundle']),
2580 prompt=True,
2581 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2582 @click.option('--description',
2583 default='',
2584 help='human readable description')
2585 #@click.option('--wait',
2586 # is_flag=True,
2587 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2588 @click.pass_context
2589 def repo_add(ctx,
2590 name,
2591 uri,
2592 type,
2593 description):
2594 """adds a repo to OSM
2595
2596 NAME: name of the repo
2597 URI: URI of the repo
2598 """
2599 # try:
2600 check_client_version(ctx.obj, ctx.command.name)
2601 repo = {}
2602 repo['name'] = name
2603 repo['url'] = uri
2604 repo['type'] = type
2605 repo['description'] = description
2606 ctx.obj.repo.create(name, repo)
2607 # except ClientException as e:
2608 # print(str(e))
2609 # exit(1)
2610
2611
2612 @cli_osm.command(name='repo-update')
2613 @click.argument('name')
2614 @click.option('--newname', help='New name for the repo')
2615 @click.option('--uri', help='URI of the repo')
2616 @click.option('--type', type=click.Choice(['helm-chart', 'juju-bundle']),
2617 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2618 @click.option('--description', help='human readable description')
2619 #@click.option('--wait',
2620 # is_flag=True,
2621 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2622 @click.pass_context
2623 def repo_update(ctx,
2624 name,
2625 newname,
2626 uri,
2627 type,
2628 description):
2629 """updates a repo in OSM
2630
2631 NAME: name of the repo
2632 """
2633 # try:
2634 check_client_version(ctx.obj, ctx.command.name)
2635 repo = {}
2636 if newname: repo['name'] = newname
2637 if uri: repo['uri'] = uri
2638 if type: repo['type'] = type
2639 if description: repo['description'] = description
2640 ctx.obj.repo.update(name, repo)
2641 # except ClientException as e:
2642 # print(str(e))
2643 # exit(1)
2644
2645
2646 @cli_osm.command(name='repo-delete')
2647 @click.argument('name')
2648 @click.option('--force', is_flag=True, help='forces the deletion from the DB (not recommended)')
2649 #@click.option('--wait',
2650 # is_flag=True,
2651 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2652 @click.pass_context
2653 def repo_delete(ctx, name, force):
2654 """deletes a repo
2655
2656 NAME: name or ID of the repo to be deleted
2657 """
2658 # try:
2659 check_client_version(ctx.obj, ctx.command.name)
2660 ctx.obj.repo.delete(name, force=force)
2661 # except ClientException as e:
2662 # print(str(e))
2663 # exit(1)
2664
2665
2666 @cli_osm.command(name='repo-list')
2667 @click.option('--filter', default=None,
2668 help='restricts the list to the repos matching the filter')
2669 @click.option('--literal', is_flag=True,
2670 help='print literally, no pretty table')
2671 @click.pass_context
2672 def repo_list(ctx, filter, literal):
2673 """list all repos"""
2674 # try:
2675 check_client_version(ctx.obj, ctx.command.name)
2676 resp = ctx.obj.repo.list(filter)
2677 if literal:
2678 print(yaml.safe_dump(resp))
2679 return
2680 table = PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
2681 for repo in resp:
2682 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
2683 table.add_row([repo['name'], repo['_id'], repo['type'], repo['url'], trunc_text(repo.get('description',''),40)])
2684 table.align = 'l'
2685 print(table)
2686 # except ClientException as e:
2687 # print(str(e))
2688 # exit(1)
2689
2690
2691 @cli_osm.command(name='repo-show')
2692 @click.argument('name')
2693 @click.option('--literal', is_flag=True,
2694 help='print literally, no pretty table')
2695 @click.pass_context
2696 def repo_show(ctx, name, literal):
2697 """shows the details of a repo
2698
2699 NAME: name or ID of the repo
2700 """
2701 # try:
2702 resp = ctx.obj.repo.get(name)
2703 if literal:
2704 print(yaml.safe_dump(resp))
2705 return
2706 table = PrettyTable(['key', 'attribute'])
2707 for k, v in list(resp.items()):
2708 table.add_row([k, json.dumps(v, indent=2)])
2709 table.align = 'l'
2710 print(table)
2711 # except ClientException as e:
2712 # print(str(e))
2713 # exit(1)
2714
2715
2716
2717 ####################
2718 # Project mgmt operations
2719 ####################
2720
2721 @cli_osm.command(name='project-create', short_help='creates a new project')
2722 @click.argument('name')
2723 #@click.option('--description',
2724 # default='no description',
2725 # help='human readable description')
2726 @click.pass_context
2727 def project_create(ctx, name):
2728 """Creates a new project
2729
2730 NAME: name of the project
2731 """
2732 logger.debug("")
2733 project = {}
2734 project['name'] = name
2735 # try:
2736 check_client_version(ctx.obj, ctx.command.name)
2737 ctx.obj.project.create(name, project)
2738 # except ClientException as e:
2739 # print(str(e))
2740 # exit(1)
2741
2742
2743 @cli_osm.command(name='project-delete', short_help='deletes a project')
2744 @click.argument('name')
2745 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2746 @click.pass_context
2747 def project_delete(ctx, name):
2748 """deletes a project
2749
2750 NAME: name or ID of the project to be deleted
2751 """
2752 logger.debug("")
2753 # try:
2754 check_client_version(ctx.obj, ctx.command.name)
2755 ctx.obj.project.delete(name)
2756 # except ClientException as e:
2757 # print(str(e))
2758 # exit(1)
2759
2760
2761 @cli_osm.command(name='project-list', short_help='list all projects')
2762 @click.option('--filter', default=None,
2763 help='restricts the list to the projects matching the filter')
2764 @click.pass_context
2765 def project_list(ctx, filter):
2766 """list all projects"""
2767 logger.debug("")
2768 # try:
2769 check_client_version(ctx.obj, ctx.command.name)
2770 resp = ctx.obj.project.list(filter)
2771 # except ClientException as e:
2772 # print(str(e))
2773 # exit(1)
2774 table = PrettyTable(['name', 'id'])
2775 for proj in resp:
2776 table.add_row([proj['name'], proj['_id']])
2777 table.align = 'l'
2778 print(table)
2779
2780
2781 @cli_osm.command(name='project-show', short_help='shows the details of a project')
2782 @click.argument('name')
2783 @click.pass_context
2784 def project_show(ctx, name):
2785 """shows the details of a project
2786
2787 NAME: name or ID of the project
2788 """
2789 logger.debug("")
2790 # try:
2791 check_client_version(ctx.obj, ctx.command.name)
2792 resp = ctx.obj.project.get(name)
2793 # except ClientException as e:
2794 # print(str(e))
2795 # exit(1)
2796
2797 table = PrettyTable(['key', 'attribute'])
2798 for k, v in resp.items():
2799 table.add_row([k, json.dumps(v, indent=2)])
2800 table.align = 'l'
2801 print(table)
2802
2803
2804 @cli_osm.command(name='project-update', short_help='updates a project (only the name can be updated)')
2805 @click.argument('project')
2806 @click.option('--name',
2807 prompt=True,
2808 help='new name for the project')
2809
2810 @click.pass_context
2811 def project_update(ctx, project, name):
2812 """
2813 Update a project name
2814
2815 :param ctx:
2816 :param project: id or name of the project to modify
2817 :param name: new name for the project
2818 :return:
2819 """
2820 logger.debug("")
2821 project_changes = {}
2822 project_changes['name'] = name
2823
2824 # try:
2825 check_client_version(ctx.obj, ctx.command.name)
2826 ctx.obj.project.update(project, project_changes)
2827 # except ClientException as e:
2828 # print(str(e))
2829
2830
2831 ####################
2832 # User mgmt operations
2833 ####################
2834
2835 @cli_osm.command(name='user-create', short_help='creates a new user')
2836 @click.argument('username')
2837 @click.option('--password',
2838 prompt=True,
2839 hide_input=True,
2840 confirmation_prompt=True,
2841 help='user password')
2842 @click.option('--projects',
2843 # prompt="Comma separate list of projects",
2844 multiple=True,
2845 callback=lambda ctx, param, value: ''.join(value).split(',') if all(len(x)==1 for x in value) else value,
2846 help='list of project ids that the user belongs to')
2847 @click.option('--project-role-mappings', 'project_role_mappings',
2848 default=None, multiple=True,
2849 help='creating user project/role(s) mapping')
2850 @click.pass_context
2851 def user_create(ctx, username, password, projects, project_role_mappings):
2852 """Creates a new user
2853
2854 \b
2855 USERNAME: name of the user
2856 PASSWORD: password of the user
2857 PROJECTS: projects assigned to user (internal only)
2858 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
2859 """
2860 logger.debug("")
2861 user = {}
2862 user['username'] = username
2863 user['password'] = password
2864 user['projects'] = projects
2865 user['project_role_mappings'] = project_role_mappings
2866
2867 # try:
2868 check_client_version(ctx.obj, ctx.command.name)
2869 ctx.obj.user.create(username, user)
2870 # except ClientException as e:
2871 # print(str(e))
2872 # exit(1)
2873
2874
2875 @cli_osm.command(name='user-update', short_help='updates user information')
2876 @click.argument('username')
2877 @click.option('--password',
2878 # prompt=True,
2879 # hide_input=True,
2880 # confirmation_prompt=True,
2881 help='user password')
2882 @click.option('--set-username', 'set_username',
2883 default=None,
2884 help='change username')
2885 @click.option('--set-project', 'set_project',
2886 default=None, multiple=True,
2887 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
2888 @click.option('--remove-project', 'remove_project',
2889 default=None, multiple=True,
2890 help='removes project from user: \'project\'')
2891 @click.option('--add-project-role', 'add_project_role',
2892 default=None, multiple=True,
2893 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
2894 @click.option('--remove-project-role', 'remove_project_role',
2895 default=None, multiple=True,
2896 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
2897 @click.pass_context
2898 def user_update(ctx, username, password, set_username, set_project, remove_project,
2899 add_project_role, remove_project_role):
2900 """Update a user information
2901
2902 \b
2903 USERNAME: name of the user
2904 PASSWORD: new password
2905 SET_USERNAME: new username
2906 SET_PROJECT: creating mappings for project/role(s)
2907 REMOVE_PROJECT: deleting mappings for project/role(s)
2908 ADD_PROJECT_ROLE: adding mappings for project/role(s)
2909 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
2910 """
2911 logger.debug("")
2912 user = {}
2913 user['password'] = password
2914 user['username'] = set_username
2915 user['set-project'] = set_project
2916 user['remove-project'] = remove_project
2917 user['add-project-role'] = add_project_role
2918 user['remove-project-role'] = remove_project_role
2919
2920 # try:
2921 check_client_version(ctx.obj, ctx.command.name)
2922 ctx.obj.user.update(username, user)
2923 # except ClientException as e:
2924 # print(str(e))
2925 # exit(1)
2926
2927
2928 @cli_osm.command(name='user-delete', short_help='deletes a user')
2929 @click.argument('name')
2930 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2931 @click.pass_context
2932 def user_delete(ctx, name):
2933 """deletes a user
2934
2935 \b
2936 NAME: name or ID of the user to be deleted
2937 """
2938 logger.debug("")
2939 # try:
2940 check_client_version(ctx.obj, ctx.command.name)
2941 ctx.obj.user.delete(name)
2942 # except ClientException as e:
2943 # print(str(e))
2944 # exit(1)
2945
2946
2947 @cli_osm.command(name='user-list', short_help='list all users')
2948 @click.option('--filter', default=None,
2949 help='restricts the list to the users matching the filter')
2950 @click.pass_context
2951 def user_list(ctx, filter):
2952 """list all users"""
2953 # try:
2954 check_client_version(ctx.obj, ctx.command.name)
2955 resp = ctx.obj.user.list(filter)
2956 # except ClientException as e:
2957 # print(str(e))
2958 # exit(1)
2959 table = PrettyTable(['name', 'id'])
2960 for user in resp:
2961 table.add_row([user['username'], user['_id']])
2962 table.align = 'l'
2963 print(table)
2964
2965
2966 @cli_osm.command(name='user-show', short_help='shows the details of a user')
2967 @click.argument('name')
2968 @click.pass_context
2969 def user_show(ctx, name):
2970 """shows the details of a user
2971
2972 NAME: name or ID of the user
2973 """
2974 logger.debug("")
2975 # try:
2976 check_client_version(ctx.obj, ctx.command.name)
2977 resp = ctx.obj.user.get(name)
2978 if 'password' in resp:
2979 resp['password']='********'
2980 # except ClientException as e:
2981 # print(str(e))
2982 # exit(1)
2983
2984 table = PrettyTable(['key', 'attribute'])
2985 for k, v in resp.items():
2986 table.add_row([k, json.dumps(v, indent=2)])
2987 table.align = 'l'
2988 print(table)
2989
2990
2991 ####################
2992 # Fault Management operations
2993 ####################
2994
2995 @cli_osm.command(name='ns-alarm-create')
2996 @click.argument('name')
2997 @click.option('--ns', prompt=True, help='NS instance id or name')
2998 @click.option('--vnf', prompt=True,
2999 help='VNF name (VNF member index as declared in the NSD)')
3000 @click.option('--vdu', prompt=True,
3001 help='VDU name (VDU name as declared in the VNFD)')
3002 @click.option('--metric', prompt=True,
3003 help='Name of the metric (e.g. cpu_utilization)')
3004 @click.option('--severity', default='WARNING',
3005 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3006 @click.option('--threshold_value', prompt=True,
3007 help='threshold value that, when crossed, an alarm is triggered')
3008 @click.option('--threshold_operator', prompt=True,
3009 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3010 @click.option('--statistic', default='AVERAGE',
3011 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3012 @click.pass_context
3013 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
3014 threshold_value, threshold_operator, statistic):
3015 """creates a new alarm for a NS instance"""
3016 # TODO: Check how to validate threshold_value.
3017 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3018 logger.debug("")
3019 # try:
3020 ns_instance = ctx.obj.ns.get(ns)
3021 alarm = {}
3022 alarm['alarm_name'] = name
3023 alarm['ns_id'] = ns_instance['_id']
3024 alarm['correlation_id'] = ns_instance['_id']
3025 alarm['vnf_member_index'] = vnf
3026 alarm['vdu_name'] = vdu
3027 alarm['metric_name'] = metric
3028 alarm['severity'] = severity
3029 alarm['threshold_value'] = int(threshold_value)
3030 alarm['operation'] = threshold_operator
3031 alarm['statistic'] = statistic
3032 check_client_version(ctx.obj, ctx.command.name)
3033 ctx.obj.ns.create_alarm(alarm)
3034 # except ClientException as e:
3035 # print(str(e))
3036 # exit(1)
3037
3038
3039 #@cli_osm.command(name='ns-alarm-delete')
3040 #@click.argument('name')
3041 #@click.pass_context
3042 #def ns_alarm_delete(ctx, name):
3043 # """deletes an alarm
3044 #
3045 # NAME: name of the alarm to be deleted
3046 # """
3047 # try:
3048 # check_client_version(ctx.obj, ctx.command.name)
3049 # ctx.obj.ns.delete_alarm(name)
3050 # except ClientException as e:
3051 # print(str(e))
3052 # exit(1)
3053
3054
3055 ####################
3056 # Performance Management operations
3057 ####################
3058
3059 @cli_osm.command(name='ns-metric-export', short_help='exports a metric to the internal OSM bus, which can be read by other apps')
3060 @click.option('--ns', prompt=True, help='NS instance id or name')
3061 @click.option('--vnf', prompt=True,
3062 help='VNF name (VNF member index as declared in the NSD)')
3063 @click.option('--vdu', prompt=True,
3064 help='VDU name (VDU name as declared in the VNFD)')
3065 @click.option('--metric', prompt=True,
3066 help='name of the metric (e.g. cpu_utilization)')
3067 #@click.option('--period', default='1w',
3068 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3069 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3070 @click.pass_context
3071 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
3072 """exports a metric to the internal OSM bus, which can be read by other apps"""
3073 # TODO: Check how to validate interval.
3074 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3075 logger.debug("")
3076 # try:
3077 ns_instance = ctx.obj.ns.get(ns)
3078 metric_data = {}
3079 metric_data['ns_id'] = ns_instance['_id']
3080 metric_data['correlation_id'] = ns_instance['_id']
3081 metric_data['vnf_member_index'] = vnf
3082 metric_data['vdu_name'] = vdu
3083 metric_data['metric_name'] = metric
3084 metric_data['collection_unit'] = 'WEEK'
3085 metric_data['collection_period'] = 1
3086 check_client_version(ctx.obj, ctx.command.name)
3087 if not interval:
3088 print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
3089 else:
3090 i = 1
3091 while True:
3092 print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
3093 time.sleep(int(interval))
3094 i+=1
3095 # except ClientException as e:
3096 # print(str(e))
3097 # exit(1)
3098
3099
3100 ####################
3101 # Other operations
3102 ####################
3103
3104 @cli_osm.command(name='version')
3105 @click.pass_context
3106 def get_version(ctx):
3107 # try:
3108 check_client_version(ctx.obj, "version")
3109 print ("Server version: {}".format(ctx.obj.get_version()))
3110 print ("Client version: {}".format(pkg_resources.get_distribution("osmclient").version))
3111 # except ClientException as e:
3112 # print(str(e))
3113 # exit(1)
3114
3115 @cli_osm.command(name='upload-package', short_help='uploads a VNF package or NS package')
3116 @click.argument('filename')
3117 @click.pass_context
3118 def upload_package(ctx, filename):
3119 """uploads a VNF package or NS package
3120
3121 FILENAME: VNF or NS package file (tar.gz)
3122 """
3123 logger.debug("")
3124 # try:
3125 ctx.obj.package.upload(filename)
3126 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
3127 if fullclassname != 'osmclient.sol005.client.Client':
3128 ctx.obj.package.wait_for_upload(filename)
3129 # except ClientException as e:
3130 # print(str(e))
3131 # exit(1)
3132
3133
3134 #@cli_osm.command(name='ns-scaling-show')
3135 #@click.argument('ns_name')
3136 #@click.pass_context
3137 #def show_ns_scaling(ctx, ns_name):
3138 # """shows the status of a NS scaling operation
3139 #
3140 # NS_NAME: name of the NS instance being scaled
3141 # """
3142 # try:
3143 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3144 # resp = ctx.obj.ns.list()
3145 # except ClientException as e:
3146 # print(str(e))
3147 # exit(1)
3148 #
3149 # table = PrettyTable(
3150 # ['group-name',
3151 # 'instance-id',
3152 # 'operational status',
3153 # 'create-time',
3154 # 'vnfr ids'])
3155 #
3156 # for ns in resp:
3157 # if ns_name == ns['name']:
3158 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3159 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3160 # for record in scaling_records:
3161 # if 'instance' in record:
3162 # instances = record['instance']
3163 # for inst in instances:
3164 # table.add_row(
3165 # [record['scaling-group-name-ref'],
3166 # inst['instance-id'],
3167 # inst['op-status'],
3168 # time.strftime('%Y-%m-%d %H:%M:%S',
3169 # time.localtime(
3170 # inst['create-time'])),
3171 # inst['vnfrs']])
3172 # table.align = 'l'
3173 # print(table)
3174
3175
3176 #@cli_osm.command(name='ns-scale')
3177 #@click.argument('ns_name')
3178 #@click.option('--ns_scale_group', prompt=True)
3179 #@click.option('--index', prompt=True)
3180 #@click.option('--wait',
3181 # required=False,
3182 # default=False,
3183 # is_flag=True,
3184 # help='do not return the control immediately, but keep it \
3185 # until the operation is completed, or timeout')
3186 #@click.pass_context
3187 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3188 # """scales NS
3189 #
3190 # NS_NAME: name of the NS instance to be scaled
3191 # """
3192 # try:
3193 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3194 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3195 # except ClientException as e:
3196 # print(str(e))
3197 # exit(1)
3198
3199
3200 #@cli_osm.command(name='config-agent-list')
3201 #@click.pass_context
3202 #def config_agent_list(ctx):
3203 # """list config agents"""
3204 # try:
3205 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3206 # except ClientException as e:
3207 # print(str(e))
3208 # exit(1)
3209 # table = PrettyTable(['name', 'account-type', 'details'])
3210 # for account in ctx.obj.vca.list():
3211 # table.add_row(
3212 # [account['name'],
3213 # account['account-type'],
3214 # account['juju']])
3215 # table.align = 'l'
3216 # print(table)
3217
3218
3219 #@cli_osm.command(name='config-agent-delete')
3220 #@click.argument('name')
3221 #@click.pass_context
3222 #def config_agent_delete(ctx, name):
3223 # """deletes a config agent
3224 #
3225 # NAME: name of the config agent to be deleted
3226 # """
3227 # try:
3228 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3229 # ctx.obj.vca.delete(name)
3230 # except ClientException as e:
3231 # print(str(e))
3232 # exit(1)
3233
3234
3235 #@cli_osm.command(name='config-agent-add')
3236 #@click.option('--name',
3237 # prompt=True)
3238 #@click.option('--account_type',
3239 # prompt=True)
3240 #@click.option('--server',
3241 # prompt=True)
3242 #@click.option('--user',
3243 # prompt=True)
3244 #@click.option('--secret',
3245 # prompt=True,
3246 # hide_input=True,
3247 # confirmation_prompt=True)
3248 #@click.pass_context
3249 #def config_agent_add(ctx, name, account_type, server, user, secret):
3250 # """adds a config agent"""
3251 # try:
3252 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3253 # ctx.obj.vca.create(name, account_type, server, user, secret)
3254 # except ClientException as e:
3255 # print(str(e))
3256 # exit(1)
3257
3258
3259 #@cli_osm.command(name='ro-dump')
3260 #@click.pass_context
3261 #def ro_dump(ctx):
3262 # """shows RO agent information"""
3263 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3264 # resp = ctx.obj.vim.get_resource_orchestrator()
3265 # table = PrettyTable(['key', 'attribute'])
3266 # for k, v in list(resp.items()):
3267 # table.add_row([k, json.dumps(v, indent=2)])
3268 # table.align = 'l'
3269 # print(table)
3270
3271
3272 #@cli_osm.command(name='vcs-list')
3273 #@click.pass_context
3274 #def vcs_list(ctx):
3275 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3276 # resp = ctx.obj.utils.get_vcs_info()
3277 # table = PrettyTable(['component name', 'state'])
3278 # for component in resp:
3279 # table.add_row([component['component_name'], component['state']])
3280 # table.align = 'l'
3281 # print(table)
3282
3283
3284 @cli_osm.command(name='ns-action', short_help='executes an action/primitive over a NS instance')
3285 @click.argument('ns_name')
3286 @click.option('--vnf_name', default=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3287 @click.option('--kdu_name', default=None, help='kdu-name if the target is a kdu)')
3288 @click.option('--vdu_id', default=None, help='vdu-id if the target is a vdu')
3289 @click.option('--vdu_count', default=None, help='number of vdu instance of this vdu_id')
3290 @click.option('--action_name', prompt=True, help='action name')
3291 @click.option('--params', default=None, help='action params in YAML/JSON inline string')
3292 @click.option('--params_file', default=None, help='YAML/JSON file with action params')
3293 @click.option('--wait',
3294 required=False,
3295 default=False,
3296 is_flag=True,
3297 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3298 @click.pass_context
3299 def ns_action(ctx,
3300 ns_name,
3301 vnf_name,
3302 kdu_name,
3303 vdu_id,
3304 vdu_count,
3305 action_name,
3306 params,
3307 params_file,
3308 wait):
3309 """executes an action/primitive over a NS instance
3310
3311 NS_NAME: name or ID of the NS instance
3312 """
3313 logger.debug("")
3314 # try:
3315 check_client_version(ctx.obj, ctx.command.name)
3316 op_data = {}
3317 if vnf_name:
3318 op_data['member_vnf_index'] = vnf_name
3319 if kdu_name:
3320 op_data['kdu_name'] = kdu_name
3321 if vdu_id:
3322 op_data['vdu_id'] = vdu_id
3323 if vdu_count:
3324 op_data['vdu_count_index'] = vdu_count
3325 op_data['primitive'] = action_name
3326 if params_file:
3327 with open(params_file, 'r') as pf:
3328 params = pf.read()
3329 if params:
3330 op_data['primitive_params'] = yaml.safe_load(params)
3331 else:
3332 op_data['primitive_params'] = {}
3333 print(ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data, wait=wait))
3334
3335 # except ClientException as e:
3336 # print(str(e))
3337 # exit(1)
3338
3339
3340 @cli_osm.command(name='vnf-scale', short_help='executes a VNF scale (adding/removing VDUs)')
3341 @click.argument('ns_name')
3342 @click.argument('vnf_name')
3343 @click.option('--scaling-group', prompt=True, help="scaling-group-descriptor name to use")
3344 @click.option('--scale-in', default=False, is_flag=True, help="performs a scale in operation")
3345 @click.option('--scale-out', default=False, is_flag=True, help="performs a scale out operation (by default)")
3346 @click.pass_context
3347 def vnf_scale(ctx,
3348 ns_name,
3349 vnf_name,
3350 scaling_group,
3351 scale_in,
3352 scale_out):
3353 """
3354 Executes a VNF scale (adding/removing VDUs)
3355
3356 \b
3357 NS_NAME: name or ID of the NS instance.
3358 VNF_NAME: member-vnf-index in the NS to be scaled.
3359 """
3360 logger.debug("")
3361 # try:
3362 check_client_version(ctx.obj, ctx.command.name)
3363 if not scale_in and not scale_out:
3364 scale_out = True
3365 ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out)
3366 # except ClientException as e:
3367 # print(str(e))
3368 # exit(1)
3369
3370
3371 ##############################
3372 # Role Management Operations #
3373 ##############################
3374
3375 @cli_osm.command(name='role-create', short_help='creates a new role')
3376 @click.argument('name')
3377 @click.option('--permissions',
3378 default=None,
3379 help='role permissions using a dictionary')
3380 @click.pass_context
3381 def role_create(ctx, name, permissions):
3382 """
3383 Creates a new role.
3384
3385 \b
3386 NAME: Name or ID of the role.
3387 DEFINITION: Definition of grant/denial of access to resources.
3388 """
3389 logger.debug("")
3390 # try:
3391 check_client_version(ctx.obj, ctx.command.name)
3392 ctx.obj.role.create(name, permissions)
3393 # except ClientException as e:
3394 # print(str(e))
3395 # exit(1)
3396
3397
3398 @cli_osm.command(name='role-update', short_help='updates a role')
3399 @click.argument('name')
3400 @click.option('--set-name',
3401 default=None,
3402 help='change name of rle')
3403 # @click.option('--permissions',
3404 # default=None,
3405 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
3406 @click.option('--add',
3407 default=None,
3408 help='yaml format dictionary with permission: True/False to access grant/denial')
3409 @click.option('--remove',
3410 default=None,
3411 help='yaml format list to remove a permission')
3412 @click.pass_context
3413 def role_update(ctx, name, set_name, add, remove):
3414 """
3415 Updates a role.
3416
3417 \b
3418 NAME: Name or ID of the role.
3419 DEFINITION: Definition overwrites the old definition.
3420 ADD: Grant/denial of access to resource to add.
3421 REMOVE: Grant/denial of access to resource to remove.
3422 """
3423 logger.debug("")
3424 # try:
3425 check_client_version(ctx.obj, ctx.command.name)
3426 ctx.obj.role.update(name, set_name, None, add, remove)
3427 # except ClientException as e:
3428 # print(str(e))
3429 # exit(1)
3430
3431
3432 @cli_osm.command(name='role-delete', short_help='deletes a role')
3433 @click.argument('name')
3434 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3435 @click.pass_context
3436 def role_delete(ctx, name):
3437 """
3438 Deletes a role.
3439
3440 \b
3441 NAME: Name or ID of the role.
3442 """
3443 logger.debug("")
3444 # try:
3445 check_client_version(ctx.obj, ctx.command.name)
3446 ctx.obj.role.delete(name)
3447 # except ClientException as e:
3448 # print(str(e))
3449 # exit(1)
3450
3451
3452 @cli_osm.command(name='role-list', short_help='list all roles')
3453 @click.option('--filter', default=None,
3454 help='restricts the list to the projects matching the filter')
3455 @click.pass_context
3456 def role_list(ctx, filter):
3457 """
3458 List all roles.
3459 """
3460 logger.debug("")
3461 # try:
3462 check_client_version(ctx.obj, ctx.command.name)
3463 resp = ctx.obj.role.list(filter)
3464 # except ClientException as e:
3465 # print(str(e))
3466 # exit(1)
3467 table = PrettyTable(['name', 'id'])
3468 for role in resp:
3469 table.add_row([role['name'], role['_id']])
3470 table.align = 'l'
3471 print(table)
3472
3473
3474 @cli_osm.command(name='role-show', short_help='show specific role')
3475 @click.argument('name')
3476 @click.pass_context
3477 def role_show(ctx, name):
3478 """
3479 Shows the details of a role.
3480
3481 \b
3482 NAME: Name or ID of the role.
3483 """
3484 logger.debug("")
3485 # try:
3486 check_client_version(ctx.obj, ctx.command.name)
3487 resp = ctx.obj.role.get(name)
3488 # except ClientException as e:
3489 # print(str(e))
3490 # exit(1)
3491
3492 table = PrettyTable(['key', 'attribute'])
3493 for k, v in resp.items():
3494 table.add_row([k, json.dumps(v, indent=2)])
3495 table.align = 'l'
3496 print(table)
3497
3498
3499 @cli_osm.command(name='package-create',
3500 short_help='Create a package descriptor')
3501 @click.argument('package-type')
3502 @click.argument('package-name')
3503 @click.option('--base-directory',
3504 default='.',
3505 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
3506 @click.option('--image',
3507 default="image-name",
3508 help='(VNF) Set the name of the vdu image. Default "image-name"')
3509 @click.option('--vdus',
3510 default=1,
3511 help='(VNF) Set the number of vdus in a VNF. Default 1')
3512 @click.option('--vcpu',
3513 default=1,
3514 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
3515 @click.option('--memory',
3516 default=1024,
3517 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
3518 @click.option('--storage',
3519 default=10,
3520 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
3521 @click.option('--interfaces',
3522 default=0,
3523 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
3524 @click.option('--vendor',
3525 default="OSM",
3526 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
3527 @click.option('--override',
3528 default=False,
3529 is_flag=True,
3530 help='(NS/VNF/NST) Flag for overriding the package if exists.')
3531 @click.option('--detailed',
3532 is_flag=True,
3533 default=False,
3534 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
3535 @click.option('--netslice-subnets',
3536 default=1,
3537 help='(NST) Number of netslice subnets. Default 1')
3538 @click.option('--netslice-vlds',
3539 default=1,
3540 help='(NST) Number of netslice vlds. Default 1')
3541 @click.pass_context
3542 def package_create(ctx,
3543 package_type,
3544 base_directory,
3545 package_name,
3546 override,
3547 image,
3548 vdus,
3549 vcpu,
3550 memory,
3551 storage,
3552 interfaces,
3553 vendor,
3554 detailed,
3555 netslice_subnets,
3556 netslice_vlds):
3557 """
3558 Creates an OSM NS, VNF, NST package
3559
3560 \b
3561 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
3562 PACKAGE_NAME: Name of the package to create the folder with the content.
3563 """
3564
3565 # try:
3566 check_client_version(ctx.obj, ctx.command.name)
3567 print("Creating the {} structure: {}/{}".format(package_type.upper(), base_directory, package_name))
3568 resp = ctx.obj.package_tool.create(package_type,
3569 base_directory,
3570 package_name,
3571 override=override,
3572 image=image,
3573 vdus=vdus,
3574 vcpu=vcpu,
3575 memory=memory,
3576 storage=storage,
3577 interfaces=interfaces,
3578 vendor=vendor,
3579 detailed=detailed,
3580 netslice_subnets=netslice_subnets,
3581 netslice_vlds=netslice_vlds)
3582 print(resp)
3583 # except ClientException as inst:
3584 # print("ERROR: {}".format(inst))
3585 # exit(1)
3586
3587 @cli_osm.command(name='package-validate',
3588 short_help='Validate a package descriptor')
3589 @click.argument('base-directory',
3590 default=".",
3591 required=False)
3592 @click.pass_context
3593 def package_validate(ctx,
3594 base_directory):
3595 """
3596 Validate descriptors given a base directory.
3597
3598 \b
3599 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
3600 """
3601 # try:
3602 check_client_version(ctx.obj, ctx.command.name)
3603 results = ctx.obj.package_tool.validate(base_directory)
3604 table = PrettyTable()
3605 table.field_names = ["TYPE", "PATH", "VALID", "ERROR"]
3606 # Print the dictionary generated by the validation function
3607 for result in results:
3608 table.add_row([result["type"], result["path"], result["valid"], result["error"]])
3609 table.sortby = "VALID"
3610 table.align["PATH"] = "l"
3611 table.align["TYPE"] = "l"
3612 table.align["ERROR"] = "l"
3613 print(table)
3614 # except ClientException as inst:
3615 # print("ERROR: {}".format(inst))
3616 # exit(1)
3617
3618 @cli_osm.command(name='package-build',
3619 short_help='Build the tar.gz of the package')
3620 @click.argument('package-folder')
3621 @click.option('--skip-validation',
3622 default=False,
3623 is_flag=True,
3624 help='skip package validation')
3625 @click.pass_context
3626 def package_build(ctx,
3627 package_folder,
3628 skip_validation):
3629 """
3630 Build the package NS, VNF given the package_folder.
3631
3632 \b
3633 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
3634 """
3635 # try:
3636 check_client_version(ctx.obj, ctx.command.name)
3637 results = ctx.obj.package_tool.build(package_folder, skip_validation)
3638 print(results)
3639 # except ClientException as inst:
3640 # print("ERROR: {}".format(inst))
3641 # exit(1)
3642
3643
3644 def cli():
3645 try:
3646 cli_osm()
3647 except pycurl.error as exc:
3648 print(exc)
3649 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
3650 exit(1)
3651 except ClientException as exc:
3652 print("ERROR: {}".format(exc))
3653 exit(1)
3654 # TODO capture other controlled exceptions here
3655 # TODO remove the ClientException captures from all places, unless they do something different
3656
3657
3658 if __name__ == '__main__':
3659 cli()
3660