osm ns-create: new option --config_file
[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 public key files to inject to vnfs')
708 @click.option('--config',
709 default=None,
710 help='ns specific yaml configuration')
711 @click.option('--config_file',
712 default=None,
713 help='ns specific yaml configuration file')
714 @click.pass_context
715 def ns_create(ctx,
716 nsd_name,
717 ns_name,
718 vim_account,
719 admin_status,
720 ssh_keys,
721 config,
722 config_file):
723 '''creates a new NS instance'''
724 try:
725 if config_file:
726 check_client_version(ctx.obj, '--config_file')
727 if config:
728 raise ClientException('"--config" option is incompatible with "--config_file" option')
729 with open(config_file, 'r') as cf:
730 config=cf.read()
731 ctx.obj.ns.create(
732 nsd_name,
733 ns_name,
734 config=config,
735 ssh_keys=ssh_keys,
736 account=vim_account)
737 except ClientException as inst:
738 print((inst.message))
739 exit(1)
740
741
742 ####################
743 # UPDATE operations
744 ####################
745
746 def nsd_update(ctx, name, content):
747 try:
748 check_client_version(ctx.obj, ctx.command.name)
749 ctx.obj.nsd.update(name, content)
750 except ClientException as inst:
751 print((inst.message))
752 exit(1)
753
754 @cli.command(name='nsd-update', short_help='updates a NSD/NSpkg')
755 @click.argument('name')
756 @click.option('--content', default=None,
757 help='filename with the NSD/NSpkg replacing the current one')
758 @click.pass_context
759 def nsd_update1(ctx, name, content):
760 '''updates a NSD/NSpkg
761
762 NAME: name or ID of the NSD/NSpkg
763 '''
764 nsd_update(ctx, name, content)
765
766
767 @cli.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
768 @click.argument('name')
769 @click.option('--content', default=None,
770 help='filename with the NSD/NSpkg replacing the current one')
771 @click.pass_context
772 def nsd_update2(ctx, name, content):
773 '''updates a NSD/NSpkg
774
775 NAME: name or ID of the NSD/NSpkg
776 '''
777 nsd_update(ctx, name, content)
778
779
780 def vnfd_update(ctx, name, content):
781 try:
782 check_client_version(ctx.obj, ctx.command.name)
783 ctx.obj.vnfd.update(name, content)
784 except ClientException as inst:
785 print((inst.message))
786 exit(1)
787
788
789 @cli.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
790 @click.argument('name')
791 @click.option('--content', default=None,
792 help='filename with the VNFD/VNFpkg replacing the current one')
793 @click.pass_context
794 def vnfd_update1(ctx, name, content):
795 '''updates a VNFD/VNFpkg
796
797 NAME: name or ID of the VNFD/VNFpkg
798 '''
799 vnfd_update(ctx, name, content)
800
801
802 @cli.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
803 @click.argument('name')
804 @click.option('--content', default=None,
805 help='filename with the VNFD/VNFpkg replacing the current one')
806 @click.pass_context
807 def vnfd_update2(ctx, name, content):
808 '''updates a VNFD/VNFpkg
809
810 NAME: VNFD yaml file or VNFpkg tar.gz file
811 '''
812 vnfd_update(ctx, name, content)
813
814
815 ####################
816 # DELETE operations
817 ####################
818
819 def nsd_delete(ctx, name, force):
820 try:
821 if not force:
822 ctx.obj.nsd.delete(name)
823 else:
824 check_client_version(ctx.obj, '--force')
825 ctx.obj.nsd.delete(name, force)
826 except ClientException as inst:
827 print((inst.message))
828 exit(1)
829
830
831 @cli.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
832 @click.argument('name')
833 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
834 @click.pass_context
835 def nsd_delete1(ctx, name, force):
836 '''deletes a NSD/NSpkg
837
838 NAME: name or ID of the NSD/NSpkg to be deleted
839 '''
840 nsd_delete(ctx, name, force)
841
842
843 @cli.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
844 @click.argument('name')
845 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
846 @click.pass_context
847 def nsd_delete2(ctx, name, force):
848 '''deletes a NSD/NSpkg
849
850 NAME: name or ID of the NSD/NSpkg to be deleted
851 '''
852 nsd_delete(ctx, name, force)
853
854
855 def vnfd_delete(ctx, name, force):
856 try:
857 if not force:
858 ctx.obj.vnfd.delete(name)
859 else:
860 check_client_version(ctx.obj, '--force')
861 ctx.obj.vnfd.delete(name, force)
862 except ClientException as inst:
863 print((inst.message))
864 exit(1)
865
866
867 @cli.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
868 @click.argument('name')
869 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
870 @click.pass_context
871 def vnfd_delete1(ctx, name, force):
872 '''deletes a VNFD/VNFpkg
873
874 NAME: name or ID of the VNFD/VNFpkg to be deleted
875 '''
876 vnfd_delete(ctx, name, force)
877
878
879 @cli.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
880 @click.argument('name')
881 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
882 @click.pass_context
883 def vnfd_delete2(ctx, name, force):
884 '''deletes a VNFD/VNFpkg
885
886 NAME: name or ID of the VNFD/VNFpkg to be deleted
887 '''
888 vnfd_delete(ctx, name, force)
889
890
891 @cli.command(name='ns-delete', short_help='deletes a NS instance')
892 @click.argument('name')
893 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
894 @click.pass_context
895 def ns_delete(ctx, name, force):
896 '''deletes a NS instance
897
898 NAME: name or ID of the NS instance to be deleted
899 '''
900 try:
901 if not force:
902 ctx.obj.ns.delete(name)
903 else:
904 check_client_version(ctx.obj, '--force')
905 ctx.obj.ns.delete(name, force)
906 except ClientException as inst:
907 print((inst.message))
908 exit(1)
909
910
911 ####################
912 # VIM operations
913 ####################
914
915 @cli.command(name='vim-create')
916 @click.option('--name',
917 prompt=True,
918 help='Name to create datacenter')
919 @click.option('--user',
920 prompt=True,
921 help='VIM username')
922 @click.option('--password',
923 prompt=True,
924 hide_input=True,
925 confirmation_prompt=True,
926 help='VIM password')
927 @click.option('--auth_url',
928 prompt=True,
929 help='VIM url')
930 @click.option('--tenant',
931 prompt=True,
932 help='VIM tenant name')
933 @click.option('--config',
934 default=None,
935 help='VIM specific config parameters')
936 @click.option('--account_type',
937 default='openstack',
938 help='VIM type')
939 @click.option('--description',
940 default='no description',
941 help='human readable description')
942 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
943 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
944 @click.pass_context
945 def vim_create(ctx,
946 name,
947 user,
948 password,
949 auth_url,
950 tenant,
951 config,
952 account_type,
953 description,
954 sdn_controller,
955 sdn_port_mapping):
956 '''creates a new VIM account
957 '''
958 try:
959 if sdn_controller:
960 check_client_version(ctx.obj, '--sdn_controller')
961 if sdn_port_mapping:
962 check_client_version(ctx.obj, '--sdn_port_mapping')
963 vim = {}
964 vim['vim-username'] = user
965 vim['vim-password'] = password
966 vim['vim-url'] = auth_url
967 vim['vim-tenant-name'] = tenant
968 vim['vim-type'] = account_type
969 vim['description'] = description
970 vim['config'] = config
971 if sdn_controller or sdn_port_mapping:
972 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping)
973 else:
974 ctx.obj.vim.create(name, vim)
975 except ClientException as inst:
976 print((inst.message))
977 exit(1)
978
979
980 @cli.command(name='vim-update', short_help='updates a VIM account')
981 @click.argument('name')
982 @click.option('--newname', help='New name for the VIM account')
983 @click.option('--user', help='VIM username')
984 @click.option('--password', help='VIM password')
985 @click.option('--auth_url', help='VIM url')
986 @click.option('--tenant', help='VIM tenant name')
987 @click.option('--config', help='VIM specific config parameters')
988 @click.option('--account_type', help='VIM type')
989 @click.option('--description', help='human readable description')
990 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
991 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
992 @click.pass_context
993 def vim_update(ctx,
994 name,
995 newname,
996 user,
997 password,
998 auth_url,
999 tenant,
1000 config,
1001 account_type,
1002 description,
1003 sdn_controller,
1004 sdn_port_mapping):
1005 '''updates a VIM account
1006
1007 NAME: name or ID of the VIM account
1008 '''
1009 try:
1010 check_client_version(ctx.obj, ctx.command.name)
1011 vim = {}
1012 if newname: vim['name'] = newname
1013 if user: vim['vim_user'] = user
1014 if password: vim['vim_password'] = password
1015 if auth_url: vim['vim_url'] = auth_url
1016 if tenant: vim['vim-tenant-name'] = tenant
1017 if account_type: vim['vim_type'] = account_type
1018 if description: vim['description'] = description
1019 if config: vim['config'] = config
1020 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping)
1021 except ClientException as inst:
1022 print((inst.message))
1023 exit(1)
1024
1025
1026 @cli.command(name='vim-delete')
1027 @click.argument('name')
1028 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1029 @click.pass_context
1030 def vim_delete(ctx, name, force):
1031 '''deletes a VIM account
1032
1033 NAME: name or ID of the VIM account to be deleted
1034 '''
1035 try:
1036 if not force:
1037 ctx.obj.vim.delete(name)
1038 else:
1039 check_client_version(ctx.obj, '--force')
1040 ctx.obj.vim.delete(name, force)
1041 except ClientException as inst:
1042 print((inst.message))
1043 exit(1)
1044
1045
1046 @cli.command(name='vim-list')
1047 @click.option('--ro_update/--no_ro_update',
1048 default=False,
1049 help='update list from RO')
1050 @click.option('--filter', default=None,
1051 help='restricts the list to the VIM accounts matching the filter')
1052 @click.pass_context
1053 def vim_list(ctx, ro_update, filter):
1054 '''list all VIM accounts'''
1055 if filter:
1056 check_client_version(ctx.obj, '--filter')
1057 if ro_update:
1058 check_client_version(ctx.obj, '--ro_update', 'v1')
1059 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1060 if fullclassname == 'osmclient.sol005.client.Client':
1061 resp = ctx.obj.vim.list(filter)
1062 else:
1063 resp = ctx.obj.vim.list(ro_update)
1064 table = PrettyTable(['vim name', 'uuid'])
1065 for vim in resp:
1066 table.add_row([vim['name'], vim['uuid']])
1067 table.align = 'l'
1068 print(table)
1069
1070
1071 @cli.command(name='vim-show')
1072 @click.argument('name')
1073 @click.pass_context
1074 def vim_show(ctx, name):
1075 '''shows the details of a VIM account
1076
1077 NAME: name or ID of the VIM account
1078 '''
1079 try:
1080 resp = ctx.obj.vim.get(name)
1081 if 'vim_password' in resp:
1082 resp['vim_password']='********'
1083 except ClientException as inst:
1084 print((inst.message))
1085 exit(1)
1086
1087 table = PrettyTable(['key', 'attribute'])
1088 for k, v in list(resp.items()):
1089 table.add_row([k, json.dumps(v, indent=2)])
1090 table.align = 'l'
1091 print(table)
1092
1093
1094 ####################
1095 # SDN controller operations
1096 ####################
1097
1098 @cli.command(name='sdnc-create')
1099 @click.option('--name',
1100 prompt=True,
1101 help='Name to create sdn controller')
1102 @click.option('--type',
1103 prompt=True,
1104 help='SDN controller type')
1105 @click.option('--sdn_controller_version',
1106 help='SDN controller username')
1107 @click.option('--ip_address',
1108 prompt=True,
1109 help='SDN controller IP address')
1110 @click.option('--port',
1111 prompt=True,
1112 help='SDN controller port')
1113 @click.option('--switch_dpid',
1114 prompt=True,
1115 help='Switch DPID (Openflow Datapath ID)')
1116 @click.option('--user',
1117 help='SDN controller username')
1118 @click.option('--password',
1119 hide_input=True,
1120 confirmation_prompt=True,
1121 help='SDN controller password')
1122 #@click.option('--description',
1123 # default='no description',
1124 # help='human readable description')
1125 @click.pass_context
1126 def sdnc_create(ctx,
1127 name,
1128 type,
1129 sdn_controller_version,
1130 ip_address,
1131 port,
1132 switch_dpid,
1133 user,
1134 password):
1135 '''creates a new SDN controller
1136 '''
1137 sdncontroller = {}
1138 sdncontroller['name'] = name
1139 sdncontroller['type'] = type
1140 sdncontroller['ip'] = ip_address
1141 sdncontroller['port'] = int(port)
1142 sdncontroller['dpid'] = switch_dpid
1143 if sdn_controller_version:
1144 sdncontroller['version'] = sdn_controller_version
1145 if user:
1146 sdncontroller['user'] = user
1147 if password:
1148 sdncontroller['password'] = password
1149 # sdncontroller['description'] = description
1150 try:
1151 check_client_version(ctx.obj, ctx.command.name)
1152 ctx.obj.sdnc.create(name, sdncontroller)
1153 except ClientException as inst:
1154 print((inst.message))
1155
1156
1157 @cli.command(name='sdnc-update', short_help='updates an SDN controller')
1158 @click.argument('name')
1159 @click.option('--newname', help='New name for the SDN controller')
1160 @click.option('--type', help='SDN controller type')
1161 @click.option('--sdn_controller_version', help='SDN controller username')
1162 @click.option('--ip_address', help='SDN controller IP address')
1163 @click.option('--port', help='SDN controller port')
1164 @click.option('--switch_dpid', help='Switch DPID (Openflow Datapath ID)')
1165 @click.option('--user', help='SDN controller username')
1166 @click.option('--password', help='SDN controller password')
1167 #@click.option('--description', default=None, help='human readable description')
1168 @click.pass_context
1169 def sdnc_update(ctx,
1170 name,
1171 newname,
1172 type,
1173 sdn_controller_version,
1174 ip_address,
1175 port,
1176 switch_dpid,
1177 user,
1178 password):
1179 '''updates an SDN controller
1180
1181 NAME: name or ID of the SDN controller
1182 '''
1183 sdncontroller = {}
1184 if newname: sdncontroller['name'] = newname
1185 if type: sdncontroller['type'] = type
1186 if ip_address: sdncontroller['ip'] = ip_address
1187 if port: sdncontroller['port'] = int(port)
1188 if switch_dpid: sdncontroller['dpid'] = switch_dpid
1189 # sdncontroller['description'] = description
1190 if sdn_controller_version is not None:
1191 if sdn_controller_version=="":
1192 sdncontroller['version'] = None
1193 else:
1194 sdncontroller['version'] = sdn_controller_version
1195 if user is not None:
1196 if user=="":
1197 sdncontroller['user'] = None
1198 else:
1199 sdncontroller['user'] = user
1200 if password is not None:
1201 if password=="":
1202 sdncontroller['password'] = None
1203 else:
1204 sdncontroller['password'] = user
1205 try:
1206 check_client_version(ctx.obj, ctx.command.name)
1207 ctx.obj.sdnc.update(name, sdncontroller)
1208 except ClientException as inst:
1209 print((inst.message))
1210 exit(1)
1211
1212
1213 @cli.command(name='sdnc-delete')
1214 @click.argument('name')
1215 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1216 @click.pass_context
1217 def sdnc_delete(ctx, name, force):
1218 '''deletes an SDN controller
1219
1220 NAME: name or ID of the SDN controller to be deleted
1221 '''
1222 try:
1223 check_client_version(ctx.obj, ctx.command.name)
1224 ctx.obj.sdnc.delete(name, force)
1225 except ClientException as inst:
1226 print((inst.message))
1227 exit(1)
1228
1229
1230 @cli.command(name='sdnc-list')
1231 @click.option('--filter', default=None,
1232 help='restricts the list to the SDN controllers matching the filter')
1233 @click.pass_context
1234 def sdnc_list(ctx, filter):
1235 '''list all SDN controllers'''
1236 try:
1237 check_client_version(ctx.obj, ctx.command.name)
1238 resp = ctx.obj.sdnc.list(filter)
1239 except ClientException as inst:
1240 print((inst.message))
1241 exit(1)
1242 table = PrettyTable(['name', 'id'])
1243 for sdnc in resp:
1244 table.add_row([sdnc['name'], sdnc['_id']])
1245 table.align = 'l'
1246 print(table)
1247
1248
1249 @cli.command(name='sdnc-show')
1250 @click.argument('name')
1251 @click.pass_context
1252 def sdnc_show(ctx, name):
1253 '''shows the details of an SDN controller
1254
1255 NAME: name or ID of the SDN controller
1256 '''
1257 try:
1258 check_client_version(ctx.obj, ctx.command.name)
1259 resp = ctx.obj.sdnc.get(name)
1260 except ClientException as inst:
1261 print((inst.message))
1262 exit(1)
1263
1264 table = PrettyTable(['key', 'attribute'])
1265 for k, v in list(resp.items()):
1266 table.add_row([k, json.dumps(v, indent=2)])
1267 table.align = 'l'
1268 print(table)
1269
1270
1271 ####################
1272 # Fault Management operations
1273 ####################
1274
1275 @cli.command(name='ns-alarm-create')
1276 @click.argument('name')
1277 @click.option('--ns', prompt=True, help='NS instance id or name')
1278 @click.option('--vnf', prompt=True,
1279 help='VNF name (VNF member index as declared in the NSD)')
1280 @click.option('--vdu', prompt=True,
1281 help='VDU name (VDU name as declared in the VNFD)')
1282 @click.option('--metric', prompt=True,
1283 help='Name of the metric (e.g. cpu_utilization)')
1284 @click.option('--severity', default='WARNING',
1285 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
1286 @click.option('--threshold_value', prompt=True,
1287 help='threshold value that, when crossed, an alarm is triggered')
1288 @click.option('--threshold_operator', prompt=True,
1289 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
1290 @click.option('--statistic', default='AVERAGE',
1291 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
1292 @click.pass_context
1293 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
1294 threshold_value, threshold_operator, statistic):
1295 '''creates a new alarm for a NS instance'''
1296 ns_instance = ctx.obj.ns.get(ns)
1297 alarm = {}
1298 alarm['alarm_name'] = name
1299 alarm['ns_id'] = ns_instance['_id']
1300 alarm['correlation_id'] = ns_instance['_id']
1301 alarm['vnf_member_index'] = vnf
1302 alarm['vdu_name'] = vdu
1303 alarm['metric_name'] = metric
1304 alarm['severity'] = severity
1305 alarm['threshold_value'] = int(threshold_value)
1306 alarm['operation'] = threshold_operator
1307 alarm['statistic'] = statistic
1308 try:
1309 check_client_version(ctx.obj, ctx.command.name)
1310 ctx.obj.ns.create_alarm(alarm)
1311 except ClientException as inst:
1312 print((inst.message))
1313 exit(1)
1314
1315
1316 #@cli.command(name='ns-alarm-delete')
1317 #@click.argument('name')
1318 #@click.pass_context
1319 #def ns_alarm_delete(ctx, name):
1320 # '''deletes an alarm
1321 #
1322 # NAME: name of the alarm to be deleted
1323 # '''
1324 # try:
1325 # check_client_version(ctx.obj, ctx.command.name)
1326 # ctx.obj.ns.delete_alarm(name)
1327 # except ClientException as inst:
1328 # print(inst.message)
1329 # exit(1)
1330
1331
1332 ####################
1333 # Performance Management operations
1334 ####################
1335
1336 @cli.command(name='ns-metric-export')
1337 @click.option('--ns', prompt=True, help='NS instance id or name')
1338 @click.option('--vnf', prompt=True,
1339 help='VNF name (VNF member index as declared in the NSD)')
1340 @click.option('--vdu', prompt=True,
1341 help='VDU name (VDU name as declared in the VNFD)')
1342 @click.option('--metric', prompt=True,
1343 help='name of the metric (e.g. cpu_utilization)')
1344 #@click.option('--period', default='1w',
1345 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
1346 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
1347 @click.pass_context
1348 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
1349 '''exports a metric to the internal OSM bus, which can be read by other apps
1350 '''
1351 ns_instance = ctx.obj.ns.get(ns)
1352 metric_data = {}
1353 metric_data['ns_id'] = ns_instance['_id']
1354 metric_data['correlation_id'] = ns_instance['_id']
1355 metric_data['vnf_member_index'] = vnf
1356 metric_data['vdu_name'] = vdu
1357 metric_data['metric_name'] = metric
1358 metric_data['collection_unit'] = 'WEEK'
1359 metric_data['collection_period'] = 1
1360 try:
1361 check_client_version(ctx.obj, ctx.command.name)
1362 if not interval:
1363 print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
1364 else:
1365 i = 1
1366 while True:
1367 print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
1368 time.sleep(int(interval))
1369 i+=1
1370 except ClientException as inst:
1371 print((inst.message))
1372 exit(1)
1373
1374
1375 ####################
1376 # Other operations
1377 ####################
1378
1379 @cli.command(name='upload-package')
1380 @click.argument('filename')
1381 @click.pass_context
1382 def upload_package(ctx, filename):
1383 '''uploads a VNF package or NS package
1384
1385 FILENAME: VNF or NS package file (tar.gz)
1386 '''
1387 try:
1388 ctx.obj.package.upload(filename)
1389 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1390 if fullclassname != 'osmclient.sol005.client.Client':
1391 ctx.obj.package.wait_for_upload(filename)
1392 except ClientException as inst:
1393 print((inst.message))
1394 exit(1)
1395
1396
1397 @cli.command(name='ns-scaling-show')
1398 @click.argument('ns_name')
1399 @click.pass_context
1400 def show_ns_scaling(ctx, ns_name):
1401 '''shows the status of a NS scaling operation
1402
1403 NS_NAME: name of the NS instance being scaled
1404 '''
1405 try:
1406 check_client_version(ctx.obj, ctx.command.name, 'v1')
1407 resp = ctx.obj.ns.list()
1408 except ClientException as inst:
1409 print((inst.message))
1410 exit(1)
1411
1412 table = PrettyTable(
1413 ['group-name',
1414 'instance-id',
1415 'operational status',
1416 'create-time',
1417 'vnfr ids'])
1418
1419 for ns in resp:
1420 if ns_name == ns['name']:
1421 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
1422 scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
1423 for record in scaling_records:
1424 if 'instance' in record:
1425 instances = record['instance']
1426 for inst in instances:
1427 table.add_row(
1428 [record['scaling-group-name-ref'],
1429 inst['instance-id'],
1430 inst['op-status'],
1431 time.strftime('%Y-%m-%d %H:%M:%S',
1432 time.localtime(
1433 inst['create-time'])),
1434 inst['vnfrs']])
1435 table.align = 'l'
1436 print(table)
1437
1438
1439 @cli.command(name='ns-scale')
1440 @click.argument('ns_name')
1441 @click.option('--ns_scale_group', prompt=True)
1442 @click.option('--index', prompt=True)
1443 @click.pass_context
1444 def ns_scale(ctx, ns_name, ns_scale_group, index):
1445 '''scales NS
1446
1447 NS_NAME: name of the NS instance to be scaled
1448 '''
1449 try:
1450 check_client_version(ctx.obj, ctx.command.name, 'v1')
1451 ctx.obj.ns.scale(ns_name, ns_scale_group, index)
1452 except ClientException as inst:
1453 print((inst.message))
1454 exit(1)
1455
1456
1457 @cli.command(name='config-agent-list')
1458 @click.pass_context
1459 def config_agent_list(ctx):
1460 '''list config agents'''
1461 try:
1462 check_client_version(ctx.obj, ctx.command.name, 'v1')
1463 except ClientException as inst:
1464 print((inst.message))
1465 exit(1)
1466 table = PrettyTable(['name', 'account-type', 'details'])
1467 for account in ctx.obj.vca.list():
1468 table.add_row(
1469 [account['name'],
1470 account['account-type'],
1471 account['juju']])
1472 table.align = 'l'
1473 print(table)
1474
1475
1476 @cli.command(name='config-agent-delete')
1477 @click.argument('name')
1478 @click.pass_context
1479 def config_agent_delete(ctx, name):
1480 '''deletes a config agent
1481
1482 NAME: name of the config agent to be deleted
1483 '''
1484 try:
1485 check_client_version(ctx.obj, ctx.command.name, 'v1')
1486 ctx.obj.vca.delete(name)
1487 except ClientException as inst:
1488 print((inst.message))
1489 exit(1)
1490
1491
1492 @cli.command(name='config-agent-add')
1493 @click.option('--name',
1494 prompt=True)
1495 @click.option('--account_type',
1496 prompt=True)
1497 @click.option('--server',
1498 prompt=True)
1499 @click.option('--user',
1500 prompt=True)
1501 @click.option('--secret',
1502 prompt=True,
1503 hide_input=True,
1504 confirmation_prompt=True)
1505 @click.pass_context
1506 def config_agent_add(ctx, name, account_type, server, user, secret):
1507 '''adds a config agent'''
1508 try:
1509 check_client_version(ctx.obj, ctx.command.name, 'v1')
1510 ctx.obj.vca.create(name, account_type, server, user, secret)
1511 except ClientException as inst:
1512 print((inst.message))
1513 exit(1)
1514
1515 @cli.command(name='ro-dump')
1516 @click.pass_context
1517 def ro_dump(ctx):
1518 '''shows RO agent information'''
1519 check_client_version(ctx.obj, ctx.command.name, 'v1')
1520 resp = ctx.obj.vim.get_resource_orchestrator()
1521 table = PrettyTable(['key', 'attribute'])
1522 for k, v in list(resp.items()):
1523 table.add_row([k, json.dumps(v, indent=2)])
1524 table.align = 'l'
1525 print(table)
1526
1527
1528 @cli.command(name='vcs-list')
1529 @click.pass_context
1530 def vcs_list(ctx):
1531 check_client_version(ctx.obj, ctx.command.name, 'v1')
1532 resp = ctx.obj.utils.get_vcs_info()
1533 table = PrettyTable(['component name', 'state'])
1534 for component in resp:
1535 table.add_row([component['component_name'], component['state']])
1536 table.align = 'l'
1537 print(table)
1538
1539
1540 @cli.command(name='ns-action')
1541 @click.argument('ns_name')
1542 @click.option('--vnf_name', default=None)
1543 @click.option('--action_name', prompt=True)
1544 @click.option('--params', prompt=True)
1545 @click.pass_context
1546 def ns_action(ctx,
1547 ns_name,
1548 vnf_name,
1549 action_name,
1550 params):
1551 '''executes an action/primitive over a NS instance
1552
1553 NS_NAME: name or ID of the NS instance
1554 '''
1555 try:
1556 check_client_version(ctx.obj, ctx.command.name)
1557 op_data={}
1558 if vnf_name:
1559 op_data['vnf_member_index'] = vnf_name
1560 op_data['primitive'] = action_name
1561 op_data['primitive_params'] = yaml.load(params)
1562 ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data)
1563
1564 except ClientException as inst:
1565 print((inst.message))
1566 exit(1)
1567
1568
1569 if __name__ == '__main__':
1570 cli()