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