fe140dd48382f4347d1b49036bed08de43e985cc
[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 import os
30
31
32 def check_client_version(obj, what, version='sol005'):
33 """
34 Checks the version of the client object and raises error if it not the expected.
35
36 :param obj: the client object
37 :what: the function or command under evaluation (used when an error is raised)
38 :return: -
39 :raises ClientError: if the specified version does not match the client version
40 """
41 fullclassname = obj.__module__ + "." + obj.__class__.__name__
42 message = 'The following commands or options are only supported with the option "--sol005": {}'.format(what)
43 if version == 'v1':
44 message = 'The following commands or options are not supported when using option "--sol005": {}'.format(what)
45 if fullclassname != 'osmclient.{}.client.Client'.format(version):
46 raise ClientException(message)
47 return
48
49
50 @click.group()
51 @click.option('--hostname',
52 default="127.0.0.1",
53 envvar='OSM_HOSTNAME',
54 help='hostname of server. ' +
55 'Also can set OSM_HOSTNAME in environment')
56 #@click.option('--sol005/--no-sol005',
57 # default=True,
58 # envvar='OSM_SOL005',
59 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
60 # 'Also can set OSM_SOL005 in environment')
61 @click.option('--user',
62 default=None,
63 envvar='OSM_USER',
64 help='user (defaults to admin). ' +
65 'Also can set OSM_USER in environment')
66 @click.option('--password',
67 default=None,
68 envvar='OSM_PASSWORD',
69 help='password (defaults to admin). ' +
70 'Also can set OSM_PASSWORD in environment')
71 @click.option('--project',
72 default=None,
73 envvar='OSM_PROJECT',
74 help='project (defaults to admin). ' +
75 'Also can set OSM_PROJECT in environment')
76 #@click.option('--so-port',
77 # default=None,
78 # envvar='OSM_SO_PORT',
79 # help='hostname of server. ' +
80 # 'Also can set OSM_SO_PORT in environment')
81 #@click.option('--so-project',
82 # default=None,
83 # envvar='OSM_SO_PROJECT',
84 # help='Project Name in SO. ' +
85 # 'Also can set OSM_SO_PROJECT in environment')
86 #@click.option('--ro-hostname',
87 # default=None,
88 # envvar='OSM_RO_HOSTNAME',
89 # help='hostname of RO server. ' +
90 # 'Also can set OSM_RO_HOSTNAME in environment')
91 #@click.option('--ro-port',
92 # default=None,
93 # envvar='OSM_RO_PORT',
94 # help='hostname of RO server. ' +
95 # 'Also can set OSM_RO_PORT in environment')
96 @click.pass_context
97 def cli(ctx, hostname, user, password, project):
98 if hostname is None:
99 print((
100 "either hostname option or OSM_HOSTNAME " +
101 "environment variable needs to be specified"))
102 exit(1)
103 kwargs={}
104 # if so_port is not None:
105 # kwargs['so_port']=so_port
106 # if so_project is not None:
107 # kwargs['so_project']=so_project
108 # if ro_hostname is not None:
109 # kwargs['ro_host']=ro_hostname
110 # if ro_port is not None:
111 # kwargs['ro_port']=ro_port
112 sol005 = os.getenv('OSM_SOL005', True)
113 if user is not None:
114 kwargs['user']=user
115 if password is not None:
116 kwargs['password']=password
117 if project is not None:
118 kwargs['project']=project
119
120 ctx.obj = client.Client(host=hostname, sol005=sol005, **kwargs)
121
122
123 ####################
124 # LIST operations
125 ####################
126
127 @cli.command(name='ns-list')
128 @click.option('--filter', default=None,
129 help='restricts the list to the NS instances matching the filter.')
130 @click.pass_context
131 def ns_list(ctx, filter):
132 """list all NS instances
133
134 \b
135 Options:
136 --filter filterExpr Restricts the list to the NS instances matching the filter
137
138 \b
139 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
140 concatenated using the "&" character:
141
142 \b
143 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
144 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
145 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
146 attrName := string
147 value := scalar value
148
149 \b
150 where:
151 * zero or more occurrences
152 ? zero or one occurrence
153 [] grouping of expressions to be used with ? and *
154 "" quotation marks for marking string constants
155 <> name separator
156
157 \b
158 "AttrName" is the name of one attribute in the data type that defines the representation
159 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
160 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
161 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
162 entries, it means that the operator "op" is applied to the attribute addressed by the last
163 <attrName> entry included in the concatenation. All simple filter expressions are combined
164 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
165 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
166 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
167 prefix". If an attribute referenced in an expression is an array, an object that contains a
168 corresponding array shall be considered to match the expression if any of the elements in the
169 array matches all expressions that have the same attribute prefix.
170
171 \b
172 Filter examples:
173 --filter admin-status=ENABLED
174 --filter nsd-ref=<NSD_NAME>
175 --filter nsd.vendor=<VENDOR>
176 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
177 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
178 """
179 if filter:
180 check_client_version(ctx.obj, '--filter')
181 resp = ctx.obj.ns.list(filter)
182 else:
183 resp = ctx.obj.ns.list()
184 table = PrettyTable(
185 ['ns instance name',
186 'id',
187 'operational status',
188 'config status',
189 'detailed status'])
190 for ns in resp:
191 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
192 if fullclassname == 'osmclient.sol005.client.Client':
193 nsr = ns
194 nsr_name = nsr['name']
195 nsr_id = nsr['_id']
196 else:
197 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
198 nsr = nsopdata['nsr:nsr']
199 nsr_name = nsr['name-ref']
200 nsr_id = nsr['ns-instance-config-ref']
201 opstatus = nsr['operational-status'] if 'operational-status' in nsr else 'Not found'
202 configstatus = nsr['config-status'] if 'config-status' in nsr else 'Not found'
203 detailed_status = nsr['detailed-status'] if 'detailed-status' in nsr else 'Not found'
204 if configstatus == "config_not_needed":
205 configstatus = "configured (no charms)"
206 table.add_row(
207 [nsr_name,
208 nsr_id,
209 opstatus,
210 configstatus,
211 detailed_status])
212 table.align = 'l'
213 print(table)
214
215
216 def nsd_list(ctx, filter):
217 if filter:
218 check_client_version(ctx.obj, '--filter')
219 resp = ctx.obj.nsd.list(filter)
220 else:
221 resp = ctx.obj.nsd.list()
222 # print(yaml.safe_dump(resp))
223 table = PrettyTable(['nsd name', 'id'])
224 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
225 if fullclassname == 'osmclient.sol005.client.Client':
226 for ns in resp:
227 name = ns['name'] if 'name' in ns else '-'
228 table.add_row([name, ns['_id']])
229 else:
230 for ns in resp:
231 table.add_row([ns['name'], ns['id']])
232 table.align = 'l'
233 print(table)
234
235
236 @cli.command(name='nsd-list')
237 @click.option('--filter', default=None,
238 help='restricts the list to the NSD/NSpkg matching the filter')
239 @click.pass_context
240 def nsd_list1(ctx, filter):
241 """list all NSD/NS pkg in the system"""
242 nsd_list(ctx, filter)
243
244
245 @cli.command(name='nspkg-list')
246 @click.option('--filter', default=None,
247 help='restricts the list to the NSD/NSpkg matching the filter')
248 @click.pass_context
249 def nsd_list2(ctx, filter):
250 """list all NSD/NS pkg in the system"""
251 nsd_list(ctx, filter)
252
253
254 def vnfd_list(ctx, nf_type, filter):
255 if nf_type:
256 check_client_version(ctx.obj, '--nf_type')
257 elif filter:
258 check_client_version(ctx.obj, '--filter')
259 if nf_type:
260 if nf_type == "vnf":
261 nf_filter = "_admin.type=vnfd"
262 elif nf_type == "pnf":
263 nf_filter = "_admin.type=pnfd"
264 elif nf_type == "hnf":
265 nf_filter = "_admin.type=hnfd"
266 else:
267 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
268 if filter:
269 filter = '{}&{}'.format(nf_filter, filter)
270 else:
271 filter = nf_filter
272 if filter:
273 resp = ctx.obj.vnfd.list(filter)
274 else:
275 resp = ctx.obj.vnfd.list()
276 # print(yaml.safe_dump(resp))
277 table = PrettyTable(['nfpkg name', 'id'])
278 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
279 if fullclassname == 'osmclient.sol005.client.Client':
280 for vnfd in resp:
281 name = vnfd['name'] if 'name' in vnfd else '-'
282 table.add_row([name, vnfd['_id']])
283 else:
284 for vnfd in resp:
285 table.add_row([vnfd['name'], vnfd['id']])
286 table.align = 'l'
287 print(table)
288
289
290 @cli.command(name='vnfd-list')
291 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
292 @click.option('--filter', default=None,
293 help='restricts the list to the NF pkg matching the filter')
294 @click.pass_context
295 def vnfd_list1(ctx, nf_type, filter):
296 """list all VNFD/VNF pkg in the system"""
297 vnfd_list(ctx, nf_type, filter)
298
299
300 @cli.command(name='vnfpkg-list')
301 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
302 @click.option('--filter', default=None,
303 help='restricts the list to the NFpkg matching the filter')
304 @click.pass_context
305 def vnfd_list2(ctx, nf_type, filter):
306 """list all VNFD/VNF pkg in the system"""
307 vnfd_list(ctx, nf_type, filter)
308
309
310 @cli.command(name='nfpkg-list')
311 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
312 @click.option('--filter', default=None,
313 help='restricts the list to the NFpkg matching the filter')
314 @click.pass_context
315 def nfpkg_list(ctx, nf_type, filter):
316 """list all NF pkg (VNF pkg, PNF pkg, HNF pkg) in the system"""
317 try:
318 check_client_version(ctx.obj, ctx.command.name)
319 vnfd_list(ctx, nf_type, filter)
320 except ClientException as inst:
321 print((inst.message))
322 exit(1)
323
324
325 def vnf_list(ctx, ns, filter):
326 try:
327 if ns or filter:
328 if ns:
329 check_client_version(ctx.obj, '--ns')
330 if filter:
331 check_client_version(ctx.obj, '--filter')
332 resp = ctx.obj.vnf.list(ns, filter)
333 else:
334 resp = ctx.obj.vnf.list()
335 except ClientException as inst:
336 print((inst.message))
337 exit(1)
338 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
339 if fullclassname == 'osmclient.sol005.client.Client':
340 table = PrettyTable(
341 ['vnf id',
342 'name',
343 'ns id',
344 'vnf member index',
345 'vnfd name',
346 'vim account id',
347 'ip address'])
348 for vnfr in resp:
349 name = vnfr['name'] if 'name' in vnfr else '-'
350 table.add_row(
351 [vnfr['_id'],
352 name,
353 vnfr['nsr-id-ref'],
354 vnfr['member-vnf-index-ref'],
355 vnfr['vnfd-ref'],
356 vnfr['vim-account-id'],
357 vnfr['ip-address']])
358 else:
359 table = PrettyTable(
360 ['vnf name',
361 'id',
362 'operational status',
363 'config status'])
364 for vnfr in resp:
365 if 'mgmt-interface' not in vnfr:
366 vnfr['mgmt-interface'] = {}
367 vnfr['mgmt-interface']['ip-address'] = None
368 table.add_row(
369 [vnfr['name'],
370 vnfr['id'],
371 vnfr['operational-status'],
372 vnfr['config-status']])
373 table.align = 'l'
374 print(table)
375
376
377 @cli.command(name='vnf-list')
378 @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list')
379 @click.option('--filter', default=None,
380 help='restricts the list to the NF instances matching the filter.')
381 @click.pass_context
382 def vnf_list1(ctx, ns, filter):
383 """list all NF instances"""
384 vnf_list(ctx, ns, filter)
385
386
387 @cli.command(name='nf-list')
388 @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list')
389 @click.option('--filter', default=None,
390 help='restricts the list to the NF instances matching the filter.')
391 @click.pass_context
392 def nf_list(ctx, ns, filter):
393 """list all NF instances
394
395 \b
396 Options:
397 --ns TEXT NS instance id or name to restrict the VNF list
398 --filter filterExpr Restricts the list to the VNF instances matching the filter
399
400 \b
401 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
402 concatenated using the "&" character:
403
404 \b
405 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
406 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
407 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
408 attrName := string
409 value := scalar value
410
411 \b
412 where:
413 * zero or more occurrences
414 ? zero or one occurrence
415 [] grouping of expressions to be used with ? and *
416 "" quotation marks for marking string constants
417 <> name separator
418
419 \b
420 "AttrName" is the name of one attribute in the data type that defines the representation
421 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
422 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
423 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
424 entries, it means that the operator "op" is applied to the attribute addressed by the last
425 <attrName> entry included in the concatenation. All simple filter expressions are combined
426 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
427 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
428 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
429 prefix". If an attribute referenced in an expression is an array, an object that contains a
430 corresponding array shall be considered to match the expression if any of the elements in the
431 array matches all expressions that have the same attribute prefix.
432
433 \b
434 Filter examples:
435 --filter vim-account-id=<VIM_ACCOUNT_ID>
436 --filter vnfd-ref=<VNFD_NAME>
437 --filter vdur.ip-address=<IP_ADDRESS>
438 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
439 """
440 vnf_list(ctx, ns, filter)
441
442
443 @cli.command(name='ns-op-list')
444 @click.argument('name')
445 @click.pass_context
446 def ns_op_list(ctx, name):
447 """shows the history of operations over a NS instance
448
449 NAME: name or ID of the NS instance
450 """
451 try:
452 check_client_version(ctx.obj, ctx.command.name)
453 resp = ctx.obj.ns.list_op(name)
454 except ClientException as inst:
455 print((inst.message))
456 exit(1)
457
458 table = PrettyTable(['id', 'operation', 'status'])
459 for op in resp:
460 table.add_row([op['id'], op['lcmOperationType'],
461 op['operationState']])
462 table.align = 'l'
463 print(table)
464
465
466 def nsi_list(ctx, filter):
467 """list all Network Slice Instances"""
468 try:
469 check_client_version(ctx.obj, ctx.command.name)
470 resp = ctx.obj.nsi.list(filter)
471 except ClientException as inst:
472 print((inst.message))
473 exit(1)
474 table = PrettyTable(
475 ['netslice instance name',
476 'id',
477 'operational status',
478 'config status',
479 'detailed status'])
480 for nsi in resp:
481 nsi_name = nsi['name']
482 nsi_id = nsi['_id']
483 opstatus = nsi['operational-status'] if 'operational-status' in nsi else 'Not found'
484 configstatus = nsi['config-status'] if 'config-status' in nsi else 'Not found'
485 detailed_status = nsi['detailed-status'] if 'detailed-status' in nsi else 'Not found'
486 if configstatus == "config_not_needed":
487 configstatus = "configured (no charms)"
488 table.add_row(
489 [nsi_name,
490 nsi_id,
491 opstatus,
492 configstatus,
493 detailed_status])
494 table.align = 'l'
495 print(table)
496
497
498 @cli.command(name='nsi-list')
499 @click.option('--filter', default=None,
500 help='restricts the list to the Network Slice Instances matching the filter')
501 @click.pass_context
502 def nsi_list1(ctx, filter):
503 """list all Network Slice Instances (NSI)"""
504 nsi_list(ctx, filter)
505
506
507 @cli.command(name='netslice-instance-list')
508 @click.option('--filter', default=None,
509 help='restricts the list to the Network Slice Instances matching the filter')
510 @click.pass_context
511 def nsi_list2(ctx, filter):
512 """list all Network Slice Instances (NSI)"""
513 nsi_list(ctx, filter)
514
515
516 def nst_list(ctx, filter):
517 try:
518 check_client_version(ctx.obj, ctx.command.name)
519 resp = ctx.obj.nst.list(filter)
520 except ClientException as inst:
521 print((inst.message))
522 exit(1)
523 # print(yaml.safe_dump(resp))
524 table = PrettyTable(['nst name', 'id'])
525 for nst in resp:
526 name = nst['name'] if 'name' in nst else '-'
527 table.add_row([name, nst['_id']])
528 table.align = 'l'
529 print(table)
530
531
532 @cli.command(name='nst-list')
533 @click.option('--filter', default=None,
534 help='restricts the list to the NST matching the filter')
535 @click.pass_context
536 def nst_list1(ctx, filter):
537 """list all Network Slice Templates (NST) in the system"""
538 nst_list(ctx, filter)
539
540
541 @cli.command(name='netslice-template-list')
542 @click.option('--filter', default=None,
543 help='restricts the list to the NST matching the filter')
544 @click.pass_context
545 def nst_list2(ctx, filter):
546 """list all Network Slice Templates (NST) in the system"""
547 nst_list(ctx, filter)
548
549
550 def nsi_op_list(ctx, name):
551 try:
552 check_client_version(ctx.obj, ctx.command.name)
553 resp = ctx.obj.nsi.list_op(name)
554 except ClientException as inst:
555 print((inst.message))
556 exit(1)
557 table = PrettyTable(['id', 'operation', 'status'])
558 for op in resp:
559 table.add_row([op['id'], op['lcmOperationType'],
560 op['operationState']])
561 table.align = 'l'
562 print(table)
563
564
565 @cli.command(name='nsi-op-list')
566 @click.argument('name')
567 @click.pass_context
568 def nsi_op_list1(ctx, name):
569 """shows the history of operations over a Network Slice Instance (NSI)
570
571 NAME: name or ID of the Network Slice Instance
572 """
573 nsi_op_list(ctx, name)
574
575
576 @cli.command(name='netslice-instance-op-list')
577 @click.argument('name')
578 @click.pass_context
579 def nsi_op_list2(ctx, name):
580 """shows the history of operations over a Network Slice Instance (NSI)
581
582 NAME: name or ID of the Network Slice Instance
583 """
584 nsi_op_list(ctx, name)
585
586
587 @cli.command(name='pdu-list')
588 @click.option('--filter', default=None,
589 help='restricts the list to the Physical Deployment Units matching the filter')
590 @click.pass_context
591 def pdu_list(ctx, filter):
592 """list all Physical Deployment Units (PDU)"""
593 try:
594 check_client_version(ctx.obj, ctx.command.name)
595 resp = ctx.obj.pdu.list(filter)
596 except ClientException as inst:
597 print((inst.message))
598 exit(1)
599 table = PrettyTable(
600 ['pdu name',
601 'id',
602 'type',
603 'mgmt ip address'])
604 for pdu in resp:
605 pdu_name = pdu['name']
606 pdu_id = pdu['_id']
607 pdu_type = pdu['type']
608 pdu_ipaddress = "None"
609 for iface in pdu['interfaces']:
610 if iface['mgmt']:
611 pdu_ipaddress = iface['ip-address']
612 break
613 table.add_row(
614 [pdu_name,
615 pdu_id,
616 pdu_type,
617 pdu_ipaddress])
618 table.align = 'l'
619 print(table)
620
621
622 ####################
623 # SHOW operations
624 ####################
625
626 def nsd_show(ctx, name, literal):
627 try:
628 resp = ctx.obj.nsd.get(name)
629 # resp = ctx.obj.nsd.get_individual(name)
630 except ClientException as inst:
631 print((inst.message))
632 exit(1)
633
634 if literal:
635 print(yaml.safe_dump(resp))
636 return
637
638 table = PrettyTable(['field', 'value'])
639 for k, v in list(resp.items()):
640 table.add_row([k, json.dumps(v, indent=2)])
641 table.align = 'l'
642 print(table)
643
644
645 @cli.command(name='nsd-show', short_help='shows the content of a NSD')
646 @click.option('--literal', is_flag=True,
647 help='print literally, no pretty table')
648 @click.argument('name')
649 @click.pass_context
650 def nsd_show1(ctx, name, literal):
651 """shows the content of a NSD
652
653 NAME: name or ID of the NSD/NSpkg
654 """
655 nsd_show(ctx, name, literal)
656
657
658 @cli.command(name='nspkg-show', short_help='shows the content of a NSD')
659 @click.option('--literal', is_flag=True,
660 help='print literally, no pretty table')
661 @click.argument('name')
662 @click.pass_context
663 def nsd_show2(ctx, name, literal):
664 """shows the content of a NSD
665
666 NAME: name or ID of the NSD/NSpkg
667 """
668 nsd_show(ctx, name, literal)
669
670
671 def vnfd_show(ctx, name, literal):
672 try:
673 resp = ctx.obj.vnfd.get(name)
674 # resp = ctx.obj.vnfd.get_individual(name)
675 except ClientException as inst:
676 print((inst.message))
677 exit(1)
678
679 if literal:
680 print(yaml.safe_dump(resp))
681 return
682
683 table = PrettyTable(['field', 'value'])
684 for k, v in list(resp.items()):
685 table.add_row([k, json.dumps(v, indent=2)])
686 table.align = 'l'
687 print(table)
688
689
690 @cli.command(name='vnfd-show', short_help='shows the content of a VNFD')
691 @click.option('--literal', is_flag=True,
692 help='print literally, no pretty table')
693 @click.argument('name')
694 @click.pass_context
695 def vnfd_show1(ctx, name, literal):
696 """shows the content of a VNFD
697
698 NAME: name or ID of the VNFD/VNFpkg
699 """
700 vnfd_show(ctx, name, literal)
701
702
703 @cli.command(name='vnfpkg-show', short_help='shows the content of a VNFD')
704 @click.option('--literal', is_flag=True,
705 help='print literally, no pretty table')
706 @click.argument('name')
707 @click.pass_context
708 def vnfd_show2(ctx, name, literal):
709 """shows the content of a VNFD
710
711 NAME: name or ID of the VNFD/VNFpkg
712 """
713 vnfd_show(ctx, name, literal)
714
715
716 @cli.command(name='nfpkg-show', short_help='shows the content of a NF Descriptor')
717 @click.option('--literal', is_flag=True,
718 help='print literally, no pretty table')
719 @click.argument('name')
720 @click.pass_context
721 def nfpkg_show(ctx, name, literal):
722 """shows the content of a NF Descriptor
723
724 NAME: name or ID of the NFpkg
725 """
726 vnfd_show(ctx, name, literal)
727
728
729 @cli.command(name='ns-show', short_help='shows the info of a NS instance')
730 @click.argument('name')
731 @click.option('--literal', is_flag=True,
732 help='print literally, no pretty table')
733 @click.option('--filter', default=None)
734 @click.pass_context
735 def ns_show(ctx, name, literal, filter):
736 """shows the info of a NS instance
737
738 NAME: name or ID of the NS instance
739 """
740 try:
741 ns = ctx.obj.ns.get(name)
742 except ClientException as inst:
743 print((inst.message))
744 exit(1)
745
746 if literal:
747 print(yaml.safe_dump(ns))
748 return
749
750 table = PrettyTable(['field', 'value'])
751
752 for k, v in list(ns.items()):
753 if filter is None or filter in k:
754 table.add_row([k, json.dumps(v, indent=2)])
755
756 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
757 if fullclassname != 'osmclient.sol005.client.Client':
758 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
759 nsr_optdata = nsopdata['nsr:nsr']
760 for k, v in list(nsr_optdata.items()):
761 if filter is None or filter in k:
762 table.add_row([k, json.dumps(v, indent=2)])
763 table.align = 'l'
764 print(table)
765
766
767 @cli.command(name='vnf-show', short_help='shows the info of a VNF instance')
768 @click.argument('name')
769 @click.option('--literal', is_flag=True,
770 help='print literally, no pretty table')
771 @click.option('--filter', default=None)
772 @click.pass_context
773 def vnf_show(ctx, name, literal, filter):
774 """shows the info of a VNF instance
775
776 NAME: name or ID of the VNF instance
777 """
778 try:
779 check_client_version(ctx.obj, ctx.command.name)
780 resp = ctx.obj.vnf.get(name)
781 except ClientException as inst:
782 print((inst.message))
783 exit(1)
784
785 if literal:
786 print(yaml.safe_dump(resp))
787 return
788
789 table = PrettyTable(['field', 'value'])
790 for k, v in list(resp.items()):
791 if filter is None or filter in k:
792 table.add_row([k, json.dumps(v, indent=2)])
793 table.align = 'l'
794 print(table)
795
796
797 #@cli.command(name='vnf-monitoring-show')
798 #@click.argument('vnf_name')
799 #@click.pass_context
800 #def vnf_monitoring_show(ctx, vnf_name):
801 # try:
802 # check_client_version(ctx.obj, ctx.command.name, 'v1')
803 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
804 # except ClientException as inst:
805 # print((inst.message))
806 # exit(1)
807 #
808 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
809 # if resp is not None:
810 # for monitor in resp:
811 # table.add_row(
812 # [vnf_name,
813 # monitor['name'],
814 # monitor['value-integer'],
815 # monitor['units']])
816 # table.align = 'l'
817 # print(table)
818
819
820 #@cli.command(name='ns-monitoring-show')
821 #@click.argument('ns_name')
822 #@click.pass_context
823 #def ns_monitoring_show(ctx, ns_name):
824 # try:
825 # check_client_version(ctx.obj, ctx.command.name, 'v1')
826 # resp = ctx.obj.ns.get_monitoring(ns_name)
827 # except ClientException as inst:
828 # print((inst.message))
829 # exit(1)
830 #
831 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
832 # for key, val in list(resp.items()):
833 # for monitor in val:
834 # table.add_row(
835 # [key,
836 # monitor['name'],
837 # monitor['value-integer'],
838 # monitor['units']])
839 # table.align = 'l'
840 # print(table)
841
842
843 @cli.command(name='ns-op-show', short_help='shows the info of an operation')
844 @click.argument('id')
845 @click.option('--filter', default=None)
846 @click.pass_context
847 def ns_op_show(ctx, id, filter):
848 """shows the detailed info of an operation
849
850 ID: operation identifier
851 """
852 try:
853 check_client_version(ctx.obj, ctx.command.name)
854 op_info = ctx.obj.ns.get_op(id)
855 except ClientException as inst:
856 print((inst.message))
857 exit(1)
858
859 table = PrettyTable(['field', 'value'])
860 for k, v in list(op_info.items()):
861 if filter is None or filter in k:
862 table.add_row([k, json.dumps(v, indent=2)])
863 table.align = 'l'
864 print(table)
865
866
867 def nst_show(ctx, name, literal):
868 try:
869 check_client_version(ctx.obj, ctx.command.name)
870 resp = ctx.obj.nst.get(name)
871 #resp = ctx.obj.nst.get_individual(name)
872 except ClientException as inst:
873 print((inst.message))
874 exit(1)
875
876 if literal:
877 print(yaml.safe_dump(resp))
878 return
879
880 table = PrettyTable(['field', 'value'])
881 for k, v in list(resp.items()):
882 table.add_row([k, json.dumps(v, indent=2)])
883 table.align = 'l'
884 print(table)
885
886
887 @cli.command(name='nst-show', short_help='shows the content of a Network Slice Template (NST)')
888 @click.option('--literal', is_flag=True,
889 help='print literally, no pretty table')
890 @click.argument('name')
891 @click.pass_context
892 def nst_show1(ctx, name, literal):
893 """shows the content of a Network Slice Template (NST)
894
895 NAME: name or ID of the NST
896 """
897 nst_show(ctx, name, literal)
898
899
900 @cli.command(name='netslice-template-show', short_help='shows the content of a Network Slice Template (NST)')
901 @click.option('--literal', is_flag=True,
902 help='print literally, no pretty table')
903 @click.argument('name')
904 @click.pass_context
905 def nst_show2(ctx, name, literal):
906 """shows the content of a Network Slice Template (NST)
907
908 NAME: name or ID of the NST
909 """
910 nst_show(ctx, name, literal)
911
912
913 def nsi_show(ctx, name, literal, filter):
914 try:
915 check_client_version(ctx.obj, ctx.command.name)
916 nsi = ctx.obj.nsi.get(name)
917 except ClientException as inst:
918 print((inst.message))
919 exit(1)
920
921 if literal:
922 print(yaml.safe_dump(nsi))
923 return
924
925 table = PrettyTable(['field', 'value'])
926
927 for k, v in list(nsi.items()):
928 if filter is None or filter in k:
929 table.add_row([k, json.dumps(v, indent=2)])
930
931 table.align = 'l'
932 print(table)
933
934
935 @cli.command(name='nsi-show', short_help='shows the content of a Network Slice Instance (NSI)')
936 @click.argument('name')
937 @click.option('--literal', is_flag=True,
938 help='print literally, no pretty table')
939 @click.option('--filter', default=None)
940 @click.pass_context
941 def nsi_show1(ctx, name, literal, filter):
942 """shows the content of a Network Slice Instance (NSI)
943
944 NAME: name or ID of the Network Slice Instance
945 """
946 nsi_show(ctx, name, literal, filter)
947
948
949 @cli.command(name='netslice-instance-show', short_help='shows the content of a Network Slice Instance (NSI)')
950 @click.argument('name')
951 @click.option('--literal', is_flag=True,
952 help='print literally, no pretty table')
953 @click.option('--filter', default=None)
954 @click.pass_context
955 def nsi_show2(ctx, name, literal, filter):
956 """shows the content of a Network Slice Instance (NSI)
957
958 NAME: name or ID of the Network Slice Instance
959 """
960 nsi_show(ctx, name, literal, filter)
961
962
963 def nsi_op_show(ctx, id, filter):
964 try:
965 check_client_version(ctx.obj, ctx.command.name)
966 op_info = ctx.obj.nsi.get_op(id)
967 except ClientException as inst:
968 print((inst.message))
969 exit(1)
970
971 table = PrettyTable(['field', 'value'])
972 for k, v in list(op_info.items()):
973 if filter is None or filter in k:
974 table.add_row([k, json.dumps(v, indent=2)])
975 table.align = 'l'
976 print(table)
977
978
979 @cli.command(name='nsi-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
980 @click.argument('id')
981 @click.option('--filter', default=None)
982 @click.pass_context
983 def nsi_op_show1(ctx, id, filter):
984 """shows the info of an operation over a Network Slice Instance(NSI)
985
986 ID: operation identifier
987 """
988 nsi_op_show(ctx, id, filter)
989
990
991 @cli.command(name='netslice-instance-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
992 @click.argument('id')
993 @click.option('--filter', default=None)
994 @click.pass_context
995 def nsi_op_show2(ctx, id, filter):
996 """shows the info of an operation over a Network Slice Instance(NSI)
997
998 ID: operation identifier
999 """
1000 nsi_op_show(ctx, id, filter)
1001
1002
1003 @cli.command(name='pdu-show', short_help='shows the content of a Physical Deployment Unit (PDU)')
1004 @click.argument('name')
1005 @click.option('--literal', is_flag=True,
1006 help='print literally, no pretty table')
1007 @click.option('--filter', default=None)
1008 @click.pass_context
1009 def pdu_show(ctx, name, literal, filter):
1010 """shows the content of a Physical Deployment Unit (PDU)
1011
1012 NAME: name or ID of the PDU
1013 """
1014 try:
1015 check_client_version(ctx.obj, ctx.command.name)
1016 pdu = ctx.obj.pdu.get(name)
1017 except ClientException as inst:
1018 print((inst.message))
1019 exit(1)
1020
1021 if literal:
1022 print(yaml.safe_dump(pdu))
1023 return
1024
1025 table = PrettyTable(['field', 'value'])
1026
1027 for k, v in list(pdu.items()):
1028 if filter is None or filter in k:
1029 table.add_row([k, json.dumps(v, indent=2)])
1030
1031 table.align = 'l'
1032 print(table)
1033
1034
1035 ####################
1036 # CREATE operations
1037 ####################
1038
1039 def nsd_create(ctx, filename, overwrite):
1040 try:
1041 check_client_version(ctx.obj, ctx.command.name)
1042 ctx.obj.nsd.create(filename, overwrite)
1043 except ClientException as inst:
1044 print((inst.message))
1045 exit(1)
1046
1047
1048 @cli.command(name='nsd-create', short_help='creates a new NSD/NSpkg')
1049 @click.argument('filename')
1050 @click.option('--overwrite', default=None,
1051 help='overwrites some fields in NSD')
1052 @click.pass_context
1053 def nsd_create1(ctx, filename, overwrite):
1054 """creates a new NSD/NSpkg
1055
1056 FILENAME: NSD yaml file or NSpkg tar.gz file
1057 """
1058 nsd_create(ctx, filename, overwrite)
1059
1060
1061 @cli.command(name='nspkg-create', short_help='creates a new NSD/NSpkg')
1062 @click.argument('filename')
1063 @click.option('--overwrite', default=None,
1064 help='overwrites some fields in NSD')
1065 @click.pass_context
1066 def nsd_create2(ctx, filename, overwrite):
1067 """creates a new NSD/NSpkg
1068
1069 FILENAME: NSD yaml file or NSpkg tar.gz file
1070 """
1071 nsd_create(ctx, filename, overwrite)
1072
1073
1074 def vnfd_create(ctx, filename, overwrite):
1075 try:
1076 check_client_version(ctx.obj, ctx.command.name)
1077 ctx.obj.vnfd.create(filename, overwrite)
1078 except ClientException as inst:
1079 print((inst.message))
1080 exit(1)
1081
1082
1083 @cli.command(name='vnfd-create', short_help='creates a new VNFD/VNFpkg')
1084 @click.argument('filename')
1085 @click.option('--overwrite', default=None,
1086 help='overwrites some fields in VNFD')
1087 @click.pass_context
1088 def vnfd_create1(ctx, filename, overwrite):
1089 """creates a new VNFD/VNFpkg
1090
1091 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1092 """
1093 vnfd_create(ctx, filename, overwrite)
1094
1095
1096 @cli.command(name='vnfpkg-create', short_help='creates a new VNFD/VNFpkg')
1097 @click.argument('filename')
1098 @click.option('--overwrite', default=None,
1099 help='overwrites some fields in VNFD')
1100 @click.pass_context
1101 def vnfd_create2(ctx, filename, overwrite):
1102 """creates a new VNFD/VNFpkg
1103
1104 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1105 """
1106 vnfd_create(ctx, filename, overwrite)
1107
1108
1109 @cli.command(name='nfpkg-create', short_help='creates a new NFpkg')
1110 @click.argument('filename')
1111 @click.option('--overwrite', default=None,
1112 help='overwrites some fields in NFD')
1113 @click.pass_context
1114 def nfpkg_create(ctx, filename, overwrite):
1115 """creates a new NFpkg
1116
1117 FILENAME: NF Descriptor yaml file or NFpkg tar.gz file
1118 """
1119 vnfd_create(ctx, filename, overwrite)
1120
1121
1122 @cli.command(name='ns-create', short_help='creates a new Network Service instance')
1123 @click.option('--ns_name',
1124 prompt=True, help='name of the NS instance')
1125 @click.option('--nsd_name',
1126 prompt=True, help='name of the NS descriptor')
1127 @click.option('--vim_account',
1128 prompt=True, help='default VIM account id or name for the deployment')
1129 @click.option('--admin_status',
1130 default='ENABLED',
1131 help='administration status')
1132 @click.option('--ssh_keys',
1133 default=None,
1134 help='comma separated list of public key files to inject to vnfs')
1135 @click.option('--config',
1136 default=None,
1137 help='ns specific yaml configuration')
1138 @click.option('--config_file',
1139 default=None,
1140 help='ns specific yaml configuration file')
1141 @click.option('--wait',
1142 required=False,
1143 default=False,
1144 is_flag=True,
1145 help='do not return the control immediately, but keep it \
1146 until the operation is completed, or timeout')
1147 @click.pass_context
1148 def ns_create(ctx,
1149 nsd_name,
1150 ns_name,
1151 vim_account,
1152 admin_status,
1153 ssh_keys,
1154 config,
1155 config_file,
1156 wait):
1157 """creates a new NS instance"""
1158 try:
1159 if config_file:
1160 check_client_version(ctx.obj, '--config_file')
1161 if config:
1162 raise ClientException('"--config" option is incompatible with "--config_file" option')
1163 with open(config_file, 'r') as cf:
1164 config=cf.read()
1165 ctx.obj.ns.create(
1166 nsd_name,
1167 ns_name,
1168 config=config,
1169 ssh_keys=ssh_keys,
1170 account=vim_account,
1171 wait=wait)
1172 except ClientException as inst:
1173 print(inst.message)
1174 exit(1)
1175
1176
1177 def nst_create(ctx, filename, overwrite):
1178 try:
1179 check_client_version(ctx.obj, ctx.command.name)
1180 ctx.obj.nst.create(filename, overwrite)
1181 except ClientException as inst:
1182 print((inst.message))
1183 exit(1)
1184
1185
1186 @cli.command(name='nst-create', short_help='creates a new Network Slice Template (NST)')
1187 @click.argument('filename')
1188 @click.option('--overwrite', default=None,
1189 help='overwrites some fields in NST')
1190 @click.pass_context
1191 def nst_create1(ctx, filename, overwrite):
1192 """creates a new Network Slice Template (NST)
1193
1194 FILENAME: NST yaml file or NSTpkg tar.gz file
1195 """
1196 nst_create(ctx, filename, overwrite)
1197
1198
1199 @cli.command(name='netslice-template-create', short_help='creates a new Network Slice Template (NST)')
1200 @click.argument('filename')
1201 @click.option('--overwrite', default=None,
1202 help='overwrites some fields in NST')
1203 @click.pass_context
1204 def nst_create2(ctx, filename, overwrite):
1205 """creates a new Network Slice Template (NST)
1206
1207 FILENAME: NST yaml file or NSTpkg tar.gz file
1208 """
1209 nst_create(ctx, filename, overwrite)
1210
1211
1212 def nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1213 """creates a new Network Slice Instance (NSI)"""
1214 try:
1215 check_client_version(ctx.obj, ctx.command.name)
1216 if config_file:
1217 if config:
1218 raise ClientException('"--config" option is incompatible with "--config_file" option')
1219 with open(config_file, 'r') as cf:
1220 config=cf.read()
1221 ctx.obj.nsi.create(nst_name, nsi_name, config=config, ssh_keys=ssh_keys,
1222 account=vim_account, wait=wait)
1223 except ClientException as inst:
1224 print(inst.message)
1225 exit(1)
1226
1227
1228 @cli.command(name='nsi-create', short_help='creates a new Network Slice Instance')
1229 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1230 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1231 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1232 @click.option('--ssh_keys', default=None,
1233 help='comma separated list of keys to inject to vnfs')
1234 @click.option('--config', default=None,
1235 help='Netslice specific yaml configuration:\n'
1236 'netslice_subnet: [\n'
1237 'id: TEXT, vim_account: TEXT,\n'
1238 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1239 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1240 'additionalParamsForNsi: {param: value, ...}\n'
1241 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1242 '],\n'
1243 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1244 )
1245 @click.option('--config_file',
1246 default=None,
1247 help='nsi specific yaml configuration file')
1248 @click.option('--wait',
1249 required=False,
1250 default=False,
1251 is_flag=True,
1252 help='do not return the control immediately, but keep it \
1253 until the operation is completed, or timeout')
1254 @click.pass_context
1255 def nsi_create1(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1256 """creates a new Network Slice Instance (NSI)"""
1257 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1258
1259
1260 @cli.command(name='netslice-instance-create', short_help='creates a new Network Slice Instance')
1261 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1262 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1263 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1264 @click.option('--ssh_keys', default=None,
1265 help='comma separated list of keys to inject to vnfs')
1266 @click.option('--config', default=None,
1267 help='Netslice specific yaml configuration:\n'
1268 'netslice_subnet: [\n'
1269 'id: TEXT, vim_account: TEXT,\n'
1270 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1271 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1272 '],\n'
1273 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1274 )
1275 @click.option('--config_file',
1276 default=None,
1277 help='nsi specific yaml configuration file')
1278 @click.option('--wait',
1279 required=False,
1280 default=False,
1281 is_flag=True,
1282 help='do not return the control immediately, but keep it \
1283 until the operation is completed, or timeout')
1284 @click.pass_context
1285 def nsi_create2(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1286 """creates a new Network Slice Instance (NSI)"""
1287 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1288
1289
1290 @cli.command(name='pdu-create', short_help='adds a new Physical Deployment Unit to the catalog')
1291 @click.option('--name', help='name of the Physical Deployment Unit')
1292 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1293 @click.option('--interface',
1294 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1295 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1296 multiple=True)
1297 @click.option('--description', help='human readable description')
1298 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple=True)
1299 @click.option('--descriptor_file', default=None, help='PDU descriptor file (as an alternative to using the other arguments')
1300 @click.pass_context
1301 def pdu_create(ctx, name, pdu_type, interface, description, vim_account, descriptor_file):
1302 """creates a new Physical Deployment Unit (PDU)"""
1303 try:
1304 check_client_version(ctx.obj, ctx.command.name)
1305 pdu = {}
1306 if not descriptor_file:
1307 if not name:
1308 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1309 if not pdu_type:
1310 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1311 if not interface:
1312 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1313 if not vim_account:
1314 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1315 else:
1316 with open(descriptor_file, 'r') as df:
1317 pdu = yaml.load(df.read())
1318 if name: pdu["name"] = name
1319 if pdu_type: pdu["type"] = pdu_type
1320 if description: pdu["description"] = description
1321 if vim_account: pdu["vim_accounts"] = vim_account
1322 if interface:
1323 ifaces_list = []
1324 for iface in interface:
1325 new_iface={k:v for k,v in [i.split('=') for i in iface.split(',')]}
1326 new_iface["mgmt"] = (new_iface.get("mgmt","false").lower() == "true")
1327 ifaces_list.append(new_iface)
1328 pdu["interfaces"] = ifaces_list
1329 ctx.obj.pdu.create(pdu)
1330 except ClientException as inst:
1331 print((inst.message))
1332 exit(1)
1333
1334 ####################
1335 # UPDATE operations
1336 ####################
1337
1338 def nsd_update(ctx, name, content):
1339 try:
1340 check_client_version(ctx.obj, ctx.command.name)
1341 ctx.obj.nsd.update(name, content)
1342 except ClientException as inst:
1343 print((inst.message))
1344 exit(1)
1345
1346
1347 @cli.command(name='nsd-update', short_help='updates a NSD/NSpkg')
1348 @click.argument('name')
1349 @click.option('--content', default=None,
1350 help='filename with the NSD/NSpkg replacing the current one')
1351 @click.pass_context
1352 def nsd_update1(ctx, name, content):
1353 """updates a NSD/NSpkg
1354
1355 NAME: name or ID of the NSD/NSpkg
1356 """
1357 nsd_update(ctx, name, content)
1358
1359
1360 @cli.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
1361 @click.argument('name')
1362 @click.option('--content', default=None,
1363 help='filename with the NSD/NSpkg replacing the current one')
1364 @click.pass_context
1365 def nsd_update2(ctx, name, content):
1366 """updates a NSD/NSpkg
1367
1368 NAME: name or ID of the NSD/NSpkg
1369 """
1370 nsd_update(ctx, name, content)
1371
1372
1373 def vnfd_update(ctx, name, content):
1374 try:
1375 check_client_version(ctx.obj, ctx.command.name)
1376 ctx.obj.vnfd.update(name, content)
1377 except ClientException as inst:
1378 print((inst.message))
1379 exit(1)
1380
1381
1382 @cli.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
1383 @click.argument('name')
1384 @click.option('--content', default=None,
1385 help='filename with the VNFD/VNFpkg replacing the current one')
1386 @click.pass_context
1387 def vnfd_update1(ctx, name, content):
1388 """updates a VNFD/VNFpkg
1389
1390 NAME: name or ID of the VNFD/VNFpkg
1391 """
1392 vnfd_update(ctx, name, content)
1393
1394
1395 @cli.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
1396 @click.argument('name')
1397 @click.option('--content', default=None,
1398 help='filename with the VNFD/VNFpkg replacing the current one')
1399 @click.pass_context
1400 def vnfd_update2(ctx, name, content):
1401 """updates a VNFD/VNFpkg
1402
1403 NAME: VNFD yaml file or VNFpkg tar.gz file
1404 """
1405 vnfd_update(ctx, name, content)
1406
1407
1408 @cli.command(name='nfpkg-update', short_help='updates a NFpkg')
1409 @click.argument('name')
1410 @click.option('--content', default=None,
1411 help='filename with the NFpkg replacing the current one')
1412 @click.pass_context
1413 def nfpkg_update(ctx, name, content):
1414 """updates a NFpkg
1415
1416 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1417 """
1418 vnfd_update(ctx, name, content)
1419
1420
1421 def nst_update(ctx, name, content):
1422 try:
1423 check_client_version(ctx.obj, ctx.command.name)
1424 ctx.obj.nst.update(name, content)
1425 except ClientException as inst:
1426 print((inst.message))
1427 exit(1)
1428
1429
1430 @cli.command(name='nst-update', short_help='updates a Network Slice Template (NST)')
1431 @click.argument('name')
1432 @click.option('--content', default=None,
1433 help='filename with the NST/NSTpkg replacing the current one')
1434 @click.pass_context
1435 def nst_update1(ctx, name, content):
1436 """updates a Network Slice Template (NST)
1437
1438 NAME: name or ID of the NSD/NSpkg
1439 """
1440 nst_update(ctx, name, content)
1441
1442
1443 @cli.command(name='netslice-template-update', short_help='updates a Network Slice Template (NST)')
1444 @click.argument('name')
1445 @click.option('--content', default=None,
1446 help='filename with the NST/NSTpkg replacing the current one')
1447 @click.pass_context
1448 def nst_update2(ctx, name, content):
1449 """updates a Network Slice Template (NST)
1450
1451 NAME: name or ID of the NSD/NSpkg
1452 """
1453 nst_update(ctx, name, content)
1454
1455
1456 ####################
1457 # DELETE operations
1458 ####################
1459
1460 def nsd_delete(ctx, name, force):
1461 try:
1462 if not force:
1463 ctx.obj.nsd.delete(name)
1464 else:
1465 check_client_version(ctx.obj, '--force')
1466 ctx.obj.nsd.delete(name, force)
1467 except ClientException as inst:
1468 print((inst.message))
1469 exit(1)
1470
1471
1472 @cli.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
1473 @click.argument('name')
1474 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1475 @click.pass_context
1476 def nsd_delete1(ctx, name, force):
1477 """deletes a NSD/NSpkg
1478
1479 NAME: name or ID of the NSD/NSpkg to be deleted
1480 """
1481 nsd_delete(ctx, name, force)
1482
1483
1484 @cli.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
1485 @click.argument('name')
1486 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1487 @click.pass_context
1488 def nsd_delete2(ctx, name, force):
1489 """deletes a NSD/NSpkg
1490
1491 NAME: name or ID of the NSD/NSpkg to be deleted
1492 """
1493 nsd_delete(ctx, name, force)
1494
1495
1496 def vnfd_delete(ctx, name, force):
1497 try:
1498 if not force:
1499 ctx.obj.vnfd.delete(name)
1500 else:
1501 check_client_version(ctx.obj, '--force')
1502 ctx.obj.vnfd.delete(name, force)
1503 except ClientException as inst:
1504 print((inst.message))
1505 exit(1)
1506
1507
1508 @cli.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
1509 @click.argument('name')
1510 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1511 @click.pass_context
1512 def vnfd_delete1(ctx, name, force):
1513 """deletes a VNFD/VNFpkg
1514
1515 NAME: name or ID of the VNFD/VNFpkg to be deleted
1516 """
1517 vnfd_delete(ctx, name, force)
1518
1519
1520 @cli.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
1521 @click.argument('name')
1522 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1523 @click.pass_context
1524 def vnfd_delete2(ctx, name, force):
1525 """deletes a VNFD/VNFpkg
1526
1527 NAME: name or ID of the VNFD/VNFpkg to be deleted
1528 """
1529 vnfd_delete(ctx, name, force)
1530
1531
1532 @cli.command(name='nfpkg-delete', short_help='deletes a NFpkg')
1533 @click.argument('name')
1534 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1535 @click.pass_context
1536 def nfpkg_delete(ctx, name, force):
1537 """deletes a NFpkg
1538
1539 NAME: name or ID of the NFpkg to be deleted
1540 """
1541 vnfd_delete(ctx, name, force)
1542
1543
1544 @cli.command(name='ns-delete', short_help='deletes a NS instance')
1545 @click.argument('name')
1546 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1547 @click.option('--wait',
1548 required=False,
1549 default=False,
1550 is_flag=True,
1551 help='do not return the control immediately, but keep it \
1552 until the operation is completed, or timeout')
1553 @click.pass_context
1554 def ns_delete(ctx, name, force, wait):
1555 """deletes a NS instance
1556
1557 NAME: name or ID of the NS instance to be deleted
1558 """
1559 try:
1560 if not force:
1561 ctx.obj.ns.delete(name, wait=wait)
1562 else:
1563 check_client_version(ctx.obj, '--force')
1564 ctx.obj.ns.delete(name, force, wait=wait)
1565 except ClientException as inst:
1566 print((inst.message))
1567 exit(1)
1568
1569
1570 def nst_delete(ctx, name, force):
1571 try:
1572 check_client_version(ctx.obj, ctx.command.name)
1573 ctx.obj.nst.delete(name, force)
1574 except ClientException as inst:
1575 print((inst.message))
1576 exit(1)
1577
1578
1579 @cli.command(name='nst-delete', short_help='deletes a Network Slice Template (NST)')
1580 @click.argument('name')
1581 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1582 @click.pass_context
1583 def nst_delete1(ctx, name, force):
1584 """deletes a Network Slice Template (NST)
1585
1586 NAME: name or ID of the NST/NSTpkg to be deleted
1587 """
1588 nst_delete(ctx, name, force)
1589
1590
1591 @cli.command(name='netslice-template-delete', short_help='deletes a Network Slice Template (NST)')
1592 @click.argument('name')
1593 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1594 @click.pass_context
1595 def nst_delete2(ctx, name, force):
1596 """deletes a Network Slice Template (NST)
1597
1598 NAME: name or ID of the NST/NSTpkg to be deleted
1599 """
1600 nst_delete(ctx, name, force)
1601
1602
1603 def nsi_delete(ctx, name, force, wait):
1604 try:
1605 check_client_version(ctx.obj, ctx.command.name)
1606 ctx.obj.nsi.delete(name, force, wait=wait)
1607 except ClientException as inst:
1608 print((inst.message))
1609 exit(1)
1610
1611
1612 @cli.command(name='nsi-delete', short_help='deletes a Network Slice Instance (NSI)')
1613 @click.argument('name')
1614 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1615 @click.option('--wait',
1616 required=False,
1617 default=False,
1618 is_flag=True,
1619 help='do not return the control immediately, but keep it \
1620 until the operation is completed, or timeout')
1621 @click.pass_context
1622 def nsi_delete1(ctx, name, force, wait):
1623 """deletes a Network Slice Instance (NSI)
1624
1625 NAME: name or ID of the Network Slice instance to be deleted
1626 """
1627 nsi_delete(ctx, name, force, wait=wait)
1628
1629
1630 @cli.command(name='netslice-instance-delete', short_help='deletes a Network Slice Instance (NSI)')
1631 @click.argument('name')
1632 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1633 @click.pass_context
1634 def nsi_delete2(ctx, name, force, wait):
1635 """deletes a Network Slice Instance (NSI)
1636
1637 NAME: name or ID of the Network Slice instance to be deleted
1638 """
1639 nsi_delete(ctx, name, force, wait=wait)
1640
1641
1642 @cli.command(name='pdu-delete', short_help='deletes a Physical Deployment Unit (PDU)')
1643 @click.argument('name')
1644 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1645 @click.pass_context
1646 def pdu_delete(ctx, name, force):
1647 """deletes a Physical Deployment Unit (PDU)
1648
1649 NAME: name or ID of the PDU to be deleted
1650 """
1651 try:
1652 check_client_version(ctx.obj, ctx.command.name)
1653 ctx.obj.pdu.delete(name, force)
1654 except ClientException as inst:
1655 print((inst.message))
1656 exit(1)
1657
1658
1659 #################
1660 # VIM operations
1661 #################
1662
1663 @cli.command(name='vim-create')
1664 @click.option('--name',
1665 prompt=True,
1666 help='Name to create datacenter')
1667 @click.option('--user',
1668 prompt=True,
1669 help='VIM username')
1670 @click.option('--password',
1671 prompt=True,
1672 hide_input=True,
1673 confirmation_prompt=True,
1674 help='VIM password')
1675 @click.option('--auth_url',
1676 prompt=True,
1677 help='VIM url')
1678 @click.option('--tenant',
1679 prompt=True,
1680 help='VIM tenant name')
1681 @click.option('--config',
1682 default=None,
1683 help='VIM specific config parameters')
1684 @click.option('--account_type',
1685 default='openstack',
1686 help='VIM type')
1687 @click.option('--description',
1688 default='no description',
1689 help='human readable description')
1690 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1691 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1692 @click.option('--wait',
1693 required=False,
1694 default=False,
1695 is_flag=True,
1696 help='do not return the control immediately, but keep it \
1697 until the operation is completed, or timeout')
1698 @click.pass_context
1699 def vim_create(ctx,
1700 name,
1701 user,
1702 password,
1703 auth_url,
1704 tenant,
1705 config,
1706 account_type,
1707 description,
1708 sdn_controller,
1709 sdn_port_mapping,
1710 wait):
1711 """creates a new VIM account"""
1712 try:
1713 if sdn_controller:
1714 check_client_version(ctx.obj, '--sdn_controller')
1715 if sdn_port_mapping:
1716 check_client_version(ctx.obj, '--sdn_port_mapping')
1717 vim = {}
1718 vim['vim-username'] = user
1719 vim['vim-password'] = password
1720 vim['vim-url'] = auth_url
1721 vim['vim-tenant-name'] = tenant
1722 vim['vim-type'] = account_type
1723 vim['description'] = description
1724 vim['config'] = config
1725 if sdn_controller or sdn_port_mapping:
1726 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1727 else:
1728 ctx.obj.vim.create(name, vim, wait=wait)
1729 except ClientException as inst:
1730 print((inst.message))
1731 exit(1)
1732
1733
1734 @cli.command(name='vim-update', short_help='updates a VIM account')
1735 @click.argument('name')
1736 @click.option('--newname', help='New name for the VIM account')
1737 @click.option('--user', help='VIM username')
1738 @click.option('--password', help='VIM password')
1739 @click.option('--auth_url', help='VIM url')
1740 @click.option('--tenant', help='VIM tenant name')
1741 @click.option('--config', help='VIM specific config parameters')
1742 @click.option('--account_type', help='VIM type')
1743 @click.option('--description', help='human readable description')
1744 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1745 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1746 @click.option('--wait',
1747 required=False,
1748 default=False,
1749 is_flag=True,
1750 help='do not return the control immediately, but keep it \
1751 until the operation is completed, or timeout')
1752 @click.pass_context
1753 def vim_update(ctx,
1754 name,
1755 newname,
1756 user,
1757 password,
1758 auth_url,
1759 tenant,
1760 config,
1761 account_type,
1762 description,
1763 sdn_controller,
1764 sdn_port_mapping,
1765 wait):
1766 """updates a VIM account
1767
1768 NAME: name or ID of the VIM account
1769 """
1770 try:
1771 check_client_version(ctx.obj, ctx.command.name)
1772 vim = {}
1773 if newname: vim['name'] = newname
1774 if user: vim['vim_user'] = user
1775 if password: vim['vim_password'] = password
1776 if auth_url: vim['vim_url'] = auth_url
1777 if tenant: vim['vim-tenant-name'] = tenant
1778 if account_type: vim['vim_type'] = account_type
1779 if description: vim['description'] = description
1780 if config: vim['config'] = config
1781 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1782 except ClientException as inst:
1783 print((inst.message))
1784 exit(1)
1785
1786
1787 @cli.command(name='vim-delete')
1788 @click.argument('name')
1789 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1790 @click.option('--wait',
1791 required=False,
1792 default=False,
1793 is_flag=True,
1794 help='do not return the control immediately, but keep it \
1795 until the operation is completed, or timeout')
1796 @click.pass_context
1797 def vim_delete(ctx, name, force, wait):
1798 """deletes a VIM account
1799
1800 NAME: name or ID of the VIM account to be deleted
1801 """
1802 try:
1803 if not force:
1804 ctx.obj.vim.delete(name, wait=wait)
1805 else:
1806 check_client_version(ctx.obj, '--force')
1807 ctx.obj.vim.delete(name, force, wait=wait)
1808 except ClientException as inst:
1809 print((inst.message))
1810 exit(1)
1811
1812
1813 @cli.command(name='vim-list')
1814 #@click.option('--ro_update/--no_ro_update',
1815 # default=False,
1816 # help='update list from RO')
1817 @click.option('--filter', default=None,
1818 help='restricts the list to the VIM accounts matching the filter')
1819 @click.pass_context
1820 def vim_list(ctx, filter):
1821 """list all VIM accounts"""
1822 if filter:
1823 check_client_version(ctx.obj, '--filter')
1824 # if ro_update:
1825 # check_client_version(ctx.obj, '--ro_update', 'v1')
1826 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1827 if fullclassname == 'osmclient.sol005.client.Client':
1828 resp = ctx.obj.vim.list(filter)
1829 # else:
1830 # resp = ctx.obj.vim.list(ro_update)
1831 table = PrettyTable(['vim name', 'uuid'])
1832 for vim in resp:
1833 table.add_row([vim['name'], vim['uuid']])
1834 table.align = 'l'
1835 print(table)
1836
1837
1838 @cli.command(name='vim-show')
1839 @click.argument('name')
1840 @click.pass_context
1841 def vim_show(ctx, name):
1842 """shows the details of a VIM account
1843
1844 NAME: name or ID of the VIM account
1845 """
1846 try:
1847 resp = ctx.obj.vim.get(name)
1848 if 'vim_password' in resp:
1849 resp['vim_password']='********'
1850 except ClientException as inst:
1851 print((inst.message))
1852 exit(1)
1853
1854 table = PrettyTable(['key', 'attribute'])
1855 for k, v in list(resp.items()):
1856 table.add_row([k, json.dumps(v, indent=2)])
1857 table.align = 'l'
1858 print(table)
1859
1860
1861 ####################
1862 # WIM operations
1863 ####################
1864
1865 @cli.command(name='wim-create')
1866 @click.option('--name',
1867 prompt=True,
1868 help='Name for the WIM account')
1869 @click.option('--user',
1870 help='WIM username')
1871 @click.option('--password',
1872 help='WIM password')
1873 @click.option('--url',
1874 prompt=True,
1875 help='WIM url')
1876 # @click.option('--tenant',
1877 # help='wIM tenant name')
1878 @click.option('--config',
1879 default=None,
1880 help='WIM specific config parameters')
1881 @click.option('--wim_type',
1882 help='WIM type')
1883 @click.option('--description',
1884 default='no description',
1885 help='human readable description')
1886 @click.option('--wim_port_mapping', default=None, help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge (WAN service endpoint id and info)")
1887 @click.option('--wait',
1888 required=False,
1889 default=False,
1890 is_flag=True,
1891 help='do not return the control immediately, but keep it \
1892 until the operation is completed, or timeout')
1893 @click.pass_context
1894 def wim_create(ctx,
1895 name,
1896 user,
1897 password,
1898 url,
1899 # tenant,
1900 config,
1901 wim_type,
1902 description,
1903 wim_port_mapping,
1904 wait):
1905 """creates a new WIM account"""
1906 try:
1907 check_client_version(ctx.obj, ctx.command.name)
1908 # if sdn_controller:
1909 # check_client_version(ctx.obj, '--sdn_controller')
1910 # if sdn_port_mapping:
1911 # check_client_version(ctx.obj, '--sdn_port_mapping')
1912 wim = {}
1913 if user: wim['user'] = user
1914 if password: wim['password'] = password
1915 if url: wim['wim_url'] = url
1916 # if tenant: wim['tenant'] = tenant
1917 wim['wim_type'] = wim_type
1918 if description: wim['description'] = description
1919 if config: wim['config'] = config
1920 ctx.obj.wim.create(name, wim, wim_port_mapping, wait=wait)
1921 except ClientException as inst:
1922 print((inst.message))
1923 exit(1)
1924
1925
1926 @cli.command(name='wim-update', short_help='updates a WIM account')
1927 @click.argument('name')
1928 @click.option('--newname', help='New name for the WIM account')
1929 @click.option('--user', help='WIM username')
1930 @click.option('--password', help='WIM password')
1931 @click.option('--url', help='WIM url')
1932 @click.option('--config', help='WIM specific config parameters')
1933 @click.option('--wim_type', help='WIM type')
1934 @click.option('--description', help='human readable description')
1935 @click.option('--wim_port_mapping', default=None, help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge (WAN service endpoint id and info)")
1936 @click.option('--wait',
1937 required=False,
1938 default=False,
1939 is_flag=True,
1940 help='do not return the control immediately, but keep it \
1941 until the operation is completed, or timeout')
1942 @click.pass_context
1943 def wim_update(ctx,
1944 name,
1945 newname,
1946 user,
1947 password,
1948 url,
1949 config,
1950 wim_type,
1951 description,
1952 wim_port_mapping,
1953 wait):
1954 """updates a WIM account
1955
1956 NAME: name or ID of the WIM account
1957 """
1958 try:
1959 check_client_version(ctx.obj, ctx.command.name)
1960 wim = {}
1961 if newname: wim['name'] = newname
1962 if user: wim['user'] = user
1963 if password: wim['password'] = password
1964 if url: wim['url'] = url
1965 # if tenant: wim['tenant'] = tenant
1966 if wim_type: wim['wim_type'] = wim_type
1967 if description: wim['description'] = description
1968 if config: wim['config'] = config
1969 ctx.obj.wim.update(name, wim, wim_port_mapping, wait=wait)
1970 except ClientException as inst:
1971 print((inst.message))
1972 exit(1)
1973
1974
1975 @cli.command(name='wim-delete')
1976 @click.argument('name')
1977 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1978 @click.option('--wait',
1979 required=False,
1980 default=False,
1981 is_flag=True,
1982 help='do not return the control immediately, but keep it \
1983 until the operation is completed, or timeout')
1984 @click.pass_context
1985 def wim_delete(ctx, name, force, wait):
1986 """deletes a WIM account
1987
1988 NAME: name or ID of the WIM account to be deleted
1989 """
1990 try:
1991 check_client_version(ctx.obj, ctx.command.name)
1992 ctx.obj.wim.delete(name, force, wait=wait)
1993 except ClientException as inst:
1994 print((inst.message))
1995 exit(1)
1996
1997
1998 @cli.command(name='wim-list')
1999 @click.option('--filter', default=None,
2000 help='restricts the list to the WIM accounts matching the filter')
2001 @click.pass_context
2002 def wim_list(ctx, filter):
2003 """list all WIM accounts"""
2004 try:
2005 check_client_version(ctx.obj, ctx.command.name)
2006 resp = ctx.obj.wim.list(filter)
2007 table = PrettyTable(['wim name', 'uuid'])
2008 for wim in resp:
2009 table.add_row([wim['name'], wim['uuid']])
2010 table.align = 'l'
2011 print(table)
2012 except ClientException as inst:
2013 print((inst.message))
2014 exit(1)
2015
2016
2017 @cli.command(name='wim-show')
2018 @click.argument('name')
2019 @click.pass_context
2020 def wim_show(ctx, name):
2021 """shows the details of a WIM account
2022
2023 NAME: name or ID of the WIM account
2024 """
2025 try:
2026 check_client_version(ctx.obj, ctx.command.name)
2027 resp = ctx.obj.wim.get(name)
2028 if 'password' in resp:
2029 resp['wim_password']='********'
2030 except ClientException as inst:
2031 print((inst.message))
2032 exit(1)
2033
2034 table = PrettyTable(['key', 'attribute'])
2035 for k, v in list(resp.items()):
2036 table.add_row([k, json.dumps(v, indent=2)])
2037 table.align = 'l'
2038 print(table)
2039
2040
2041 ####################
2042 # SDN controller operations
2043 ####################
2044
2045 @cli.command(name='sdnc-create')
2046 @click.option('--name',
2047 prompt=True,
2048 help='Name to create sdn controller')
2049 @click.option('--type',
2050 prompt=True,
2051 help='SDN controller type')
2052 @click.option('--sdn_controller_version',
2053 help='SDN controller version')
2054 @click.option('--ip_address',
2055 prompt=True,
2056 help='SDN controller IP address')
2057 @click.option('--port',
2058 prompt=True,
2059 help='SDN controller port')
2060 @click.option('--switch_dpid',
2061 prompt=True,
2062 help='Switch DPID (Openflow Datapath ID)')
2063 @click.option('--user',
2064 help='SDN controller username')
2065 @click.option('--password',
2066 hide_input=True,
2067 confirmation_prompt=True,
2068 help='SDN controller password')
2069 #@click.option('--description',
2070 # default='no description',
2071 # help='human readable description')
2072 @click.option('--wait',
2073 required=False,
2074 default=False,
2075 is_flag=True,
2076 help='do not return the control immediately, but keep it \
2077 until the operation is completed, or timeout')
2078 @click.pass_context
2079 def sdnc_create(ctx,
2080 name,
2081 type,
2082 sdn_controller_version,
2083 ip_address,
2084 port,
2085 switch_dpid,
2086 user,
2087 password,
2088 wait):
2089 """creates a new SDN controller"""
2090 sdncontroller = {}
2091 sdncontroller['name'] = name
2092 sdncontroller['type'] = type
2093 sdncontroller['ip'] = ip_address
2094 sdncontroller['port'] = int(port)
2095 sdncontroller['dpid'] = switch_dpid
2096 if sdn_controller_version:
2097 sdncontroller['version'] = sdn_controller_version
2098 if user:
2099 sdncontroller['user'] = user
2100 if password:
2101 sdncontroller['password'] = password
2102 # sdncontroller['description'] = description
2103 try:
2104 check_client_version(ctx.obj, ctx.command.name)
2105 ctx.obj.sdnc.create(name, sdncontroller, wait=wait)
2106 except ClientException as inst:
2107 print((inst.message))
2108 exit(1)
2109
2110 @cli.command(name='sdnc-update', short_help='updates an SDN controller')
2111 @click.argument('name')
2112 @click.option('--newname', help='New name for the SDN controller')
2113 @click.option('--type', help='SDN controller type')
2114 @click.option('--sdn_controller_version', help='SDN controller username')
2115 @click.option('--ip_address', help='SDN controller IP address')
2116 @click.option('--port', help='SDN controller port')
2117 @click.option('--switch_dpid', help='Switch DPID (Openflow Datapath ID)')
2118 @click.option('--user', help='SDN controller username')
2119 @click.option('--password', help='SDN controller password')
2120 #@click.option('--description', default=None, help='human readable description')
2121 @click.option('--wait',
2122 required=False,
2123 default=False,
2124 is_flag=True,
2125 help='do not return the control immediately, but keep it \
2126 until the operation is completed, or timeout')
2127 @click.pass_context
2128 def sdnc_update(ctx,
2129 name,
2130 newname,
2131 type,
2132 sdn_controller_version,
2133 ip_address,
2134 port,
2135 switch_dpid,
2136 user,
2137 password,
2138 wait):
2139 """updates an SDN controller
2140
2141 NAME: name or ID of the SDN controller
2142 """
2143 sdncontroller = {}
2144 if newname: sdncontroller['name'] = newname
2145 if type: sdncontroller['type'] = type
2146 if ip_address: sdncontroller['ip'] = ip_address
2147 if port: sdncontroller['port'] = int(port)
2148 if switch_dpid: sdncontroller['dpid'] = switch_dpid
2149 # sdncontroller['description'] = description
2150 if sdn_controller_version is not None:
2151 if sdn_controller_version=="":
2152 sdncontroller['version'] = None
2153 else:
2154 sdncontroller['version'] = sdn_controller_version
2155 if user is not None:
2156 if user=="":
2157 sdncontroller['user'] = None
2158 else:
2159 sdncontroller['user'] = user
2160 if password is not None:
2161 if password=="":
2162 sdncontroller['password'] = None
2163 else:
2164 sdncontroller['password'] = user
2165 try:
2166 check_client_version(ctx.obj, ctx.command.name)
2167 ctx.obj.sdnc.update(name, sdncontroller, wait=wait)
2168 except ClientException as inst:
2169 print((inst.message))
2170 exit(1)
2171
2172
2173 @cli.command(name='sdnc-delete')
2174 @click.argument('name')
2175 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2176 @click.option('--wait',
2177 required=False,
2178 default=False,
2179 is_flag=True,
2180 help='do not return the control immediately, but keep it \
2181 until the operation is completed, or timeout')
2182 @click.pass_context
2183 def sdnc_delete(ctx, name, force, wait):
2184 """deletes an SDN controller
2185
2186 NAME: name or ID of the SDN controller to be deleted
2187 """
2188 try:
2189 check_client_version(ctx.obj, ctx.command.name)
2190 ctx.obj.sdnc.delete(name, force, wait=wait)
2191 except ClientException as inst:
2192 print((inst.message))
2193 exit(1)
2194
2195
2196 @cli.command(name='sdnc-list')
2197 @click.option('--filter', default=None,
2198 help='restricts the list to the SDN controllers matching the filter')
2199 @click.pass_context
2200 def sdnc_list(ctx, filter):
2201 """list all SDN controllers"""
2202 try:
2203 check_client_version(ctx.obj, ctx.command.name)
2204 resp = ctx.obj.sdnc.list(filter)
2205 except ClientException as inst:
2206 print((inst.message))
2207 exit(1)
2208 table = PrettyTable(['sdnc name', 'id'])
2209 for sdnc in resp:
2210 table.add_row([sdnc['name'], sdnc['_id']])
2211 table.align = 'l'
2212 print(table)
2213
2214
2215 @cli.command(name='sdnc-show')
2216 @click.argument('name')
2217 @click.pass_context
2218 def sdnc_show(ctx, name):
2219 """shows the details of an SDN controller
2220
2221 NAME: name or ID of the SDN controller
2222 """
2223 try:
2224 check_client_version(ctx.obj, ctx.command.name)
2225 resp = ctx.obj.sdnc.get(name)
2226 except ClientException as inst:
2227 print((inst.message))
2228 exit(1)
2229
2230 table = PrettyTable(['key', 'attribute'])
2231 for k, v in list(resp.items()):
2232 table.add_row([k, json.dumps(v, indent=2)])
2233 table.align = 'l'
2234 print(table)
2235
2236
2237 ####################
2238 # Project mgmt operations
2239 ####################
2240
2241 @cli.command(name='project-create')
2242 @click.argument('name')
2243 #@click.option('--description',
2244 # default='no description',
2245 # help='human readable description')
2246 @click.pass_context
2247 def project_create(ctx, name):
2248 """Creates a new project
2249
2250 NAME: name of the project
2251 """
2252 project = {}
2253 project['name'] = name
2254 try:
2255 check_client_version(ctx.obj, ctx.command.name)
2256 ctx.obj.project.create(name, project)
2257 except ClientException as inst:
2258 print(inst.message)
2259 exit(1)
2260
2261
2262 @cli.command(name='project-delete')
2263 @click.argument('name')
2264 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2265 @click.pass_context
2266 def project_delete(ctx, name):
2267 """deletes a project
2268
2269 NAME: name or ID of the project to be deleted
2270 """
2271 try:
2272 check_client_version(ctx.obj, ctx.command.name)
2273 ctx.obj.project.delete(name)
2274 except ClientException as inst:
2275 print(inst.message)
2276 exit(1)
2277
2278
2279 @cli.command(name='project-list')
2280 @click.option('--filter', default=None,
2281 help='restricts the list to the projects matching the filter')
2282 @click.pass_context
2283 def project_list(ctx, filter):
2284 """list all projects"""
2285 try:
2286 check_client_version(ctx.obj, ctx.command.name)
2287 resp = ctx.obj.project.list(filter)
2288 except ClientException as inst:
2289 print(inst.message)
2290 exit(1)
2291 table = PrettyTable(['name', 'id'])
2292 for proj in resp:
2293 table.add_row([proj['name'], proj['_id']])
2294 table.align = 'l'
2295 print(table)
2296
2297
2298 @cli.command(name='project-show')
2299 @click.argument('name')
2300 @click.pass_context
2301 def project_show(ctx, name):
2302 """shows the details of a project
2303
2304 NAME: name or ID of the project
2305 """
2306 try:
2307 check_client_version(ctx.obj, ctx.command.name)
2308 resp = ctx.obj.project.get(name)
2309 except ClientException as inst:
2310 print(inst.message)
2311 exit(1)
2312
2313 table = PrettyTable(['key', 'attribute'])
2314 for k, v in resp.items():
2315 table.add_row([k, json.dumps(v, indent=2)])
2316 table.align = 'l'
2317 print(table)
2318
2319
2320 @cli.command(name='project-update')
2321 @click.argument('project')
2322 @click.option('--name',
2323 prompt=True,
2324 help='new name for the project')
2325
2326 @click.pass_context
2327 def project_update(ctx, project, name):
2328 """
2329 Update a project name
2330
2331 :param ctx:
2332 :param project: id or name of the project to modify
2333 :param name: new name for the project
2334 :return:
2335 """
2336
2337 project_changes = {}
2338 project_changes['name'] = name
2339
2340 try:
2341 check_client_version(ctx.obj, ctx.command.name)
2342 ctx.obj.project.update(project, project_changes)
2343 except ClientException as inst:
2344 print(inst.message)
2345
2346
2347 ####################
2348 # User mgmt operations
2349 ####################
2350
2351 @cli.command(name='user-create')
2352 @click.argument('username')
2353 @click.option('--password',
2354 prompt=True,
2355 hide_input=True,
2356 confirmation_prompt=True,
2357 help='user password')
2358 @click.option('--projects',
2359 # prompt="Comma separate list of projects",
2360 multiple=True,
2361 callback=lambda ctx, param, value: ''.join(value).split(',') if all(len(x)==1 for x in value) else value,
2362 help='list of project ids that the user belongs to')
2363 @click.option('--project-role-mappings', 'project_role_mappings',
2364 default=None, multiple=True,
2365 help='creating user project/role(s) mapping')
2366 @click.pass_context
2367 def user_create(ctx, username, password, projects, project_role_mappings):
2368 """Creates a new user
2369
2370 \b
2371 USERNAME: name of the user
2372 PASSWORD: password of the user
2373 PROJECTS: projects assigned to user (internal only)
2374 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
2375 """
2376 user = {}
2377 user['username'] = username
2378 user['password'] = password
2379 user['projects'] = projects
2380 user['project_role_mappings'] = project_role_mappings
2381
2382 try:
2383 check_client_version(ctx.obj, ctx.command.name)
2384 ctx.obj.user.create(username, user)
2385 except ClientException as inst:
2386 print(inst.message)
2387 exit(1)
2388
2389
2390 @cli.command(name='user-update')
2391 @click.argument('username')
2392 @click.option('--password',
2393 # prompt=True,
2394 # hide_input=True,
2395 # confirmation_prompt=True,
2396 help='user password')
2397 @click.option('--set-username', 'set_username',
2398 default=None,
2399 help='change username')
2400 @click.option('--set-project', 'set_project',
2401 default=None, multiple=True,
2402 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
2403 @click.option('--remove-project', 'remove_project',
2404 default=None, multiple=True,
2405 help='removes project from user: \'project\'')
2406 @click.option('--add-project-role', 'add_project_role',
2407 default=None, multiple=True,
2408 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
2409 @click.option('--remove-project-role', 'remove_project_role',
2410 default=None, multiple=True,
2411 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
2412 @click.pass_context
2413 def user_update(ctx, username, password, set_username, set_project, remove_project,
2414 add_project_role, remove_project_role):
2415 """Update a user information
2416
2417 \b
2418 USERNAME: name of the user
2419 PASSWORD: new password
2420 SET_USERNAME: new username
2421 SET_PROJECT: creating mappings for project/role(s)
2422 REMOVE_PROJECT: deleting mappings for project/role(s)
2423 ADD_PROJECT_ROLE: adding mappings for project/role(s)
2424 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
2425 """
2426 user = {}
2427 user['password'] = password
2428 user['username'] = set_username
2429 user['set-project'] = set_project
2430 user['remove-project'] = remove_project
2431 user['add-project-role'] = add_project_role
2432 user['remove-project-role'] = remove_project_role
2433
2434 try:
2435 check_client_version(ctx.obj, ctx.command.name)
2436 ctx.obj.user.update(username, user)
2437 except ClientException as inst:
2438 print(inst.message)
2439 exit(1)
2440
2441
2442 @cli.command(name='user-delete')
2443 @click.argument('name')
2444 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2445 @click.pass_context
2446 def user_delete(ctx, name):
2447 """deletes a user
2448
2449 \b
2450 NAME: name or ID of the user to be deleted
2451 """
2452 try:
2453 check_client_version(ctx.obj, ctx.command.name)
2454 ctx.obj.user.delete(name)
2455 except ClientException as inst:
2456 print(inst.message)
2457 exit(1)
2458
2459
2460 @cli.command(name='user-list')
2461 @click.option('--filter', default=None,
2462 help='restricts the list to the users matching the filter')
2463 @click.pass_context
2464 def user_list(ctx, filter):
2465 """list all users"""
2466 try:
2467 check_client_version(ctx.obj, ctx.command.name)
2468 resp = ctx.obj.user.list(filter)
2469 except ClientException as inst:
2470 print(inst.message)
2471 exit(1)
2472 table = PrettyTable(['name', 'id'])
2473 for user in resp:
2474 table.add_row([user['username'], user['_id']])
2475 table.align = 'l'
2476 print(table)
2477
2478
2479 @cli.command(name='user-show')
2480 @click.argument('name')
2481 @click.pass_context
2482 def user_show(ctx, name):
2483 """shows the details of a user
2484
2485 NAME: name or ID of the user
2486 """
2487 try:
2488 check_client_version(ctx.obj, ctx.command.name)
2489 resp = ctx.obj.user.get(name)
2490 if 'password' in resp:
2491 resp['password']='********'
2492 except ClientException as inst:
2493 print(inst.message)
2494 exit(1)
2495
2496 table = PrettyTable(['key', 'attribute'])
2497 for k, v in resp.items():
2498 table.add_row([k, json.dumps(v, indent=2)])
2499 table.align = 'l'
2500 print(table)
2501
2502
2503 ####################
2504 # Fault Management operations
2505 ####################
2506
2507 @cli.command(name='ns-alarm-create')
2508 @click.argument('name')
2509 @click.option('--ns', prompt=True, help='NS instance id or name')
2510 @click.option('--vnf', prompt=True,
2511 help='VNF name (VNF member index as declared in the NSD)')
2512 @click.option('--vdu', prompt=True,
2513 help='VDU name (VDU name as declared in the VNFD)')
2514 @click.option('--metric', prompt=True,
2515 help='Name of the metric (e.g. cpu_utilization)')
2516 @click.option('--severity', default='WARNING',
2517 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
2518 @click.option('--threshold_value', prompt=True,
2519 help='threshold value that, when crossed, an alarm is triggered')
2520 @click.option('--threshold_operator', prompt=True,
2521 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
2522 @click.option('--statistic', default='AVERAGE',
2523 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
2524 @click.pass_context
2525 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
2526 threshold_value, threshold_operator, statistic):
2527 """creates a new alarm for a NS instance"""
2528 # TODO: Check how to validate threshold_value.
2529 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
2530 try:
2531 ns_instance = ctx.obj.ns.get(ns)
2532 alarm = {}
2533 alarm['alarm_name'] = name
2534 alarm['ns_id'] = ns_instance['_id']
2535 alarm['correlation_id'] = ns_instance['_id']
2536 alarm['vnf_member_index'] = vnf
2537 alarm['vdu_name'] = vdu
2538 alarm['metric_name'] = metric
2539 alarm['severity'] = severity
2540 alarm['threshold_value'] = int(threshold_value)
2541 alarm['operation'] = threshold_operator
2542 alarm['statistic'] = statistic
2543 check_client_version(ctx.obj, ctx.command.name)
2544 ctx.obj.ns.create_alarm(alarm)
2545 except ClientException as inst:
2546 print((inst.message))
2547 exit(1)
2548
2549
2550 #@cli.command(name='ns-alarm-delete')
2551 #@click.argument('name')
2552 #@click.pass_context
2553 #def ns_alarm_delete(ctx, name):
2554 # """deletes an alarm
2555 #
2556 # NAME: name of the alarm to be deleted
2557 # """
2558 # try:
2559 # check_client_version(ctx.obj, ctx.command.name)
2560 # ctx.obj.ns.delete_alarm(name)
2561 # except ClientException as inst:
2562 # print(inst.message)
2563 # exit(1)
2564
2565
2566 ####################
2567 # Performance Management operations
2568 ####################
2569
2570 @cli.command(name='ns-metric-export')
2571 @click.option('--ns', prompt=True, help='NS instance id or name')
2572 @click.option('--vnf', prompt=True,
2573 help='VNF name (VNF member index as declared in the NSD)')
2574 @click.option('--vdu', prompt=True,
2575 help='VDU name (VDU name as declared in the VNFD)')
2576 @click.option('--metric', prompt=True,
2577 help='name of the metric (e.g. cpu_utilization)')
2578 #@click.option('--period', default='1w',
2579 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
2580 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
2581 @click.pass_context
2582 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
2583 """exports a metric to the internal OSM bus, which can be read by other apps"""
2584 # TODO: Check how to validate interval.
2585 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
2586 try:
2587 ns_instance = ctx.obj.ns.get(ns)
2588 metric_data = {}
2589 metric_data['ns_id'] = ns_instance['_id']
2590 metric_data['correlation_id'] = ns_instance['_id']
2591 metric_data['vnf_member_index'] = vnf
2592 metric_data['vdu_name'] = vdu
2593 metric_data['metric_name'] = metric
2594 metric_data['collection_unit'] = 'WEEK'
2595 metric_data['collection_period'] = 1
2596 check_client_version(ctx.obj, ctx.command.name)
2597 if not interval:
2598 print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
2599 else:
2600 i = 1
2601 while True:
2602 print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
2603 time.sleep(int(interval))
2604 i+=1
2605 except ClientException as inst:
2606 print((inst.message))
2607 exit(1)
2608
2609
2610 ####################
2611 # Other operations
2612 ####################
2613
2614 @cli.command(name='upload-package')
2615 @click.argument('filename')
2616 @click.pass_context
2617 def upload_package(ctx, filename):
2618 """uploads a VNF package or NS package
2619
2620 FILENAME: VNF or NS package file (tar.gz)
2621 """
2622 try:
2623 ctx.obj.package.upload(filename)
2624 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
2625 if fullclassname != 'osmclient.sol005.client.Client':
2626 ctx.obj.package.wait_for_upload(filename)
2627 except ClientException as inst:
2628 print((inst.message))
2629 exit(1)
2630
2631
2632 #@cli.command(name='ns-scaling-show')
2633 #@click.argument('ns_name')
2634 #@click.pass_context
2635 #def show_ns_scaling(ctx, ns_name):
2636 # """shows the status of a NS scaling operation
2637 #
2638 # NS_NAME: name of the NS instance being scaled
2639 # """
2640 # try:
2641 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2642 # resp = ctx.obj.ns.list()
2643 # except ClientException as inst:
2644 # print((inst.message))
2645 # exit(1)
2646 #
2647 # table = PrettyTable(
2648 # ['group-name',
2649 # 'instance-id',
2650 # 'operational status',
2651 # 'create-time',
2652 # 'vnfr ids'])
2653 #
2654 # for ns in resp:
2655 # if ns_name == ns['name']:
2656 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
2657 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
2658 # for record in scaling_records:
2659 # if 'instance' in record:
2660 # instances = record['instance']
2661 # for inst in instances:
2662 # table.add_row(
2663 # [record['scaling-group-name-ref'],
2664 # inst['instance-id'],
2665 # inst['op-status'],
2666 # time.strftime('%Y-%m-%d %H:%M:%S',
2667 # time.localtime(
2668 # inst['create-time'])),
2669 # inst['vnfrs']])
2670 # table.align = 'l'
2671 # print(table)
2672
2673
2674 #@cli.command(name='ns-scale')
2675 #@click.argument('ns_name')
2676 #@click.option('--ns_scale_group', prompt=True)
2677 #@click.option('--index', prompt=True)
2678 #@click.option('--wait',
2679 # required=False,
2680 # default=False,
2681 # is_flag=True,
2682 # help='do not return the control immediately, but keep it \
2683 # until the operation is completed, or timeout')
2684 #@click.pass_context
2685 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
2686 # """scales NS
2687 #
2688 # NS_NAME: name of the NS instance to be scaled
2689 # """
2690 # try:
2691 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2692 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
2693 # except ClientException as inst:
2694 # print((inst.message))
2695 # exit(1)
2696
2697
2698 #@cli.command(name='config-agent-list')
2699 #@click.pass_context
2700 #def config_agent_list(ctx):
2701 # """list config agents"""
2702 # try:
2703 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2704 # except ClientException as inst:
2705 # print((inst.message))
2706 # exit(1)
2707 # table = PrettyTable(['name', 'account-type', 'details'])
2708 # for account in ctx.obj.vca.list():
2709 # table.add_row(
2710 # [account['name'],
2711 # account['account-type'],
2712 # account['juju']])
2713 # table.align = 'l'
2714 # print(table)
2715
2716
2717 #@cli.command(name='config-agent-delete')
2718 #@click.argument('name')
2719 #@click.pass_context
2720 #def config_agent_delete(ctx, name):
2721 # """deletes a config agent
2722 #
2723 # NAME: name of the config agent to be deleted
2724 # """
2725 # try:
2726 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2727 # ctx.obj.vca.delete(name)
2728 # except ClientException as inst:
2729 # print((inst.message))
2730 # exit(1)
2731
2732
2733 #@cli.command(name='config-agent-add')
2734 #@click.option('--name',
2735 # prompt=True)
2736 #@click.option('--account_type',
2737 # prompt=True)
2738 #@click.option('--server',
2739 # prompt=True)
2740 #@click.option('--user',
2741 # prompt=True)
2742 #@click.option('--secret',
2743 # prompt=True,
2744 # hide_input=True,
2745 # confirmation_prompt=True)
2746 #@click.pass_context
2747 #def config_agent_add(ctx, name, account_type, server, user, secret):
2748 # """adds a config agent"""
2749 # try:
2750 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2751 # ctx.obj.vca.create(name, account_type, server, user, secret)
2752 # except ClientException as inst:
2753 # print((inst.message))
2754 # exit(1)
2755
2756
2757 #@cli.command(name='ro-dump')
2758 #@click.pass_context
2759 #def ro_dump(ctx):
2760 # """shows RO agent information"""
2761 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2762 # resp = ctx.obj.vim.get_resource_orchestrator()
2763 # table = PrettyTable(['key', 'attribute'])
2764 # for k, v in list(resp.items()):
2765 # table.add_row([k, json.dumps(v, indent=2)])
2766 # table.align = 'l'
2767 # print(table)
2768
2769
2770 #@cli.command(name='vcs-list')
2771 #@click.pass_context
2772 #def vcs_list(ctx):
2773 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2774 # resp = ctx.obj.utils.get_vcs_info()
2775 # table = PrettyTable(['component name', 'state'])
2776 # for component in resp:
2777 # table.add_row([component['component_name'], component['state']])
2778 # table.align = 'l'
2779 # print(table)
2780
2781
2782 @cli.command(name='ns-action')
2783 @click.argument('ns_name')
2784 @click.option('--vnf_name', default=None, help='member-vnf-index if the target is a vnf instead of a ns)')
2785 @click.option('--vdu_id', default=None, help='vdu-id if the target is a vdu o a vnf')
2786 @click.option('--vdu_count', default=None, help='number of vdu instance of this vdu_id')
2787 @click.option('--action_name', prompt=True)
2788 @click.option('--params', default=None)
2789 @click.option('--wait',
2790 required=False,
2791 default=False,
2792 is_flag=True,
2793 help='do not return the control immediately, but keep it \
2794 until the operation is completed, or timeout')
2795 @click.pass_context
2796 def ns_action(ctx,
2797 ns_name,
2798 vnf_name,
2799 vdu_id,
2800 vdu_count,
2801 action_name,
2802 params,
2803 wait):
2804 """executes an action/primitive over a NS instance
2805
2806 NS_NAME: name or ID of the NS instance
2807 """
2808 try:
2809 check_client_version(ctx.obj, ctx.command.name)
2810 op_data = {}
2811 if vnf_name:
2812 op_data['member_vnf_index'] = vnf_name
2813 if vdu_id:
2814 op_data['vdu_id'] = vdu_id
2815 if vdu_count:
2816 op_data['vdu_count_index'] = vdu_count
2817 op_data['primitive'] = action_name
2818 if params:
2819 op_data['primitive_params'] = yaml.load(params)
2820 else:
2821 op_data['primitive_params'] = {}
2822 ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data, wait=wait)
2823
2824 except ClientException as inst:
2825 print(inst.message)
2826 exit(1)
2827
2828
2829 @cli.command(name='vnf-scale')
2830 @click.argument('ns_name')
2831 @click.argument('vnf_name')
2832 @click.option('--scaling-group', prompt=True, help="scaling-group-descriptor name to use")
2833 @click.option('--scale-in', default=False, is_flag=True, help="performs a scale in operation")
2834 @click.option('--scale-out', default=False, is_flag=True, help="performs a scale out operation (by default)")
2835 @click.pass_context
2836 def vnf_scale(ctx,
2837 ns_name,
2838 vnf_name,
2839 scaling_group,
2840 scale_in,
2841 scale_out):
2842 """
2843 Executes a VNF scale (adding/removing VDUs)
2844
2845 \b
2846 NS_NAME: name or ID of the NS instance.
2847 VNF_NAME: member-vnf-index in the NS to be scaled.
2848 """
2849 try:
2850 check_client_version(ctx.obj, ctx.command.name)
2851 if not scale_in and not scale_out:
2852 scale_out = True
2853 ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out)
2854 except ClientException as inst:
2855 print((inst.message))
2856 exit(1)
2857
2858
2859 ##############################
2860 # Role Management Operations #
2861 ##############################
2862
2863 @cli.command(name='role-create', short_help='creates a role')
2864 @click.argument('name')
2865 @click.option('--permissions',
2866 default=None,
2867 help='role permissions using a dictionary')
2868 @click.pass_context
2869 def role_create(ctx, name, permissions):
2870 """
2871 Creates a new role.
2872
2873 \b
2874 NAME: Name or ID of the role.
2875 DEFINITION: Definition of grant/denial of access to resources.
2876 """
2877 try:
2878 check_client_version(ctx.obj, ctx.command.name)
2879 ctx.obj.role.create(name, permissions)
2880 except ClientException as inst:
2881 print(inst.message)
2882 exit(1)
2883
2884
2885 @cli.command(name='role-update', short_help='updates a role')
2886 @click.argument('name')
2887 @click.option('--set-name',
2888 default=None,
2889 help='change name of rle')
2890 # @click.option('--permissions',
2891 # default=None,
2892 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
2893 @click.option('--add',
2894 default=None,
2895 help='yaml format dictionary with permission: True/False to access grant/denial')
2896 @click.option('--remove',
2897 default=None,
2898 help='yaml format list to remove a permission')
2899 @click.pass_context
2900 def role_update(ctx, name, set_name, add, remove):
2901 """
2902 Updates a role.
2903
2904 \b
2905 NAME: Name or ID of the role.
2906 DEFINITION: Definition overwrites the old definition.
2907 ADD: Grant/denial of access to resource to add.
2908 REMOVE: Grant/denial of access to resource to remove.
2909 """
2910 try:
2911 check_client_version(ctx.obj, ctx.command.name)
2912 ctx.obj.role.update(name, set_name, None, add, remove)
2913 except ClientException as inst:
2914 print(inst.message)
2915 exit(1)
2916
2917
2918 @cli.command(name='role-delete', short_help='deletes a role')
2919 @click.argument('name')
2920 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2921 @click.pass_context
2922 def role_delete(ctx, name):
2923 """
2924 Deletes a role.
2925
2926 \b
2927 NAME: Name or ID of the role.
2928 """
2929 try:
2930 check_client_version(ctx.obj, ctx.command.name)
2931 ctx.obj.role.delete(name)
2932 except ClientException as inst:
2933 print(inst.message)
2934 exit(1)
2935
2936
2937 @cli.command(name='role-list', short_help='list all roles')
2938 @click.option('--filter', default=None,
2939 help='restricts the list to the projects matching the filter')
2940 @click.pass_context
2941 def role_list(ctx, filter):
2942 """
2943 List all roles.
2944 """
2945 try:
2946 check_client_version(ctx.obj, ctx.command.name)
2947 resp = ctx.obj.role.list(filter)
2948 except ClientException as inst:
2949 print(inst.message)
2950 exit(1)
2951 table = PrettyTable(['name', 'id'])
2952 for role in resp:
2953 table.add_row([role['name'], role['_id']])
2954 table.align = 'l'
2955 print(table)
2956
2957
2958 @cli.command(name='role-show', short_help='show specific role')
2959 @click.argument('name')
2960 @click.pass_context
2961 def role_show(ctx, name):
2962 """
2963 Shows the details of a role.
2964
2965 \b
2966 NAME: Name or ID of the role.
2967 """
2968 try:
2969 check_client_version(ctx.obj, ctx.command.name)
2970 resp = ctx.obj.role.get(name)
2971 except ClientException as inst:
2972 print(inst.message)
2973 exit(1)
2974
2975 table = PrettyTable(['key', 'attribute'])
2976 for k, v in resp.items():
2977 table.add_row([k, json.dumps(v, indent=2)])
2978 table.align = 'l'
2979 print(table)
2980
2981
2982 if __name__ == '__main__':
2983 try:
2984 cli()
2985 except pycurl.error as e:
2986 print(e)
2987 print('Maybe "--hostname" option or OSM_HOSTNAME' +
2988 'environment variable needs to be specified')
2989 exit(1)