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