vnf-list: support of filter string; documented help for --filter
[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
29 def check_client_version(obj, what, version='sol005'):
30 '''
31 Checks the version of the client object and raises error if it not the expected.
32
33 :param obj: the client object
34 :what: the function or command under evaluation (used when an error is raised)
35 :return: -
36 :raises ClientError: if the specified version does not match the client version
37 '''
38 fullclassname = obj.__module__ + "." + obj.__class__.__name__
39 message = 'The following commands or options are only supported with the option "--sol005": {}'.format(what)
40 if version == 'v1':
41 message = 'The following commands or options are not supported when using option "--sol005": {}'.format(what)
42 if fullclassname != 'osmclient.{}.client.Client'.format(version):
43 raise ClientException(message)
44 return
45
46 @click.group()
47 @click.option('--hostname',
48 default=None,
49 envvar='OSM_HOSTNAME',
50 help='hostname of server. ' +
51 'Also can set OSM_HOSTNAME in environment')
52 @click.option('--so-port',
53 default=None,
54 envvar='OSM_SO_PORT',
55 help='hostname of server. ' +
56 'Also can set OSM_SO_PORT in environment')
57 @click.option('--so-project',
58 default=None,
59 envvar='OSM_SO_PROJECT',
60 help='Project Name in SO. ' +
61 'Also can set OSM_SO_PROJECT in environment')
62 @click.option('--ro-hostname',
63 default=None,
64 envvar='OSM_RO_HOSTNAME',
65 help='hostname of RO server. ' +
66 'Also can set OSM_RO_HOSTNAME in environment')
67 @click.option('--ro-port',
68 default=9090,
69 envvar='OSM_RO_PORT',
70 help='hostname of RO server. ' +
71 'Also can set OSM_RO_PORT in environment')
72 @click.option('--sol005/--no-sol005',
73 default=True,
74 envvar='OSM_SOL005',
75 help='Use ETSI NFV SOL005 API (default) or the previous SO API')
76 @click.pass_context
77 def cli(ctx, hostname, so_port, so_project, ro_hostname, ro_port, sol005):
78 if hostname is None:
79 print((
80 "either hostname option or OSM_HOSTNAME " +
81 "environment variable needs to be specified"))
82 exit(1)
83 kwargs={}
84 if so_port is not None:
85 kwargs['so_port']=so_port
86 if so_project is not None:
87 kwargs['so_project']=so_project
88 if ro_hostname is not None:
89 kwargs['ro_host']=ro_hostname
90 if ro_port is not None:
91 kwargs['ro_port']=ro_port
92
93 ctx.obj = client.Client(host=hostname, sol005=sol005, **kwargs)
94
95
96 ####################
97 # LIST operations
98 ####################
99
100 @cli.command(name='ns-list')
101 @click.option('--filter', default=None,
102 help='restricts the list to the NS instances matching the filter.')
103 @click.pass_context
104 def ns_list(ctx, filter):
105 '''list all NS instances
106
107 \b
108 Options:
109 --filter filterExpr Restricts the list to the NS instances matching the filter
110
111 \b
112 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
113 concatenated using the "&" character:
114
115 \b
116 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
117 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
118 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
119 attrName := string
120 value := scalar value
121
122 \b
123 where:
124 * zero or more occurrences
125 ? zero or one occurrence
126 [] grouping of expressions to be used with ? and *
127 "" quotation marks for marking string constants
128 <> name separator
129
130 \b
131 "AttrName" is the name of one attribute in the data type that defines the representation
132 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
133 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
134 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
135 entries, it means that the operator "op" is applied to the attribute addressed by the last
136 <attrName> entry included in the concatenation. All simple filter expressions are combined
137 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
138 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
139 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
140 prefix". If an attribute referenced in an expression is an array, an object that contains a
141 corresponding array shall be considered to match the expression if any of the elements in the
142 array matches all expressions that have the same attribute prefix.
143
144 \b
145 Filter examples:
146 --filter admin-status=ENABLED
147 --filter nsd-ref=<NSD_NAME>
148 --filter nsd.vendor=<VENDOR>
149 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
150 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
151 '''
152 if filter:
153 check_client_version(ctx.obj, '--filter')
154 resp = ctx.obj.ns.list(filter)
155 else:
156 resp = ctx.obj.ns.list()
157 table = PrettyTable(
158 ['ns instance name',
159 'id',
160 'operational status',
161 'config status',
162 'detailed status'])
163 for ns in resp:
164 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
165 if fullclassname == 'osmclient.sol005.client.Client':
166 nsr = ns
167 nsr_name = nsr['name']
168 nsr_id = nsr['_id']
169 else:
170 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
171 nsr = nsopdata['nsr:nsr']
172 nsr_name = nsr['name-ref']
173 nsr_id = nsr['ns-instance-config-ref']
174 opstatus = nsr['operational-status'] if 'operational-status' in nsr else 'Not found'
175 configstatus = nsr['config-status'] if 'config-status' in nsr else 'Not found'
176 detailed_status = nsr['detailed-status'] if 'detailed-status' in nsr else 'Not found'
177 if configstatus == "config_not_needed":
178 configstatus = "configured (no charms)"
179 table.add_row(
180 [nsr_name,
181 nsr_id,
182 opstatus,
183 configstatus,
184 detailed_status])
185 table.align = 'l'
186 print(table)
187
188
189 def nsd_list(ctx, filter):
190 if filter:
191 check_client_version(ctx.obj, '--filter')
192 resp = ctx.obj.nsd.list(filter)
193 else:
194 resp = ctx.obj.nsd.list()
195 #print yaml.safe_dump(resp)
196 table = PrettyTable(['nsd name', 'id'])
197 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
198 if fullclassname == 'osmclient.sol005.client.Client':
199 for ns in resp:
200 name = ns['name'] if 'name' in ns else '-'
201 table.add_row([name, ns['_id']])
202 else:
203 for ns in resp:
204 table.add_row([ns['name'], ns['id']])
205 table.align = 'l'
206 print(table)
207
208
209 @cli.command(name='nsd-list')
210 @click.option('--filter', default=None,
211 help='restricts the list to the NSD/NSpkg matching the filter')
212 @click.pass_context
213 def nsd_list1(ctx, filter):
214 '''list all NSD/NSpkg in the system'''
215 nsd_list(ctx,filter)
216
217
218 @cli.command(name='nspkg-list')
219 @click.option('--filter', default=None,
220 help='restricts the list to the NSD/NSpkg matching the filter')
221 @click.pass_context
222 def nsd_list2(ctx, filter):
223 '''list all NSD/NSpkg in the system'''
224 nsd_list(ctx,filter)
225
226
227 def vnfd_list(ctx, filter):
228 if filter:
229 check_client_version(ctx.obj, '--filter')
230 resp = ctx.obj.vnfd.list(filter)
231 else:
232 resp = ctx.obj.vnfd.list()
233 #print yaml.safe_dump(resp)
234 table = PrettyTable(['vnfd name', 'id'])
235 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
236 if fullclassname == 'osmclient.sol005.client.Client':
237 for vnfd in resp:
238 name = vnfd['name'] if 'name' in vnfd else '-'
239 table.add_row([name, vnfd['_id']])
240 else:
241 for vnfd in resp:
242 table.add_row([vnfd['name'], vnfd['id']])
243 table.align = 'l'
244 print(table)
245
246
247 @cli.command(name='vnfd-list')
248 @click.option('--filter', default=None,
249 help='restricts the list to the VNFD/VNFpkg matching the filter')
250 @click.pass_context
251 def vnfd_list1(ctx, filter):
252 '''list all VNFD/VNFpkg in the system'''
253 vnfd_list(ctx,filter)
254
255
256 @cli.command(name='vnfpkg-list')
257 @click.option('--filter', default=None,
258 help='restricts the list to the VNFD/VNFpkg matching the filter')
259 @click.pass_context
260 def vnfd_list2(ctx, filter):
261 '''list all VNFD/VNFpkg in the system'''
262 vnfd_list(ctx,filter)
263
264
265 @cli.command(name='vnf-list')
266 @click.option('--ns', default=None, help='NS instance id or name to restrict the VNF list')
267 @click.option('--filter', default=None,
268 help='restricts the list to the VNF instances matching the filter.')
269 @click.pass_context
270 def vnf_list(ctx, ns, filter):
271 '''list all VNF instances
272
273 \b
274 Options:
275 --ns TEXT NS instance id or name to restrict the VNF list
276 --filter filterExpr Restricts the list to the VNF instances matching the filter
277
278 \b
279 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
280 concatenated using the "&" character:
281
282 \b
283 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
284 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
285 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
286 attrName := string
287 value := scalar value
288
289 \b
290 where:
291 * zero or more occurrences
292 ? zero or one occurrence
293 [] grouping of expressions to be used with ? and *
294 "" quotation marks for marking string constants
295 <> name separator
296
297 \b
298 "AttrName" is the name of one attribute in the data type that defines the representation
299 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
300 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
301 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
302 entries, it means that the operator "op" is applied to the attribute addressed by the last
303 <attrName> entry included in the concatenation. All simple filter expressions are combined
304 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
305 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
306 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
307 prefix". If an attribute referenced in an expression is an array, an object that contains a
308 corresponding array shall be considered to match the expression if any of the elements in the
309 array matches all expressions that have the same attribute prefix.
310
311 \b
312 Filter examples:
313 --filter vim-account-id=<VIM_ACCOUNT_ID>
314 --filter vnfd-ref=<VNFD_NAME>
315 --filter vdur.ip-address=<IP_ADDRESS>
316 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
317 '''
318 try:
319 if ns or filter:
320 if ns:
321 check_client_version(ctx.obj, '--ns')
322 if filter:
323 check_client_version(ctx.obj, '--filter')
324 resp = ctx.obj.vnf.list(ns, filter)
325 else:
326 resp = ctx.obj.vnf.list()
327 except ClientException as inst:
328 print((inst.message))
329 exit(1)
330 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
331 if fullclassname == 'osmclient.sol005.client.Client':
332 table = PrettyTable(
333 ['vnf id',
334 'name',
335 'ns id',
336 'vnf member index',
337 'vnfd name',
338 'vim account id',
339 'ip address'])
340 for vnfr in resp:
341 name = vnfr['name'] if 'name' in vnfr else '-'
342 table.add_row(
343 [vnfr['_id'],
344 name,
345 vnfr['nsr-id-ref'],
346 vnfr['member-vnf-index-ref'],
347 vnfr['vnfd-ref'],
348 vnfr['vim-account-id'],
349 vnfr['ip-address']])
350 else:
351 table = PrettyTable(
352 ['vnf name',
353 'id',
354 'operational status',
355 'config status'])
356 for vnfr in resp:
357 if 'mgmt-interface' not in vnfr:
358 vnfr['mgmt-interface'] = {}
359 vnfr['mgmt-interface']['ip-address'] = None
360 table.add_row(
361 [vnfr['name'],
362 vnfr['id'],
363 vnfr['operational-status'],
364 vnfr['config-status']])
365 table.align = 'l'
366 print(table)
367
368 @cli.command(name='ns-op-list')
369 @click.argument('name')
370 @click.pass_context
371 def ns_op_list(ctx, name):
372 '''shows the history of operations over a NS instance
373
374 NAME: name or ID of the NS instance
375 '''
376 try:
377 check_client_version(ctx.obj, ctx.command.name)
378 resp = ctx.obj.ns.list_op(name)
379 except ClientException as inst:
380 print((inst.message))
381 exit(1)
382
383 table = PrettyTable(['id', 'operation', 'status'])
384 for op in resp:
385 table.add_row([op['id'], op['lcmOperationType'],
386 op['operationState']])
387 table.align = 'l'
388 print(table)
389
390 ####################
391 # SHOW operations
392 ####################
393
394 def nsd_show(ctx, name, literal):
395 try:
396 resp = ctx.obj.nsd.get(name)
397 #resp = ctx.obj.nsd.get_individual(name)
398 except ClientException as inst:
399 print((inst.message))
400 exit(1)
401
402 if literal:
403 print(yaml.safe_dump(resp))
404 return
405
406 table = PrettyTable(['field', 'value'])
407 for k, v in list(resp.items()):
408 table.add_row([k, json.dumps(v, indent=2)])
409 table.align = 'l'
410 print(table)
411
412
413 @cli.command(name='nsd-show', short_help='shows the content of a NSD')
414 @click.option('--literal', is_flag=True,
415 help='print literally, no pretty table')
416 @click.argument('name')
417 @click.pass_context
418 def nsd_show1(ctx, name, literal):
419 '''shows the content of a NSD
420
421 NAME: name or ID of the NSD/NSpkg
422 '''
423 nsd_show(ctx, name, literal)
424
425
426 @cli.command(name='nspkg-show', short_help='shows the content of a NSD')
427 @click.option('--literal', is_flag=True,
428 help='print literally, no pretty table')
429 @click.argument('name')
430 @click.pass_context
431 def nsd_show2(ctx, name, literal):
432 '''shows the content of a NSD
433
434 NAME: name or ID of the NSD/NSpkg
435 '''
436 nsd_show(ctx, name, literal)
437
438
439 def vnfd_show(ctx, name, literal):
440 try:
441 resp = ctx.obj.vnfd.get(name)
442 #resp = ctx.obj.vnfd.get_individual(name)
443 except ClientException as inst:
444 print((inst.message))
445 exit(1)
446
447 if literal:
448 print(yaml.safe_dump(resp))
449 return
450
451 table = PrettyTable(['field', 'value'])
452 for k, v in list(resp.items()):
453 table.add_row([k, json.dumps(v, indent=2)])
454 table.align = 'l'
455 print(table)
456
457
458 @cli.command(name='vnfd-show', short_help='shows the content of a VNFD')
459 @click.option('--literal', is_flag=True,
460 help='print literally, no pretty table')
461 @click.argument('name')
462 @click.pass_context
463 def vnfd_show1(ctx, name, literal):
464 '''shows the content of a VNFD
465
466 NAME: name or ID of the VNFD/VNFpkg
467 '''
468 vnfd_show(ctx, name, literal)
469
470
471 @cli.command(name='vnfpkg-show', short_help='shows the content of a VNFD')
472 @click.option('--literal', is_flag=True,
473 help='print literally, no pretty table')
474 @click.argument('name')
475 @click.pass_context
476 def vnfd_show2(ctx, name, literal):
477 '''shows the content of a VNFD
478
479 NAME: name or ID of the VNFD/VNFpkg
480 '''
481 vnfd_show(ctx, name, literal)
482
483
484 @cli.command(name='ns-show', short_help='shows the info of a NS instance')
485 @click.argument('name')
486 @click.option('--literal', is_flag=True,
487 help='print literally, no pretty table')
488 @click.option('--filter', default=None)
489 @click.pass_context
490 def ns_show(ctx, name, literal, filter):
491 '''shows the info of a NS instance
492
493 NAME: name or ID of the NS instance
494 '''
495 try:
496 ns = ctx.obj.ns.get(name)
497 except ClientException as inst:
498 print((inst.message))
499 exit(1)
500
501 if literal:
502 print(yaml.safe_dump(ns))
503 return
504
505 table = PrettyTable(['field', 'value'])
506
507 for k, v in list(ns.items()):
508 if filter is None or filter in k:
509 table.add_row([k, json.dumps(v, indent=2)])
510
511 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
512 if fullclassname != 'osmclient.sol005.client.Client':
513 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
514 nsr_optdata = nsopdata['nsr:nsr']
515 for k, v in list(nsr_optdata.items()):
516 if filter is None or filter in k:
517 table.add_row([k, json.dumps(v, indent=2)])
518 table.align = 'l'
519 print(table)
520
521
522 @cli.command(name='vnf-show', short_help='shows the info of a VNF instance')
523 @click.argument('name')
524 @click.option('--literal', is_flag=True,
525 help='print literally, no pretty table')
526 @click.option('--filter', default=None)
527 @click.pass_context
528 def vnf_show(ctx, name, literal, filter):
529 '''shows the info of a VNF instance
530
531 NAME: name or ID of the VNF instance
532 '''
533 try:
534 check_client_version(ctx.obj, ctx.command.name)
535 resp = ctx.obj.vnf.get(name)
536 except ClientException as inst:
537 print((inst.message))
538 exit(1)
539
540 if literal:
541 print(yaml.safe_dump(resp))
542 return
543
544 table = PrettyTable(['field', 'value'])
545 for k, v in list(resp.items()):
546 if filter is None or filter in k:
547 table.add_row([k, json.dumps(v, indent=2)])
548 table.align = 'l'
549 print(table)
550
551
552 @cli.command(name='vnf-monitoring-show')
553 @click.argument('vnf_name')
554 @click.pass_context
555 def vnf_monitoring_show(ctx, vnf_name):
556 try:
557 check_client_version(ctx.obj, ctx.command.name, 'v1')
558 resp = ctx.obj.vnf.get_monitoring(vnf_name)
559 except ClientException as inst:
560 print((inst.message))
561 exit(1)
562
563 table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
564 if resp is not None:
565 for monitor in resp:
566 table.add_row(
567 [vnf_name,
568 monitor['name'],
569 monitor['value-integer'],
570 monitor['units']])
571 table.align = 'l'
572 print(table)
573
574
575 @cli.command(name='ns-monitoring-show')
576 @click.argument('ns_name')
577 @click.pass_context
578 def ns_monitoring_show(ctx, ns_name):
579 try:
580 check_client_version(ctx.obj, ctx.command.name, 'v1')
581 resp = ctx.obj.ns.get_monitoring(ns_name)
582 except ClientException as inst:
583 print((inst.message))
584 exit(1)
585
586 table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
587 for key, val in list(resp.items()):
588 for monitor in val:
589 table.add_row(
590 [key,
591 monitor['name'],
592 monitor['value-integer'],
593 monitor['units']])
594 table.align = 'l'
595 print(table)
596
597 @cli.command(name='ns-op-show', short_help='shows the info of an operation')
598 @click.argument('id')
599 @click.option('--filter', default=None)
600 @click.pass_context
601 def ns_op_show(ctx, id, filter):
602 '''shows the detailed info of an operation
603
604 ID: operation identifier
605 '''
606 try:
607 check_client_version(ctx.obj, ctx.command.name)
608 op_info = ctx.obj.ns.get_op(id)
609 except ClientException as inst:
610 print((inst.message))
611 exit(1)
612
613 table = PrettyTable(['field', 'value'])
614 for k, v in list(op_info.items()):
615 if filter is None or filter in k:
616 table.add_row([k, json.dumps(v, indent=2)])
617 table.align = 'l'
618 print(table)
619
620
621 ####################
622 # CREATE operations
623 ####################
624
625 def nsd_create(ctx, filename, overwrite):
626 try:
627 check_client_version(ctx.obj, ctx.command.name)
628 ctx.obj.nsd.create(filename, overwrite)
629 except ClientException as inst:
630 print((inst.message))
631 exit(1)
632
633
634 @cli.command(name='nsd-create', short_help='creates a new NSD/NSpkg')
635 @click.argument('filename')
636 @click.option('--overwrite', default=None,
637 help='overwrites some fields in NSD')
638 @click.pass_context
639 def nsd_create1(ctx, filename, overwrite):
640 '''creates a new NSD/NSpkg
641
642 FILENAME: NSD yaml file or NSpkg tar.gz file
643 '''
644 nsd_create(ctx, filename, overwrite)
645
646
647 @cli.command(name='nspkg-create', short_help='creates a new NSD/NSpkg')
648 @click.argument('filename')
649 @click.option('--overwrite', default=None,
650 help='overwrites some fields in NSD')
651 @click.pass_context
652 def nsd_create2(ctx, filename, overwrite):
653 '''creates a new NSD/NSpkg
654
655 FILENAME: NSD yaml file or NSpkg tar.gz file
656 '''
657 nsd_create(ctx, filename, overwrite)
658
659
660 def vnfd_create(ctx, filename, overwrite):
661 try:
662 check_client_version(ctx.obj, ctx.command.name)
663 ctx.obj.vnfd.create(filename, overwrite)
664 except ClientException as inst:
665 print((inst.message))
666 exit(1)
667
668
669 @cli.command(name='vnfd-create', short_help='creates a new VNFD/VNFpkg')
670 @click.argument('filename')
671 @click.option('--overwrite', default=None,
672 help='overwrites some fields in VNFD')
673 @click.pass_context
674 def vnfd_create1(ctx, filename, overwrite):
675 '''creates a new VNFD/VNFpkg
676
677 FILENAME: VNFD yaml file or VNFpkg tar.gz file
678 '''
679 vnfd_create(ctx, filename, overwrite)
680
681
682 @cli.command(name='vnfpkg-create', short_help='creates a new VNFD/VNFpkg')
683 @click.argument('filename')
684 @click.option('--overwrite', default=None,
685 help='overwrites some fields in VNFD')
686 @click.pass_context
687 def vnfd_create2(ctx, filename, overwrite):
688 '''creates a new VNFD/VNFpkg
689
690 FILENAME: VNFD yaml file or VNFpkg tar.gz file
691 '''
692 vnfd_create(ctx, filename, overwrite)
693
694
695 @cli.command(name='ns-create')
696 @click.option('--ns_name',
697 prompt=True)
698 @click.option('--nsd_name',
699 prompt=True)
700 @click.option('--vim_account',
701 prompt=True)
702 @click.option('--admin_status',
703 default='ENABLED',
704 help='administration status')
705 @click.option('--ssh_keys',
706 default=None,
707 help='comma separated list of keys to inject to vnfs')
708 @click.option('--config',
709 default=None,
710 help='ns specific yaml configuration:\nvnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
711 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]')
712 @click.pass_context
713 def ns_create(ctx,
714 nsd_name,
715 ns_name,
716 vim_account,
717 admin_status,
718 ssh_keys,
719 config):
720 '''creates a new NS instance'''
721 try:
722 # if config:
723 # check_client_version(ctx.obj, '--config', 'v1')
724 ctx.obj.ns.create(
725 nsd_name,
726 ns_name,
727 config=config,
728 ssh_keys=ssh_keys,
729 account=vim_account)
730 except ClientException as inst:
731 print((inst.message))
732 exit(1)
733
734
735 ####################
736 # UPDATE operations
737 ####################
738
739 def nsd_update(ctx, name, content):
740 try:
741 check_client_version(ctx.obj, ctx.command.name)
742 ctx.obj.nsd.update(name, content)
743 except ClientException as inst:
744 print((inst.message))
745 exit(1)
746
747 @cli.command(name='nsd-update', short_help='updates a NSD/NSpkg')
748 @click.argument('name')
749 @click.option('--content', default=None,
750 help='filename with the NSD/NSpkg replacing the current one')
751 @click.pass_context
752 def nsd_update1(ctx, name, content):
753 '''updates a NSD/NSpkg
754
755 NAME: name or ID of the NSD/NSpkg
756 '''
757 nsd_update(ctx, name, content)
758
759
760 @cli.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
761 @click.argument('name')
762 @click.option('--content', default=None,
763 help='filename with the NSD/NSpkg replacing the current one')
764 @click.pass_context
765 def nsd_update2(ctx, name, content):
766 '''updates a NSD/NSpkg
767
768 NAME: name or ID of the NSD/NSpkg
769 '''
770 nsd_update(ctx, name, content)
771
772
773 def vnfd_update(ctx, name, content):
774 try:
775 check_client_version(ctx.obj, ctx.command.name)
776 ctx.obj.vnfd.update(name, content)
777 except ClientException as inst:
778 print((inst.message))
779 exit(1)
780
781
782 @cli.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
783 @click.argument('name')
784 @click.option('--content', default=None,
785 help='filename with the VNFD/VNFpkg replacing the current one')
786 @click.pass_context
787 def vnfd_update1(ctx, name, content):
788 '''updates a VNFD/VNFpkg
789
790 NAME: name or ID of the VNFD/VNFpkg
791 '''
792 vnfd_update(ctx, name, content)
793
794
795 @cli.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
796 @click.argument('name')
797 @click.option('--content', default=None,
798 help='filename with the VNFD/VNFpkg replacing the current one')
799 @click.pass_context
800 def vnfd_update2(ctx, name, content):
801 '''updates a VNFD/VNFpkg
802
803 NAME: VNFD yaml file or VNFpkg tar.gz file
804 '''
805 vnfd_update(ctx, name, content)
806
807
808 ####################
809 # DELETE operations
810 ####################
811
812 def nsd_delete(ctx, name, force):
813 try:
814 if not force:
815 ctx.obj.nsd.delete(name)
816 else:
817 check_client_version(ctx.obj, '--force')
818 ctx.obj.nsd.delete(name, force)
819 except ClientException as inst:
820 print((inst.message))
821 exit(1)
822
823
824 @cli.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
825 @click.argument('name')
826 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
827 @click.pass_context
828 def nsd_delete1(ctx, name, force):
829 '''deletes a NSD/NSpkg
830
831 NAME: name or ID of the NSD/NSpkg to be deleted
832 '''
833 nsd_delete(ctx, name, force)
834
835
836 @cli.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
837 @click.argument('name')
838 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
839 @click.pass_context
840 def nsd_delete2(ctx, name, force):
841 '''deletes a NSD/NSpkg
842
843 NAME: name or ID of the NSD/NSpkg to be deleted
844 '''
845 nsd_delete(ctx, name, force)
846
847
848 def vnfd_delete(ctx, name, force):
849 try:
850 if not force:
851 ctx.obj.vnfd.delete(name)
852 else:
853 check_client_version(ctx.obj, '--force')
854 ctx.obj.vnfd.delete(name, force)
855 except ClientException as inst:
856 print((inst.message))
857 exit(1)
858
859
860 @cli.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
861 @click.argument('name')
862 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
863 @click.pass_context
864 def vnfd_delete1(ctx, name, force):
865 '''deletes a VNFD/VNFpkg
866
867 NAME: name or ID of the VNFD/VNFpkg to be deleted
868 '''
869 vnfd_delete(ctx, name, force)
870
871
872 @cli.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
873 @click.argument('name')
874 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
875 @click.pass_context
876 def vnfd_delete2(ctx, name, force):
877 '''deletes a VNFD/VNFpkg
878
879 NAME: name or ID of the VNFD/VNFpkg to be deleted
880 '''
881 vnfd_delete(ctx, name, force)
882
883
884 @cli.command(name='ns-delete', short_help='deletes a NS instance')
885 @click.argument('name')
886 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
887 @click.pass_context
888 def ns_delete(ctx, name, force):
889 '''deletes a NS instance
890
891 NAME: name or ID of the NS instance to be deleted
892 '''
893 try:
894 if not force:
895 ctx.obj.ns.delete(name)
896 else:
897 check_client_version(ctx.obj, '--force')
898 ctx.obj.ns.delete(name, force)
899 except ClientException as inst:
900 print((inst.message))
901 exit(1)
902
903
904 ####################
905 # VIM operations
906 ####################
907
908 @cli.command(name='vim-create')
909 @click.option('--name',
910 prompt=True,
911 help='Name to create datacenter')
912 @click.option('--user',
913 prompt=True,
914 help='VIM username')
915 @click.option('--password',
916 prompt=True,
917 hide_input=True,
918 confirmation_prompt=True,
919 help='VIM password')
920 @click.option('--auth_url',
921 prompt=True,
922 help='VIM url')
923 @click.option('--tenant',
924 prompt=True,
925 help='VIM tenant name')
926 @click.option('--config',
927 default=None,
928 help='VIM specific config parameters')
929 @click.option('--account_type',
930 default='openstack',
931 help='VIM type')
932 @click.option('--description',
933 default='no description',
934 help='human readable description')
935 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
936 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
937 @click.pass_context
938 def vim_create(ctx,
939 name,
940 user,
941 password,
942 auth_url,
943 tenant,
944 config,
945 account_type,
946 description,
947 sdn_controller,
948 sdn_port_mapping):
949 '''creates a new VIM account
950 '''
951 try:
952 if sdn_controller:
953 check_client_version(ctx.obj, '--sdn_controller')
954 if sdn_port_mapping:
955 check_client_version(ctx.obj, '--sdn_port_mapping')
956 vim = {}
957 vim['vim-username'] = user
958 vim['vim-password'] = password
959 vim['vim-url'] = auth_url
960 vim['vim-tenant-name'] = tenant
961 vim['vim-type'] = account_type
962 vim['description'] = description
963 vim['config'] = config
964 if sdn_controller or sdn_port_mapping:
965 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping)
966 else:
967 ctx.obj.vim.create(name, vim)
968 except ClientException as inst:
969 print((inst.message))
970 exit(1)
971
972
973 @cli.command(name='vim-update', short_help='updates a VIM account')
974 @click.argument('name')
975 @click.option('--newname', help='New name for the VIM account')
976 @click.option('--user', help='VIM username')
977 @click.option('--password', help='VIM password')
978 @click.option('--auth_url', help='VIM url')
979 @click.option('--tenant', help='VIM tenant name')
980 @click.option('--config', help='VIM specific config parameters')
981 @click.option('--account_type', help='VIM type')
982 @click.option('--description', help='human readable description')
983 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
984 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
985 @click.pass_context
986 def vim_update(ctx,
987 name,
988 newname,
989 user,
990 password,
991 auth_url,
992 tenant,
993 config,
994 account_type,
995 description,
996 sdn_controller,
997 sdn_port_mapping):
998 '''updates a VIM account
999
1000 NAME: name or ID of the VIM account
1001 '''
1002 try:
1003 check_client_version(ctx.obj, ctx.command.name)
1004 vim = {}
1005 if newname: vim['name'] = newname
1006 if user: vim['vim_user'] = user
1007 if password: vim['vim_password'] = password
1008 if auth_url: vim['vim_url'] = auth_url
1009 if tenant: vim['vim-tenant-name'] = tenant
1010 if account_type: vim['vim_type'] = account_type
1011 if description: vim['description'] = description
1012 if config: vim['config'] = config
1013 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping)
1014 except ClientException as inst:
1015 print((inst.message))
1016 exit(1)
1017
1018
1019 @cli.command(name='vim-delete')
1020 @click.argument('name')
1021 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1022 @click.pass_context
1023 def vim_delete(ctx, name, force):
1024 '''deletes a VIM account
1025
1026 NAME: name or ID of the VIM account to be deleted
1027 '''
1028 try:
1029 if not force:
1030 ctx.obj.vim.delete(name)
1031 else:
1032 check_client_version(ctx.obj, '--force')
1033 ctx.obj.vim.delete(name, force)
1034 except ClientException as inst:
1035 print((inst.message))
1036 exit(1)
1037
1038
1039 @cli.command(name='vim-list')
1040 @click.option('--ro_update/--no_ro_update',
1041 default=False,
1042 help='update list from RO')
1043 @click.option('--filter', default=None,
1044 help='restricts the list to the VIM accounts matching the filter')
1045 @click.pass_context
1046 def vim_list(ctx, ro_update, filter):
1047 '''list all VIM accounts'''
1048 if filter:
1049 check_client_version(ctx.obj, '--filter')
1050 if ro_update:
1051 check_client_version(ctx.obj, '--ro_update', 'v1')
1052 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1053 if fullclassname == 'osmclient.sol005.client.Client':
1054 resp = ctx.obj.vim.list(filter)
1055 else:
1056 resp = ctx.obj.vim.list(ro_update)
1057 table = PrettyTable(['vim name', 'uuid'])
1058 for vim in resp:
1059 table.add_row([vim['name'], vim['uuid']])
1060 table.align = 'l'
1061 print(table)
1062
1063
1064 @cli.command(name='vim-show')
1065 @click.argument('name')
1066 @click.pass_context
1067 def vim_show(ctx, name):
1068 '''shows the details of a VIM account
1069
1070 NAME: name or ID of the VIM account
1071 '''
1072 try:
1073 resp = ctx.obj.vim.get(name)
1074 if 'vim_password' in resp:
1075 resp['vim_password']='********'
1076 except ClientException as inst:
1077 print((inst.message))
1078 exit(1)
1079
1080 table = PrettyTable(['key', 'attribute'])
1081 for k, v in list(resp.items()):
1082 table.add_row([k, json.dumps(v, indent=2)])
1083 table.align = 'l'
1084 print(table)
1085
1086
1087 ####################
1088 # SDN controller operations
1089 ####################
1090
1091 @cli.command(name='sdnc-create')
1092 @click.option('--name',
1093 prompt=True,
1094 help='Name to create sdn controller')
1095 @click.option('--type',
1096 prompt=True,
1097 help='SDN controller type')
1098 @click.option('--sdn_controller_version',
1099 help='SDN controller username')
1100 @click.option('--ip_address',
1101 prompt=True,
1102 help='SDN controller IP address')
1103 @click.option('--port',
1104 prompt=True,
1105 help='SDN controller port')
1106 @click.option('--switch_dpid',
1107 prompt=True,
1108 help='Switch DPID (Openflow Datapath ID)')
1109 @click.option('--user',
1110 help='SDN controller username')
1111 @click.option('--password',
1112 hide_input=True,
1113 confirmation_prompt=True,
1114 help='SDN controller password')
1115 #@click.option('--description',
1116 # default='no description',
1117 # help='human readable description')
1118 @click.pass_context
1119 def sdnc_create(ctx,
1120 name,
1121 type,
1122 sdn_controller_version,
1123 ip_address,
1124 port,
1125 switch_dpid,
1126 user,
1127 password):
1128 '''creates a new SDN controller
1129 '''
1130 sdncontroller = {}
1131 sdncontroller['name'] = name
1132 sdncontroller['type'] = type
1133 sdncontroller['ip'] = ip_address
1134 sdncontroller['port'] = int(port)
1135 sdncontroller['dpid'] = switch_dpid
1136 if sdn_controller_version:
1137 sdncontroller['version'] = sdn_controller_version
1138 if user:
1139 sdncontroller['user'] = user
1140 if password:
1141 sdncontroller['password'] = password
1142 # sdncontroller['description'] = description
1143 try:
1144 check_client_version(ctx.obj, ctx.command.name)
1145 ctx.obj.sdnc.create(name, sdncontroller)
1146 except ClientException as inst:
1147 print((inst.message))
1148
1149
1150 @cli.command(name='sdnc-update', short_help='updates an SDN controller')
1151 @click.argument('name')
1152 @click.option('--newname', help='New name for the SDN controller')
1153 @click.option('--type', help='SDN controller type')
1154 @click.option('--sdn_controller_version', help='SDN controller username')
1155 @click.option('--ip_address', help='SDN controller IP address')
1156 @click.option('--port', help='SDN controller port')
1157 @click.option('--switch_dpid', help='Switch DPID (Openflow Datapath ID)')
1158 @click.option('--user', help='SDN controller username')
1159 @click.option('--password', help='SDN controller password')
1160 #@click.option('--description', default=None, help='human readable description')
1161 @click.pass_context
1162 def sdnc_update(ctx,
1163 name,
1164 newname,
1165 type,
1166 sdn_controller_version,
1167 ip_address,
1168 port,
1169 switch_dpid,
1170 user,
1171 password):
1172 '''updates an SDN controller
1173
1174 NAME: name or ID of the SDN controller
1175 '''
1176 sdncontroller = {}
1177 if newname: sdncontroller['name'] = newname
1178 if type: sdncontroller['type'] = type
1179 if ip_address: sdncontroller['ip'] = ip_address
1180 if port: sdncontroller['port'] = int(port)
1181 if switch_dpid: sdncontroller['dpid'] = switch_dpid
1182 # sdncontroller['description'] = description
1183 if sdn_controller_version is not None:
1184 if sdn_controller_version=="":
1185 sdncontroller['version'] = None
1186 else:
1187 sdncontroller['version'] = sdn_controller_version
1188 if user is not None:
1189 if user=="":
1190 sdncontroller['user'] = None
1191 else:
1192 sdncontroller['user'] = user
1193 if password is not None:
1194 if password=="":
1195 sdncontroller['password'] = None
1196 else:
1197 sdncontroller['password'] = user
1198 try:
1199 check_client_version(ctx.obj, ctx.command.name)
1200 ctx.obj.sdnc.update(name, sdncontroller)
1201 except ClientException as inst:
1202 print((inst.message))
1203 exit(1)
1204
1205
1206 @cli.command(name='sdnc-delete')
1207 @click.argument('name')
1208 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1209 @click.pass_context
1210 def sdnc_delete(ctx, name, force):
1211 '''deletes an SDN controller
1212
1213 NAME: name or ID of the SDN controller to be deleted
1214 '''
1215 try:
1216 check_client_version(ctx.obj, ctx.command.name)
1217 ctx.obj.sdnc.delete(name, force)
1218 except ClientException as inst:
1219 print((inst.message))
1220 exit(1)
1221
1222
1223 @cli.command(name='sdnc-list')
1224 @click.option('--filter', default=None,
1225 help='restricts the list to the SDN controllers matching the filter')
1226 @click.pass_context
1227 def sdnc_list(ctx, filter):
1228 '''list all SDN controllers'''
1229 try:
1230 check_client_version(ctx.obj, ctx.command.name)
1231 resp = ctx.obj.sdnc.list(filter)
1232 except ClientException as inst:
1233 print((inst.message))
1234 exit(1)
1235 table = PrettyTable(['name', 'id'])
1236 for sdnc in resp:
1237 table.add_row([sdnc['name'], sdnc['_id']])
1238 table.align = 'l'
1239 print(table)
1240
1241
1242 @cli.command(name='sdnc-show')
1243 @click.argument('name')
1244 @click.pass_context
1245 def sdnc_show(ctx, name):
1246 '''shows the details of an SDN controller
1247
1248 NAME: name or ID of the SDN controller
1249 '''
1250 try:
1251 check_client_version(ctx.obj, ctx.command.name)
1252 resp = ctx.obj.sdnc.get(name)
1253 except ClientException as inst:
1254 print((inst.message))
1255 exit(1)
1256
1257 table = PrettyTable(['key', 'attribute'])
1258 for k, v in list(resp.items()):
1259 table.add_row([k, json.dumps(v, indent=2)])
1260 table.align = 'l'
1261 print(table)
1262
1263
1264 ####################
1265 # Fault Management operations
1266 ####################
1267
1268 @cli.command(name='ns-alarm-create')
1269 @click.argument('name')
1270 @click.option('--ns', prompt=True, help='NS instance id or name')
1271 @click.option('--vnf', prompt=True,
1272 help='VNF name (VNF member index as declared in the NSD)')
1273 @click.option('--vdu', prompt=True,
1274 help='VDU name (VDU name as declared in the VNFD)')
1275 @click.option('--metric', prompt=True,
1276 help='Name of the metric (e.g. cpu_utilization)')
1277 @click.option('--severity', default='WARNING',
1278 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
1279 @click.option('--threshold_value', prompt=True,
1280 help='threshold value that, when crossed, an alarm is triggered')
1281 @click.option('--threshold_operator', prompt=True,
1282 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
1283 @click.option('--statistic', default='AVERAGE',
1284 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
1285 @click.pass_context
1286 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
1287 threshold_value, threshold_operator, statistic):
1288 '''creates a new alarm for a NS instance'''
1289 ns_instance = ctx.obj.ns.get(ns)
1290 alarm = {}
1291 alarm['alarm_name'] = name
1292 alarm['ns_id'] = ns_instance['_id']
1293 alarm['correlation_id'] = ns_instance['_id']
1294 alarm['vnf_member_index'] = vnf
1295 alarm['vdu_name'] = vdu
1296 alarm['metric_name'] = metric
1297 alarm['severity'] = severity
1298 alarm['threshold_value'] = int(threshold_value)
1299 alarm['operation'] = threshold_operator
1300 alarm['statistic'] = statistic
1301 try:
1302 check_client_version(ctx.obj, ctx.command.name)
1303 ctx.obj.ns.create_alarm(alarm)
1304 except ClientException as inst:
1305 print((inst.message))
1306 exit(1)
1307
1308
1309 #@cli.command(name='ns-alarm-delete')
1310 #@click.argument('name')
1311 #@click.pass_context
1312 #def ns_alarm_delete(ctx, name):
1313 # '''deletes an alarm
1314 #
1315 # NAME: name of the alarm to be deleted
1316 # '''
1317 # try:
1318 # check_client_version(ctx.obj, ctx.command.name)
1319 # ctx.obj.ns.delete_alarm(name)
1320 # except ClientException as inst:
1321 # print(inst.message)
1322 # exit(1)
1323
1324
1325 ####################
1326 # Performance Management operations
1327 ####################
1328
1329 @cli.command(name='ns-metric-export')
1330 @click.option('--ns', prompt=True, help='NS instance id or name')
1331 @click.option('--vnf', prompt=True,
1332 help='VNF name (VNF member index as declared in the NSD)')
1333 @click.option('--vdu', prompt=True,
1334 help='VDU name (VDU name as declared in the VNFD)')
1335 @click.option('--metric', prompt=True,
1336 help='name of the metric (e.g. cpu_utilization)')
1337 #@click.option('--period', default='1w',
1338 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
1339 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
1340 @click.pass_context
1341 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
1342 '''exports a metric to the internal OSM bus, which can be read by other apps
1343 '''
1344 ns_instance = ctx.obj.ns.get(ns)
1345 metric_data = {}
1346 metric_data['ns_id'] = ns_instance['_id']
1347 metric_data['correlation_id'] = ns_instance['_id']
1348 metric_data['vnf_member_index'] = vnf
1349 metric_data['vdu_name'] = vdu
1350 metric_data['metric_name'] = metric
1351 metric_data['collection_unit'] = 'WEEK'
1352 metric_data['collection_period'] = 1
1353 try:
1354 check_client_version(ctx.obj, ctx.command.name)
1355 if not interval:
1356 print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
1357 else:
1358 i = 1
1359 while True:
1360 print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
1361 time.sleep(int(interval))
1362 i+=1
1363 except ClientException as inst:
1364 print((inst.message))
1365 exit(1)
1366
1367
1368 ####################
1369 # Other operations
1370 ####################
1371
1372 @cli.command(name='upload-package')
1373 @click.argument('filename')
1374 @click.pass_context
1375 def upload_package(ctx, filename):
1376 '''uploads a VNF package or NS package
1377
1378 FILENAME: VNF or NS package file (tar.gz)
1379 '''
1380 try:
1381 ctx.obj.package.upload(filename)
1382 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1383 if fullclassname != 'osmclient.sol005.client.Client':
1384 ctx.obj.package.wait_for_upload(filename)
1385 except ClientException as inst:
1386 print((inst.message))
1387 exit(1)
1388
1389
1390 @cli.command(name='ns-scaling-show')
1391 @click.argument('ns_name')
1392 @click.pass_context
1393 def show_ns_scaling(ctx, ns_name):
1394 '''shows the status of a NS scaling operation
1395
1396 NS_NAME: name of the NS instance being scaled
1397 '''
1398 try:
1399 check_client_version(ctx.obj, ctx.command.name, 'v1')
1400 resp = ctx.obj.ns.list()
1401 except ClientException as inst:
1402 print((inst.message))
1403 exit(1)
1404
1405 table = PrettyTable(
1406 ['group-name',
1407 'instance-id',
1408 'operational status',
1409 'create-time',
1410 'vnfr ids'])
1411
1412 for ns in resp:
1413 if ns_name == ns['name']:
1414 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
1415 scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
1416 for record in scaling_records:
1417 if 'instance' in record:
1418 instances = record['instance']
1419 for inst in instances:
1420 table.add_row(
1421 [record['scaling-group-name-ref'],
1422 inst['instance-id'],
1423 inst['op-status'],
1424 time.strftime('%Y-%m-%d %H:%M:%S',
1425 time.localtime(
1426 inst['create-time'])),
1427 inst['vnfrs']])
1428 table.align = 'l'
1429 print(table)
1430
1431
1432 @cli.command(name='ns-scale')
1433 @click.argument('ns_name')
1434 @click.option('--ns_scale_group', prompt=True)
1435 @click.option('--index', prompt=True)
1436 @click.pass_context
1437 def ns_scale(ctx, ns_name, ns_scale_group, index):
1438 '''scales NS
1439
1440 NS_NAME: name of the NS instance to be scaled
1441 '''
1442 try:
1443 check_client_version(ctx.obj, ctx.command.name, 'v1')
1444 ctx.obj.ns.scale(ns_name, ns_scale_group, index)
1445 except ClientException as inst:
1446 print((inst.message))
1447 exit(1)
1448
1449
1450 @cli.command(name='config-agent-list')
1451 @click.pass_context
1452 def config_agent_list(ctx):
1453 '''list config agents'''
1454 try:
1455 check_client_version(ctx.obj, ctx.command.name, 'v1')
1456 except ClientException as inst:
1457 print((inst.message))
1458 exit(1)
1459 table = PrettyTable(['name', 'account-type', 'details'])
1460 for account in ctx.obj.vca.list():
1461 table.add_row(
1462 [account['name'],
1463 account['account-type'],
1464 account['juju']])
1465 table.align = 'l'
1466 print(table)
1467
1468
1469 @cli.command(name='config-agent-delete')
1470 @click.argument('name')
1471 @click.pass_context
1472 def config_agent_delete(ctx, name):
1473 '''deletes a config agent
1474
1475 NAME: name of the config agent to be deleted
1476 '''
1477 try:
1478 check_client_version(ctx.obj, ctx.command.name, 'v1')
1479 ctx.obj.vca.delete(name)
1480 except ClientException as inst:
1481 print((inst.message))
1482 exit(1)
1483
1484
1485 @cli.command(name='config-agent-add')
1486 @click.option('--name',
1487 prompt=True)
1488 @click.option('--account_type',
1489 prompt=True)
1490 @click.option('--server',
1491 prompt=True)
1492 @click.option('--user',
1493 prompt=True)
1494 @click.option('--secret',
1495 prompt=True,
1496 hide_input=True,
1497 confirmation_prompt=True)
1498 @click.pass_context
1499 def config_agent_add(ctx, name, account_type, server, user, secret):
1500 '''adds a config agent'''
1501 try:
1502 check_client_version(ctx.obj, ctx.command.name, 'v1')
1503 ctx.obj.vca.create(name, account_type, server, user, secret)
1504 except ClientException as inst:
1505 print((inst.message))
1506 exit(1)
1507
1508 @cli.command(name='ro-dump')
1509 @click.pass_context
1510 def ro_dump(ctx):
1511 '''shows RO agent information'''
1512 check_client_version(ctx.obj, ctx.command.name, 'v1')
1513 resp = ctx.obj.vim.get_resource_orchestrator()
1514 table = PrettyTable(['key', 'attribute'])
1515 for k, v in list(resp.items()):
1516 table.add_row([k, json.dumps(v, indent=2)])
1517 table.align = 'l'
1518 print(table)
1519
1520
1521 @cli.command(name='vcs-list')
1522 @click.pass_context
1523 def vcs_list(ctx):
1524 check_client_version(ctx.obj, ctx.command.name, 'v1')
1525 resp = ctx.obj.utils.get_vcs_info()
1526 table = PrettyTable(['component name', 'state'])
1527 for component in resp:
1528 table.add_row([component['component_name'], component['state']])
1529 table.align = 'l'
1530 print(table)
1531
1532
1533 @cli.command(name='ns-action')
1534 @click.argument('ns_name')
1535 @click.option('--vnf_name', default=None)
1536 @click.option('--action_name', prompt=True)
1537 @click.option('--params', prompt=True)
1538 @click.pass_context
1539 def ns_action(ctx,
1540 ns_name,
1541 vnf_name,
1542 action_name,
1543 params):
1544 '''executes an action/primitive over a NS instance
1545
1546 NS_NAME: name or ID of the NS instance
1547 '''
1548 try:
1549 check_client_version(ctx.obj, ctx.command.name)
1550 op_data={}
1551 if vnf_name:
1552 op_data['vnf_member_index'] = vnf_name
1553 op_data['primitive'] = action_name
1554 op_data['primitive_params'] = yaml.load(params)
1555 ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data)
1556
1557 except ClientException as inst:
1558 print((inst.message))
1559 exit(1)
1560
1561
1562 if __name__ == '__main__':
1563 cli()