52e3bc8bb11a1fb893f49c11cbbaad3dd9878fc2
[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 def nsi_list(ctx, filter):
415 '''list all Network Slice Instances'''
416 try:
417 check_client_version(ctx.obj, ctx.command.name)
418 resp = ctx.obj.nsi.list(filter)
419 except ClientException as inst:
420 print((inst.message))
421 exit(1)
422 table = PrettyTable(
423 ['netslice instance name',
424 'id',
425 'operational status',
426 'config status',
427 'detailed status'])
428 for nsi in resp:
429 nsi_name = nsi['name']
430 nsi_id = nsi['_id']
431 opstatus = nsi['operational-status'] if 'operational-status' in nsi else 'Not found'
432 configstatus = nsi['config-status'] if 'config-status' in nsi else 'Not found'
433 detailed_status = nsi['detailed-status'] if 'detailed-status' in nsi else 'Not found'
434 if configstatus == "config_not_needed":
435 configstatus = "configured (no charms)"
436 table.add_row(
437 [nsi_name,
438 nsi_id,
439 opstatus,
440 configstatus,
441 detailed_status])
442 table.align = 'l'
443 print(table)
444
445
446 @cli.command(name='nsi-list')
447 @click.option('--filter', default=None,
448 help='restricts the list to the Network Slice Instances matching the filter')
449 @click.pass_context
450 def nsi_list1(ctx, filter):
451 '''list all Network Slice Instances (NSI)'''
452 nsi_list(ctx,filter)
453
454
455 @cli.command(name='netslice-instance-list')
456 @click.option('--filter', default=None,
457 help='restricts the list to the Network Slice Instances matching the filter')
458 @click.pass_context
459 def nsi_list2(ctx, filter):
460 '''list all Network Slice Instances (NSI)'''
461 nsi_list(ctx,filter)
462
463
464 def nst_list(ctx, filter):
465 try:
466 check_client_version(ctx.obj, ctx.command.name)
467 resp = ctx.obj.nst.list(filter)
468 except ClientException as inst:
469 print((inst.message))
470 exit(1)
471 #print yaml.safe_dump(resp)
472 table = PrettyTable(['nst name', 'id'])
473 for nst in resp:
474 name = nst['name'] if 'name' in nst else '-'
475 table.add_row([name, nst['_id']])
476 table.align = 'l'
477 print(table)
478
479
480 @cli.command(name='nst-list')
481 @click.option('--filter', default=None,
482 help='restricts the list to the NST matching the filter')
483 @click.pass_context
484 def nst_list1(ctx, filter):
485 '''list all Network Slice Templates (NST) in the system'''
486 nst_list(ctx,filter)
487
488
489 @cli.command(name='netslice-template-list')
490 @click.option('--filter', default=None,
491 help='restricts the list to the NST matching the filter')
492 @click.pass_context
493 def nst_list2(ctx, filter):
494 '''list all Network Slice Templates (NST) in the system'''
495 nst_list(ctx,filter)
496
497
498 def nsi_op_list(ctx, name):
499 try:
500 check_client_version(ctx.obj, ctx.command.name)
501 resp = ctx.obj.nsi.list_op(name)
502 except ClientException as inst:
503 print((inst.message))
504 exit(1)
505 table = PrettyTable(['id', 'operation', 'status'])
506 for op in resp:
507 table.add_row([op['id'], op['lcmOperationType'],
508 op['operationState']])
509 table.align = 'l'
510 print(table)
511
512
513 @cli.command(name='nsi-op-list')
514 @click.argument('name')
515 @click.pass_context
516 def nsi_op_list1(ctx, name):
517 '''shows the history of operations over a Network Slice Instance (NSI)
518
519 NAME: name or ID of the Network Slice Instance
520 '''
521 nsi_op_list(ctx,name)
522
523
524 @cli.command(name='netslice-instance-op-list')
525 @click.argument('name')
526 @click.pass_context
527 def nsi_op_list2(ctx, name):
528 '''shows the history of operations over a Network Slice Instance (NSI)
529
530 NAME: name or ID of the Network Slice Instance
531 '''
532 nsi_op_list(ctx,name)
533
534
535 @cli.command(name='pdu-list')
536 @click.option('--filter', default=None,
537 help='restricts the list to the Physical Deployment Units matching the filter')
538 @click.pass_context
539 def pdu_list(ctx, filter):
540 '''list all Physical Deployment Units (PDU)'''
541 try:
542 check_client_version(ctx.obj, ctx.command.name)
543 resp = ctx.obj.pdu.list(filter)
544 except ClientException as inst:
545 print((inst.message))
546 exit(1)
547 table = PrettyTable(
548 ['pdu name',
549 'id',
550 'type',
551 'shared',
552 'mgmt ip address'])
553 for pdu in resp:
554 pdu_name = pdu['name']
555 pdu_id = pdu['_id']
556 pdu_type = pdu['type']
557 pdu_shared = pdu['shared']
558 pdu_ipaddress = "None"
559 for iface in pdu['interfaces']:
560 if iface['mgmt']:
561 pdu_ipaddress = iface['ip-address']
562 break
563 table.add_row(
564 [pdu_name,
565 pdu_id,
566 pdu_type,
567 pdu_shared,
568 pdu_ipaddress])
569 table.align = 'l'
570 print(table)
571
572
573 ####################
574 # SHOW operations
575 ####################
576
577 def nsd_show(ctx, name, literal):
578 try:
579 resp = ctx.obj.nsd.get(name)
580 #resp = ctx.obj.nsd.get_individual(name)
581 except ClientException as inst:
582 print((inst.message))
583 exit(1)
584
585 if literal:
586 print(yaml.safe_dump(resp))
587 return
588
589 table = PrettyTable(['field', 'value'])
590 for k, v in list(resp.items()):
591 table.add_row([k, json.dumps(v, indent=2)])
592 table.align = 'l'
593 print(table)
594
595
596 @cli.command(name='nsd-show', short_help='shows the content of a NSD')
597 @click.option('--literal', is_flag=True,
598 help='print literally, no pretty table')
599 @click.argument('name')
600 @click.pass_context
601 def nsd_show1(ctx, name, literal):
602 '''shows the content of a NSD
603
604 NAME: name or ID of the NSD/NSpkg
605 '''
606 nsd_show(ctx, name, literal)
607
608
609 @cli.command(name='nspkg-show', short_help='shows the content of a NSD')
610 @click.option('--literal', is_flag=True,
611 help='print literally, no pretty table')
612 @click.argument('name')
613 @click.pass_context
614 def nsd_show2(ctx, name, literal):
615 '''shows the content of a NSD
616
617 NAME: name or ID of the NSD/NSpkg
618 '''
619 nsd_show(ctx, name, literal)
620
621
622 def vnfd_show(ctx, name, literal):
623 try:
624 resp = ctx.obj.vnfd.get(name)
625 #resp = ctx.obj.vnfd.get_individual(name)
626 except ClientException as inst:
627 print((inst.message))
628 exit(1)
629
630 if literal:
631 print(yaml.safe_dump(resp))
632 return
633
634 table = PrettyTable(['field', 'value'])
635 for k, v in list(resp.items()):
636 table.add_row([k, json.dumps(v, indent=2)])
637 table.align = 'l'
638 print(table)
639
640
641 @cli.command(name='vnfd-show', short_help='shows the content of a VNFD')
642 @click.option('--literal', is_flag=True,
643 help='print literally, no pretty table')
644 @click.argument('name')
645 @click.pass_context
646 def vnfd_show1(ctx, name, literal):
647 '''shows the content of a VNFD
648
649 NAME: name or ID of the VNFD/VNFpkg
650 '''
651 vnfd_show(ctx, name, literal)
652
653
654 @cli.command(name='vnfpkg-show', short_help='shows the content of a VNFD')
655 @click.option('--literal', is_flag=True,
656 help='print literally, no pretty table')
657 @click.argument('name')
658 @click.pass_context
659 def vnfd_show2(ctx, name, literal):
660 '''shows the content of a VNFD
661
662 NAME: name or ID of the VNFD/VNFpkg
663 '''
664 vnfd_show(ctx, name, literal)
665
666
667 @cli.command(name='ns-show', short_help='shows the info of a NS instance')
668 @click.argument('name')
669 @click.option('--literal', is_flag=True,
670 help='print literally, no pretty table')
671 @click.option('--filter', default=None)
672 @click.pass_context
673 def ns_show(ctx, name, literal, filter):
674 '''shows the info of a NS instance
675
676 NAME: name or ID of the NS instance
677 '''
678 try:
679 ns = ctx.obj.ns.get(name)
680 except ClientException as inst:
681 print((inst.message))
682 exit(1)
683
684 if literal:
685 print(yaml.safe_dump(ns))
686 return
687
688 table = PrettyTable(['field', 'value'])
689
690 for k, v in list(ns.items()):
691 if filter is None or filter in k:
692 table.add_row([k, json.dumps(v, indent=2)])
693
694 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
695 if fullclassname != 'osmclient.sol005.client.Client':
696 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
697 nsr_optdata = nsopdata['nsr:nsr']
698 for k, v in list(nsr_optdata.items()):
699 if filter is None or filter in k:
700 table.add_row([k, json.dumps(v, indent=2)])
701 table.align = 'l'
702 print(table)
703
704
705 @cli.command(name='vnf-show', short_help='shows the info of a VNF instance')
706 @click.argument('name')
707 @click.option('--literal', is_flag=True,
708 help='print literally, no pretty table')
709 @click.option('--filter', default=None)
710 @click.pass_context
711 def vnf_show(ctx, name, literal, filter):
712 '''shows the info of a VNF instance
713
714 NAME: name or ID of the VNF instance
715 '''
716 try:
717 check_client_version(ctx.obj, ctx.command.name)
718 resp = ctx.obj.vnf.get(name)
719 except ClientException as inst:
720 print((inst.message))
721 exit(1)
722
723 if literal:
724 print(yaml.safe_dump(resp))
725 return
726
727 table = PrettyTable(['field', 'value'])
728 for k, v in list(resp.items()):
729 if filter is None or filter in k:
730 table.add_row([k, json.dumps(v, indent=2)])
731 table.align = 'l'
732 print(table)
733
734
735 @cli.command(name='vnf-monitoring-show')
736 @click.argument('vnf_name')
737 @click.pass_context
738 def vnf_monitoring_show(ctx, vnf_name):
739 try:
740 check_client_version(ctx.obj, ctx.command.name, 'v1')
741 resp = ctx.obj.vnf.get_monitoring(vnf_name)
742 except ClientException as inst:
743 print((inst.message))
744 exit(1)
745
746 table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
747 if resp is not None:
748 for monitor in resp:
749 table.add_row(
750 [vnf_name,
751 monitor['name'],
752 monitor['value-integer'],
753 monitor['units']])
754 table.align = 'l'
755 print(table)
756
757
758 @cli.command(name='ns-monitoring-show')
759 @click.argument('ns_name')
760 @click.pass_context
761 def ns_monitoring_show(ctx, ns_name):
762 try:
763 check_client_version(ctx.obj, ctx.command.name, 'v1')
764 resp = ctx.obj.ns.get_monitoring(ns_name)
765 except ClientException as inst:
766 print((inst.message))
767 exit(1)
768
769 table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
770 for key, val in list(resp.items()):
771 for monitor in val:
772 table.add_row(
773 [key,
774 monitor['name'],
775 monitor['value-integer'],
776 monitor['units']])
777 table.align = 'l'
778 print(table)
779
780
781 @cli.command(name='ns-op-show', short_help='shows the info of an operation')
782 @click.argument('id')
783 @click.option('--filter', default=None)
784 @click.pass_context
785 def ns_op_show(ctx, id, filter):
786 '''shows the detailed info of an operation
787
788 ID: operation identifier
789 '''
790 try:
791 check_client_version(ctx.obj, ctx.command.name)
792 op_info = ctx.obj.ns.get_op(id)
793 except ClientException as inst:
794 print((inst.message))
795 exit(1)
796
797 table = PrettyTable(['field', 'value'])
798 for k, v in list(op_info.items()):
799 if filter is None or filter in k:
800 table.add_row([k, json.dumps(v, indent=2)])
801 table.align = 'l'
802 print(table)
803
804
805 def nst_show(ctx, name, literal):
806 try:
807 check_client_version(ctx.obj, ctx.command.name)
808 resp = ctx.obj.nst.get(name)
809 #resp = ctx.obj.nst.get_individual(name)
810 except ClientException as inst:
811 print((inst.message))
812 exit(1)
813
814 if literal:
815 print(yaml.safe_dump(resp))
816 return
817
818 table = PrettyTable(['field', 'value'])
819 for k, v in list(resp.items()):
820 table.add_row([k, json.dumps(v, indent=2)])
821 table.align = 'l'
822 print(table)
823
824
825 @cli.command(name='nst-show', short_help='shows the content of a Network Slice Template (NST)')
826 @click.option('--literal', is_flag=True,
827 help='print literally, no pretty table')
828 @click.argument('name')
829 @click.pass_context
830 def nst_show1(ctx, name, literal):
831 '''shows the content of a Network Slice Template (NST)
832
833 NAME: name or ID of the NST
834 '''
835 nst_show(ctx, name, literal)
836
837
838 @cli.command(name='netslice-template-show', short_help='shows the content of a Network Slice Template (NST)')
839 @click.option('--literal', is_flag=True,
840 help='print literally, no pretty table')
841 @click.argument('name')
842 @click.pass_context
843 def nst_show2(ctx, name, literal):
844 '''shows the content of a Network Slice Template (NST)
845
846 NAME: name or ID of the NST
847 '''
848 nst_show(ctx, name, literal)
849
850
851 def nsi_show(ctx, name, literal, filter):
852 try:
853 check_client_version(ctx.obj, ctx.command.name)
854 nsi = ctx.obj.nsi.get(name)
855 except ClientException as inst:
856 print((inst.message))
857 exit(1)
858
859 if literal:
860 print(yaml.safe_dump(nsi))
861 return
862
863 table = PrettyTable(['field', 'value'])
864
865 for k, v in list(nsi.items()):
866 if filter is None or filter in k:
867 table.add_row([k, json.dumps(v, indent=2)])
868
869 table.align = 'l'
870 print(table)
871
872
873 @cli.command(name='nsi-show', short_help='shows the content of a Network Slice Instance (NSI)')
874 @click.argument('name')
875 @click.option('--literal', is_flag=True,
876 help='print literally, no pretty table')
877 @click.option('--filter', default=None)
878 @click.pass_context
879 def nsi_show1(ctx, name, literal, filter):
880 '''shows the content of a Network Slice Instance (NSI)
881
882 NAME: name or ID of the Network Slice Instance
883 '''
884 nsi_show(ctx, name, literal, filter)
885
886
887 @cli.command(name='netslice-instance-show', short_help='shows the content of a Network Slice Instance (NSI)')
888 @click.argument('name')
889 @click.option('--literal', is_flag=True,
890 help='print literally, no pretty table')
891 @click.option('--filter', default=None)
892 @click.pass_context
893 def nsi_show2(ctx, name, literal, filter):
894 '''shows the content of a Network Slice Instance (NSI)
895
896 NAME: name or ID of the Network Slice Instance
897 '''
898 nsi_show(ctx, name, literal, filter)
899
900
901 def nsi_op_show(ctx, id, filter):
902 try:
903 check_client_version(ctx.obj, ctx.command.name)
904 op_info = ctx.obj.nsi.get_op(id)
905 except ClientException as inst:
906 print((inst.message))
907 exit(1)
908
909 table = PrettyTable(['field', 'value'])
910 for k, v in list(op_info.items()):
911 if filter is None or filter in k:
912 table.add_row([k, json.dumps(v, indent=2)])
913 table.align = 'l'
914 print(table)
915
916
917 @cli.command(name='nsi-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
918 @click.argument('id')
919 @click.option('--filter', default=None)
920 @click.pass_context
921 def nsi_op_show1(ctx, id, filter):
922 '''shows the info of an operation over a Network Slice Instance(NSI)
923
924 ID: operation identifier
925 '''
926 nsi_op_show(ctx, id, filter)
927
928
929 @cli.command(name='netslice-instance-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
930 @click.argument('id')
931 @click.option('--filter', default=None)
932 @click.pass_context
933 def nsi_op_show2(ctx, id, filter):
934 '''shows the info of an operation over a Network Slice Instance(NSI)
935
936 ID: operation identifier
937 '''
938 nsi_op_show(ctx, id, filter)
939
940
941 @cli.command(name='pdu-show', short_help='shows the content of a Physical Deployment Unit (PDU)')
942 @click.argument('name')
943 @click.option('--literal', is_flag=True,
944 help='print literally, no pretty table')
945 @click.option('--filter', default=None)
946 @click.pass_context
947 def pdu_show(ctx, name, literal, filter):
948 '''shows the content of a Physical Deployment Unit (PDU)
949
950 NAME: name or ID of the PDU
951 '''
952 try:
953 check_client_version(ctx.obj, ctx.command.name)
954 pdu = ctx.obj.pdu.get(name)
955 except ClientException as inst:
956 print((inst.message))
957 exit(1)
958
959 if literal:
960 print(yaml.safe_dump(pdu))
961 return
962
963 table = PrettyTable(['field', 'value'])
964
965 for k, v in list(pdu.items()):
966 if filter is None or filter in k:
967 table.add_row([k, json.dumps(v, indent=2)])
968
969 table.align = 'l'
970 print(table)
971
972
973 ####################
974 # CREATE operations
975 ####################
976
977 def nsd_create(ctx, filename, overwrite):
978 try:
979 check_client_version(ctx.obj, ctx.command.name)
980 ctx.obj.nsd.create(filename, overwrite)
981 except ClientException as inst:
982 print((inst.message))
983 exit(1)
984
985
986 @cli.command(name='nsd-create', short_help='creates a new NSD/NSpkg')
987 @click.argument('filename')
988 @click.option('--overwrite', default=None,
989 help='overwrites some fields in NSD')
990 @click.pass_context
991 def nsd_create1(ctx, filename, overwrite):
992 '''creates a new NSD/NSpkg
993
994 FILENAME: NSD yaml file or NSpkg tar.gz file
995 '''
996 nsd_create(ctx, filename, overwrite)
997
998
999 @cli.command(name='nspkg-create', short_help='creates a new NSD/NSpkg')
1000 @click.argument('filename')
1001 @click.option('--overwrite', default=None,
1002 help='overwrites some fields in NSD')
1003 @click.pass_context
1004 def nsd_create2(ctx, filename, overwrite):
1005 '''creates a new NSD/NSpkg
1006
1007 FILENAME: NSD yaml file or NSpkg tar.gz file
1008 '''
1009 nsd_create(ctx, filename, overwrite)
1010
1011
1012 def vnfd_create(ctx, filename, overwrite):
1013 try:
1014 check_client_version(ctx.obj, ctx.command.name)
1015 ctx.obj.vnfd.create(filename, overwrite)
1016 except ClientException as inst:
1017 print((inst.message))
1018 exit(1)
1019
1020
1021 @cli.command(name='vnfd-create', short_help='creates a new VNFD/VNFpkg')
1022 @click.argument('filename')
1023 @click.option('--overwrite', default=None,
1024 help='overwrites some fields in VNFD')
1025 @click.pass_context
1026 def vnfd_create1(ctx, filename, overwrite):
1027 '''creates a new VNFD/VNFpkg
1028
1029 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1030 '''
1031 vnfd_create(ctx, filename, overwrite)
1032
1033
1034 @cli.command(name='vnfpkg-create', short_help='creates a new VNFD/VNFpkg')
1035 @click.argument('filename')
1036 @click.option('--overwrite', default=None,
1037 help='overwrites some fields in VNFD')
1038 @click.pass_context
1039 def vnfd_create2(ctx, filename, overwrite):
1040 '''creates a new VNFD/VNFpkg
1041
1042 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1043 '''
1044 vnfd_create(ctx, filename, overwrite)
1045
1046
1047 @cli.command(name='ns-create', short_help='creates a new Network Service instance')
1048 @click.option('--ns_name',
1049 prompt=True, help='name of the NS instance')
1050 @click.option('--nsd_name',
1051 prompt=True, help='name of the NS descriptor')
1052 @click.option('--vim_account',
1053 prompt=True, help='default VIM account id or name for the deployment')
1054 @click.option('--admin_status',
1055 default='ENABLED',
1056 help='administration status')
1057 @click.option('--ssh_keys',
1058 default=None,
1059 help='comma separated list of public key files to inject to vnfs')
1060 @click.option('--config',
1061 default=None,
1062 help='ns specific yaml configuration')
1063 @click.option('--config_file',
1064 default=None,
1065 help='ns specific yaml configuration file')
1066 @click.pass_context
1067 def ns_create(ctx,
1068 nsd_name,
1069 ns_name,
1070 vim_account,
1071 admin_status,
1072 ssh_keys,
1073 config,
1074 config_file):
1075 '''creates a new NS instance'''
1076 try:
1077 if config_file:
1078 check_client_version(ctx.obj, '--config_file')
1079 if config:
1080 raise ClientException('"--config" option is incompatible with "--config_file" option')
1081 with open(config_file, 'r') as cf:
1082 config=cf.read()
1083 ctx.obj.ns.create(
1084 nsd_name,
1085 ns_name,
1086 config=config,
1087 ssh_keys=ssh_keys,
1088 account=vim_account)
1089 except ClientException as inst:
1090 print((inst.message))
1091 exit(1)
1092
1093
1094 def nst_create(ctx, filename, overwrite):
1095 try:
1096 check_client_version(ctx.obj, ctx.command.name)
1097 ctx.obj.nst.create(filename, overwrite)
1098 except ClientException as inst:
1099 print((inst.message))
1100 exit(1)
1101
1102
1103 @cli.command(name='nst-create', short_help='creates a new Network Slice Template (NST)')
1104 @click.argument('filename')
1105 @click.option('--overwrite', default=None,
1106 help='overwrites some fields in NST')
1107 @click.pass_context
1108 def nst_create1(ctx, filename, overwrite):
1109 '''creates a new Network Slice Template (NST)
1110
1111 FILENAME: NST yaml file or NSTpkg tar.gz file
1112 '''
1113 nst_create(ctx, filename, overwrite)
1114
1115
1116 @cli.command(name='netslice-template-create', short_help='creates a new Network Slice Template (NST)')
1117 @click.argument('filename')
1118 @click.option('--overwrite', default=None,
1119 help='overwrites some fields in NST')
1120 @click.pass_context
1121 def nst_create2(ctx, filename, overwrite):
1122 '''creates a new Network Slice Template (NST)
1123
1124 FILENAME: NST yaml file or NSTpkg tar.gz file
1125 '''
1126 nst_create(ctx, filename, overwrite)
1127
1128
1129 def nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file):
1130 '''creates a new Network Slice Instance (NSI)'''
1131 try:
1132 check_client_version(ctx.obj, ctx.command.name)
1133 if config_file:
1134 if config:
1135 raise ClientException('"--config" option is incompatible with "--config_file" option')
1136 with open(config_file, 'r') as cf:
1137 config=cf.read()
1138 ctx.obj.nsi.create(nst_name, nsi_name, config=config, ssh_keys=ssh_keys,
1139 account=vim_account)
1140 except ClientException as inst:
1141 print((inst.message))
1142 exit(1)
1143
1144
1145 @cli.command(name='nsi-create', short_help='creates a new Network Slice Instance')
1146 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1147 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1148 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1149 @click.option('--ssh_keys', default=None,
1150 help='comma separated list of keys to inject to vnfs')
1151 @click.option('--config', default=None,
1152 help='Netslice specific yaml configuration:\n'
1153 'netslice_subnet: [\n'
1154 'id: TEXT, vim_account: TEXT,\n'
1155 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1156 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1157 '],\n'
1158 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1159 )
1160 @click.option('--config_file',
1161 default=None,
1162 help='nsi specific yaml configuration file')
1163 @click.pass_context
1164 def nsi_create1(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file):
1165 '''creates a new Network Slice Instance (NSI)'''
1166 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file)
1167
1168
1169 @cli.command(name='netslice-instance-create', short_help='creates a new Network Slice Instance')
1170 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1171 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1172 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1173 @click.option('--ssh_keys', default=None,
1174 help='comma separated list of keys to inject to vnfs')
1175 @click.option('--config', default=None,
1176 help='Netslice specific yaml configuration:\n'
1177 'netslice_subnet: [\n'
1178 'id: TEXT, vim_account: TEXT,\n'
1179 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1180 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1181 '],\n'
1182 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1183 )
1184 @click.option('--config_file',
1185 default=None,
1186 help='nsi specific yaml configuration file')
1187 @click.pass_context
1188 def nsi_create2(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file):
1189 '''creates a new Network Slice Instance (NSI)'''
1190 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file)
1191
1192
1193 @cli.command(name='pdu-create', short_help='adds a new Physical Deployment Unit to the catalog')
1194 @click.option('--name', help='name of the Physical Deployment Unit')
1195 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1196 @click.option('--interface',
1197 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1198 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1199 multiple=True)
1200 @click.option('--description', help='human readable description')
1201 @click.option('--shared', is_flag=True, help='flag to indicate if the PDU is shared')
1202 @click.option('--vimAccounts', help='list of VIM accounts where this PDU is physically connected')
1203 @click.option('--descriptor_file', default=None, help='PDU descriptor file (as an alternative to using the other arguments')
1204 @click.pass_context
1205 #TODO
1206 def pdu_create(ctx, name, pdu_type, interface, description, shared, vimAccounts, descriptor_file):
1207 '''creates a new Physical Deployment Unit (PDU)'''
1208 try:
1209 check_client_version(ctx.obj, ctx.command.name)
1210 pdu = {}
1211 if not descriptor_file:
1212 if not name:
1213 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1214 if not pdu_type:
1215 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1216 if not interface:
1217 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1218 else:
1219 with open(descriptor_file, 'r') as df:
1220 pdu = yaml.load(df.read())
1221 if name: pdu["name"] = name
1222 if pdu_type: pdu["type"] = pdu_type
1223 if description: pdu["description"] = description
1224 if shared: pdu["shared"] = shared
1225 if vimAccounts: pdu["vim_accounts"] = yaml.load(vimAccounts)
1226 if interface:
1227 ifaces_list = []
1228 for iface in interface:
1229 ifaces_list.append({k:v for k,v in [i.split('=') for i in iface.split(',')]})
1230 pdu["interfaces"] = ifaces_list
1231 ctx.obj.pdu.create(pdu)
1232 except ClientException as inst:
1233 print((inst.message))
1234 exit(1)
1235
1236
1237 ####################
1238 # UPDATE operations
1239 ####################
1240
1241 def nsd_update(ctx, name, content):
1242 try:
1243 check_client_version(ctx.obj, ctx.command.name)
1244 ctx.obj.nsd.update(name, content)
1245 except ClientException as inst:
1246 print((inst.message))
1247 exit(1)
1248
1249
1250 @cli.command(name='nsd-update', short_help='updates a NSD/NSpkg')
1251 @click.argument('name')
1252 @click.option('--content', default=None,
1253 help='filename with the NSD/NSpkg replacing the current one')
1254 @click.pass_context
1255 def nsd_update1(ctx, name, content):
1256 '''updates a NSD/NSpkg
1257
1258 NAME: name or ID of the NSD/NSpkg
1259 '''
1260 nsd_update(ctx, name, content)
1261
1262
1263 @cli.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
1264 @click.argument('name')
1265 @click.option('--content', default=None,
1266 help='filename with the NSD/NSpkg replacing the current one')
1267 @click.pass_context
1268 def nsd_update2(ctx, name, content):
1269 '''updates a NSD/NSpkg
1270
1271 NAME: name or ID of the NSD/NSpkg
1272 '''
1273 nsd_update(ctx, name, content)
1274
1275
1276 def vnfd_update(ctx, name, content):
1277 try:
1278 check_client_version(ctx.obj, ctx.command.name)
1279 ctx.obj.vnfd.update(name, content)
1280 except ClientException as inst:
1281 print((inst.message))
1282 exit(1)
1283
1284
1285 @cli.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
1286 @click.argument('name')
1287 @click.option('--content', default=None,
1288 help='filename with the VNFD/VNFpkg replacing the current one')
1289 @click.pass_context
1290 def vnfd_update1(ctx, name, content):
1291 '''updates a VNFD/VNFpkg
1292
1293 NAME: name or ID of the VNFD/VNFpkg
1294 '''
1295 vnfd_update(ctx, name, content)
1296
1297
1298 @cli.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
1299 @click.argument('name')
1300 @click.option('--content', default=None,
1301 help='filename with the VNFD/VNFpkg replacing the current one')
1302 @click.pass_context
1303 def vnfd_update2(ctx, name, content):
1304 '''updates a VNFD/VNFpkg
1305
1306 NAME: VNFD yaml file or VNFpkg tar.gz file
1307 '''
1308 vnfd_update(ctx, name, content)
1309
1310
1311 def nst_update(ctx, name, content):
1312 try:
1313 check_client_version(ctx.obj, ctx.command.name)
1314 ctx.obj.nst.update(name, content)
1315 except ClientException as inst:
1316 print((inst.message))
1317 exit(1)
1318
1319
1320 @cli.command(name='nst-update', short_help='updates a Network Slice Template (NST)')
1321 @click.argument('name')
1322 @click.option('--content', default=None,
1323 help='filename with the NST/NSTpkg replacing the current one')
1324 @click.pass_context
1325 def nst_update1(ctx, name, content):
1326 '''updates a Network Slice Template (NST)
1327
1328 NAME: name or ID of the NSD/NSpkg
1329 '''
1330 nst_update(ctx, name, content)
1331
1332
1333 @cli.command(name='netslice-template-update', short_help='updates a Network Slice Template (NST)')
1334 @click.argument('name')
1335 @click.option('--content', default=None,
1336 help='filename with the NST/NSTpkg replacing the current one')
1337 @click.pass_context
1338 def nst_update2(ctx, name, content):
1339 '''updates a Network Slice Template (NST)
1340
1341 NAME: name or ID of the NSD/NSpkg
1342 '''
1343 nst_update(ctx, name, content)
1344
1345
1346 ####################
1347 # DELETE operations
1348 ####################
1349
1350 def nsd_delete(ctx, name, force):
1351 try:
1352 if not force:
1353 ctx.obj.nsd.delete(name)
1354 else:
1355 check_client_version(ctx.obj, '--force')
1356 ctx.obj.nsd.delete(name, force)
1357 except ClientException as inst:
1358 print((inst.message))
1359 exit(1)
1360
1361
1362 @cli.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
1363 @click.argument('name')
1364 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1365 @click.pass_context
1366 def nsd_delete1(ctx, name, force):
1367 '''deletes a NSD/NSpkg
1368
1369 NAME: name or ID of the NSD/NSpkg to be deleted
1370 '''
1371 nsd_delete(ctx, name, force)
1372
1373
1374 @cli.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
1375 @click.argument('name')
1376 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1377 @click.pass_context
1378 def nsd_delete2(ctx, name, force):
1379 '''deletes a NSD/NSpkg
1380
1381 NAME: name or ID of the NSD/NSpkg to be deleted
1382 '''
1383 nsd_delete(ctx, name, force)
1384
1385
1386 def vnfd_delete(ctx, name, force):
1387 try:
1388 if not force:
1389 ctx.obj.vnfd.delete(name)
1390 else:
1391 check_client_version(ctx.obj, '--force')
1392 ctx.obj.vnfd.delete(name, force)
1393 except ClientException as inst:
1394 print((inst.message))
1395 exit(1)
1396
1397
1398 @cli.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
1399 @click.argument('name')
1400 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1401 @click.pass_context
1402 def vnfd_delete1(ctx, name, force):
1403 '''deletes a VNFD/VNFpkg
1404
1405 NAME: name or ID of the VNFD/VNFpkg to be deleted
1406 '''
1407 vnfd_delete(ctx, name, force)
1408
1409
1410 @cli.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
1411 @click.argument('name')
1412 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1413 @click.pass_context
1414 def vnfd_delete2(ctx, name, force):
1415 '''deletes a VNFD/VNFpkg
1416
1417 NAME: name or ID of the VNFD/VNFpkg to be deleted
1418 '''
1419 vnfd_delete(ctx, name, force)
1420
1421
1422 @cli.command(name='ns-delete', short_help='deletes a NS instance')
1423 @click.argument('name')
1424 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1425 @click.pass_context
1426 def ns_delete(ctx, name, force):
1427 '''deletes a NS instance
1428
1429 NAME: name or ID of the NS instance to be deleted
1430 '''
1431 try:
1432 if not force:
1433 ctx.obj.ns.delete(name)
1434 else:
1435 check_client_version(ctx.obj, '--force')
1436 ctx.obj.ns.delete(name, force)
1437 except ClientException as inst:
1438 print((inst.message))
1439 exit(1)
1440
1441
1442 def nst_delete(ctx, name, force):
1443 try:
1444 check_client_version(ctx.obj, ctx.command.name)
1445 ctx.obj.nst.delete(name, force)
1446 except ClientException as inst:
1447 print((inst.message))
1448 exit(1)
1449
1450
1451 @cli.command(name='nst-delete', short_help='deletes a Network Slice Template (NST)')
1452 @click.argument('name')
1453 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1454 @click.pass_context
1455 def nst_delete1(ctx, name, force):
1456 '''deletes a Network Slice Template (NST)
1457
1458 NAME: name or ID of the NST/NSTpkg to be deleted
1459 '''
1460 nst_delete(ctx, name, force)
1461
1462
1463 @cli.command(name='netslice-template-delete', short_help='deletes a Network Slice Template (NST)')
1464 @click.argument('name')
1465 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1466 @click.pass_context
1467 def nst_delete2(ctx, name, force):
1468 '''deletes a Network Slice Template (NST)
1469
1470 NAME: name or ID of the NST/NSTpkg to be deleted
1471 '''
1472 nst_delete(ctx, name, force)
1473
1474
1475 def nsi_delete(ctx, name, force):
1476 try:
1477 check_client_version(ctx.obj, ctx.command.name)
1478 ctx.obj.nsi.delete(name, force)
1479 except ClientException as inst:
1480 print((inst.message))
1481 exit(1)
1482
1483
1484 @cli.command(name='nsi-delete', short_help='deletes a Network Slice Instance (NSI)')
1485 @click.argument('name')
1486 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1487 @click.pass_context
1488 def nsi_delete1(ctx, name, force):
1489 '''deletes a Network Slice Instance (NSI)
1490
1491 NAME: name or ID of the Network Slice instance to be deleted
1492 '''
1493 nsi_delete(ctx, name, force)
1494
1495
1496 @cli.command(name='netslice-instance-delete', short_help='deletes a Network Slice Instance (NSI)')
1497 @click.argument('name')
1498 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1499 @click.pass_context
1500 def nsi_delete2(ctx, name, force):
1501 '''deletes a Network Slice Instance (NSI)
1502
1503 NAME: name or ID of the Network Slice instance to be deleted
1504 '''
1505 nsi_delete(ctx, name, force)
1506
1507
1508 @cli.command(name='pdu-delete', short_help='deletes a Physical Deployment Unit (PDU)')
1509 @click.argument('name')
1510 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1511 @click.pass_context
1512 def pdu_delete(ctx, name, force):
1513 '''deletes a Physical Deployment Unit (PDU)
1514
1515 NAME: name or ID of the PDU to be deleted
1516 '''
1517 try:
1518 check_client_version(ctx.obj, ctx.command.name)
1519 ctx.obj.pdu.delete(name, force)
1520 except ClientException as inst:
1521 print((inst.message))
1522 exit(1)
1523
1524
1525 ####################
1526 # VIM operations
1527 ####################
1528
1529 @cli.command(name='vim-create')
1530 @click.option('--name',
1531 prompt=True,
1532 help='Name to create datacenter')
1533 @click.option('--user',
1534 prompt=True,
1535 help='VIM username')
1536 @click.option('--password',
1537 prompt=True,
1538 hide_input=True,
1539 confirmation_prompt=True,
1540 help='VIM password')
1541 @click.option('--auth_url',
1542 prompt=True,
1543 help='VIM url')
1544 @click.option('--tenant',
1545 prompt=True,
1546 help='VIM tenant name')
1547 @click.option('--config',
1548 default=None,
1549 help='VIM specific config parameters')
1550 @click.option('--account_type',
1551 default='openstack',
1552 help='VIM type')
1553 @click.option('--description',
1554 default='no description',
1555 help='human readable description')
1556 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1557 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1558 @click.pass_context
1559 def vim_create(ctx,
1560 name,
1561 user,
1562 password,
1563 auth_url,
1564 tenant,
1565 config,
1566 account_type,
1567 description,
1568 sdn_controller,
1569 sdn_port_mapping):
1570 '''creates a new VIM account
1571 '''
1572 try:
1573 if sdn_controller:
1574 check_client_version(ctx.obj, '--sdn_controller')
1575 if sdn_port_mapping:
1576 check_client_version(ctx.obj, '--sdn_port_mapping')
1577 vim = {}
1578 vim['vim-username'] = user
1579 vim['vim-password'] = password
1580 vim['vim-url'] = auth_url
1581 vim['vim-tenant-name'] = tenant
1582 vim['vim-type'] = account_type
1583 vim['description'] = description
1584 vim['config'] = config
1585 if sdn_controller or sdn_port_mapping:
1586 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping)
1587 else:
1588 ctx.obj.vim.create(name, vim)
1589 except ClientException as inst:
1590 print((inst.message))
1591 exit(1)
1592
1593
1594 @cli.command(name='vim-update', short_help='updates a VIM account')
1595 @click.argument('name')
1596 @click.option('--newname', help='New name for the VIM account')
1597 @click.option('--user', help='VIM username')
1598 @click.option('--password', help='VIM password')
1599 @click.option('--auth_url', help='VIM url')
1600 @click.option('--tenant', help='VIM tenant name')
1601 @click.option('--config', help='VIM specific config parameters')
1602 @click.option('--account_type', help='VIM type')
1603 @click.option('--description', help='human readable description')
1604 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1605 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1606 @click.pass_context
1607 def vim_update(ctx,
1608 name,
1609 newname,
1610 user,
1611 password,
1612 auth_url,
1613 tenant,
1614 config,
1615 account_type,
1616 description,
1617 sdn_controller,
1618 sdn_port_mapping):
1619 '''updates a VIM account
1620
1621 NAME: name or ID of the VIM account
1622 '''
1623 try:
1624 check_client_version(ctx.obj, ctx.command.name)
1625 vim = {}
1626 if newname: vim['name'] = newname
1627 if user: vim['vim_user'] = user
1628 if password: vim['vim_password'] = password
1629 if auth_url: vim['vim_url'] = auth_url
1630 if tenant: vim['vim-tenant-name'] = tenant
1631 if account_type: vim['vim_type'] = account_type
1632 if description: vim['description'] = description
1633 if config: vim['config'] = config
1634 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping)
1635 except ClientException as inst:
1636 print((inst.message))
1637 exit(1)
1638
1639
1640 @cli.command(name='vim-delete')
1641 @click.argument('name')
1642 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1643 @click.pass_context
1644 def vim_delete(ctx, name, force):
1645 '''deletes a VIM account
1646
1647 NAME: name or ID of the VIM account to be deleted
1648 '''
1649 try:
1650 if not force:
1651 ctx.obj.vim.delete(name)
1652 else:
1653 check_client_version(ctx.obj, '--force')
1654 ctx.obj.vim.delete(name, force)
1655 except ClientException as inst:
1656 print((inst.message))
1657 exit(1)
1658
1659
1660 @cli.command(name='vim-list')
1661 @click.option('--ro_update/--no_ro_update',
1662 default=False,
1663 help='update list from RO')
1664 @click.option('--filter', default=None,
1665 help='restricts the list to the VIM accounts matching the filter')
1666 @click.pass_context
1667 def vim_list(ctx, ro_update, filter):
1668 '''list all VIM accounts'''
1669 if filter:
1670 check_client_version(ctx.obj, '--filter')
1671 if ro_update:
1672 check_client_version(ctx.obj, '--ro_update', 'v1')
1673 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1674 if fullclassname == 'osmclient.sol005.client.Client':
1675 resp = ctx.obj.vim.list(filter)
1676 else:
1677 resp = ctx.obj.vim.list(ro_update)
1678 table = PrettyTable(['vim name', 'uuid'])
1679 for vim in resp:
1680 table.add_row([vim['name'], vim['uuid']])
1681 table.align = 'l'
1682 print(table)
1683
1684
1685 @cli.command(name='vim-show')
1686 @click.argument('name')
1687 @click.pass_context
1688 def vim_show(ctx, name):
1689 '''shows the details of a VIM account
1690
1691 NAME: name or ID of the VIM account
1692 '''
1693 try:
1694 resp = ctx.obj.vim.get(name)
1695 if 'vim_password' in resp:
1696 resp['vim_password']='********'
1697 except ClientException as inst:
1698 print((inst.message))
1699 exit(1)
1700
1701 table = PrettyTable(['key', 'attribute'])
1702 for k, v in list(resp.items()):
1703 table.add_row([k, json.dumps(v, indent=2)])
1704 table.align = 'l'
1705 print(table)
1706
1707
1708 ####################
1709 # SDN controller operations
1710 ####################
1711
1712 @cli.command(name='sdnc-create')
1713 @click.option('--name',
1714 prompt=True,
1715 help='Name to create sdn controller')
1716 @click.option('--type',
1717 prompt=True,
1718 help='SDN controller type')
1719 @click.option('--sdn_controller_version',
1720 help='SDN controller username')
1721 @click.option('--ip_address',
1722 prompt=True,
1723 help='SDN controller IP address')
1724 @click.option('--port',
1725 prompt=True,
1726 help='SDN controller port')
1727 @click.option('--switch_dpid',
1728 prompt=True,
1729 help='Switch DPID (Openflow Datapath ID)')
1730 @click.option('--user',
1731 help='SDN controller username')
1732 @click.option('--password',
1733 hide_input=True,
1734 confirmation_prompt=True,
1735 help='SDN controller password')
1736 #@click.option('--description',
1737 # default='no description',
1738 # help='human readable description')
1739 @click.pass_context
1740 def sdnc_create(ctx,
1741 name,
1742 type,
1743 sdn_controller_version,
1744 ip_address,
1745 port,
1746 switch_dpid,
1747 user,
1748 password):
1749 '''creates a new SDN controller
1750 '''
1751 sdncontroller = {}
1752 sdncontroller['name'] = name
1753 sdncontroller['type'] = type
1754 sdncontroller['ip'] = ip_address
1755 sdncontroller['port'] = int(port)
1756 sdncontroller['dpid'] = switch_dpid
1757 if sdn_controller_version:
1758 sdncontroller['version'] = sdn_controller_version
1759 if user:
1760 sdncontroller['user'] = user
1761 if password:
1762 sdncontroller['password'] = password
1763 # sdncontroller['description'] = description
1764 try:
1765 check_client_version(ctx.obj, ctx.command.name)
1766 ctx.obj.sdnc.create(name, sdncontroller)
1767 except ClientException as inst:
1768 print((inst.message))
1769
1770
1771 @cli.command(name='sdnc-update', short_help='updates an SDN controller')
1772 @click.argument('name')
1773 @click.option('--newname', help='New name for the SDN controller')
1774 @click.option('--type', help='SDN controller type')
1775 @click.option('--sdn_controller_version', help='SDN controller username')
1776 @click.option('--ip_address', help='SDN controller IP address')
1777 @click.option('--port', help='SDN controller port')
1778 @click.option('--switch_dpid', help='Switch DPID (Openflow Datapath ID)')
1779 @click.option('--user', help='SDN controller username')
1780 @click.option('--password', help='SDN controller password')
1781 #@click.option('--description', default=None, help='human readable description')
1782 @click.pass_context
1783 def sdnc_update(ctx,
1784 name,
1785 newname,
1786 type,
1787 sdn_controller_version,
1788 ip_address,
1789 port,
1790 switch_dpid,
1791 user,
1792 password):
1793 '''updates an SDN controller
1794
1795 NAME: name or ID of the SDN controller
1796 '''
1797 sdncontroller = {}
1798 if newname: sdncontroller['name'] = newname
1799 if type: sdncontroller['type'] = type
1800 if ip_address: sdncontroller['ip'] = ip_address
1801 if port: sdncontroller['port'] = int(port)
1802 if switch_dpid: sdncontroller['dpid'] = switch_dpid
1803 # sdncontroller['description'] = description
1804 if sdn_controller_version is not None:
1805 if sdn_controller_version=="":
1806 sdncontroller['version'] = None
1807 else:
1808 sdncontroller['version'] = sdn_controller_version
1809 if user is not None:
1810 if user=="":
1811 sdncontroller['user'] = None
1812 else:
1813 sdncontroller['user'] = user
1814 if password is not None:
1815 if password=="":
1816 sdncontroller['password'] = None
1817 else:
1818 sdncontroller['password'] = user
1819 try:
1820 check_client_version(ctx.obj, ctx.command.name)
1821 ctx.obj.sdnc.update(name, sdncontroller)
1822 except ClientException as inst:
1823 print((inst.message))
1824 exit(1)
1825
1826
1827 @cli.command(name='sdnc-delete')
1828 @click.argument('name')
1829 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1830 @click.pass_context
1831 def sdnc_delete(ctx, name, force):
1832 '''deletes an SDN controller
1833
1834 NAME: name or ID of the SDN controller to be deleted
1835 '''
1836 try:
1837 check_client_version(ctx.obj, ctx.command.name)
1838 ctx.obj.sdnc.delete(name, force)
1839 except ClientException as inst:
1840 print((inst.message))
1841 exit(1)
1842
1843
1844 @cli.command(name='sdnc-list')
1845 @click.option('--filter', default=None,
1846 help='restricts the list to the SDN controllers matching the filter')
1847 @click.pass_context
1848 def sdnc_list(ctx, filter):
1849 '''list all SDN controllers'''
1850 try:
1851 check_client_version(ctx.obj, ctx.command.name)
1852 resp = ctx.obj.sdnc.list(filter)
1853 except ClientException as inst:
1854 print((inst.message))
1855 exit(1)
1856 table = PrettyTable(['name', 'id'])
1857 for sdnc in resp:
1858 table.add_row([sdnc['name'], sdnc['_id']])
1859 table.align = 'l'
1860 print(table)
1861
1862
1863 @cli.command(name='sdnc-show')
1864 @click.argument('name')
1865 @click.pass_context
1866 def sdnc_show(ctx, name):
1867 '''shows the details of an SDN controller
1868
1869 NAME: name or ID of the SDN controller
1870 '''
1871 try:
1872 check_client_version(ctx.obj, ctx.command.name)
1873 resp = ctx.obj.sdnc.get(name)
1874 except ClientException as inst:
1875 print((inst.message))
1876 exit(1)
1877
1878 table = PrettyTable(['key', 'attribute'])
1879 for k, v in list(resp.items()):
1880 table.add_row([k, json.dumps(v, indent=2)])
1881 table.align = 'l'
1882 print(table)
1883
1884
1885 ####################
1886 # Project mgmt operations
1887 ####################
1888
1889 @cli.command(name='project-create')
1890 @click.argument('name')
1891 #@click.option('--description',
1892 # default='no description',
1893 # help='human readable description')
1894 @click.pass_context
1895 def project_create(ctx, name):
1896 '''Creates a new project
1897
1898 NAME: name of the project
1899 '''
1900 project = {}
1901 project['name'] = name
1902 try:
1903 check_client_version(ctx.obj, ctx.command.name)
1904 ctx.obj.project.create(name, project)
1905 except ClientException as inst:
1906 print(inst.message)
1907
1908
1909 @cli.command(name='project-delete')
1910 @click.argument('name')
1911 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1912 @click.pass_context
1913 def project_delete(ctx, name):
1914 '''deletes a project
1915
1916 NAME: name or ID of the project to be deleted
1917 '''
1918 try:
1919 check_client_version(ctx.obj, ctx.command.name)
1920 ctx.obj.project.delete(name)
1921 except ClientException as inst:
1922 print(inst.message)
1923 exit(1)
1924
1925
1926 @cli.command(name='project-list')
1927 @click.option('--filter', default=None,
1928 help='restricts the list to the projects matching the filter')
1929 @click.pass_context
1930 def project_list(ctx, filter):
1931 '''list all projects'''
1932 try:
1933 check_client_version(ctx.obj, ctx.command.name)
1934 resp = ctx.obj.project.list(filter)
1935 except ClientException as inst:
1936 print(inst.message)
1937 exit(1)
1938 table = PrettyTable(['name', 'id'])
1939 for proj in resp:
1940 table.add_row([proj['name'], proj['_id']])
1941 table.align = 'l'
1942 print(table)
1943
1944
1945 @cli.command(name='project-show')
1946 @click.argument('name')
1947 @click.pass_context
1948 def project_show(ctx, name):
1949 '''shows the details of a project
1950
1951 NAME: name or ID of the project
1952 '''
1953 try:
1954 check_client_version(ctx.obj, ctx.command.name)
1955 resp = ctx.obj.project.get(name)
1956 except ClientException as inst:
1957 print(inst.message)
1958 exit(1)
1959
1960 table = PrettyTable(['key', 'attribute'])
1961 for k, v in resp.items():
1962 table.add_row([k, json.dumps(v, indent=2)])
1963 table.align = 'l'
1964 print(table)
1965
1966
1967 ####################
1968 # User mgmt operations
1969 ####################
1970
1971 @cli.command(name='user-create')
1972 @click.argument('username')
1973 @click.option('--password',
1974 prompt=True,
1975 hide_input=True,
1976 confirmation_prompt=True,
1977 help='user password')
1978 @click.option('--projects',
1979 default=None,
1980 help='list of project ids that the user belongs to')
1981 #@click.option('--description',
1982 # default='no description',
1983 # help='human readable description')
1984 @click.pass_context
1985 def user_create(ctx, username, password, projects):
1986 '''Creates a new user
1987
1988 USERNAME: name of the user
1989 '''
1990 user = {}
1991 user['username'] = username
1992 user['password'] = password
1993 user['projects'] = projects
1994 try:
1995 check_client_version(ctx.obj, ctx.command.name)
1996 ctx.obj.user.create(username, user)
1997 except ClientException as inst:
1998 print(inst.message)
1999
2000
2001 @cli.command(name='user-delete')
2002 @click.argument('name')
2003 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2004 @click.pass_context
2005 def user_delete(ctx, name):
2006 '''deletes a user
2007
2008 NAME: name or ID of the user to be deleted
2009 '''
2010 try:
2011 check_client_version(ctx.obj, ctx.command.name)
2012 ctx.obj.user.delete(name)
2013 except ClientException as inst:
2014 print(inst.message)
2015 exit(1)
2016
2017
2018 @cli.command(name='user-list')
2019 @click.option('--filter', default=None,
2020 help='restricts the list to the users matching the filter')
2021 @click.pass_context
2022 def user_list(ctx, filter):
2023 '''list all users'''
2024 try:
2025 check_client_version(ctx.obj, ctx.command.name)
2026 resp = ctx.obj.user.list(filter)
2027 except ClientException as inst:
2028 print(inst.message)
2029 exit(1)
2030 table = PrettyTable(['name', 'id'])
2031 for user in resp:
2032 table.add_row([user['name'], user['_id']])
2033 table.align = 'l'
2034 print(table)
2035
2036
2037 @cli.command(name='user-show')
2038 @click.argument('name')
2039 @click.pass_context
2040 def user_show(ctx, name):
2041 '''shows the details of a user
2042
2043 NAME: name or ID of the user
2044 '''
2045 try:
2046 check_client_version(ctx.obj, ctx.command.name)
2047 resp = ctx.obj.user.get(name)
2048 if 'password' in resp:
2049 resp['password']='********'
2050 except ClientException as inst:
2051 print(inst.message)
2052 exit(1)
2053
2054 table = PrettyTable(['key', 'attribute'])
2055 for k, v in resp.items():
2056 table.add_row([k, json.dumps(v, indent=2)])
2057 table.align = 'l'
2058 print(table)
2059
2060
2061 ####################
2062 # Fault Management operations
2063 ####################
2064
2065 @cli.command(name='ns-alarm-create')
2066 @click.argument('name')
2067 @click.option('--ns', prompt=True, help='NS instance id or name')
2068 @click.option('--vnf', prompt=True,
2069 help='VNF name (VNF member index as declared in the NSD)')
2070 @click.option('--vdu', prompt=True,
2071 help='VDU name (VDU name as declared in the VNFD)')
2072 @click.option('--metric', prompt=True,
2073 help='Name of the metric (e.g. cpu_utilization)')
2074 @click.option('--severity', default='WARNING',
2075 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
2076 @click.option('--threshold_value', prompt=True,
2077 help='threshold value that, when crossed, an alarm is triggered')
2078 @click.option('--threshold_operator', prompt=True,
2079 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
2080 @click.option('--statistic', default='AVERAGE',
2081 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
2082 @click.pass_context
2083 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
2084 threshold_value, threshold_operator, statistic):
2085 '''creates a new alarm for a NS instance'''
2086 ns_instance = ctx.obj.ns.get(ns)
2087 alarm = {}
2088 alarm['alarm_name'] = name
2089 alarm['ns_id'] = ns_instance['_id']
2090 alarm['correlation_id'] = ns_instance['_id']
2091 alarm['vnf_member_index'] = vnf
2092 alarm['vdu_name'] = vdu
2093 alarm['metric_name'] = metric
2094 alarm['severity'] = severity
2095 alarm['threshold_value'] = int(threshold_value)
2096 alarm['operation'] = threshold_operator
2097 alarm['statistic'] = statistic
2098 try:
2099 check_client_version(ctx.obj, ctx.command.name)
2100 ctx.obj.ns.create_alarm(alarm)
2101 except ClientException as inst:
2102 print((inst.message))
2103 exit(1)
2104
2105
2106 #@cli.command(name='ns-alarm-delete')
2107 #@click.argument('name')
2108 #@click.pass_context
2109 #def ns_alarm_delete(ctx, name):
2110 # '''deletes an alarm
2111 #
2112 # NAME: name of the alarm to be deleted
2113 # '''
2114 # try:
2115 # check_client_version(ctx.obj, ctx.command.name)
2116 # ctx.obj.ns.delete_alarm(name)
2117 # except ClientException as inst:
2118 # print(inst.message)
2119 # exit(1)
2120
2121
2122 ####################
2123 # Performance Management operations
2124 ####################
2125
2126 @cli.command(name='ns-metric-export')
2127 @click.option('--ns', prompt=True, help='NS instance id or name')
2128 @click.option('--vnf', prompt=True,
2129 help='VNF name (VNF member index as declared in the NSD)')
2130 @click.option('--vdu', prompt=True,
2131 help='VDU name (VDU name as declared in the VNFD)')
2132 @click.option('--metric', prompt=True,
2133 help='name of the metric (e.g. cpu_utilization)')
2134 #@click.option('--period', default='1w',
2135 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
2136 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
2137 @click.pass_context
2138 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
2139 '''exports a metric to the internal OSM bus, which can be read by other apps
2140 '''
2141 ns_instance = ctx.obj.ns.get(ns)
2142 metric_data = {}
2143 metric_data['ns_id'] = ns_instance['_id']
2144 metric_data['correlation_id'] = ns_instance['_id']
2145 metric_data['vnf_member_index'] = vnf
2146 metric_data['vdu_name'] = vdu
2147 metric_data['metric_name'] = metric
2148 metric_data['collection_unit'] = 'WEEK'
2149 metric_data['collection_period'] = 1
2150 try:
2151 check_client_version(ctx.obj, ctx.command.name)
2152 if not interval:
2153 print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
2154 else:
2155 i = 1
2156 while True:
2157 print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
2158 time.sleep(int(interval))
2159 i+=1
2160 except ClientException as inst:
2161 print((inst.message))
2162 exit(1)
2163
2164
2165 ####################
2166 # Other operations
2167 ####################
2168
2169 @cli.command(name='upload-package')
2170 @click.argument('filename')
2171 @click.pass_context
2172 def upload_package(ctx, filename):
2173 '''uploads a VNF package or NS package
2174
2175 FILENAME: VNF or NS package file (tar.gz)
2176 '''
2177 try:
2178 ctx.obj.package.upload(filename)
2179 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
2180 if fullclassname != 'osmclient.sol005.client.Client':
2181 ctx.obj.package.wait_for_upload(filename)
2182 except ClientException as inst:
2183 print((inst.message))
2184 exit(1)
2185
2186
2187 @cli.command(name='ns-scaling-show')
2188 @click.argument('ns_name')
2189 @click.pass_context
2190 def show_ns_scaling(ctx, ns_name):
2191 '''shows the status of a NS scaling operation
2192
2193 NS_NAME: name of the NS instance being scaled
2194 '''
2195 try:
2196 check_client_version(ctx.obj, ctx.command.name, 'v1')
2197 resp = ctx.obj.ns.list()
2198 except ClientException as inst:
2199 print((inst.message))
2200 exit(1)
2201
2202 table = PrettyTable(
2203 ['group-name',
2204 'instance-id',
2205 'operational status',
2206 'create-time',
2207 'vnfr ids'])
2208
2209 for ns in resp:
2210 if ns_name == ns['name']:
2211 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
2212 scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
2213 for record in scaling_records:
2214 if 'instance' in record:
2215 instances = record['instance']
2216 for inst in instances:
2217 table.add_row(
2218 [record['scaling-group-name-ref'],
2219 inst['instance-id'],
2220 inst['op-status'],
2221 time.strftime('%Y-%m-%d %H:%M:%S',
2222 time.localtime(
2223 inst['create-time'])),
2224 inst['vnfrs']])
2225 table.align = 'l'
2226 print(table)
2227
2228
2229 @cli.command(name='ns-scale')
2230 @click.argument('ns_name')
2231 @click.option('--ns_scale_group', prompt=True)
2232 @click.option('--index', prompt=True)
2233 @click.pass_context
2234 def ns_scale(ctx, ns_name, ns_scale_group, index):
2235 '''scales NS
2236
2237 NS_NAME: name of the NS instance to be scaled
2238 '''
2239 try:
2240 check_client_version(ctx.obj, ctx.command.name, 'v1')
2241 ctx.obj.ns.scale(ns_name, ns_scale_group, index)
2242 except ClientException as inst:
2243 print((inst.message))
2244 exit(1)
2245
2246
2247 @cli.command(name='config-agent-list')
2248 @click.pass_context
2249 def config_agent_list(ctx):
2250 '''list config agents'''
2251 try:
2252 check_client_version(ctx.obj, ctx.command.name, 'v1')
2253 except ClientException as inst:
2254 print((inst.message))
2255 exit(1)
2256 table = PrettyTable(['name', 'account-type', 'details'])
2257 for account in ctx.obj.vca.list():
2258 table.add_row(
2259 [account['name'],
2260 account['account-type'],
2261 account['juju']])
2262 table.align = 'l'
2263 print(table)
2264
2265
2266 @cli.command(name='config-agent-delete')
2267 @click.argument('name')
2268 @click.pass_context
2269 def config_agent_delete(ctx, name):
2270 '''deletes a config agent
2271
2272 NAME: name of the config agent to be deleted
2273 '''
2274 try:
2275 check_client_version(ctx.obj, ctx.command.name, 'v1')
2276 ctx.obj.vca.delete(name)
2277 except ClientException as inst:
2278 print((inst.message))
2279 exit(1)
2280
2281
2282 @cli.command(name='config-agent-add')
2283 @click.option('--name',
2284 prompt=True)
2285 @click.option('--account_type',
2286 prompt=True)
2287 @click.option('--server',
2288 prompt=True)
2289 @click.option('--user',
2290 prompt=True)
2291 @click.option('--secret',
2292 prompt=True,
2293 hide_input=True,
2294 confirmation_prompt=True)
2295 @click.pass_context
2296 def config_agent_add(ctx, name, account_type, server, user, secret):
2297 '''adds a config agent'''
2298 try:
2299 check_client_version(ctx.obj, ctx.command.name, 'v1')
2300 ctx.obj.vca.create(name, account_type, server, user, secret)
2301 except ClientException as inst:
2302 print((inst.message))
2303 exit(1)
2304
2305 @cli.command(name='ro-dump')
2306 @click.pass_context
2307 def ro_dump(ctx):
2308 '''shows RO agent information'''
2309 check_client_version(ctx.obj, ctx.command.name, 'v1')
2310 resp = ctx.obj.vim.get_resource_orchestrator()
2311 table = PrettyTable(['key', 'attribute'])
2312 for k, v in list(resp.items()):
2313 table.add_row([k, json.dumps(v, indent=2)])
2314 table.align = 'l'
2315 print(table)
2316
2317
2318 @cli.command(name='vcs-list')
2319 @click.pass_context
2320 def vcs_list(ctx):
2321 check_client_version(ctx.obj, ctx.command.name, 'v1')
2322 resp = ctx.obj.utils.get_vcs_info()
2323 table = PrettyTable(['component name', 'state'])
2324 for component in resp:
2325 table.add_row([component['component_name'], component['state']])
2326 table.align = 'l'
2327 print(table)
2328
2329
2330 @cli.command(name='ns-action')
2331 @click.argument('ns_name')
2332 @click.option('--vnf_name', default=None)
2333 @click.option('--action_name', prompt=True)
2334 @click.option('--params', prompt=True)
2335 @click.pass_context
2336 def ns_action(ctx,
2337 ns_name,
2338 vnf_name,
2339 action_name,
2340 params):
2341 '''executes an action/primitive over a NS instance
2342
2343 NS_NAME: name or ID of the NS instance
2344 '''
2345 try:
2346 check_client_version(ctx.obj, ctx.command.name)
2347 op_data={}
2348 if vnf_name:
2349 op_data['vnf_member_index'] = vnf_name
2350 op_data['primitive'] = action_name
2351 op_data['primitive_params'] = yaml.load(params)
2352 ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data)
2353
2354 except ClientException as inst:
2355 print((inst.message))
2356 exit(1)
2357
2358
2359 @cli.command(name='vnf-scale')
2360 @click.argument('ns_name')
2361 @click.argument('vnf_name')
2362 @click.option('--scaling-group', prompt=True, help="scaling-group-descriptor name to use")
2363 @click.option('--scale-in', default=False, is_flag=True, help="performs a scale in operation")
2364 @click.option('--scale-out', default=False, is_flag=True, help="performs a scale out operation (by default)")
2365 @click.pass_context
2366 def vnf_scale(ctx,
2367 ns_name,
2368 vnf_name,
2369 scaling_group,
2370 scale_in,
2371 scale_out):
2372 '''executes a VNF scale (adding/removing VDUs)
2373
2374 \b
2375 NS_NAME: name or ID of the NS instance.
2376 VNF_NAME: member-vnf-index in the NS to be scaled.
2377 '''
2378 try:
2379 check_client_version(ctx.obj, ctx.command.name)
2380 if not scale_in and not scale_out:
2381 scale_out = True
2382 ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out)
2383 except ClientException as inst:
2384 print((inst.message))
2385 exit(1)
2386
2387
2388 if __name__ == '__main__':
2389 try:
2390 cli()
2391 except pycurl.error as e:
2392 print(e)
2393 print('Maybe "--hostname" option or OSM_HOSTNAME' +
2394 'environment variable needs to be specified')
2395 exit(1)
2396