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