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