fix bug 643 750. Allow project update to change name
[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 ####################
1334 # UPDATE operations
1335 ####################
1336
1337 def nsd_update(ctx, name, content):
1338 try:
1339 check_client_version(ctx.obj, ctx.command.name)
1340 ctx.obj.nsd.update(name, content)
1341 except ClientException as inst:
1342 print((inst.message))
1343 exit(1)
1344
1345
1346 @cli.command(name='nsd-update', short_help='updates a NSD/NSpkg')
1347 @click.argument('name')
1348 @click.option('--content', default=None,
1349 help='filename with the NSD/NSpkg replacing the current one')
1350 @click.pass_context
1351 def nsd_update1(ctx, name, content):
1352 """updates a NSD/NSpkg
1353
1354 NAME: name or ID of the NSD/NSpkg
1355 """
1356 nsd_update(ctx, name, content)
1357
1358
1359 @cli.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
1360 @click.argument('name')
1361 @click.option('--content', default=None,
1362 help='filename with the NSD/NSpkg replacing the current one')
1363 @click.pass_context
1364 def nsd_update2(ctx, name, content):
1365 """updates a NSD/NSpkg
1366
1367 NAME: name or ID of the NSD/NSpkg
1368 """
1369 nsd_update(ctx, name, content)
1370
1371
1372 def vnfd_update(ctx, name, content):
1373 try:
1374 check_client_version(ctx.obj, ctx.command.name)
1375 ctx.obj.vnfd.update(name, content)
1376 except ClientException as inst:
1377 print((inst.message))
1378 exit(1)
1379
1380
1381 @cli.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
1382 @click.argument('name')
1383 @click.option('--content', default=None,
1384 help='filename with the VNFD/VNFpkg replacing the current one')
1385 @click.pass_context
1386 def vnfd_update1(ctx, name, content):
1387 """updates a VNFD/VNFpkg
1388
1389 NAME: name or ID of the VNFD/VNFpkg
1390 """
1391 vnfd_update(ctx, name, content)
1392
1393
1394 @cli.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
1395 @click.argument('name')
1396 @click.option('--content', default=None,
1397 help='filename with the VNFD/VNFpkg replacing the current one')
1398 @click.pass_context
1399 def vnfd_update2(ctx, name, content):
1400 """updates a VNFD/VNFpkg
1401
1402 NAME: VNFD yaml file or VNFpkg tar.gz file
1403 """
1404 vnfd_update(ctx, name, content)
1405
1406
1407 @cli.command(name='nfpkg-update', short_help='updates a NFpkg')
1408 @click.argument('name')
1409 @click.option('--content', default=None,
1410 help='filename with the NFpkg replacing the current one')
1411 @click.pass_context
1412 def nfpkg_update(ctx, name, content):
1413 """updates a NFpkg
1414
1415 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1416 """
1417 vnfd_update(ctx, name, content)
1418
1419
1420 def nst_update(ctx, name, content):
1421 try:
1422 check_client_version(ctx.obj, ctx.command.name)
1423 ctx.obj.nst.update(name, content)
1424 except ClientException as inst:
1425 print((inst.message))
1426 exit(1)
1427
1428
1429 @cli.command(name='nst-update', short_help='updates a Network Slice Template (NST)')
1430 @click.argument('name')
1431 @click.option('--content', default=None,
1432 help='filename with the NST/NSTpkg replacing the current one')
1433 @click.pass_context
1434 def nst_update1(ctx, name, content):
1435 """updates a Network Slice Template (NST)
1436
1437 NAME: name or ID of the NSD/NSpkg
1438 """
1439 nst_update(ctx, name, content)
1440
1441
1442 @cli.command(name='netslice-template-update', short_help='updates a Network Slice Template (NST)')
1443 @click.argument('name')
1444 @click.option('--content', default=None,
1445 help='filename with the NST/NSTpkg replacing the current one')
1446 @click.pass_context
1447 def nst_update2(ctx, name, content):
1448 """updates a Network Slice Template (NST)
1449
1450 NAME: name or ID of the NSD/NSpkg
1451 """
1452 nst_update(ctx, name, content)
1453
1454
1455 ####################
1456 # DELETE operations
1457 ####################
1458
1459 def nsd_delete(ctx, name, force):
1460 try:
1461 if not force:
1462 ctx.obj.nsd.delete(name)
1463 else:
1464 check_client_version(ctx.obj, '--force')
1465 ctx.obj.nsd.delete(name, force)
1466 except ClientException as inst:
1467 print((inst.message))
1468 exit(1)
1469
1470
1471 @cli.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
1472 @click.argument('name')
1473 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1474 @click.pass_context
1475 def nsd_delete1(ctx, name, force):
1476 """deletes a NSD/NSpkg
1477
1478 NAME: name or ID of the NSD/NSpkg to be deleted
1479 """
1480 nsd_delete(ctx, name, force)
1481
1482
1483 @cli.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
1484 @click.argument('name')
1485 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1486 @click.pass_context
1487 def nsd_delete2(ctx, name, force):
1488 """deletes a NSD/NSpkg
1489
1490 NAME: name or ID of the NSD/NSpkg to be deleted
1491 """
1492 nsd_delete(ctx, name, force)
1493
1494
1495 def vnfd_delete(ctx, name, force):
1496 try:
1497 if not force:
1498 ctx.obj.vnfd.delete(name)
1499 else:
1500 check_client_version(ctx.obj, '--force')
1501 ctx.obj.vnfd.delete(name, force)
1502 except ClientException as inst:
1503 print((inst.message))
1504 exit(1)
1505
1506
1507 @cli.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
1508 @click.argument('name')
1509 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1510 @click.pass_context
1511 def vnfd_delete1(ctx, name, force):
1512 """deletes a VNFD/VNFpkg
1513
1514 NAME: name or ID of the VNFD/VNFpkg to be deleted
1515 """
1516 vnfd_delete(ctx, name, force)
1517
1518
1519 @cli.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
1520 @click.argument('name')
1521 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1522 @click.pass_context
1523 def vnfd_delete2(ctx, name, force):
1524 """deletes a VNFD/VNFpkg
1525
1526 NAME: name or ID of the VNFD/VNFpkg to be deleted
1527 """
1528 vnfd_delete(ctx, name, force)
1529
1530
1531 @cli.command(name='nfpkg-delete', short_help='deletes a NFpkg')
1532 @click.argument('name')
1533 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1534 @click.pass_context
1535 def nfpkg_delete(ctx, name, force):
1536 """deletes a NFpkg
1537
1538 NAME: name or ID of the NFpkg to be deleted
1539 """
1540 vnfd_delete(ctx, name, force)
1541
1542
1543 @cli.command(name='ns-delete', short_help='deletes a NS instance')
1544 @click.argument('name')
1545 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1546 @click.option('--wait',
1547 required=False,
1548 default=False,
1549 is_flag=True,
1550 help='do not return the control immediately, but keep it \
1551 until the operation is completed, or timeout')
1552 @click.pass_context
1553 def ns_delete(ctx, name, force, wait):
1554 """deletes a NS instance
1555
1556 NAME: name or ID of the NS instance to be deleted
1557 """
1558 try:
1559 if not force:
1560 ctx.obj.ns.delete(name, wait=wait)
1561 else:
1562 check_client_version(ctx.obj, '--force')
1563 ctx.obj.ns.delete(name, force, wait=wait)
1564 except ClientException as inst:
1565 print((inst.message))
1566 exit(1)
1567
1568
1569 def nst_delete(ctx, name, force):
1570 try:
1571 check_client_version(ctx.obj, ctx.command.name)
1572 ctx.obj.nst.delete(name, force)
1573 except ClientException as inst:
1574 print((inst.message))
1575 exit(1)
1576
1577
1578 @cli.command(name='nst-delete', short_help='deletes a Network Slice Template (NST)')
1579 @click.argument('name')
1580 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1581 @click.pass_context
1582 def nst_delete1(ctx, name, force):
1583 """deletes a Network Slice Template (NST)
1584
1585 NAME: name or ID of the NST/NSTpkg to be deleted
1586 """
1587 nst_delete(ctx, name, force)
1588
1589
1590 @cli.command(name='netslice-template-delete', short_help='deletes a Network Slice Template (NST)')
1591 @click.argument('name')
1592 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1593 @click.pass_context
1594 def nst_delete2(ctx, name, force):
1595 """deletes a Network Slice Template (NST)
1596
1597 NAME: name or ID of the NST/NSTpkg to be deleted
1598 """
1599 nst_delete(ctx, name, force)
1600
1601
1602 def nsi_delete(ctx, name, force, wait):
1603 try:
1604 check_client_version(ctx.obj, ctx.command.name)
1605 ctx.obj.nsi.delete(name, force, wait=wait)
1606 except ClientException as inst:
1607 print((inst.message))
1608 exit(1)
1609
1610
1611 @cli.command(name='nsi-delete', short_help='deletes a Network Slice Instance (NSI)')
1612 @click.argument('name')
1613 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1614 @click.option('--wait',
1615 required=False,
1616 default=False,
1617 is_flag=True,
1618 help='do not return the control immediately, but keep it \
1619 until the operation is completed, or timeout')
1620 @click.pass_context
1621 def nsi_delete1(ctx, name, force, wait):
1622 """deletes a Network Slice Instance (NSI)
1623
1624 NAME: name or ID of the Network Slice instance to be deleted
1625 """
1626 nsi_delete(ctx, name, force, wait=wait)
1627
1628
1629 @cli.command(name='netslice-instance-delete', short_help='deletes a Network Slice Instance (NSI)')
1630 @click.argument('name')
1631 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1632 @click.pass_context
1633 def nsi_delete2(ctx, name, force, wait):
1634 """deletes a Network Slice Instance (NSI)
1635
1636 NAME: name or ID of the Network Slice instance to be deleted
1637 """
1638 nsi_delete(ctx, name, force, wait=wait)
1639
1640
1641 @cli.command(name='pdu-delete', short_help='deletes a Physical Deployment Unit (PDU)')
1642 @click.argument('name')
1643 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1644 @click.pass_context
1645 def pdu_delete(ctx, name, force):
1646 """deletes a Physical Deployment Unit (PDU)
1647
1648 NAME: name or ID of the PDU to be deleted
1649 """
1650 try:
1651 check_client_version(ctx.obj, ctx.command.name)
1652 ctx.obj.pdu.delete(name, force)
1653 except ClientException as inst:
1654 print((inst.message))
1655 exit(1)
1656
1657
1658 ####################
1659 # VIM operations
1660 ####################
1661
1662 @cli.command(name='vim-create')
1663 @click.option('--name',
1664 prompt=True,
1665 help='Name to create datacenter')
1666 @click.option('--user',
1667 prompt=True,
1668 help='VIM username')
1669 @click.option('--password',
1670 prompt=True,
1671 hide_input=True,
1672 confirmation_prompt=True,
1673 help='VIM password')
1674 @click.option('--auth_url',
1675 prompt=True,
1676 help='VIM url')
1677 @click.option('--tenant',
1678 prompt=True,
1679 help='VIM tenant name')
1680 @click.option('--config',
1681 default=None,
1682 help='VIM specific config parameters')
1683 @click.option('--account_type',
1684 default='openstack',
1685 help='VIM type')
1686 @click.option('--description',
1687 default='no description',
1688 help='human readable description')
1689 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1690 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1691 @click.option('--wait',
1692 required=False,
1693 default=False,
1694 is_flag=True,
1695 help='do not return the control immediately, but keep it \
1696 until the operation is completed, or timeout')
1697 @click.pass_context
1698 def vim_create(ctx,
1699 name,
1700 user,
1701 password,
1702 auth_url,
1703 tenant,
1704 config,
1705 account_type,
1706 description,
1707 sdn_controller,
1708 sdn_port_mapping,
1709 wait):
1710 """creates a new VIM account"""
1711 try:
1712 if sdn_controller:
1713 check_client_version(ctx.obj, '--sdn_controller')
1714 if sdn_port_mapping:
1715 check_client_version(ctx.obj, '--sdn_port_mapping')
1716 vim = {}
1717 vim['vim-username'] = user
1718 vim['vim-password'] = password
1719 vim['vim-url'] = auth_url
1720 vim['vim-tenant-name'] = tenant
1721 vim['vim-type'] = account_type
1722 vim['description'] = description
1723 vim['config'] = config
1724 if sdn_controller or sdn_port_mapping:
1725 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1726 else:
1727 ctx.obj.vim.create(name, vim, wait=wait)
1728 except ClientException as inst:
1729 print((inst.message))
1730 exit(1)
1731
1732
1733 @cli.command(name='vim-update', short_help='updates a VIM account')
1734 @click.argument('name')
1735 @click.option('--newname', help='New name for the VIM account')
1736 @click.option('--user', help='VIM username')
1737 @click.option('--password', help='VIM password')
1738 @click.option('--auth_url', help='VIM url')
1739 @click.option('--tenant', help='VIM tenant name')
1740 @click.option('--config', help='VIM specific config parameters')
1741 @click.option('--account_type', help='VIM type')
1742 @click.option('--description', help='human readable description')
1743 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1744 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1745 @click.option('--wait',
1746 required=False,
1747 default=False,
1748 is_flag=True,
1749 help='do not return the control immediately, but keep it \
1750 until the operation is completed, or timeout')
1751 @click.pass_context
1752 def vim_update(ctx,
1753 name,
1754 newname,
1755 user,
1756 password,
1757 auth_url,
1758 tenant,
1759 config,
1760 account_type,
1761 description,
1762 sdn_controller,
1763 sdn_port_mapping,
1764 wait):
1765 """updates a VIM account
1766
1767 NAME: name or ID of the VIM account
1768 """
1769 try:
1770 check_client_version(ctx.obj, ctx.command.name)
1771 vim = {}
1772 if newname: vim['name'] = newname
1773 if user: vim['vim_user'] = user
1774 if password: vim['vim_password'] = password
1775 if auth_url: vim['vim_url'] = auth_url
1776 if tenant: vim['vim-tenant-name'] = tenant
1777 if account_type: vim['vim_type'] = account_type
1778 if description: vim['description'] = description
1779 if config: vim['config'] = config
1780 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1781 except ClientException as inst:
1782 print((inst.message))
1783 exit(1)
1784
1785
1786 @cli.command(name='vim-delete')
1787 @click.argument('name')
1788 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1789 @click.option('--wait',
1790 required=False,
1791 default=False,
1792 is_flag=True,
1793 help='do not return the control immediately, but keep it \
1794 until the operation is completed, or timeout')
1795 @click.pass_context
1796 def vim_delete(ctx, name, force, wait):
1797 """deletes a VIM account
1798
1799 NAME: name or ID of the VIM account to be deleted
1800 """
1801 try:
1802 if not force:
1803 ctx.obj.vim.delete(name, wait=wait)
1804 else:
1805 check_client_version(ctx.obj, '--force')
1806 ctx.obj.vim.delete(name, force, wait=wait)
1807 except ClientException as inst:
1808 print((inst.message))
1809 exit(1)
1810
1811
1812 @cli.command(name='vim-list')
1813 @click.option('--ro_update/--no_ro_update',
1814 default=False,
1815 help='update list from RO')
1816 @click.option('--filter', default=None,
1817 help='restricts the list to the VIM accounts matching the filter')
1818 @click.pass_context
1819 def vim_list(ctx, ro_update, filter):
1820 """list all VIM accounts"""
1821 if filter:
1822 check_client_version(ctx.obj, '--filter')
1823 if ro_update:
1824 check_client_version(ctx.obj, '--ro_update', 'v1')
1825 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1826 if fullclassname == 'osmclient.sol005.client.Client':
1827 resp = ctx.obj.vim.list(filter)
1828 else:
1829 resp = ctx.obj.vim.list(ro_update)
1830 table = PrettyTable(['vim name', 'uuid'])
1831 for vim in resp:
1832 table.add_row([vim['name'], vim['uuid']])
1833 table.align = 'l'
1834 print(table)
1835
1836
1837 @cli.command(name='vim-show')
1838 @click.argument('name')
1839 @click.pass_context
1840 def vim_show(ctx, name):
1841 """shows the details of a VIM account
1842
1843 NAME: name or ID of the VIM account
1844 """
1845 try:
1846 resp = ctx.obj.vim.get(name)
1847 if 'vim_password' in resp:
1848 resp['vim_password']='********'
1849 except ClientException as inst:
1850 print((inst.message))
1851 exit(1)
1852
1853 table = PrettyTable(['key', 'attribute'])
1854 for k, v in list(resp.items()):
1855 table.add_row([k, json.dumps(v, indent=2)])
1856 table.align = 'l'
1857 print(table)
1858
1859
1860 ####################
1861 # WIM operations
1862 ####################
1863
1864 @cli.command(name='wim-create')
1865 @click.option('--name',
1866 prompt=True,
1867 help='Name for the WIM account')
1868 @click.option('--user',
1869 help='WIM username')
1870 @click.option('--password',
1871 help='WIM password')
1872 @click.option('--url',
1873 prompt=True,
1874 help='WIM url')
1875 # @click.option('--tenant',
1876 # help='wIM tenant name')
1877 @click.option('--config',
1878 default=None,
1879 help='WIM specific config parameters')
1880 @click.option('--wim_type',
1881 help='WIM type')
1882 @click.option('--description',
1883 default='no description',
1884 help='human readable description')
1885 @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)")
1886 @click.option('--wait',
1887 required=False,
1888 default=False,
1889 is_flag=True,
1890 help='do not return the control immediately, but keep it \
1891 until the operation is completed, or timeout')
1892 @click.pass_context
1893 def wim_create(ctx,
1894 name,
1895 user,
1896 password,
1897 url,
1898 # tenant,
1899 config,
1900 wim_type,
1901 description,
1902 wim_port_mapping,
1903 wait):
1904 """creates a new WIM account"""
1905 try:
1906 check_client_version(ctx.obj, ctx.command.name)
1907 # if sdn_controller:
1908 # check_client_version(ctx.obj, '--sdn_controller')
1909 # if sdn_port_mapping:
1910 # check_client_version(ctx.obj, '--sdn_port_mapping')
1911 wim = {}
1912 if user: wim['user'] = user
1913 if password: wim['password'] = password
1914 if url: wim['wim_url'] = url
1915 # if tenant: wim['tenant'] = tenant
1916 wim['wim_type'] = wim_type
1917 if description: wim['description'] = description
1918 if config: wim['config'] = config
1919 ctx.obj.wim.create(name, wim, wim_port_mapping, wait=wait)
1920 except ClientException as inst:
1921 print((inst.message))
1922 exit(1)
1923
1924
1925 @cli.command(name='wim-update', short_help='updates a WIM account')
1926 @click.argument('name')
1927 @click.option('--newname', help='New name for the WIM account')
1928 @click.option('--user', help='WIM username')
1929 @click.option('--password', help='WIM password')
1930 @click.option('--url', help='WIM url')
1931 @click.option('--config', help='WIM specific config parameters')
1932 @click.option('--wim_type', help='WIM type')
1933 @click.option('--description', help='human readable description')
1934 @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)")
1935 @click.option('--wait',
1936 required=False,
1937 default=False,
1938 is_flag=True,
1939 help='do not return the control immediately, but keep it \
1940 until the operation is completed, or timeout')
1941 @click.pass_context
1942 def wim_update(ctx,
1943 name,
1944 newname,
1945 user,
1946 password,
1947 url,
1948 config,
1949 wim_type,
1950 description,
1951 wim_port_mapping,
1952 wait):
1953 """updates a WIM account
1954
1955 NAME: name or ID of the WIM account
1956 """
1957 try:
1958 check_client_version(ctx.obj, ctx.command.name)
1959 wim = {}
1960 if newname: wim['name'] = newname
1961 if user: wim['user'] = user
1962 if password: wim['password'] = password
1963 if url: wim['url'] = url
1964 # if tenant: wim['tenant'] = tenant
1965 if wim_type: wim['wim_type'] = wim_type
1966 if description: wim['description'] = description
1967 if config: wim['config'] = config
1968 ctx.obj.wim.update(name, wim, wim_port_mapping, wait=wait)
1969 except ClientException as inst:
1970 print((inst.message))
1971 exit(1)
1972
1973
1974 @cli.command(name='wim-delete')
1975 @click.argument('name')
1976 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1977 @click.option('--wait',
1978 required=False,
1979 default=False,
1980 is_flag=True,
1981 help='do not return the control immediately, but keep it \
1982 until the operation is completed, or timeout')
1983 @click.pass_context
1984 def wim_delete(ctx, name, force, wait):
1985 """deletes a WIM account
1986
1987 NAME: name or ID of the WIM account to be deleted
1988 """
1989 try:
1990 check_client_version(ctx.obj, ctx.command.name)
1991 ctx.obj.wim.delete(name, force, wait=wait)
1992 except ClientException as inst:
1993 print((inst.message))
1994 exit(1)
1995
1996
1997 @cli.command(name='wim-list')
1998 @click.option('--filter', default=None,
1999 help='restricts the list to the WIM accounts matching the filter')
2000 @click.pass_context
2001 def wim_list(ctx, filter):
2002 """list all WIM accounts"""
2003 try:
2004 check_client_version(ctx.obj, ctx.command.name)
2005 resp = ctx.obj.wim.list(filter)
2006 table = PrettyTable(['wim name', 'uuid'])
2007 for wim in resp:
2008 table.add_row([wim['name'], wim['uuid']])
2009 table.align = 'l'
2010 print(table)
2011 except ClientException as inst:
2012 print((inst.message))
2013 exit(1)
2014
2015
2016 @cli.command(name='wim-show')
2017 @click.argument('name')
2018 @click.pass_context
2019 def wim_show(ctx, name):
2020 """shows the details of a WIM account
2021
2022 NAME: name or ID of the WIM account
2023 """
2024 try:
2025 check_client_version(ctx.obj, ctx.command.name)
2026 resp = ctx.obj.wim.get(name)
2027 if 'password' in resp:
2028 resp['wim_password']='********'
2029 except ClientException as inst:
2030 print((inst.message))
2031 exit(1)
2032
2033 table = PrettyTable(['key', 'attribute'])
2034 for k, v in list(resp.items()):
2035 table.add_row([k, json.dumps(v, indent=2)])
2036 table.align = 'l'
2037 print(table)
2038
2039
2040 ####################
2041 # SDN controller operations
2042 ####################
2043
2044 @cli.command(name='sdnc-create')
2045 @click.option('--name',
2046 prompt=True,
2047 help='Name to create sdn controller')
2048 @click.option('--type',
2049 prompt=True,
2050 help='SDN controller type')
2051 @click.option('--sdn_controller_version',
2052 help='SDN controller version')
2053 @click.option('--ip_address',
2054 prompt=True,
2055 help='SDN controller IP address')
2056 @click.option('--port',
2057 prompt=True,
2058 help='SDN controller port')
2059 @click.option('--switch_dpid',
2060 prompt=True,
2061 help='Switch DPID (Openflow Datapath ID)')
2062 @click.option('--user',
2063 help='SDN controller username')
2064 @click.option('--password',
2065 hide_input=True,
2066 confirmation_prompt=True,
2067 help='SDN controller password')
2068 #@click.option('--description',
2069 # default='no description',
2070 # help='human readable description')
2071 @click.option('--wait',
2072 required=False,
2073 default=False,
2074 is_flag=True,
2075 help='do not return the control immediately, but keep it \
2076 until the operation is completed, or timeout')
2077 @click.pass_context
2078 def sdnc_create(ctx,
2079 name,
2080 type,
2081 sdn_controller_version,
2082 ip_address,
2083 port,
2084 switch_dpid,
2085 user,
2086 password,
2087 wait):
2088 """creates a new SDN controller"""
2089 sdncontroller = {}
2090 sdncontroller['name'] = name
2091 sdncontroller['type'] = type
2092 sdncontroller['ip'] = ip_address
2093 sdncontroller['port'] = int(port)
2094 sdncontroller['dpid'] = switch_dpid
2095 if sdn_controller_version:
2096 sdncontroller['version'] = sdn_controller_version
2097 if user:
2098 sdncontroller['user'] = user
2099 if password:
2100 sdncontroller['password'] = password
2101 # sdncontroller['description'] = description
2102 try:
2103 check_client_version(ctx.obj, ctx.command.name)
2104 ctx.obj.sdnc.create(name, sdncontroller, wait=wait)
2105 except ClientException as inst:
2106 print((inst.message))
2107
2108
2109 @cli.command(name='sdnc-update', short_help='updates an SDN controller')
2110 @click.argument('name')
2111 @click.option('--newname', help='New name for the SDN controller')
2112 @click.option('--type', help='SDN controller type')
2113 @click.option('--sdn_controller_version', help='SDN controller username')
2114 @click.option('--ip_address', help='SDN controller IP address')
2115 @click.option('--port', help='SDN controller port')
2116 @click.option('--switch_dpid', help='Switch DPID (Openflow Datapath ID)')
2117 @click.option('--user', help='SDN controller username')
2118 @click.option('--password', help='SDN controller password')
2119 #@click.option('--description', default=None, help='human readable description')
2120 @click.option('--wait',
2121 required=False,
2122 default=False,
2123 is_flag=True,
2124 help='do not return the control immediately, but keep it \
2125 until the operation is completed, or timeout')
2126 @click.pass_context
2127 def sdnc_update(ctx,
2128 name,
2129 newname,
2130 type,
2131 sdn_controller_version,
2132 ip_address,
2133 port,
2134 switch_dpid,
2135 user,
2136 password,
2137 wait):
2138 """updates an SDN controller
2139
2140 NAME: name or ID of the SDN controller
2141 """
2142 sdncontroller = {}
2143 if newname: sdncontroller['name'] = newname
2144 if type: sdncontroller['type'] = type
2145 if ip_address: sdncontroller['ip'] = ip_address
2146 if port: sdncontroller['port'] = int(port)
2147 if switch_dpid: sdncontroller['dpid'] = switch_dpid
2148 # sdncontroller['description'] = description
2149 if sdn_controller_version is not None:
2150 if sdn_controller_version=="":
2151 sdncontroller['version'] = None
2152 else:
2153 sdncontroller['version'] = sdn_controller_version
2154 if user is not None:
2155 if user=="":
2156 sdncontroller['user'] = None
2157 else:
2158 sdncontroller['user'] = user
2159 if password is not None:
2160 if password=="":
2161 sdncontroller['password'] = None
2162 else:
2163 sdncontroller['password'] = user
2164 try:
2165 check_client_version(ctx.obj, ctx.command.name)
2166 ctx.obj.sdnc.update(name, sdncontroller, wait=wait)
2167 except ClientException as inst:
2168 print((inst.message))
2169 exit(1)
2170
2171
2172 @cli.command(name='sdnc-delete')
2173 @click.argument('name')
2174 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2175 @click.option('--wait',
2176 required=False,
2177 default=False,
2178 is_flag=True,
2179 help='do not return the control immediately, but keep it \
2180 until the operation is completed, or timeout')
2181 @click.pass_context
2182 def sdnc_delete(ctx, name, force, wait):
2183 """deletes an SDN controller
2184
2185 NAME: name or ID of the SDN controller to be deleted
2186 """
2187 try:
2188 check_client_version(ctx.obj, ctx.command.name)
2189 ctx.obj.sdnc.delete(name, force, wait=wait)
2190 except ClientException as inst:
2191 print((inst.message))
2192 exit(1)
2193
2194
2195 @cli.command(name='sdnc-list')
2196 @click.option('--filter', default=None,
2197 help='restricts the list to the SDN controllers matching the filter')
2198 @click.pass_context
2199 def sdnc_list(ctx, filter):
2200 """list all SDN controllers"""
2201 try:
2202 check_client_version(ctx.obj, ctx.command.name)
2203 resp = ctx.obj.sdnc.list(filter)
2204 except ClientException as inst:
2205 print((inst.message))
2206 exit(1)
2207 table = PrettyTable(['name', 'id'])
2208 for sdnc in resp:
2209 table.add_row([sdnc['name'], sdnc['_id']])
2210 table.align = 'l'
2211 print(table)
2212
2213
2214 @cli.command(name='sdnc-show')
2215 @click.argument('name')
2216 @click.pass_context
2217 def sdnc_show(ctx, name):
2218 """shows the details of an SDN controller
2219
2220 NAME: name or ID of the SDN controller
2221 """
2222 try:
2223 check_client_version(ctx.obj, ctx.command.name)
2224 resp = ctx.obj.sdnc.get(name)
2225 except ClientException as inst:
2226 print((inst.message))
2227 exit(1)
2228
2229 table = PrettyTable(['key', 'attribute'])
2230 for k, v in list(resp.items()):
2231 table.add_row([k, json.dumps(v, indent=2)])
2232 table.align = 'l'
2233 print(table)
2234
2235
2236 ####################
2237 # Project mgmt operations
2238 ####################
2239
2240 @cli.command(name='project-create')
2241 @click.argument('name')
2242 #@click.option('--description',
2243 # default='no description',
2244 # help='human readable description')
2245 @click.pass_context
2246 def project_create(ctx, name):
2247 """Creates a new project
2248
2249 NAME: name of the project
2250 """
2251 project = {}
2252 project['name'] = name
2253 try:
2254 check_client_version(ctx.obj, ctx.command.name)
2255 ctx.obj.project.create(name, project)
2256 except ClientException as inst:
2257 print(inst.message)
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
2386
2387 @cli.command(name='user-update')
2388 @click.argument('username')
2389 @click.option('--password',
2390 # prompt=True,
2391 # hide_input=True,
2392 # confirmation_prompt=True,
2393 help='user password')
2394 @click.option('--set-project', 'set_project',
2395 default=None, multiple=True,
2396 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
2397 @click.option('--remove-project', 'remove_project',
2398 default=None, multiple=True,
2399 help='removes project from user: \'project\'')
2400 @click.option('--add-project-role', 'add_project_role',
2401 default=None, multiple=True,
2402 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
2403 @click.option('--remove-project-role', 'remove_project_role',
2404 default=None, multiple=True,
2405 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
2406 @click.pass_context
2407 def user_update(ctx, username, password, set_project, remove_project,
2408 add_project_role, remove_project_role):
2409 """Update a user information
2410
2411 \b
2412 USERNAME: name of the user
2413 PASSWORD: new password
2414 SET_PROJECT: creating mappings for project/role(s)
2415 REMOVE_PROJECT: deleting mappings for project/role(s)
2416 ADD_PROJECT_ROLE: adding mappings for project/role(s)
2417 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
2418 """
2419 user = {}
2420 user['username'] = username
2421 user['password'] = password
2422 user['set-project'] = set_project
2423 user['remove-project'] = remove_project
2424 user['add-project-role'] = add_project_role
2425 user['remove-project-role'] = remove_project_role
2426
2427 try:
2428 check_client_version(ctx.obj, ctx.command.name)
2429 ctx.obj.user.update(username, user)
2430 except ClientException as inst:
2431 print(inst.message)
2432
2433
2434 @cli.command(name='user-delete')
2435 @click.argument('name')
2436 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2437 @click.pass_context
2438 def user_delete(ctx, name):
2439 """deletes a user
2440
2441 \b
2442 NAME: name or ID of the user to be deleted
2443 """
2444 try:
2445 check_client_version(ctx.obj, ctx.command.name)
2446 ctx.obj.user.delete(name)
2447 except ClientException as inst:
2448 print(inst.message)
2449 exit(1)
2450
2451
2452 @cli.command(name='user-list')
2453 @click.option('--filter', default=None,
2454 help='restricts the list to the users matching the filter')
2455 @click.pass_context
2456 def user_list(ctx, filter):
2457 """list all users"""
2458 try:
2459 check_client_version(ctx.obj, ctx.command.name)
2460 resp = ctx.obj.user.list(filter)
2461 except ClientException as inst:
2462 print(inst.message)
2463 exit(1)
2464 table = PrettyTable(['name', 'id'])
2465 for user in resp:
2466 table.add_row([user['username'], user['_id']])
2467 table.align = 'l'
2468 print(table)
2469
2470
2471 @cli.command(name='user-show')
2472 @click.argument('name')
2473 @click.pass_context
2474 def user_show(ctx, name):
2475 """shows the details of a user
2476
2477 NAME: name or ID of the user
2478 """
2479 try:
2480 check_client_version(ctx.obj, ctx.command.name)
2481 resp = ctx.obj.user.get(name)
2482 if 'password' in resp:
2483 resp['password']='********'
2484 except ClientException as inst:
2485 print(inst.message)
2486 exit(1)
2487
2488 table = PrettyTable(['key', 'attribute'])
2489 for k, v in resp.items():
2490 table.add_row([k, json.dumps(v, indent=2)])
2491 table.align = 'l'
2492 print(table)
2493
2494
2495 ####################
2496 # Fault Management operations
2497 ####################
2498
2499 @cli.command(name='ns-alarm-create')
2500 @click.argument('name')
2501 @click.option('--ns', prompt=True, help='NS instance id or name')
2502 @click.option('--vnf', prompt=True,
2503 help='VNF name (VNF member index as declared in the NSD)')
2504 @click.option('--vdu', prompt=True,
2505 help='VDU name (VDU name as declared in the VNFD)')
2506 @click.option('--metric', prompt=True,
2507 help='Name of the metric (e.g. cpu_utilization)')
2508 @click.option('--severity', default='WARNING',
2509 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
2510 @click.option('--threshold_value', prompt=True,
2511 help='threshold value that, when crossed, an alarm is triggered')
2512 @click.option('--threshold_operator', prompt=True,
2513 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
2514 @click.option('--statistic', default='AVERAGE',
2515 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
2516 @click.pass_context
2517 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
2518 threshold_value, threshold_operator, statistic):
2519 """creates a new alarm for a NS instance"""
2520 ns_instance = ctx.obj.ns.get(ns)
2521 alarm = {}
2522 alarm['alarm_name'] = name
2523 alarm['ns_id'] = ns_instance['_id']
2524 alarm['correlation_id'] = ns_instance['_id']
2525 alarm['vnf_member_index'] = vnf
2526 alarm['vdu_name'] = vdu
2527 alarm['metric_name'] = metric
2528 alarm['severity'] = severity
2529 alarm['threshold_value'] = int(threshold_value)
2530 alarm['operation'] = threshold_operator
2531 alarm['statistic'] = statistic
2532 try:
2533 check_client_version(ctx.obj, ctx.command.name)
2534 ctx.obj.ns.create_alarm(alarm)
2535 except ClientException as inst:
2536 print((inst.message))
2537 exit(1)
2538
2539
2540 #@cli.command(name='ns-alarm-delete')
2541 #@click.argument('name')
2542 #@click.pass_context
2543 #def ns_alarm_delete(ctx, name):
2544 # """deletes an alarm
2545 #
2546 # NAME: name of the alarm to be deleted
2547 # """
2548 # try:
2549 # check_client_version(ctx.obj, ctx.command.name)
2550 # ctx.obj.ns.delete_alarm(name)
2551 # except ClientException as inst:
2552 # print(inst.message)
2553 # exit(1)
2554
2555
2556 ####################
2557 # Performance Management operations
2558 ####################
2559
2560 @cli.command(name='ns-metric-export')
2561 @click.option('--ns', prompt=True, help='NS instance id or name')
2562 @click.option('--vnf', prompt=True,
2563 help='VNF name (VNF member index as declared in the NSD)')
2564 @click.option('--vdu', prompt=True,
2565 help='VDU name (VDU name as declared in the VNFD)')
2566 @click.option('--metric', prompt=True,
2567 help='name of the metric (e.g. cpu_utilization)')
2568 #@click.option('--period', default='1w',
2569 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
2570 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
2571 @click.pass_context
2572 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
2573 """exports a metric to the internal OSM bus, which can be read by other apps"""
2574 ns_instance = ctx.obj.ns.get(ns)
2575 metric_data = {}
2576 metric_data['ns_id'] = ns_instance['_id']
2577 metric_data['correlation_id'] = ns_instance['_id']
2578 metric_data['vnf_member_index'] = vnf
2579 metric_data['vdu_name'] = vdu
2580 metric_data['metric_name'] = metric
2581 metric_data['collection_unit'] = 'WEEK'
2582 metric_data['collection_period'] = 1
2583 try:
2584 check_client_version(ctx.obj, ctx.command.name)
2585 if not interval:
2586 print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
2587 else:
2588 i = 1
2589 while True:
2590 print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
2591 time.sleep(int(interval))
2592 i+=1
2593 except ClientException as inst:
2594 print((inst.message))
2595 exit(1)
2596
2597
2598 ####################
2599 # Other operations
2600 ####################
2601
2602 @cli.command(name='upload-package')
2603 @click.argument('filename')
2604 @click.pass_context
2605 def upload_package(ctx, filename):
2606 """uploads a VNF package or NS package
2607
2608 FILENAME: VNF or NS package file (tar.gz)
2609 """
2610 try:
2611 ctx.obj.package.upload(filename)
2612 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
2613 if fullclassname != 'osmclient.sol005.client.Client':
2614 ctx.obj.package.wait_for_upload(filename)
2615 except ClientException as inst:
2616 print((inst.message))
2617 exit(1)
2618
2619
2620 @cli.command(name='ns-scaling-show')
2621 @click.argument('ns_name')
2622 @click.pass_context
2623 def show_ns_scaling(ctx, ns_name):
2624 """shows the status of a NS scaling operation
2625
2626 NS_NAME: name of the NS instance being scaled
2627 """
2628 try:
2629 check_client_version(ctx.obj, ctx.command.name, 'v1')
2630 resp = ctx.obj.ns.list()
2631 except ClientException as inst:
2632 print((inst.message))
2633 exit(1)
2634
2635 table = PrettyTable(
2636 ['group-name',
2637 'instance-id',
2638 'operational status',
2639 'create-time',
2640 'vnfr ids'])
2641
2642 for ns in resp:
2643 if ns_name == ns['name']:
2644 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
2645 scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
2646 for record in scaling_records:
2647 if 'instance' in record:
2648 instances = record['instance']
2649 for inst in instances:
2650 table.add_row(
2651 [record['scaling-group-name-ref'],
2652 inst['instance-id'],
2653 inst['op-status'],
2654 time.strftime('%Y-%m-%d %H:%M:%S',
2655 time.localtime(
2656 inst['create-time'])),
2657 inst['vnfrs']])
2658 table.align = 'l'
2659 print(table)
2660
2661
2662 @cli.command(name='ns-scale')
2663 @click.argument('ns_name')
2664 @click.option('--ns_scale_group', prompt=True)
2665 @click.option('--index', prompt=True)
2666 @click.option('--wait',
2667 required=False,
2668 default=False,
2669 is_flag=True,
2670 help='do not return the control immediately, but keep it \
2671 until the operation is completed, or timeout')
2672 @click.pass_context
2673 def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
2674 """scales NS
2675
2676 NS_NAME: name of the NS instance to be scaled
2677 """
2678 try:
2679 check_client_version(ctx.obj, ctx.command.name, 'v1')
2680 ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
2681 except ClientException as inst:
2682 print((inst.message))
2683 exit(1)
2684
2685
2686 @cli.command(name='config-agent-list')
2687 @click.pass_context
2688 def config_agent_list(ctx):
2689 """list config agents"""
2690 try:
2691 check_client_version(ctx.obj, ctx.command.name, 'v1')
2692 except ClientException as inst:
2693 print((inst.message))
2694 exit(1)
2695 table = PrettyTable(['name', 'account-type', 'details'])
2696 for account in ctx.obj.vca.list():
2697 table.add_row(
2698 [account['name'],
2699 account['account-type'],
2700 account['juju']])
2701 table.align = 'l'
2702 print(table)
2703
2704
2705 @cli.command(name='config-agent-delete')
2706 @click.argument('name')
2707 @click.pass_context
2708 def config_agent_delete(ctx, name):
2709 """deletes a config agent
2710
2711 NAME: name of the config agent to be deleted
2712 """
2713 try:
2714 check_client_version(ctx.obj, ctx.command.name, 'v1')
2715 ctx.obj.vca.delete(name)
2716 except ClientException as inst:
2717 print((inst.message))
2718 exit(1)
2719
2720
2721 @cli.command(name='config-agent-add')
2722 @click.option('--name',
2723 prompt=True)
2724 @click.option('--account_type',
2725 prompt=True)
2726 @click.option('--server',
2727 prompt=True)
2728 @click.option('--user',
2729 prompt=True)
2730 @click.option('--secret',
2731 prompt=True,
2732 hide_input=True,
2733 confirmation_prompt=True)
2734 @click.pass_context
2735 def config_agent_add(ctx, name, account_type, server, user, secret):
2736 """adds a config agent"""
2737 try:
2738 check_client_version(ctx.obj, ctx.command.name, 'v1')
2739 ctx.obj.vca.create(name, account_type, server, user, secret)
2740 except ClientException as inst:
2741 print((inst.message))
2742 exit(1)
2743
2744
2745 @cli.command(name='ro-dump')
2746 @click.pass_context
2747 def ro_dump(ctx):
2748 """shows RO agent information"""
2749 check_client_version(ctx.obj, ctx.command.name, 'v1')
2750 resp = ctx.obj.vim.get_resource_orchestrator()
2751 table = PrettyTable(['key', 'attribute'])
2752 for k, v in list(resp.items()):
2753 table.add_row([k, json.dumps(v, indent=2)])
2754 table.align = 'l'
2755 print(table)
2756
2757
2758 @cli.command(name='vcs-list')
2759 @click.pass_context
2760 def vcs_list(ctx):
2761 check_client_version(ctx.obj, ctx.command.name, 'v1')
2762 resp = ctx.obj.utils.get_vcs_info()
2763 table = PrettyTable(['component name', 'state'])
2764 for component in resp:
2765 table.add_row([component['component_name'], component['state']])
2766 table.align = 'l'
2767 print(table)
2768
2769
2770 @cli.command(name='ns-action')
2771 @click.argument('ns_name')
2772 @click.option('--vnf_name', default=None)
2773 @click.option('--action_name', prompt=True)
2774 @click.option('--params', prompt=True)
2775 @click.option('--wait',
2776 required=False,
2777 default=False,
2778 is_flag=True,
2779 help='do not return the control immediately, but keep it \
2780 until the operation is completed, or timeout')
2781 @click.pass_context
2782 def ns_action(ctx,
2783 ns_name,
2784 vnf_name,
2785 action_name,
2786 params,
2787 wait):
2788 """executes an action/primitive over a NS instance
2789
2790 NS_NAME: name or ID of the NS instance
2791 """
2792 try:
2793 check_client_version(ctx.obj, ctx.command.name)
2794 op_data={}
2795 if vnf_name:
2796 op_data['vnf_member_index'] = vnf_name
2797 op_data['primitive'] = action_name
2798 op_data['primitive_params'] = yaml.load(params)
2799 ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data, wait=wait)
2800
2801 except ClientException as inst:
2802 print((inst.message))
2803 exit(1)
2804
2805
2806 @cli.command(name='vnf-scale')
2807 @click.argument('ns_name')
2808 @click.argument('vnf_name')
2809 @click.option('--scaling-group', prompt=True, help="scaling-group-descriptor name to use")
2810 @click.option('--scale-in', default=False, is_flag=True, help="performs a scale in operation")
2811 @click.option('--scale-out', default=False, is_flag=True, help="performs a scale out operation (by default)")
2812 @click.pass_context
2813 def vnf_scale(ctx,
2814 ns_name,
2815 vnf_name,
2816 scaling_group,
2817 scale_in,
2818 scale_out):
2819 """
2820 Executes a VNF scale (adding/removing VDUs)
2821
2822 \b
2823 NS_NAME: name or ID of the NS instance.
2824 VNF_NAME: member-vnf-index in the NS to be scaled.
2825 """
2826 try:
2827 check_client_version(ctx.obj, ctx.command.name)
2828 if not scale_in and not scale_out:
2829 scale_out = True
2830 ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out)
2831 except ClientException as inst:
2832 print((inst.message))
2833 exit(1)
2834
2835
2836 ##############################
2837 # Role Management Operations #
2838 ##############################
2839
2840 @cli.command(name='role-create', short_help='creates a role')
2841 @click.argument('name')
2842 @click.option('--definition',
2843 default=None,
2844 help='role definition using a dictionary')
2845 @click.pass_context
2846 def role_create(ctx, name, definition):
2847 """
2848 Creates a new role.
2849
2850 \b
2851 NAME: Name or ID of the role.
2852 DEFINITION: Definition of grant/denial of access to resources.
2853 """
2854 try:
2855 check_client_version(ctx.obj, ctx.command.name)
2856 ctx.obj.role.create(name, definition)
2857 except ClientException as inst:
2858 print(inst.message)
2859
2860
2861 @cli.command(name='role-update', short_help='updates a role')
2862 @click.argument('name')
2863 @click.option('--definition',
2864 default=None,
2865 help='add a new definition to the role')
2866 @click.option('--add',
2867 default=None,
2868 help='add a resource access grant/denial')
2869 @click.option('--remove',
2870 default=None,
2871 help='remove a resource access grant/denial')
2872 @click.pass_context
2873 def role_update(ctx, name, definition, add, remove):
2874 """
2875 Updates a role.
2876
2877 \b
2878 NAME: Name or ID of the role.
2879 DEFINITION: Definition overwrites the old definition.
2880 ADD: Grant/denial of access to resource to add.
2881 REMOVE: Grant/denial of access to resource to remove.
2882 """
2883 try:
2884 check_client_version(ctx.obj, ctx.command.name)
2885 ctx.obj.role.update(name, definition, add, remove)
2886 except ClientException as inst:
2887 print(inst.message)
2888 exit(1)
2889
2890
2891 @cli.command(name='role-delete', short_help='deletes a role')
2892 @click.argument('name')
2893 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2894 @click.pass_context
2895 def role_delete(ctx, name):
2896 """
2897 Deletes a role.
2898
2899 \b
2900 NAME: Name or ID of the role.
2901 """
2902 try:
2903 check_client_version(ctx.obj, ctx.command.name)
2904 ctx.obj.role.delete(name)
2905 except ClientException as inst:
2906 print(inst.message)
2907 exit(1)
2908
2909
2910 @cli.command(name='role-list', short_help='list all roles')
2911 @click.option('--filter', default=None,
2912 help='restricts the list to the projects matching the filter')
2913 @click.pass_context
2914 def role_list(ctx, filter):
2915 """
2916 List all roles.
2917 """
2918 try:
2919 check_client_version(ctx.obj, ctx.command.name)
2920 resp = ctx.obj.role.list(filter)
2921 except ClientException as inst:
2922 print(inst.message)
2923 exit(1)
2924 table = PrettyTable(['name', 'id'])
2925 for role in resp:
2926 table.add_row([role['name'], role['_id']])
2927 table.align = 'l'
2928 print(table)
2929
2930
2931 @cli.command(name='role-show', short_help='show specific role')
2932 @click.argument('name')
2933 @click.pass_context
2934 def role_show(ctx, name):
2935 """
2936 Shows the details of a role.
2937
2938 \b
2939 NAME: Name or ID of the role.
2940 """
2941 try:
2942 check_client_version(ctx.obj, ctx.command.name)
2943 resp = ctx.obj.role.get(name)
2944 except ClientException as inst:
2945 print(inst.message)
2946 exit(1)
2947
2948 table = PrettyTable(['key', 'attribute'])
2949 for k, v in resp.items():
2950 table.add_row([k, json.dumps(v, indent=2)])
2951 table.align = 'l'
2952 print(table)
2953
2954
2955 if __name__ == '__main__':
2956 try:
2957 cli()
2958 except pycurl.error as e:
2959 print(e)
2960 print('Maybe "--hostname" option or OSM_HOSTNAME' +
2961 'environment variable needs to be specified')
2962 exit(1)