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