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