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