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