83b4727c5a9a4c66cd08647aeb3a5ce7a94bdc50
[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
30
31 def check_client_version(obj, what, version='sol005'):
32 """
33 Checks the version of the client object and raises error if it not the expected.
34
35 :param obj: the client object
36 :what: the function or command under evaluation (used when an error is raised)
37 :return: -
38 :raises ClientError: if the specified version does not match the client version
39 """
40 fullclassname = obj.__module__ + "." + obj.__class__.__name__
41 message = 'The following commands or options are only supported with the option "--sol005": {}'.format(what)
42 if version == 'v1':
43 message = 'The following commands or options are not supported when using option "--sol005": {}'.format(what)
44 if fullclassname != 'osmclient.{}.client.Client'.format(version):
45 raise ClientException(message)
46 return
47
48
49 @click.group()
50 @click.option('--hostname',
51 default="127.0.0.1",
52 envvar='OSM_HOSTNAME',
53 help='hostname of server. ' +
54 'Also can set OSM_HOSTNAME in environment')
55 @click.option('--sol005/--no-sol005',
56 default=True,
57 envvar='OSM_SOL005',
58 help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
59 'Also can set OSM_SOL005 in environment')
60 @click.option('--user',
61 default=None,
62 envvar='OSM_USER',
63 help='user (only from Release FOUR, defaults to admin). ' +
64 'Also can set OSM_USER in environment')
65 @click.option('--password',
66 default=None,
67 envvar='OSM_PASSWORD',
68 help='password (only from Release FOUR, defaults to admin). ' +
69 'Also can set OSM_PASSWORD in environment')
70 @click.option('--project',
71 default=None,
72 envvar='OSM_PROJECT',
73 help='project (only from Release FOUR, defaults to admin). ' +
74 'Also can set OSM_PROJECT in environment')
75 @click.option('--so-port',
76 default=None,
77 envvar='OSM_SO_PORT',
78 help='hostname of server. ' +
79 'Also can set OSM_SO_PORT in environment')
80 @click.option('--so-project',
81 default=None,
82 envvar='OSM_SO_PROJECT',
83 help='Project Name in SO. ' +
84 'Also can set OSM_SO_PROJECT in environment')
85 @click.option('--ro-hostname',
86 default=None,
87 envvar='OSM_RO_HOSTNAME',
88 help='hostname of RO server. ' +
89 'Also can set OSM_RO_HOSTNAME in environment')
90 @click.option('--ro-port',
91 default=None,
92 envvar='OSM_RO_PORT',
93 help='hostname of RO server. ' +
94 'Also can set OSM_RO_PORT in environment')
95 @click.pass_context
96 def cli(ctx, hostname, sol005, user, password, project, so_port, so_project, ro_hostname, ro_port):
97 if hostname is None:
98 print((
99 "either hostname option or OSM_HOSTNAME " +
100 "environment variable needs to be specified"))
101 exit(1)
102 kwargs={}
103 if so_port is not None:
104 kwargs['so_port']=so_port
105 if so_project is not None:
106 kwargs['so_project']=so_project
107 if ro_hostname is not None:
108 kwargs['ro_host']=ro_hostname
109 if ro_port is not None:
110 kwargs['ro_port']=ro_port
111 if user is not None:
112 kwargs['user']=user
113 if password is not None:
114 kwargs['password']=password
115 if project is not None:
116 kwargs['project']=project
117
118 ctx.obj = client.Client(host=hostname, sol005=sol005, **kwargs)
119
120
121 ####################
122 # LIST operations
123 ####################
124
125 @cli.command(name='ns-list')
126 @click.option('--filter', default=None,
127 help='restricts the list to the NS instances matching the filter.')
128 @click.pass_context
129 def ns_list(ctx, filter):
130 """list all NS instances
131
132 \b
133 Options:
134 --filter filterExpr Restricts the list to the NS instances matching the filter
135
136 \b
137 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
138 concatenated using the "&" character:
139
140 \b
141 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
142 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
143 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
144 attrName := string
145 value := scalar value
146
147 \b
148 where:
149 * zero or more occurrences
150 ? zero or one occurrence
151 [] grouping of expressions to be used with ? and *
152 "" quotation marks for marking string constants
153 <> name separator
154
155 \b
156 "AttrName" is the name of one attribute in the data type that defines the representation
157 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
158 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
159 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
160 entries, it means that the operator "op" is applied to the attribute addressed by the last
161 <attrName> entry included in the concatenation. All simple filter expressions are combined
162 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
163 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
164 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
165 prefix". If an attribute referenced in an expression is an array, an object that contains a
166 corresponding array shall be considered to match the expression if any of the elements in the
167 array matches all expressions that have the same attribute prefix.
168
169 \b
170 Filter examples:
171 --filter admin-status=ENABLED
172 --filter nsd-ref=<NSD_NAME>
173 --filter nsd.vendor=<VENDOR>
174 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
175 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
176 """
177 if filter:
178 check_client_version(ctx.obj, '--filter')
179 resp = ctx.obj.ns.list(filter)
180 else:
181 resp = ctx.obj.ns.list()
182 table = PrettyTable(
183 ['ns instance name',
184 'id',
185 'operational status',
186 'config status',
187 'detailed status'])
188 for ns in resp:
189 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
190 if fullclassname == 'osmclient.sol005.client.Client':
191 nsr = ns
192 nsr_name = nsr['name']
193 nsr_id = nsr['_id']
194 else:
195 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
196 nsr = nsopdata['nsr:nsr']
197 nsr_name = nsr['name-ref']
198 nsr_id = nsr['ns-instance-config-ref']
199 opstatus = nsr['operational-status'] if 'operational-status' in nsr else 'Not found'
200 configstatus = nsr['config-status'] if 'config-status' in nsr else 'Not found'
201 detailed_status = nsr['detailed-status'] if 'detailed-status' in nsr else 'Not found'
202 if configstatus == "config_not_needed":
203 configstatus = "configured (no charms)"
204 table.add_row(
205 [nsr_name,
206 nsr_id,
207 opstatus,
208 configstatus,
209 detailed_status])
210 table.align = 'l'
211 print(table)
212
213
214 def nsd_list(ctx, filter):
215 if filter:
216 check_client_version(ctx.obj, '--filter')
217 resp = ctx.obj.nsd.list(filter)
218 else:
219 resp = ctx.obj.nsd.list()
220 # print yaml.safe_dump(resp)
221 table = PrettyTable(['nsd name', 'id'])
222 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
223 if fullclassname == 'osmclient.sol005.client.Client':
224 for ns in resp:
225 name = ns['name'] if 'name' in ns else '-'
226 table.add_row([name, ns['_id']])
227 else:
228 for ns in resp:
229 table.add_row([ns['name'], ns['id']])
230 table.align = 'l'
231 print(table)
232
233
234 @cli.command(name='nsd-list')
235 @click.option('--filter', default=None,
236 help='restricts the list to the NSD/NSpkg matching the filter')
237 @click.pass_context
238 def nsd_list1(ctx, filter):
239 """list all NSD/NS pkg in the system"""
240 nsd_list(ctx, filter)
241
242
243 @cli.command(name='nspkg-list')
244 @click.option('--filter', default=None,
245 help='restricts the list to the NSD/NSpkg matching the filter')
246 @click.pass_context
247 def nsd_list2(ctx, filter):
248 """list all NSD/NS pkg in the system"""
249 nsd_list(ctx, filter)
250
251
252 def vnfd_list(ctx, nf_type, filter):
253 if nf_type:
254 check_client_version(ctx.obj, '--nf_type')
255 elif filter:
256 check_client_version(ctx.obj, '--filter')
257 if nf_type:
258 if nf_type == "vnf":
259 nf_filter = "_admin.type=vnfd"
260 elif nf_type == "pnf":
261 nf_filter = "_admin.type=pnfd"
262 elif nf_type == "hnf":
263 nf_filter = "_admin.type=hnfd"
264 else:
265 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
266 if filter:
267 filter = '{}&{}'.format(nf_filter, filter)
268 else:
269 filter = nf_filter
270 if filter:
271 resp = ctx.obj.vnfd.list(filter)
272 else:
273 resp = ctx.obj.vnfd.list()
274 # print yaml.safe_dump(resp)
275 table = PrettyTable(['nfpkg name', 'id'])
276 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
277 if fullclassname == 'osmclient.sol005.client.Client':
278 for vnfd in resp:
279 name = vnfd['name'] if 'name' in vnfd else '-'
280 table.add_row([name, vnfd['_id']])
281 else:
282 for vnfd in resp:
283 table.add_row([vnfd['name'], vnfd['id']])
284 table.align = 'l'
285 print(table)
286
287
288 @cli.command(name='vnfd-list')
289 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
290 @click.option('--filter', default=None,
291 help='restricts the list to the NF pkg matching the filter')
292 @click.pass_context
293 def vnfd_list1(ctx, nf_type, filter):
294 """list all VNFD/VNF pkg in the system"""
295 vnfd_list(ctx, nf_type, filter)
296
297
298 @cli.command(name='vnfpkg-list')
299 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
300 @click.option('--filter', default=None,
301 help='restricts the list to the NFpkg matching the filter')
302 @click.pass_context
303 def vnfd_list2(ctx, nf_type, filter):
304 """list all VNFD/VNF pkg in the system"""
305 vnfd_list(ctx, nf_type, filter)
306
307
308 @cli.command(name='nfpkg-list')
309 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
310 @click.option('--filter', default=None,
311 help='restricts the list to the NFpkg matching the filter')
312 @click.pass_context
313 def nfpkg_list(ctx, nf_type, filter):
314 """list all NF pkg (VNF pkg, PNF pkg, HNF pkg) in the system"""
315 try:
316 check_client_version(ctx.obj, ctx.command.name)
317 vnfd_list(ctx, nf_type, filter)
318 except ClientException as inst:
319 print((inst.message))
320 exit(1)
321
322
323 def vnf_list(ctx, ns, filter):
324 try:
325 if ns or filter:
326 if ns:
327 check_client_version(ctx.obj, '--ns')
328 if filter:
329 check_client_version(ctx.obj, '--filter')
330 resp = ctx.obj.vnf.list(ns, filter)
331 else:
332 resp = ctx.obj.vnf.list()
333 except ClientException as inst:
334 print((inst.message))
335 exit(1)
336 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
337 if fullclassname == 'osmclient.sol005.client.Client':
338 table = PrettyTable(
339 ['vnf id',
340 'name',
341 'ns id',
342 'vnf member index',
343 'vnfd name',
344 'vim account id',
345 'ip address'])
346 for vnfr in resp:
347 name = vnfr['name'] if 'name' in vnfr else '-'
348 table.add_row(
349 [vnfr['_id'],
350 name,
351 vnfr['nsr-id-ref'],
352 vnfr['member-vnf-index-ref'],
353 vnfr['vnfd-ref'],
354 vnfr['vim-account-id'],
355 vnfr['ip-address']])
356 else:
357 table = PrettyTable(
358 ['vnf name',
359 'id',
360 'operational status',
361 'config status'])
362 for vnfr in resp:
363 if 'mgmt-interface' not in vnfr:
364 vnfr['mgmt-interface'] = {}
365 vnfr['mgmt-interface']['ip-address'] = None
366 table.add_row(
367 [vnfr['name'],
368 vnfr['id'],
369 vnfr['operational-status'],
370 vnfr['config-status']])
371 table.align = 'l'
372 print(table)
373
374
375 @cli.command(name='vnf-list')
376 @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list')
377 @click.option('--filter', default=None,
378 help='restricts the list to the NF instances matching the filter.')
379 @click.pass_context
380 def vnf_list1(ctx, ns, filter):
381 """list all NF instances"""
382 vnf_list(ctx, ns, filter)
383
384
385 @cli.command(name='nf-list')
386 @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list')
387 @click.option('--filter', default=None,
388 help='restricts the list to the NF instances matching the filter.')
389 @click.pass_context
390 def nf_list(ctx, ns, filter):
391 """list all NF instances
392
393 \b
394 Options:
395 --ns TEXT NS instance id or name to restrict the VNF list
396 --filter filterExpr Restricts the list to the VNF instances matching the filter
397
398 \b
399 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
400 concatenated using the "&" character:
401
402 \b
403 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
404 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
405 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
406 attrName := string
407 value := scalar value
408
409 \b
410 where:
411 * zero or more occurrences
412 ? zero or one occurrence
413 [] grouping of expressions to be used with ? and *
414 "" quotation marks for marking string constants
415 <> name separator
416
417 \b
418 "AttrName" is the name of one attribute in the data type that defines the representation
419 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
420 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
421 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
422 entries, it means that the operator "op" is applied to the attribute addressed by the last
423 <attrName> entry included in the concatenation. All simple filter expressions are combined
424 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
425 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
426 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
427 prefix". If an attribute referenced in an expression is an array, an object that contains a
428 corresponding array shall be considered to match the expression if any of the elements in the
429 array matches all expressions that have the same attribute prefix.
430
431 \b
432 Filter examples:
433 --filter vim-account-id=<VIM_ACCOUNT_ID>
434 --filter vnfd-ref=<VNFD_NAME>
435 --filter vdur.ip-address=<IP_ADDRESS>
436 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
437 """
438 vnf_list(ctx, ns, filter)
439
440
441 @cli.command(name='ns-op-list')
442 @click.argument('name')
443 @click.pass_context
444 def ns_op_list(ctx, name):
445 """shows the history of operations over a NS instance
446
447 NAME: name or ID of the NS instance
448 """
449 try:
450 check_client_version(ctx.obj, ctx.command.name)
451 resp = ctx.obj.ns.list_op(name)
452 except ClientException as inst:
453 print((inst.message))
454 exit(1)
455
456 table = PrettyTable(['id', 'operation', 'status'])
457 for op in resp:
458 table.add_row([op['id'], op['lcmOperationType'],
459 op['operationState']])
460 table.align = 'l'
461 print(table)
462
463
464 def nsi_list(ctx, filter):
465 """list all Network Slice Instances"""
466 try:
467 check_client_version(ctx.obj, ctx.command.name)
468 resp = ctx.obj.nsi.list(filter)
469 except ClientException as inst:
470 print((inst.message))
471 exit(1)
472 table = PrettyTable(
473 ['netslice instance name',
474 'id',
475 'operational status',
476 'config status',
477 'detailed status'])
478 for nsi in resp:
479 nsi_name = nsi['name']
480 nsi_id = nsi['_id']
481 opstatus = nsi['operational-status'] if 'operational-status' in nsi else 'Not found'
482 configstatus = nsi['config-status'] if 'config-status' in nsi else 'Not found'
483 detailed_status = nsi['detailed-status'] if 'detailed-status' in nsi else 'Not found'
484 if configstatus == "config_not_needed":
485 configstatus = "configured (no charms)"
486 table.add_row(
487 [nsi_name,
488 nsi_id,
489 opstatus,
490 configstatus,
491 detailed_status])
492 table.align = 'l'
493 print(table)
494
495
496 @cli.command(name='nsi-list')
497 @click.option('--filter', default=None,
498 help='restricts the list to the Network Slice Instances matching the filter')
499 @click.pass_context
500 def nsi_list1(ctx, filter):
501 """list all Network Slice Instances (NSI)"""
502 nsi_list(ctx, filter)
503
504
505 @cli.command(name='netslice-instance-list')
506 @click.option('--filter', default=None,
507 help='restricts the list to the Network Slice Instances matching the filter')
508 @click.pass_context
509 def nsi_list2(ctx, filter):
510 """list all Network Slice Instances (NSI)"""
511 nsi_list(ctx, filter)
512
513
514 def nst_list(ctx, filter):
515 try:
516 check_client_version(ctx.obj, ctx.command.name)
517 resp = ctx.obj.nst.list(filter)
518 except ClientException as inst:
519 print((inst.message))
520 exit(1)
521 # print yaml.safe_dump(resp)
522 table = PrettyTable(['nst name', 'id'])
523 for nst in resp:
524 name = nst['name'] if 'name' in nst else '-'
525 table.add_row([name, nst['_id']])
526 table.align = 'l'
527 print(table)
528
529
530 @cli.command(name='nst-list')
531 @click.option('--filter', default=None,
532 help='restricts the list to the NST matching the filter')
533 @click.pass_context
534 def nst_list1(ctx, filter):
535 """list all Network Slice Templates (NST) in the system"""
536 nst_list(ctx, filter)
537
538
539 @cli.command(name='netslice-template-list')
540 @click.option('--filter', default=None,
541 help='restricts the list to the NST matching the filter')
542 @click.pass_context
543 def nst_list2(ctx, filter):
544 """list all Network Slice Templates (NST) in the system"""
545 nst_list(ctx, filter)
546
547
548 def nsi_op_list(ctx, name):
549 try:
550 check_client_version(ctx.obj, ctx.command.name)
551 resp = ctx.obj.nsi.list_op(name)
552 except ClientException as inst:
553 print((inst.message))
554 exit(1)
555 table = PrettyTable(['id', 'operation', 'status'])
556 for op in resp:
557 table.add_row([op['id'], op['lcmOperationType'],
558 op['operationState']])
559 table.align = 'l'
560 print(table)
561
562
563 @cli.command(name='nsi-op-list')
564 @click.argument('name')
565 @click.pass_context
566 def nsi_op_list1(ctx, name):
567 """shows the history of operations over a Network Slice Instance (NSI)
568
569 NAME: name or ID of the Network Slice Instance
570 """
571 nsi_op_list(ctx, name)
572
573
574 @cli.command(name='netslice-instance-op-list')
575 @click.argument('name')
576 @click.pass_context
577 def nsi_op_list2(ctx, name):
578 """shows the history of operations over a Network Slice Instance (NSI)
579
580 NAME: name or ID of the Network Slice Instance
581 """
582 nsi_op_list(ctx, name)
583
584
585 @cli.command(name='pdu-list')
586 @click.option('--filter', default=None,
587 help='restricts the list to the Physical Deployment Units matching the filter')
588 @click.pass_context
589 def pdu_list(ctx, filter):
590 """list all Physical Deployment Units (PDU)"""
591 try:
592 check_client_version(ctx.obj, ctx.command.name)
593 resp = ctx.obj.pdu.list(filter)
594 except ClientException as inst:
595 print((inst.message))
596 exit(1)
597 table = PrettyTable(
598 ['pdu name',
599 'id',
600 'type',
601 'mgmt ip address'])
602 for pdu in resp:
603 pdu_name = pdu['name']
604 pdu_id = pdu['_id']
605 pdu_type = pdu['type']
606 pdu_ipaddress = "None"
607 for iface in pdu['interfaces']:
608 if iface['mgmt']:
609 pdu_ipaddress = iface['ip-address']
610 break
611 table.add_row(
612 [pdu_name,
613 pdu_id,
614 pdu_type,
615 pdu_ipaddress])
616 table.align = 'l'
617 print(table)
618
619
620 ####################
621 # SHOW operations
622 ####################
623
624 def nsd_show(ctx, name, literal):
625 try:
626 resp = ctx.obj.nsd.get(name)
627 # resp = ctx.obj.nsd.get_individual(name)
628 except ClientException as inst:
629 print((inst.message))
630 exit(1)
631
632 if literal:
633 print(yaml.safe_dump(resp))
634 return
635
636 table = PrettyTable(['field', 'value'])
637 for k, v in list(resp.items()):
638 table.add_row([k, json.dumps(v, indent=2)])
639 table.align = 'l'
640 print(table)
641
642
643 @cli.command(name='nsd-show', short_help='shows the content of a NSD')
644 @click.option('--literal', is_flag=True,
645 help='print literally, no pretty table')
646 @click.argument('name')
647 @click.pass_context
648 def nsd_show1(ctx, name, literal):
649 """shows the content of a NSD
650
651 NAME: name or ID of the NSD/NSpkg
652 """
653 nsd_show(ctx, name, literal)
654
655
656 @cli.command(name='nspkg-show', short_help='shows the content of a NSD')
657 @click.option('--literal', is_flag=True,
658 help='print literally, no pretty table')
659 @click.argument('name')
660 @click.pass_context
661 def nsd_show2(ctx, name, literal):
662 """shows the content of a NSD
663
664 NAME: name or ID of the NSD/NSpkg
665 """
666 nsd_show(ctx, name, literal)
667
668
669 def vnfd_show(ctx, name, literal):
670 try:
671 resp = ctx.obj.vnfd.get(name)
672 # resp = ctx.obj.vnfd.get_individual(name)
673 except ClientException as inst:
674 print((inst.message))
675 exit(1)
676
677 if literal:
678 print(yaml.safe_dump(resp))
679 return
680
681 table = PrettyTable(['field', 'value'])
682 for k, v in list(resp.items()):
683 table.add_row([k, json.dumps(v, indent=2)])
684 table.align = 'l'
685 print(table)
686
687
688 @cli.command(name='vnfd-show', short_help='shows the content of a VNFD')
689 @click.option('--literal', is_flag=True,
690 help='print literally, no pretty table')
691 @click.argument('name')
692 @click.pass_context
693 def vnfd_show1(ctx, name, literal):
694 """shows the content of a VNFD
695
696 NAME: name or ID of the VNFD/VNFpkg
697 """
698 vnfd_show(ctx, name, literal)
699
700
701 @cli.command(name='vnfpkg-show', short_help='shows the content of a VNFD')
702 @click.option('--literal', is_flag=True,
703 help='print literally, no pretty table')
704 @click.argument('name')
705 @click.pass_context
706 def vnfd_show2(ctx, name, literal):
707 """shows the content of a VNFD
708
709 NAME: name or ID of the VNFD/VNFpkg
710 """
711 vnfd_show(ctx, name, literal)
712
713
714 @cli.command(name='nfpkg-show', short_help='shows the content of a NF Descriptor')
715 @click.option('--literal', is_flag=True,
716 help='print literally, no pretty table')
717 @click.argument('name')
718 @click.pass_context
719 def nfpkg_show(ctx, name, literal):
720 """shows the content of a NF Descriptor
721
722 NAME: name or ID of the NFpkg
723 """
724 vnfd_show(ctx, name, literal)
725
726
727 @cli.command(name='ns-show', short_help='shows the info of a NS instance')
728 @click.argument('name')
729 @click.option('--literal', is_flag=True,
730 help='print literally, no pretty table')
731 @click.option('--filter', default=None)
732 @click.pass_context
733 def ns_show(ctx, name, literal, filter):
734 """shows the info of a NS instance
735
736 NAME: name or ID of the NS instance
737 """
738 try:
739 ns = ctx.obj.ns.get(name)
740 except ClientException as inst:
741 print((inst.message))
742 exit(1)
743
744 if literal:
745 print(yaml.safe_dump(ns))
746 return
747
748 table = PrettyTable(['field', 'value'])
749
750 for k, v in list(ns.items()):
751 if filter is None or filter in k:
752 table.add_row([k, json.dumps(v, indent=2)])
753
754 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
755 if fullclassname != 'osmclient.sol005.client.Client':
756 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
757 nsr_optdata = nsopdata['nsr:nsr']
758 for k, v in list(nsr_optdata.items()):
759 if filter is None or filter in k:
760 table.add_row([k, json.dumps(v, indent=2)])
761 table.align = 'l'
762 print(table)
763
764
765 @cli.command(name='vnf-show', short_help='shows the info of a VNF instance')
766 @click.argument('name')
767 @click.option('--literal', is_flag=True,
768 help='print literally, no pretty table')
769 @click.option('--filter', default=None)
770 @click.pass_context
771 def vnf_show(ctx, name, literal, filter):
772 """shows the info of a VNF instance
773
774 NAME: name or ID of the VNF instance
775 """
776 try:
777 check_client_version(ctx.obj, ctx.command.name)
778 resp = ctx.obj.vnf.get(name)
779 except ClientException as inst:
780 print((inst.message))
781 exit(1)
782
783 if literal:
784 print(yaml.safe_dump(resp))
785 return
786
787 table = PrettyTable(['field', 'value'])
788 for k, v in list(resp.items()):
789 if filter is None or filter in k:
790 table.add_row([k, json.dumps(v, indent=2)])
791 table.align = 'l'
792 print(table)
793
794
795 @cli.command(name='vnf-monitoring-show')
796 @click.argument('vnf_name')
797 @click.pass_context
798 def vnf_monitoring_show(ctx, vnf_name):
799 try:
800 check_client_version(ctx.obj, ctx.command.name, 'v1')
801 resp = ctx.obj.vnf.get_monitoring(vnf_name)
802 except ClientException as inst:
803 print((inst.message))
804 exit(1)
805
806 table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
807 if resp is not None:
808 for monitor in resp:
809 table.add_row(
810 [vnf_name,
811 monitor['name'],
812 monitor['value-integer'],
813 monitor['units']])
814 table.align = 'l'
815 print(table)
816
817
818 @cli.command(name='ns-monitoring-show')
819 @click.argument('ns_name')
820 @click.pass_context
821 def ns_monitoring_show(ctx, ns_name):
822 try:
823 check_client_version(ctx.obj, ctx.command.name, 'v1')
824 resp = ctx.obj.ns.get_monitoring(ns_name)
825 except ClientException as inst:
826 print((inst.message))
827 exit(1)
828
829 table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
830 for key, val in list(resp.items()):
831 for monitor in val:
832 table.add_row(
833 [key,
834 monitor['name'],
835 monitor['value-integer'],
836 monitor['units']])
837 table.align = 'l'
838 print(table)
839
840
841 @cli.command(name='ns-op-show', short_help='shows the info of an operation')
842 @click.argument('id')
843 @click.option('--filter', default=None)
844 @click.pass_context
845 def ns_op_show(ctx, id, filter):
846 """shows the detailed info of an operation
847
848 ID: operation identifier
849 """
850 try:
851 check_client_version(ctx.obj, ctx.command.name)
852 op_info = ctx.obj.ns.get_op(id)
853 except ClientException as inst:
854 print((inst.message))
855 exit(1)
856
857 table = PrettyTable(['field', 'value'])
858 for k, v in list(op_info.items()):
859 if filter is None or filter in k:
860 table.add_row([k, json.dumps(v, indent=2)])
861 table.align = 'l'
862 print(table)
863
864
865 def nst_show(ctx, name, literal):
866 try:
867 check_client_version(ctx.obj, ctx.command.name)
868 resp = ctx.obj.nst.get(name)
869 #resp = ctx.obj.nst.get_individual(name)
870 except ClientException as inst:
871 print((inst.message))
872 exit(1)
873
874 if literal:
875 print(yaml.safe_dump(resp))
876 return
877
878 table = PrettyTable(['field', 'value'])
879 for k, v in list(resp.items()):
880 table.add_row([k, json.dumps(v, indent=2)])
881 table.align = 'l'
882 print(table)
883
884
885 @cli.command(name='nst-show', short_help='shows the content of a Network Slice Template (NST)')
886 @click.option('--literal', is_flag=True,
887 help='print literally, no pretty table')
888 @click.argument('name')
889 @click.pass_context
890 def nst_show1(ctx, name, literal):
891 """shows the content of a Network Slice Template (NST)
892
893 NAME: name or ID of the NST
894 """
895 nst_show(ctx, name, literal)
896
897
898 @cli.command(name='netslice-template-show', short_help='shows the content of a Network Slice Template (NST)')
899 @click.option('--literal', is_flag=True,
900 help='print literally, no pretty table')
901 @click.argument('name')
902 @click.pass_context
903 def nst_show2(ctx, name, literal):
904 """shows the content of a Network Slice Template (NST)
905
906 NAME: name or ID of the NST
907 """
908 nst_show(ctx, name, literal)
909
910
911 def nsi_show(ctx, name, literal, filter):
912 try:
913 check_client_version(ctx.obj, ctx.command.name)
914 nsi = ctx.obj.nsi.get(name)
915 except ClientException as inst:
916 print((inst.message))
917 exit(1)
918
919 if literal:
920 print(yaml.safe_dump(nsi))
921 return
922
923 table = PrettyTable(['field', 'value'])
924
925 for k, v in list(nsi.items()):
926 if filter is None or filter in k:
927 table.add_row([k, json.dumps(v, indent=2)])
928
929 table.align = 'l'
930 print(table)
931
932
933 @cli.command(name='nsi-show', short_help='shows the content of a Network Slice Instance (NSI)')
934 @click.argument('name')
935 @click.option('--literal', is_flag=True,
936 help='print literally, no pretty table')
937 @click.option('--filter', default=None)
938 @click.pass_context
939 def nsi_show1(ctx, name, literal, filter):
940 """shows the content of a Network Slice Instance (NSI)
941
942 NAME: name or ID of the Network Slice Instance
943 """
944 nsi_show(ctx, name, literal, filter)
945
946
947 @cli.command(name='netslice-instance-show', short_help='shows the content of a Network Slice Instance (NSI)')
948 @click.argument('name')
949 @click.option('--literal', is_flag=True,
950 help='print literally, no pretty table')
951 @click.option('--filter', default=None)
952 @click.pass_context
953 def nsi_show2(ctx, name, literal, filter):
954 """shows the content of a Network Slice Instance (NSI)
955
956 NAME: name or ID of the Network Slice Instance
957 """
958 nsi_show(ctx, name, literal, filter)
959
960
961 def nsi_op_show(ctx, id, filter):
962 try:
963 check_client_version(ctx.obj, ctx.command.name)
964 op_info = ctx.obj.nsi.get_op(id)
965 except ClientException as inst:
966 print((inst.message))
967 exit(1)
968
969 table = PrettyTable(['field', 'value'])
970 for k, v in list(op_info.items()):
971 if filter is None or filter in k:
972 table.add_row([k, json.dumps(v, indent=2)])
973 table.align = 'l'
974 print(table)
975
976
977 @cli.command(name='nsi-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
978 @click.argument('id')
979 @click.option('--filter', default=None)
980 @click.pass_context
981 def nsi_op_show1(ctx, id, filter):
982 """shows the info of an operation over a Network Slice Instance(NSI)
983
984 ID: operation identifier
985 """
986 nsi_op_show(ctx, id, filter)
987
988
989 @cli.command(name='netslice-instance-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
990 @click.argument('id')
991 @click.option('--filter', default=None)
992 @click.pass_context
993 def nsi_op_show2(ctx, id, filter):
994 """shows the info of an operation over a Network Slice Instance(NSI)
995
996 ID: operation identifier
997 """
998 nsi_op_show(ctx, id, filter)
999
1000
1001 @cli.command(name='pdu-show', short_help='shows the content of a Physical Deployment Unit (PDU)')
1002 @click.argument('name')
1003 @click.option('--literal', is_flag=True,
1004 help='print literally, no pretty table')
1005 @click.option('--filter', default=None)
1006 @click.pass_context
1007 def pdu_show(ctx, name, literal, filter):
1008 """shows the content of a Physical Deployment Unit (PDU)
1009
1010 NAME: name or ID of the PDU
1011 """
1012 try:
1013 check_client_version(ctx.obj, ctx.command.name)
1014 pdu = ctx.obj.pdu.get(name)
1015 except ClientException as inst:
1016 print((inst.message))
1017 exit(1)
1018
1019 if literal:
1020 print(yaml.safe_dump(pdu))
1021 return
1022
1023 table = PrettyTable(['field', 'value'])
1024
1025 for k, v in list(pdu.items()):
1026 if filter is None or filter in k:
1027 table.add_row([k, json.dumps(v, indent=2)])
1028
1029 table.align = 'l'
1030 print(table)
1031
1032
1033 ####################
1034 # CREATE operations
1035 ####################
1036
1037 def nsd_create(ctx, filename, overwrite):
1038 try:
1039 check_client_version(ctx.obj, ctx.command.name)
1040 ctx.obj.nsd.create(filename, overwrite)
1041 except ClientException as inst:
1042 print((inst.message))
1043 exit(1)
1044
1045
1046 @cli.command(name='nsd-create', short_help='creates a new NSD/NSpkg')
1047 @click.argument('filename')
1048 @click.option('--overwrite', default=None,
1049 help='overwrites some fields in NSD')
1050 @click.pass_context
1051 def nsd_create1(ctx, filename, overwrite):
1052 """creates a new NSD/NSpkg
1053
1054 FILENAME: NSD yaml file or NSpkg tar.gz file
1055 """
1056 nsd_create(ctx, filename, overwrite)
1057
1058
1059 @cli.command(name='nspkg-create', short_help='creates a new NSD/NSpkg')
1060 @click.argument('filename')
1061 @click.option('--overwrite', default=None,
1062 help='overwrites some fields in NSD')
1063 @click.pass_context
1064 def nsd_create2(ctx, filename, overwrite):
1065 """creates a new NSD/NSpkg
1066
1067 FILENAME: NSD yaml file or NSpkg tar.gz file
1068 """
1069 nsd_create(ctx, filename, overwrite)
1070
1071
1072 def vnfd_create(ctx, filename, overwrite):
1073 try:
1074 check_client_version(ctx.obj, ctx.command.name)
1075 ctx.obj.vnfd.create(filename, overwrite)
1076 except ClientException as inst:
1077 print((inst.message))
1078 exit(1)
1079
1080
1081 @cli.command(name='vnfd-create', short_help='creates a new VNFD/VNFpkg')
1082 @click.argument('filename')
1083 @click.option('--overwrite', default=None,
1084 help='overwrites some fields in VNFD')
1085 @click.pass_context
1086 def vnfd_create1(ctx, filename, overwrite):
1087 """creates a new VNFD/VNFpkg
1088
1089 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1090 """
1091 vnfd_create(ctx, filename, overwrite)
1092
1093
1094 @cli.command(name='vnfpkg-create', short_help='creates a new VNFD/VNFpkg')
1095 @click.argument('filename')
1096 @click.option('--overwrite', default=None,
1097 help='overwrites some fields in VNFD')
1098 @click.pass_context
1099 def vnfd_create2(ctx, filename, overwrite):
1100 """creates a new VNFD/VNFpkg
1101
1102 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1103 """
1104 vnfd_create(ctx, filename, overwrite)
1105
1106
1107 @cli.command(name='nfpkg-create', short_help='creates a new NFpkg')
1108 @click.argument('filename')
1109 @click.option('--overwrite', default=None,
1110 help='overwrites some fields in NFD')
1111 @click.pass_context
1112 def nfpkg_create(ctx, filename, overwrite):
1113 """creates a new NFpkg
1114
1115 FILENAME: NF Descriptor yaml file or NFpkg tar.gz file
1116 """
1117 vnfd_create(ctx, filename, overwrite)
1118
1119
1120 @cli.command(name='ns-create', short_help='creates a new Network Service instance')
1121 @click.option('--ns_name',
1122 prompt=True, help='name of the NS instance')
1123 @click.option('--nsd_name',
1124 prompt=True, help='name of the NS descriptor')
1125 @click.option('--vim_account',
1126 prompt=True, help='default VIM account id or name for the deployment')
1127 @click.option('--admin_status',
1128 default='ENABLED',
1129 help='administration status')
1130 @click.option('--ssh_keys',
1131 default=None,
1132 help='comma separated list of public key files to inject to vnfs')
1133 @click.option('--config',
1134 default=None,
1135 help='ns specific yaml configuration')
1136 @click.option('--config_file',
1137 default=None,
1138 help='ns specific yaml configuration file')
1139 @click.option('--wait',
1140 required=False,
1141 default=False,
1142 is_flag=True,
1143 help='do not return the control immediately, but keep it \
1144 until the operation is completed, or timeout')
1145 @click.pass_context
1146 def ns_create(ctx,
1147 nsd_name,
1148 ns_name,
1149 vim_account,
1150 admin_status,
1151 ssh_keys,
1152 config,
1153 config_file,
1154 wait):
1155 """creates a new NS instance"""
1156 try:
1157 if config_file:
1158 check_client_version(ctx.obj, '--config_file')
1159 if config:
1160 raise ClientException('"--config" option is incompatible with "--config_file" option')
1161 with open(config_file, 'r') as cf:
1162 config=cf.read()
1163 ctx.obj.ns.create(
1164 nsd_name,
1165 ns_name,
1166 config=config,
1167 ssh_keys=ssh_keys,
1168 account=vim_account,
1169 wait=wait)
1170 except ClientException as inst:
1171 print(inst.message)
1172 exit(1)
1173
1174
1175 def nst_create(ctx, filename, overwrite):
1176 try:
1177 check_client_version(ctx.obj, ctx.command.name)
1178 ctx.obj.nst.create(filename, overwrite)
1179 except ClientException as inst:
1180 print((inst.message))
1181 exit(1)
1182
1183
1184 @cli.command(name='nst-create', short_help='creates a new Network Slice Template (NST)')
1185 @click.argument('filename')
1186 @click.option('--overwrite', default=None,
1187 help='overwrites some fields in NST')
1188 @click.pass_context
1189 def nst_create1(ctx, filename, overwrite):
1190 """creates a new Network Slice Template (NST)
1191
1192 FILENAME: NST yaml file or NSTpkg tar.gz file
1193 """
1194 nst_create(ctx, filename, overwrite)
1195
1196
1197 @cli.command(name='netslice-template-create', short_help='creates a new Network Slice Template (NST)')
1198 @click.argument('filename')
1199 @click.option('--overwrite', default=None,
1200 help='overwrites some fields in NST')
1201 @click.pass_context
1202 def nst_create2(ctx, filename, overwrite):
1203 """creates a new Network Slice Template (NST)
1204
1205 FILENAME: NST yaml file or NSTpkg tar.gz file
1206 """
1207 nst_create(ctx, filename, overwrite)
1208
1209
1210 def nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1211 """creates a new Network Slice Instance (NSI)"""
1212 try:
1213 check_client_version(ctx.obj, ctx.command.name)
1214 if config_file:
1215 if config:
1216 raise ClientException('"--config" option is incompatible with "--config_file" option')
1217 with open(config_file, 'r') as cf:
1218 config=cf.read()
1219 ctx.obj.nsi.create(nst_name, nsi_name, config=config, ssh_keys=ssh_keys,
1220 account=vim_account, wait=wait)
1221 except ClientException as inst:
1222 print(inst.message)
1223 exit(1)
1224
1225
1226 @cli.command(name='nsi-create', short_help='creates a new Network Slice Instance')
1227 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1228 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1229 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1230 @click.option('--ssh_keys', default=None,
1231 help='comma separated list of keys to inject to vnfs')
1232 @click.option('--config', default=None,
1233 help='Netslice specific yaml configuration:\n'
1234 'netslice_subnet: [\n'
1235 'id: TEXT, vim_account: TEXT,\n'
1236 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1237 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1238 'additionalParamsForNsi: {param: value, ...}\n'
1239 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1240 '],\n'
1241 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1242 )
1243 @click.option('--config_file',
1244 default=None,
1245 help='nsi specific yaml configuration file')
1246 @click.option('--wait',
1247 required=False,
1248 default=False,
1249 is_flag=True,
1250 help='do not return the control immediately, but keep it \
1251 until the operation is completed, or timeout')
1252 @click.pass_context
1253 def nsi_create1(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1254 """creates a new Network Slice Instance (NSI)"""
1255 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1256
1257
1258 @cli.command(name='netslice-instance-create', short_help='creates a new Network Slice Instance')
1259 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1260 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1261 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1262 @click.option('--ssh_keys', default=None,
1263 help='comma separated list of keys to inject to vnfs')
1264 @click.option('--config', default=None,
1265 help='Netslice specific yaml configuration:\n'
1266 'netslice_subnet: [\n'
1267 'id: TEXT, vim_account: TEXT,\n'
1268 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1269 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1270 '],\n'
1271 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1272 )
1273 @click.option('--config_file',
1274 default=None,
1275 help='nsi specific yaml configuration file')
1276 @click.option('--wait',
1277 required=False,
1278 default=False,
1279 is_flag=True,
1280 help='do not return the control immediately, but keep it \
1281 until the operation is completed, or timeout')
1282 @click.pass_context
1283 def nsi_create2(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1284 """creates a new Network Slice Instance (NSI)"""
1285 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1286
1287
1288 @cli.command(name='pdu-create', short_help='adds a new Physical Deployment Unit to the catalog')
1289 @click.option('--name', help='name of the Physical Deployment Unit')
1290 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1291 @click.option('--interface',
1292 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1293 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1294 multiple=True)
1295 @click.option('--description', help='human readable description')
1296 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple=True)
1297 @click.option('--descriptor_file', default=None, help='PDU descriptor file (as an alternative to using the other arguments')
1298 @click.pass_context
1299 def pdu_create(ctx, name, pdu_type, interface, description, vim_account, descriptor_file):
1300 """creates a new Physical Deployment Unit (PDU)"""
1301 try:
1302 check_client_version(ctx.obj, ctx.command.name)
1303 pdu = {}
1304 if not descriptor_file:
1305 if not name:
1306 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1307 if not pdu_type:
1308 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1309 if not interface:
1310 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1311 if not vim_account:
1312 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1313 else:
1314 with open(descriptor_file, 'r') as df:
1315 pdu = yaml.load(df.read())
1316 if name: pdu["name"] = name
1317 if pdu_type: pdu["type"] = pdu_type
1318 if description: pdu["description"] = description
1319 if vim_account: pdu["vim_accounts"] = vim_account
1320 if interface:
1321 ifaces_list = []
1322 for iface in interface:
1323 new_iface={k:v for k,v in [i.split('=') for i in iface.split(',')]}
1324 new_iface["mgmt"] = (new_iface.get("mgmt","false").lower() == "true")
1325 ifaces_list.append(new_iface)
1326 pdu["interfaces"] = ifaces_list
1327 ctx.obj.pdu.create(pdu)
1328 except ClientException as inst:
1329 print((inst.message))
1330 exit(1)
1331
1332 ####################
1333 # UPDATE operations
1334 ####################
1335
1336 def nsd_update(ctx, name, content):
1337 try:
1338 check_client_version(ctx.obj, ctx.command.name)
1339 ctx.obj.nsd.update(name, content)
1340 except ClientException as inst:
1341 print((inst.message))
1342 exit(1)
1343
1344
1345 @cli.command(name='nsd-update', short_help='updates a NSD/NSpkg')
1346 @click.argument('name')
1347 @click.option('--content', default=None,
1348 help='filename with the NSD/NSpkg replacing the current one')
1349 @click.pass_context
1350 def nsd_update1(ctx, name, content):
1351 """updates a NSD/NSpkg
1352
1353 NAME: name or ID of the NSD/NSpkg
1354 """
1355 nsd_update(ctx, name, content)
1356
1357
1358 @cli.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
1359 @click.argument('name')
1360 @click.option('--content', default=None,
1361 help='filename with the NSD/NSpkg replacing the current one')
1362 @click.pass_context
1363 def nsd_update2(ctx, name, content):
1364 """updates a NSD/NSpkg
1365
1366 NAME: name or ID of the NSD/NSpkg
1367 """
1368 nsd_update(ctx, name, content)
1369
1370
1371 def vnfd_update(ctx, name, content):
1372 try:
1373 check_client_version(ctx.obj, ctx.command.name)
1374 ctx.obj.vnfd.update(name, content)
1375 except ClientException as inst:
1376 print((inst.message))
1377 exit(1)
1378
1379
1380 @cli.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
1381 @click.argument('name')
1382 @click.option('--content', default=None,
1383 help='filename with the VNFD/VNFpkg replacing the current one')
1384 @click.pass_context
1385 def vnfd_update1(ctx, name, content):
1386 """updates a VNFD/VNFpkg
1387
1388 NAME: name or ID of the VNFD/VNFpkg
1389 """
1390 vnfd_update(ctx, name, content)
1391
1392
1393 @cli.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
1394 @click.argument('name')
1395 @click.option('--content', default=None,
1396 help='filename with the VNFD/VNFpkg replacing the current one')
1397 @click.pass_context
1398 def vnfd_update2(ctx, name, content):
1399 """updates a VNFD/VNFpkg
1400
1401 NAME: VNFD yaml file or VNFpkg tar.gz file
1402 """
1403 vnfd_update(ctx, name, content)
1404
1405
1406 @cli.command(name='nfpkg-update', short_help='updates a NFpkg')
1407 @click.argument('name')
1408 @click.option('--content', default=None,
1409 help='filename with the NFpkg replacing the current one')
1410 @click.pass_context
1411 def nfpkg_update(ctx, name, content):
1412 """updates a NFpkg
1413
1414 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1415 """
1416 vnfd_update(ctx, name, content)
1417
1418
1419 def nst_update(ctx, name, content):
1420 try:
1421 check_client_version(ctx.obj, ctx.command.name)
1422 ctx.obj.nst.update(name, content)
1423 except ClientException as inst:
1424 print((inst.message))
1425 exit(1)
1426
1427
1428 @cli.command(name='nst-update', short_help='updates a Network Slice Template (NST)')
1429 @click.argument('name')
1430 @click.option('--content', default=None,
1431 help='filename with the NST/NSTpkg replacing the current one')
1432 @click.pass_context
1433 def nst_update1(ctx, name, content):
1434 """updates a Network Slice Template (NST)
1435
1436 NAME: name or ID of the NSD/NSpkg
1437 """
1438 nst_update(ctx, name, content)
1439
1440
1441 @cli.command(name='netslice-template-update', short_help='updates a Network Slice Template (NST)')
1442 @click.argument('name')
1443 @click.option('--content', default=None,
1444 help='filename with the NST/NSTpkg replacing the current one')
1445 @click.pass_context
1446 def nst_update2(ctx, name, content):
1447 """updates a Network Slice Template (NST)
1448
1449 NAME: name or ID of the NSD/NSpkg
1450 """
1451 nst_update(ctx, name, content)
1452
1453
1454 ####################
1455 # DELETE operations
1456 ####################
1457
1458 def nsd_delete(ctx, name, force):
1459 try:
1460 if not force:
1461 ctx.obj.nsd.delete(name)
1462 else:
1463 check_client_version(ctx.obj, '--force')
1464 ctx.obj.nsd.delete(name, force)
1465 except ClientException as inst:
1466 print((inst.message))
1467 exit(1)
1468
1469
1470 @cli.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
1471 @click.argument('name')
1472 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1473 @click.pass_context
1474 def nsd_delete1(ctx, name, force):
1475 """deletes a NSD/NSpkg
1476
1477 NAME: name or ID of the NSD/NSpkg to be deleted
1478 """
1479 nsd_delete(ctx, name, force)
1480
1481
1482 @cli.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
1483 @click.argument('name')
1484 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1485 @click.pass_context
1486 def nsd_delete2(ctx, name, force):
1487 """deletes a NSD/NSpkg
1488
1489 NAME: name or ID of the NSD/NSpkg to be deleted
1490 """
1491 nsd_delete(ctx, name, force)
1492
1493
1494 def vnfd_delete(ctx, name, force):
1495 try:
1496 if not force:
1497 ctx.obj.vnfd.delete(name)
1498 else:
1499 check_client_version(ctx.obj, '--force')
1500 ctx.obj.vnfd.delete(name, force)
1501 except ClientException as inst:
1502 print((inst.message))
1503 exit(1)
1504
1505
1506 @cli.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
1507 @click.argument('name')
1508 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1509 @click.pass_context
1510 def vnfd_delete1(ctx, name, force):
1511 """deletes a VNFD/VNFpkg
1512
1513 NAME: name or ID of the VNFD/VNFpkg to be deleted
1514 """
1515 vnfd_delete(ctx, name, force)
1516
1517
1518 @cli.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
1519 @click.argument('name')
1520 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1521 @click.pass_context
1522 def vnfd_delete2(ctx, name, force):
1523 """deletes a VNFD/VNFpkg
1524
1525 NAME: name or ID of the VNFD/VNFpkg to be deleted
1526 """
1527 vnfd_delete(ctx, name, force)
1528
1529
1530 @cli.command(name='nfpkg-delete', short_help='deletes a NFpkg')
1531 @click.argument('name')
1532 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1533 @click.pass_context
1534 def nfpkg_delete(ctx, name, force):
1535 """deletes a NFpkg
1536
1537 NAME: name or ID of the NFpkg to be deleted
1538 """
1539 vnfd_delete(ctx, name, force)
1540
1541
1542 @cli.command(name='ns-delete', short_help='deletes a NS instance')
1543 @click.argument('name')
1544 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1545 @click.option('--wait',
1546 required=False,
1547 default=False,
1548 is_flag=True,
1549 help='do not return the control immediately, but keep it \
1550 until the operation is completed, or timeout')
1551 @click.pass_context
1552 def ns_delete(ctx, name, force, wait):
1553 """deletes a NS instance
1554
1555 NAME: name or ID of the NS instance to be deleted
1556 """
1557 try:
1558 if not force:
1559 ctx.obj.ns.delete(name, wait=wait)
1560 else:
1561 check_client_version(ctx.obj, '--force')
1562 ctx.obj.ns.delete(name, force, wait=wait)
1563 except ClientException as inst:
1564 print((inst.message))
1565 exit(1)
1566
1567
1568 def nst_delete(ctx, name, force):
1569 try:
1570 check_client_version(ctx.obj, ctx.command.name)
1571 ctx.obj.nst.delete(name, force)
1572 except ClientException as inst:
1573 print((inst.message))
1574 exit(1)
1575
1576
1577 @cli.command(name='nst-delete', short_help='deletes a Network Slice Template (NST)')
1578 @click.argument('name')
1579 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1580 @click.pass_context
1581 def nst_delete1(ctx, name, force):
1582 """deletes a Network Slice Template (NST)
1583
1584 NAME: name or ID of the NST/NSTpkg to be deleted
1585 """
1586 nst_delete(ctx, name, force)
1587
1588
1589 @cli.command(name='netslice-template-delete', short_help='deletes a Network Slice Template (NST)')
1590 @click.argument('name')
1591 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1592 @click.pass_context
1593 def nst_delete2(ctx, name, force):
1594 """deletes a Network Slice Template (NST)
1595
1596 NAME: name or ID of the NST/NSTpkg to be deleted
1597 """
1598 nst_delete(ctx, name, force)
1599
1600
1601 def nsi_delete(ctx, name, force, wait):
1602 try:
1603 check_client_version(ctx.obj, ctx.command.name)
1604 ctx.obj.nsi.delete(name, force, wait=wait)
1605 except ClientException as inst:
1606 print((inst.message))
1607 exit(1)
1608
1609
1610 @cli.command(name='nsi-delete', short_help='deletes a Network Slice Instance (NSI)')
1611 @click.argument('name')
1612 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1613 @click.option('--wait',
1614 required=False,
1615 default=False,
1616 is_flag=True,
1617 help='do not return the control immediately, but keep it \
1618 until the operation is completed, or timeout')
1619 @click.pass_context
1620 def nsi_delete1(ctx, name, force, wait):
1621 """deletes a Network Slice Instance (NSI)
1622
1623 NAME: name or ID of the Network Slice instance to be deleted
1624 """
1625 nsi_delete(ctx, name, force, wait=wait)
1626
1627
1628 @cli.command(name='netslice-instance-delete', short_help='deletes a Network Slice Instance (NSI)')
1629 @click.argument('name')
1630 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1631 @click.pass_context
1632 def nsi_delete2(ctx, name, force, wait):
1633 """deletes a Network Slice Instance (NSI)
1634
1635 NAME: name or ID of the Network Slice instance to be deleted
1636 """
1637 nsi_delete(ctx, name, force, wait=wait)
1638
1639
1640 @cli.command(name='pdu-delete', short_help='deletes a Physical Deployment Unit (PDU)')
1641 @click.argument('name')
1642 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1643 @click.pass_context
1644 def pdu_delete(ctx, name, force):
1645 """deletes a Physical Deployment Unit (PDU)
1646
1647 NAME: name or ID of the PDU to be deleted
1648 """
1649 try:
1650 check_client_version(ctx.obj, ctx.command.name)
1651 ctx.obj.pdu.delete(name, force)
1652 except ClientException as inst:
1653 print((inst.message))
1654 exit(1)
1655
1656
1657 #################
1658 # VIM operations
1659 #################
1660
1661 @cli.command(name='vim-create')
1662 @click.option('--name',
1663 prompt=True,
1664 help='Name to create datacenter')
1665 @click.option('--user',
1666 prompt=True,
1667 help='VIM username')
1668 @click.option('--password',
1669 prompt=True,
1670 hide_input=True,
1671 confirmation_prompt=True,
1672 help='VIM password')
1673 @click.option('--auth_url',
1674 prompt=True,
1675 help='VIM url')
1676 @click.option('--tenant',
1677 prompt=True,
1678 help='VIM tenant name')
1679 @click.option('--config',
1680 default=None,
1681 help='VIM specific config parameters')
1682 @click.option('--account_type',
1683 default='openstack',
1684 help='VIM type')
1685 @click.option('--description',
1686 default='no description',
1687 help='human readable description')
1688 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1689 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1690 @click.option('--wait',
1691 required=False,
1692 default=False,
1693 is_flag=True,
1694 help='do not return the control immediately, but keep it \
1695 until the operation is completed, or timeout')
1696 @click.pass_context
1697 def vim_create(ctx,
1698 name,
1699 user,
1700 password,
1701 auth_url,
1702 tenant,
1703 config,
1704 account_type,
1705 description,
1706 sdn_controller,
1707 sdn_port_mapping,
1708 wait):
1709 """creates a new VIM account"""
1710 try:
1711 if sdn_controller:
1712 check_client_version(ctx.obj, '--sdn_controller')
1713 if sdn_port_mapping:
1714 check_client_version(ctx.obj, '--sdn_port_mapping')
1715 vim = {}
1716 vim['vim-username'] = user
1717 vim['vim-password'] = password
1718 vim['vim-url'] = auth_url
1719 vim['vim-tenant-name'] = tenant
1720 vim['vim-type'] = account_type
1721 vim['description'] = description
1722 vim['config'] = config
1723 if sdn_controller or sdn_port_mapping:
1724 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1725 else:
1726 ctx.obj.vim.create(name, vim, wait=wait)
1727 except ClientException as inst:
1728 print((inst.message))
1729 exit(1)
1730
1731
1732 @cli.command(name='vim-update', short_help='updates a VIM account')
1733 @click.argument('name')
1734 @click.option('--newname', help='New name for the VIM account')
1735 @click.option('--user', help='VIM username')
1736 @click.option('--password', help='VIM password')
1737 @click.option('--auth_url', help='VIM url')
1738 @click.option('--tenant', help='VIM tenant name')
1739 @click.option('--config', help='VIM specific config parameters')
1740 @click.option('--account_type', help='VIM type')
1741 @click.option('--description', help='human readable description')
1742 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1743 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1744 @click.option('--wait',
1745 required=False,
1746 default=False,
1747 is_flag=True,
1748 help='do not return the control immediately, but keep it \
1749 until the operation is completed, or timeout')
1750 @click.pass_context
1751 def vim_update(ctx,
1752 name,
1753 newname,
1754 user,
1755 password,
1756 auth_url,
1757 tenant,
1758 config,
1759 account_type,
1760 description,
1761 sdn_controller,
1762 sdn_port_mapping,
1763 wait):
1764 """updates a VIM account
1765
1766 NAME: name or ID of the VIM account
1767 """
1768 try:
1769 check_client_version(ctx.obj, ctx.command.name)
1770 vim = {}
1771 if newname: vim['name'] = newname
1772 if user: vim['vim_user'] = user
1773 if password: vim['vim_password'] = password
1774 if auth_url: vim['vim_url'] = auth_url
1775 if tenant: vim['vim-tenant-name'] = tenant
1776 if account_type: vim['vim_type'] = account_type
1777 if description: vim['description'] = description
1778 if config: vim['config'] = config
1779 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1780 except ClientException as inst:
1781 print((inst.message))
1782 exit(1)
1783
1784
1785 @cli.command(name='vim-delete')
1786 @click.argument('name')
1787 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1788 @click.option('--wait',
1789 required=False,
1790 default=False,
1791 is_flag=True,
1792 help='do not return the control immediately, but keep it \
1793 until the operation is completed, or timeout')
1794 @click.pass_context
1795 def vim_delete(ctx, name, force, wait):
1796 """deletes a VIM account
1797
1798 NAME: name or ID of the VIM account to be deleted
1799 """
1800 try:
1801 if not force:
1802 ctx.obj.vim.delete(name, wait=wait)
1803 else:
1804 check_client_version(ctx.obj, '--force')
1805 ctx.obj.vim.delete(name, force, wait=wait)
1806 except ClientException as inst:
1807 print((inst.message))
1808 exit(1)
1809
1810
1811 @cli.command(name='vim-list')
1812 @click.option('--ro_update/--no_ro_update',
1813 default=False,
1814 help='update list from RO')
1815 @click.option('--filter', default=None,
1816 help='restricts the list to the VIM accounts matching the filter')
1817 @click.pass_context
1818 def vim_list(ctx, ro_update, filter):
1819 """list all VIM accounts"""
1820 if filter:
1821 check_client_version(ctx.obj, '--filter')
1822 if ro_update:
1823 check_client_version(ctx.obj, '--ro_update', 'v1')
1824 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1825 if fullclassname == 'osmclient.sol005.client.Client':
1826 resp = ctx.obj.vim.list(filter)
1827 else:
1828 resp = ctx.obj.vim.list(ro_update)
1829 table = PrettyTable(['vim name', 'uuid'])
1830 for vim in resp:
1831 table.add_row([vim['name'], vim['uuid']])
1832 table.align = 'l'
1833 print(table)
1834
1835
1836 @cli.command(name='vim-show')
1837 @click.argument('name')
1838 @click.pass_context
1839 def vim_show(ctx, name):
1840 """shows the details of a VIM account
1841
1842 NAME: name or ID of the VIM account
1843 """
1844 try:
1845 resp = ctx.obj.vim.get(name)
1846 if 'vim_password' in resp:
1847 resp['vim_password']='********'
1848 except ClientException as inst:
1849 print((inst.message))
1850 exit(1)
1851
1852 table = PrettyTable(['key', 'attribute'])
1853 for k, v in list(resp.items()):
1854 table.add_row([k, json.dumps(v, indent=2)])
1855 table.align = 'l'
1856 print(table)
1857
1858
1859 ####################
1860 # WIM operations
1861 ####################
1862
1863 @cli.command(name='wim-create')
1864 @click.option('--name',
1865 prompt=True,
1866 help='Name for the WIM account')
1867 @click.option('--user',
1868 help='WIM username')
1869 @click.option('--password',
1870 help='WIM password')
1871 @click.option('--url',
1872 prompt=True,
1873 help='WIM url')
1874 # @click.option('--tenant',
1875 # help='wIM tenant name')
1876 @click.option('--config',
1877 default=None,
1878 help='WIM specific config parameters')
1879 @click.option('--wim_type',
1880 help='WIM type')
1881 @click.option('--description',
1882 default='no description',
1883 help='human readable description')
1884 @click.option('--wim_port_mapping', default=None, help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge (WAN service endpoint id and info)")
1885 @click.option('--wait',
1886 required=False,
1887 default=False,
1888 is_flag=True,
1889 help='do not return the control immediately, but keep it \
1890 until the operation is completed, or timeout')
1891 @click.pass_context
1892 def wim_create(ctx,
1893 name,
1894 user,
1895 password,
1896 url,
1897 # tenant,
1898 config,
1899 wim_type,
1900 description,
1901 wim_port_mapping,
1902 wait):
1903 """creates a new WIM account"""
1904 try:
1905 check_client_version(ctx.obj, ctx.command.name)
1906 # if sdn_controller:
1907 # check_client_version(ctx.obj, '--sdn_controller')
1908 # if sdn_port_mapping:
1909 # check_client_version(ctx.obj, '--sdn_port_mapping')
1910 wim = {}
1911 if user: wim['user'] = user
1912 if password: wim['password'] = password
1913 if url: wim['wim_url'] = url
1914 # if tenant: wim['tenant'] = tenant
1915 wim['wim_type'] = wim_type
1916 if description: wim['description'] = description
1917 if config: wim['config'] = config
1918 ctx.obj.wim.create(name, wim, wim_port_mapping, wait=wait)
1919 except ClientException as inst:
1920 print((inst.message))
1921 exit(1)
1922
1923
1924 @cli.command(name='wim-update', short_help='updates a WIM account')
1925 @click.argument('name')
1926 @click.option('--newname', help='New name for the WIM account')
1927 @click.option('--user', help='WIM username')
1928 @click.option('--password', help='WIM password')
1929 @click.option('--url', help='WIM url')
1930 @click.option('--config', help='WIM specific config parameters')
1931 @click.option('--wim_type', help='WIM type')
1932 @click.option('--description', help='human readable description')
1933 @click.option('--wim_port_mapping', default=None, help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge (WAN service endpoint id and info)")
1934 @click.option('--wait',
1935 required=False,
1936 default=False,
1937 is_flag=True,
1938 help='do not return the control immediately, but keep it \
1939 until the operation is completed, or timeout')
1940 @click.pass_context
1941 def wim_update(ctx,
1942 name,
1943 newname,
1944 user,
1945 password,
1946 url,
1947 config,
1948 wim_type,
1949 description,
1950 wim_port_mapping,
1951 wait):
1952 """updates a WIM account
1953
1954 NAME: name or ID of the WIM account
1955 """
1956 try:
1957 check_client_version(ctx.obj, ctx.command.name)
1958 wim = {}
1959 if newname: wim['name'] = newname
1960 if user: wim['user'] = user
1961 if password: wim['password'] = password
1962 if url: wim['url'] = url
1963 # if tenant: wim['tenant'] = tenant
1964 if wim_type: wim['wim_type'] = wim_type
1965 if description: wim['description'] = description
1966 if config: wim['config'] = config
1967 ctx.obj.wim.update(name, wim, wim_port_mapping, wait=wait)
1968 except ClientException as inst:
1969 print((inst.message))
1970 exit(1)
1971
1972
1973 @cli.command(name='wim-delete')
1974 @click.argument('name')
1975 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1976 @click.option('--wait',
1977 required=False,
1978 default=False,
1979 is_flag=True,
1980 help='do not return the control immediately, but keep it \
1981 until the operation is completed, or timeout')
1982 @click.pass_context
1983 def wim_delete(ctx, name, force, wait):
1984 """deletes a WIM account
1985
1986 NAME: name or ID of the WIM account to be deleted
1987 """
1988 try:
1989 check_client_version(ctx.obj, ctx.command.name)
1990 ctx.obj.wim.delete(name, force, wait=wait)
1991 except ClientException as inst:
1992 print((inst.message))
1993 exit(1)
1994
1995
1996 @cli.command(name='wim-list')
1997 @click.option('--filter', default=None,
1998 help='restricts the list to the WIM accounts matching the filter')
1999 @click.pass_context
2000 def wim_list(ctx, filter):
2001 """list all WIM accounts"""
2002 try:
2003 check_client_version(ctx.obj, ctx.command.name)
2004 resp = ctx.obj.wim.list(filter)
2005 table = PrettyTable(['wim name', 'uuid'])
2006 for wim in resp:
2007 table.add_row([wim['name'], wim['uuid']])
2008 table.align = 'l'
2009 print(table)
2010 except ClientException as inst:
2011 print((inst.message))
2012 exit(1)
2013
2014
2015 @cli.command(name='wim-show')
2016 @click.argument('name')
2017 @click.pass_context
2018 def wim_show(ctx, name):
2019 """shows the details of a WIM account
2020
2021 NAME: name or ID of the WIM account
2022 """
2023 try:
2024 check_client_version(ctx.obj, ctx.command.name)
2025 resp = ctx.obj.wim.get(name)
2026 if 'password' in resp:
2027 resp['wim_password']='********'
2028 except ClientException as inst:
2029 print((inst.message))
2030 exit(1)
2031
2032 table = PrettyTable(['key', 'attribute'])
2033 for k, v in list(resp.items()):
2034 table.add_row([k, json.dumps(v, indent=2)])
2035 table.align = 'l'
2036 print(table)
2037
2038
2039 ####################
2040 # SDN controller operations
2041 ####################
2042
2043 @cli.command(name='sdnc-create')
2044 @click.option('--name',
2045 prompt=True,
2046 help='Name to create sdn controller')
2047 @click.option('--type',
2048 prompt=True,
2049 help='SDN controller type')
2050 @click.option('--sdn_controller_version',
2051 help='SDN controller version')
2052 @click.option('--ip_address',
2053 prompt=True,
2054 help='SDN controller IP address')
2055 @click.option('--port',
2056 prompt=True,
2057 help='SDN controller port')
2058 @click.option('--switch_dpid',
2059 prompt=True,
2060 help='Switch DPID (Openflow Datapath ID)')
2061 @click.option('--user',
2062 help='SDN controller username')
2063 @click.option('--password',
2064 hide_input=True,
2065 confirmation_prompt=True,
2066 help='SDN controller password')
2067 #@click.option('--description',
2068 # default='no description',
2069 # help='human readable description')
2070 @click.option('--wait',
2071 required=False,
2072 default=False,
2073 is_flag=True,
2074 help='do not return the control immediately, but keep it \
2075 until the operation is completed, or timeout')
2076 @click.pass_context
2077 def sdnc_create(ctx,
2078 name,
2079 type,
2080 sdn_controller_version,
2081 ip_address,
2082 port,
2083 switch_dpid,
2084 user,
2085 password,
2086 wait):
2087 """creates a new SDN controller"""
2088 sdncontroller = {}
2089 sdncontroller['name'] = name
2090 sdncontroller['type'] = type
2091 sdncontroller['ip'] = ip_address
2092 sdncontroller['port'] = int(port)
2093 sdncontroller['dpid'] = switch_dpid
2094 if sdn_controller_version:
2095 sdncontroller['version'] = sdn_controller_version
2096 if user:
2097 sdncontroller['user'] = user
2098 if password:
2099 sdncontroller['password'] = password
2100 # sdncontroller['description'] = description
2101 try:
2102 check_client_version(ctx.obj, ctx.command.name)
2103 ctx.obj.sdnc.create(name, sdncontroller, wait=wait)
2104 except ClientException as inst:
2105 print((inst.message))
2106 exit(1)
2107
2108 @cli.command(name='sdnc-update', short_help='updates an SDN controller')
2109 @click.argument('name')
2110 @click.option('--newname', help='New name for the SDN controller')
2111 @click.option('--type', help='SDN controller type')
2112 @click.option('--sdn_controller_version', help='SDN controller username')
2113 @click.option('--ip_address', help='SDN controller IP address')
2114 @click.option('--port', help='SDN controller port')
2115 @click.option('--switch_dpid', help='Switch DPID (Openflow Datapath ID)')
2116 @click.option('--user', help='SDN controller username')
2117 @click.option('--password', help='SDN controller password')
2118 #@click.option('--description', default=None, help='human readable description')
2119 @click.option('--wait',
2120 required=False,
2121 default=False,
2122 is_flag=True,
2123 help='do not return the control immediately, but keep it \
2124 until the operation is completed, or timeout')
2125 @click.pass_context
2126 def sdnc_update(ctx,
2127 name,
2128 newname,
2129 type,
2130 sdn_controller_version,
2131 ip_address,
2132 port,
2133 switch_dpid,
2134 user,
2135 password,
2136 wait):
2137 """updates an SDN controller
2138
2139 NAME: name or ID of the SDN controller
2140 """
2141 sdncontroller = {}
2142 if newname: sdncontroller['name'] = newname
2143 if type: sdncontroller['type'] = type
2144 if ip_address: sdncontroller['ip'] = ip_address
2145 if port: sdncontroller['port'] = int(port)
2146 if switch_dpid: sdncontroller['dpid'] = switch_dpid
2147 # sdncontroller['description'] = description
2148 if sdn_controller_version is not None:
2149 if sdn_controller_version=="":
2150 sdncontroller['version'] = None
2151 else:
2152 sdncontroller['version'] = sdn_controller_version
2153 if user is not None:
2154 if user=="":
2155 sdncontroller['user'] = None
2156 else:
2157 sdncontroller['user'] = user
2158 if password is not None:
2159 if password=="":
2160 sdncontroller['password'] = None
2161 else:
2162 sdncontroller['password'] = user
2163 try:
2164 check_client_version(ctx.obj, ctx.command.name)
2165 ctx.obj.sdnc.update(name, sdncontroller, wait=wait)
2166 except ClientException as inst:
2167 print((inst.message))
2168 exit(1)
2169
2170
2171 @cli.command(name='sdnc-delete')
2172 @click.argument('name')
2173 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2174 @click.option('--wait',
2175 required=False,
2176 default=False,
2177 is_flag=True,
2178 help='do not return the control immediately, but keep it \
2179 until the operation is completed, or timeout')
2180 @click.pass_context
2181 def sdnc_delete(ctx, name, force, wait):
2182 """deletes an SDN controller
2183
2184 NAME: name or ID of the SDN controller to be deleted
2185 """
2186 try:
2187 check_client_version(ctx.obj, ctx.command.name)
2188 ctx.obj.sdnc.delete(name, force, wait=wait)
2189 except ClientException as inst:
2190 print((inst.message))
2191 exit(1)
2192
2193
2194 @cli.command(name='sdnc-list')
2195 @click.option('--filter', default=None,
2196 help='restricts the list to the SDN controllers matching the filter')
2197 @click.pass_context
2198 def sdnc_list(ctx, filter):
2199 """list all SDN controllers"""
2200 try:
2201 check_client_version(ctx.obj, ctx.command.name)
2202 resp = ctx.obj.sdnc.list(filter)
2203 except ClientException as inst:
2204 print((inst.message))
2205 exit(1)
2206 table = PrettyTable(['sdnc name', 'id'])
2207 for sdnc in resp:
2208 table.add_row([sdnc['name'], sdnc['_id']])
2209 table.align = 'l'
2210 print(table)
2211
2212
2213 @cli.command(name='sdnc-show')
2214 @click.argument('name')
2215 @click.pass_context
2216 def sdnc_show(ctx, name):
2217 """shows the details of an SDN controller
2218
2219 NAME: name or ID of the SDN controller
2220 """
2221 try:
2222 check_client_version(ctx.obj, ctx.command.name)
2223 resp = ctx.obj.sdnc.get(name)
2224 except ClientException as inst:
2225 print((inst.message))
2226 exit(1)
2227
2228 table = PrettyTable(['key', 'attribute'])
2229 for k, v in list(resp.items()):
2230 table.add_row([k, json.dumps(v, indent=2)])
2231 table.align = 'l'
2232 print(table)
2233
2234
2235 ####################
2236 # Project mgmt operations
2237 ####################
2238
2239 @cli.command(name='project-create')
2240 @click.argument('name')
2241 #@click.option('--description',
2242 # default='no description',
2243 # help='human readable description')
2244 @click.pass_context
2245 def project_create(ctx, name):
2246 """Creates a new project
2247
2248 NAME: name of the project
2249 """
2250 project = {}
2251 project['name'] = name
2252 try:
2253 check_client_version(ctx.obj, ctx.command.name)
2254 ctx.obj.project.create(name, project)
2255 except ClientException as inst:
2256 print(inst.message)
2257 exit(1)
2258
2259
2260 @cli.command(name='project-delete')
2261 @click.argument('name')
2262 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2263 @click.pass_context
2264 def project_delete(ctx, name):
2265 """deletes a project
2266
2267 NAME: name or ID of the project to be deleted
2268 """
2269 try:
2270 check_client_version(ctx.obj, ctx.command.name)
2271 ctx.obj.project.delete(name)
2272 except ClientException as inst:
2273 print(inst.message)
2274 exit(1)
2275
2276
2277 @cli.command(name='project-list')
2278 @click.option('--filter', default=None,
2279 help='restricts the list to the projects matching the filter')
2280 @click.pass_context
2281 def project_list(ctx, filter):
2282 """list all projects"""
2283 try:
2284 check_client_version(ctx.obj, ctx.command.name)
2285 resp = ctx.obj.project.list(filter)
2286 except ClientException as inst:
2287 print(inst.message)
2288 exit(1)
2289 table = PrettyTable(['name', 'id'])
2290 for proj in resp:
2291 table.add_row([proj['name'], proj['_id']])
2292 table.align = 'l'
2293 print(table)
2294
2295
2296 @cli.command(name='project-show')
2297 @click.argument('name')
2298 @click.pass_context
2299 def project_show(ctx, name):
2300 """shows the details of a project
2301
2302 NAME: name or ID of the project
2303 """
2304 try:
2305 check_client_version(ctx.obj, ctx.command.name)
2306 resp = ctx.obj.project.get(name)
2307 except ClientException as inst:
2308 print(inst.message)
2309 exit(1)
2310
2311 table = PrettyTable(['key', 'attribute'])
2312 for k, v in resp.items():
2313 table.add_row([k, json.dumps(v, indent=2)])
2314 table.align = 'l'
2315 print(table)
2316
2317
2318 @cli.command(name='project-update')
2319 @click.argument('project')
2320 @click.option('--name',
2321 prompt=True,
2322 help='new name for the project')
2323
2324 @click.pass_context
2325 def project_update(ctx, project, name):
2326 """
2327 Update a project name
2328
2329 :param ctx:
2330 :param project: id or name of the project to modify
2331 :param name: new name for the project
2332 :return:
2333 """
2334
2335 project_changes = {}
2336 project_changes['name'] = name
2337
2338 try:
2339 check_client_version(ctx.obj, ctx.command.name)
2340 ctx.obj.project.update(project, project_changes)
2341 except ClientException as inst:
2342 print(inst.message)
2343
2344
2345 ####################
2346 # User mgmt operations
2347 ####################
2348
2349 @cli.command(name='user-create')
2350 @click.argument('username')
2351 @click.option('--password',
2352 prompt=True,
2353 hide_input=True,
2354 confirmation_prompt=True,
2355 help='user password')
2356 @click.option('--projects',
2357 # prompt="Comma separate list of projects",
2358 multiple=True,
2359 callback=lambda ctx, param, value: ''.join(value).split(',') if all(len(x)==1 for x in value) else value,
2360 help='list of project ids that the user belongs to')
2361 @click.option('--project-role-mappings', 'project_role_mappings',
2362 default=None, multiple=True,
2363 help='creating user project/role(s) mapping')
2364 @click.pass_context
2365 def user_create(ctx, username, password, projects, project_role_mappings):
2366 """Creates a new user
2367
2368 \b
2369 USERNAME: name of the user
2370 PASSWORD: password of the user
2371 PROJECTS: projects assigned to user (internal only)
2372 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
2373 """
2374 user = {}
2375 user['username'] = username
2376 user['password'] = password
2377 user['projects'] = projects
2378 user['project_role_mappings'] = project_role_mappings
2379
2380 try:
2381 check_client_version(ctx.obj, ctx.command.name)
2382 ctx.obj.user.create(username, user)
2383 except ClientException as inst:
2384 print(inst.message)
2385 exit(1)
2386
2387
2388 @cli.command(name='user-update')
2389 @click.argument('username')
2390 @click.option('--password',
2391 # prompt=True,
2392 # hide_input=True,
2393 # confirmation_prompt=True,
2394 help='user password')
2395 @click.option('--set-username', 'set_username',
2396 default=None,
2397 help='change username')
2398 @click.option('--set-project', 'set_project',
2399 default=None, multiple=True,
2400 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
2401 @click.option('--remove-project', 'remove_project',
2402 default=None, multiple=True,
2403 help='removes project from user: \'project\'')
2404 @click.option('--add-project-role', 'add_project_role',
2405 default=None, multiple=True,
2406 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
2407 @click.option('--remove-project-role', 'remove_project_role',
2408 default=None, multiple=True,
2409 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
2410 @click.pass_context
2411 def user_update(ctx, username, password, set_username, set_project, remove_project,
2412 add_project_role, remove_project_role):
2413 """Update a user information
2414
2415 \b
2416 USERNAME: name of the user
2417 PASSWORD: new password
2418 SET_USERNAME: new username
2419 SET_PROJECT: creating mappings for project/role(s)
2420 REMOVE_PROJECT: deleting mappings for project/role(s)
2421 ADD_PROJECT_ROLE: adding mappings for project/role(s)
2422 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
2423 """
2424 user = {}
2425 user['password'] = password
2426 user['username'] = set_username
2427 user['set-project'] = set_project
2428 user['remove-project'] = remove_project
2429 user['add-project-role'] = add_project_role
2430 user['remove-project-role'] = remove_project_role
2431
2432 try:
2433 check_client_version(ctx.obj, ctx.command.name)
2434 ctx.obj.user.update(username, user)
2435 except ClientException as inst:
2436 print(inst.message)
2437 exit(1)
2438
2439
2440 @cli.command(name='user-delete')
2441 @click.argument('name')
2442 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2443 @click.pass_context
2444 def user_delete(ctx, name):
2445 """deletes a user
2446
2447 \b
2448 NAME: name or ID of the user to be deleted
2449 """
2450 try:
2451 check_client_version(ctx.obj, ctx.command.name)
2452 ctx.obj.user.delete(name)
2453 except ClientException as inst:
2454 print(inst.message)
2455 exit(1)
2456
2457
2458 @cli.command(name='user-list')
2459 @click.option('--filter', default=None,
2460 help='restricts the list to the users matching the filter')
2461 @click.pass_context
2462 def user_list(ctx, filter):
2463 """list all users"""
2464 try:
2465 check_client_version(ctx.obj, ctx.command.name)
2466 resp = ctx.obj.user.list(filter)
2467 except ClientException as inst:
2468 print(inst.message)
2469 exit(1)
2470 table = PrettyTable(['name', 'id'])
2471 for user in resp:
2472 table.add_row([user['username'], user['_id']])
2473 table.align = 'l'
2474 print(table)
2475
2476
2477 @cli.command(name='user-show')
2478 @click.argument('name')
2479 @click.pass_context
2480 def user_show(ctx, name):
2481 """shows the details of a user
2482
2483 NAME: name or ID of the user
2484 """
2485 try:
2486 check_client_version(ctx.obj, ctx.command.name)
2487 resp = ctx.obj.user.get(name)
2488 if 'password' in resp:
2489 resp['password']='********'
2490 except ClientException as inst:
2491 print(inst.message)
2492 exit(1)
2493
2494 table = PrettyTable(['key', 'attribute'])
2495 for k, v in resp.items():
2496 table.add_row([k, json.dumps(v, indent=2)])
2497 table.align = 'l'
2498 print(table)
2499
2500
2501 ####################
2502 # Fault Management operations
2503 ####################
2504
2505 @cli.command(name='ns-alarm-create')
2506 @click.argument('name')
2507 @click.option('--ns', prompt=True, help='NS instance id or name')
2508 @click.option('--vnf', prompt=True,
2509 help='VNF name (VNF member index as declared in the NSD)')
2510 @click.option('--vdu', prompt=True,
2511 help='VDU name (VDU name as declared in the VNFD)')
2512 @click.option('--metric', prompt=True,
2513 help='Name of the metric (e.g. cpu_utilization)')
2514 @click.option('--severity', default='WARNING',
2515 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
2516 @click.option('--threshold_value', prompt=True,
2517 help='threshold value that, when crossed, an alarm is triggered')
2518 @click.option('--threshold_operator', prompt=True,
2519 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
2520 @click.option('--statistic', default='AVERAGE',
2521 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
2522 @click.pass_context
2523 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
2524 threshold_value, threshold_operator, statistic):
2525 """creates a new alarm for a NS instance"""
2526 # TODO: Check how to validate threshold_value.
2527 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
2528 try:
2529 ns_instance = ctx.obj.ns.get(ns)
2530 alarm = {}
2531 alarm['alarm_name'] = name
2532 alarm['ns_id'] = ns_instance['_id']
2533 alarm['correlation_id'] = ns_instance['_id']
2534 alarm['vnf_member_index'] = vnf
2535 alarm['vdu_name'] = vdu
2536 alarm['metric_name'] = metric
2537 alarm['severity'] = severity
2538 alarm['threshold_value'] = int(threshold_value)
2539 alarm['operation'] = threshold_operator
2540 alarm['statistic'] = statistic
2541 check_client_version(ctx.obj, ctx.command.name)
2542 ctx.obj.ns.create_alarm(alarm)
2543 except ClientException as inst:
2544 print((inst.message))
2545 exit(1)
2546
2547
2548 #@cli.command(name='ns-alarm-delete')
2549 #@click.argument('name')
2550 #@click.pass_context
2551 #def ns_alarm_delete(ctx, name):
2552 # """deletes an alarm
2553 #
2554 # NAME: name of the alarm to be deleted
2555 # """
2556 # try:
2557 # check_client_version(ctx.obj, ctx.command.name)
2558 # ctx.obj.ns.delete_alarm(name)
2559 # except ClientException as inst:
2560 # print(inst.message)
2561 # exit(1)
2562
2563
2564 ####################
2565 # Performance Management operations
2566 ####################
2567
2568 @cli.command(name='ns-metric-export')
2569 @click.option('--ns', prompt=True, help='NS instance id or name')
2570 @click.option('--vnf', prompt=True,
2571 help='VNF name (VNF member index as declared in the NSD)')
2572 @click.option('--vdu', prompt=True,
2573 help='VDU name (VDU name as declared in the VNFD)')
2574 @click.option('--metric', prompt=True,
2575 help='name of the metric (e.g. cpu_utilization)')
2576 #@click.option('--period', default='1w',
2577 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
2578 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
2579 @click.pass_context
2580 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
2581 """exports a metric to the internal OSM bus, which can be read by other apps"""
2582 # TODO: Check how to validate interval.
2583 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
2584 try:
2585 ns_instance = ctx.obj.ns.get(ns)
2586 metric_data = {}
2587 metric_data['ns_id'] = ns_instance['_id']
2588 metric_data['correlation_id'] = ns_instance['_id']
2589 metric_data['vnf_member_index'] = vnf
2590 metric_data['vdu_name'] = vdu
2591 metric_data['metric_name'] = metric
2592 metric_data['collection_unit'] = 'WEEK'
2593 metric_data['collection_period'] = 1
2594 check_client_version(ctx.obj, ctx.command.name)
2595 if not interval:
2596 print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
2597 else:
2598 i = 1
2599 while True:
2600 print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
2601 time.sleep(int(interval))
2602 i+=1
2603 except ClientException as inst:
2604 print((inst.message))
2605 exit(1)
2606
2607
2608 ####################
2609 # Other operations
2610 ####################
2611
2612 @cli.command(name='upload-package')
2613 @click.argument('filename')
2614 @click.pass_context
2615 def upload_package(ctx, filename):
2616 """uploads a VNF package or NS package
2617
2618 FILENAME: VNF or NS package file (tar.gz)
2619 """
2620 try:
2621 ctx.obj.package.upload(filename)
2622 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
2623 if fullclassname != 'osmclient.sol005.client.Client':
2624 ctx.obj.package.wait_for_upload(filename)
2625 except ClientException as inst:
2626 print((inst.message))
2627 exit(1)
2628
2629
2630 @cli.command(name='ns-scaling-show')
2631 @click.argument('ns_name')
2632 @click.pass_context
2633 def show_ns_scaling(ctx, ns_name):
2634 """shows the status of a NS scaling operation
2635
2636 NS_NAME: name of the NS instance being scaled
2637 """
2638 try:
2639 check_client_version(ctx.obj, ctx.command.name, 'v1')
2640 resp = ctx.obj.ns.list()
2641 except ClientException as inst:
2642 print((inst.message))
2643 exit(1)
2644
2645 table = PrettyTable(
2646 ['group-name',
2647 'instance-id',
2648 'operational status',
2649 'create-time',
2650 'vnfr ids'])
2651
2652 for ns in resp:
2653 if ns_name == ns['name']:
2654 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
2655 scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
2656 for record in scaling_records:
2657 if 'instance' in record:
2658 instances = record['instance']
2659 for inst in instances:
2660 table.add_row(
2661 [record['scaling-group-name-ref'],
2662 inst['instance-id'],
2663 inst['op-status'],
2664 time.strftime('%Y-%m-%d %H:%M:%S',
2665 time.localtime(
2666 inst['create-time'])),
2667 inst['vnfrs']])
2668 table.align = 'l'
2669 print(table)
2670
2671
2672 @cli.command(name='ns-scale')
2673 @click.argument('ns_name')
2674 @click.option('--ns_scale_group', prompt=True)
2675 @click.option('--index', prompt=True)
2676 @click.option('--wait',
2677 required=False,
2678 default=False,
2679 is_flag=True,
2680 help='do not return the control immediately, but keep it \
2681 until the operation is completed, or timeout')
2682 @click.pass_context
2683 def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
2684 """scales NS
2685
2686 NS_NAME: name of the NS instance to be scaled
2687 """
2688 try:
2689 check_client_version(ctx.obj, ctx.command.name, 'v1')
2690 ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
2691 except ClientException as inst:
2692 print((inst.message))
2693 exit(1)
2694
2695
2696 @cli.command(name='config-agent-list')
2697 @click.pass_context
2698 def config_agent_list(ctx):
2699 """list config agents"""
2700 try:
2701 check_client_version(ctx.obj, ctx.command.name, 'v1')
2702 except ClientException as inst:
2703 print((inst.message))
2704 exit(1)
2705 table = PrettyTable(['name', 'account-type', 'details'])
2706 for account in ctx.obj.vca.list():
2707 table.add_row(
2708 [account['name'],
2709 account['account-type'],
2710 account['juju']])
2711 table.align = 'l'
2712 print(table)
2713
2714
2715 @cli.command(name='config-agent-delete')
2716 @click.argument('name')
2717 @click.pass_context
2718 def config_agent_delete(ctx, name):
2719 """deletes a config agent
2720
2721 NAME: name of the config agent to be deleted
2722 """
2723 try:
2724 check_client_version(ctx.obj, ctx.command.name, 'v1')
2725 ctx.obj.vca.delete(name)
2726 except ClientException as inst:
2727 print((inst.message))
2728 exit(1)
2729
2730
2731 @cli.command(name='config-agent-add')
2732 @click.option('--name',
2733 prompt=True)
2734 @click.option('--account_type',
2735 prompt=True)
2736 @click.option('--server',
2737 prompt=True)
2738 @click.option('--user',
2739 prompt=True)
2740 @click.option('--secret',
2741 prompt=True,
2742 hide_input=True,
2743 confirmation_prompt=True)
2744 @click.pass_context
2745 def config_agent_add(ctx, name, account_type, server, user, secret):
2746 """adds a config agent"""
2747 try:
2748 check_client_version(ctx.obj, ctx.command.name, 'v1')
2749 ctx.obj.vca.create(name, account_type, server, user, secret)
2750 except ClientException as inst:
2751 print((inst.message))
2752 exit(1)
2753
2754
2755 @cli.command(name='ro-dump')
2756 @click.pass_context
2757 def ro_dump(ctx):
2758 """shows RO agent information"""
2759 check_client_version(ctx.obj, ctx.command.name, 'v1')
2760 resp = ctx.obj.vim.get_resource_orchestrator()
2761 table = PrettyTable(['key', 'attribute'])
2762 for k, v in list(resp.items()):
2763 table.add_row([k, json.dumps(v, indent=2)])
2764 table.align = 'l'
2765 print(table)
2766
2767
2768 @cli.command(name='vcs-list')
2769 @click.pass_context
2770 def vcs_list(ctx):
2771 check_client_version(ctx.obj, ctx.command.name, 'v1')
2772 resp = ctx.obj.utils.get_vcs_info()
2773 table = PrettyTable(['component name', 'state'])
2774 for component in resp:
2775 table.add_row([component['component_name'], component['state']])
2776 table.align = 'l'
2777 print(table)
2778
2779
2780 @cli.command(name='ns-action')
2781 @click.argument('ns_name')
2782 @click.option('--vnf_name', default=None)
2783 @click.option('--action_name', prompt=True)
2784 @click.option('--params', prompt=True)
2785 @click.option('--wait',
2786 required=False,
2787 default=False,
2788 is_flag=True,
2789 help='do not return the control immediately, but keep it \
2790 until the operation is completed, or timeout')
2791 @click.pass_context
2792 def ns_action(ctx,
2793 ns_name,
2794 vnf_name,
2795 action_name,
2796 params,
2797 wait):
2798 """executes an action/primitive over a NS instance
2799
2800 NS_NAME: name or ID of the NS instance
2801 """
2802 try:
2803 check_client_version(ctx.obj, ctx.command.name)
2804 op_data={}
2805 if vnf_name:
2806 op_data['vnf_member_index'] = vnf_name
2807 op_data['primitive'] = action_name
2808 op_data['primitive_params'] = yaml.load(params)
2809 ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data, wait=wait)
2810
2811 except ClientException as inst:
2812 print((inst.message))
2813 exit(1)
2814
2815
2816 @cli.command(name='vnf-scale')
2817 @click.argument('ns_name')
2818 @click.argument('vnf_name')
2819 @click.option('--scaling-group', prompt=True, help="scaling-group-descriptor name to use")
2820 @click.option('--scale-in', default=False, is_flag=True, help="performs a scale in operation")
2821 @click.option('--scale-out', default=False, is_flag=True, help="performs a scale out operation (by default)")
2822 @click.pass_context
2823 def vnf_scale(ctx,
2824 ns_name,
2825 vnf_name,
2826 scaling_group,
2827 scale_in,
2828 scale_out):
2829 """
2830 Executes a VNF scale (adding/removing VDUs)
2831
2832 \b
2833 NS_NAME: name or ID of the NS instance.
2834 VNF_NAME: member-vnf-index in the NS to be scaled.
2835 """
2836 try:
2837 check_client_version(ctx.obj, ctx.command.name)
2838 if not scale_in and not scale_out:
2839 scale_out = True
2840 ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out)
2841 except ClientException as inst:
2842 print((inst.message))
2843 exit(1)
2844
2845
2846 ##############################
2847 # Role Management Operations #
2848 ##############################
2849
2850 @cli.command(name='role-create', short_help='creates a role')
2851 @click.argument('name')
2852 @click.option('--permissions',
2853 default=None,
2854 help='role permissions using a dictionary')
2855 @click.pass_context
2856 def role_create(ctx, name, permissions):
2857 """
2858 Creates a new role.
2859
2860 \b
2861 NAME: Name or ID of the role.
2862 DEFINITION: Definition of grant/denial of access to resources.
2863 """
2864 try:
2865 check_client_version(ctx.obj, ctx.command.name)
2866 ctx.obj.role.create(name, permissions)
2867 except ClientException as inst:
2868 print(inst.message)
2869 exit(1)
2870
2871
2872 @cli.command(name='role-update', short_help='updates a role')
2873 @click.argument('name')
2874 @click.option('--set-name',
2875 default=None,
2876 help='change name of rle')
2877 # @click.option('--permissions',
2878 # default=None,
2879 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
2880 @click.option('--add',
2881 default=None,
2882 help='yaml format dictionary with permission: True/False to access grant/denial')
2883 @click.option('--remove',
2884 default=None,
2885 help='yaml format list to remove a permission')
2886 @click.pass_context
2887 def role_update(ctx, name, set_name, add, remove):
2888 """
2889 Updates a role.
2890
2891 \b
2892 NAME: Name or ID of the role.
2893 DEFINITION: Definition overwrites the old definition.
2894 ADD: Grant/denial of access to resource to add.
2895 REMOVE: Grant/denial of access to resource to remove.
2896 """
2897 try:
2898 check_client_version(ctx.obj, ctx.command.name)
2899 ctx.obj.role.update(name, set_name, None, add, remove)
2900 except ClientException as inst:
2901 print(inst.message)
2902 exit(1)
2903
2904
2905 @cli.command(name='role-delete', short_help='deletes a role')
2906 @click.argument('name')
2907 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2908 @click.pass_context
2909 def role_delete(ctx, name):
2910 """
2911 Deletes a role.
2912
2913 \b
2914 NAME: Name or ID of the role.
2915 """
2916 try:
2917 check_client_version(ctx.obj, ctx.command.name)
2918 ctx.obj.role.delete(name)
2919 except ClientException as inst:
2920 print(inst.message)
2921 exit(1)
2922
2923
2924 @cli.command(name='role-list', short_help='list all roles')
2925 @click.option('--filter', default=None,
2926 help='restricts the list to the projects matching the filter')
2927 @click.pass_context
2928 def role_list(ctx, filter):
2929 """
2930 List all roles.
2931 """
2932 try:
2933 check_client_version(ctx.obj, ctx.command.name)
2934 resp = ctx.obj.role.list(filter)
2935 except ClientException as inst:
2936 print(inst.message)
2937 exit(1)
2938 table = PrettyTable(['name', 'id'])
2939 for role in resp:
2940 table.add_row([role['name'], role['_id']])
2941 table.align = 'l'
2942 print(table)
2943
2944
2945 @cli.command(name='role-show', short_help='show specific role')
2946 @click.argument('name')
2947 @click.pass_context
2948 def role_show(ctx, name):
2949 """
2950 Shows the details of a role.
2951
2952 \b
2953 NAME: Name or ID of the role.
2954 """
2955 try:
2956 check_client_version(ctx.obj, ctx.command.name)
2957 resp = ctx.obj.role.get(name)
2958 except ClientException as inst:
2959 print(inst.message)
2960 exit(1)
2961
2962 table = PrettyTable(['key', 'attribute'])
2963 for k, v in resp.items():
2964 table.add_row([k, json.dumps(v, indent=2)])
2965 table.align = 'l'
2966 print(table)
2967
2968
2969 if __name__ == '__main__':
2970 try:
2971 cli()
2972 except pycurl.error as e:
2973 print(e)
2974 print('Maybe "--hostname" option or OSM_HOSTNAME' +
2975 'environment variable needs to be specified')
2976 exit(1)