Feature 8047: osmclient package creation and validation tool
[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 e:
323 print(str(e))
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 e:
338 print(str(e))
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 e:
457 print(str(e))
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 e:
474 print(str(e))
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 e:
523 print(str(e))
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 e:
557 print(str(e))
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 e:
599 print(str(e))
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 e:
633 print(str(e))
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 e:
678 print(str(e))
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 e:
745 print(str(e))
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 e:
784 print(str(e))
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 e:
807 # print(str(e))
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 e:
830 # print(str(e))
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 e:
858 print(str(e))
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 e:
875 print(str(e))
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 e:
920 print(str(e))
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 e:
970 print(str(e))
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 e:
1020 print(str(e))
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 e:
1046 print(str(e))
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', 'overwrite', default=None,
1053 help='overwrite deprecated, use override')
1054 @click.option('--override', 'overwrite', default=None,
1055 help='overrides fields in descriptor, format: '
1056 '"key1.key2...=value[;key3...=value;...]"')
1057 @click.pass_context
1058 def nsd_create1(ctx, filename, overwrite):
1059 """creates a new NSD/NSpkg
1060
1061 FILENAME: NSD yaml file or NSpkg tar.gz file
1062 """
1063 nsd_create(ctx, filename, overwrite)
1064
1065
1066 @cli.command(name='nspkg-create', short_help='creates a new NSD/NSpkg')
1067 @click.argument('filename')
1068 @click.option('--overwrite', 'overwrite', default=None,
1069 help='overwrite deprecated, use override')
1070 @click.option('--override', 'overwrite', default=None,
1071 help='overrides fields in descriptor, format: '
1072 '"key1.key2...=value[;key3...=value;...]"')
1073 @click.pass_context
1074 def nsd_create2(ctx, filename, overwrite):
1075 """creates a new NSD/NSpkg
1076
1077 FILENAME: NSD yaml file or NSpkg tar.gz file
1078 """
1079 nsd_create(ctx, filename, overwrite)
1080
1081
1082 def vnfd_create(ctx, filename, overwrite):
1083 try:
1084 check_client_version(ctx.obj, ctx.command.name)
1085 ctx.obj.vnfd.create(filename, overwrite)
1086 except ClientException as e:
1087 print(str(e))
1088 exit(1)
1089
1090
1091 @cli.command(name='vnfd-create', short_help='creates a new VNFD/VNFpkg')
1092 @click.argument('filename')
1093 @click.option('--overwrite', 'overwrite', default=None,
1094 help='overwrite deprecated, use override')
1095 @click.option('--override', 'overwrite', default=None,
1096 help='overrides fields in descriptor, format: '
1097 '"key1.key2...=value[;key3...=value;...]"')
1098 @click.pass_context
1099 def vnfd_create1(ctx, filename, overwrite):
1100 """creates a new VNFD/VNFpkg
1101
1102 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1103 """
1104 vnfd_create(ctx, filename, overwrite)
1105
1106
1107 @cli.command(name='vnfpkg-create', short_help='creates a new VNFD/VNFpkg')
1108 @click.argument('filename')
1109 @click.option('--overwrite', 'overwrite', default=None,
1110 help='overwrite deprecated, use override')
1111 @click.option('--override', 'overwrite', default=None,
1112 help='overrides fields in descriptor, format: '
1113 '"key1.key2...=value[;key3...=value;...]"')
1114 @click.pass_context
1115 def vnfd_create2(ctx, filename, overwrite):
1116 """creates a new VNFD/VNFpkg
1117
1118 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1119 """
1120 vnfd_create(ctx, filename, overwrite)
1121
1122
1123 @cli.command(name='nfpkg-create', short_help='creates a new NFpkg')
1124 @click.argument('filename')
1125 @click.option('--overwrite', 'overwrite', default=None,
1126 help='overwrite deprecated, use override')
1127 @click.option('--override', 'overwrite', default=None,
1128 help='overrides fields in descriptor, format: '
1129 '"key1.key2...=value[;key3...=value;...]"')
1130 @click.pass_context
1131 def nfpkg_create(ctx, filename, overwrite):
1132 """creates a new NFpkg
1133
1134 FILENAME: NF Descriptor yaml file or NFpkg tar.gz file
1135 """
1136 vnfd_create(ctx, filename, overwrite)
1137
1138
1139 @cli.command(name='ns-create', short_help='creates a new Network Service instance')
1140 @click.option('--ns_name',
1141 prompt=True, help='name of the NS instance')
1142 @click.option('--nsd_name',
1143 prompt=True, help='name of the NS descriptor')
1144 @click.option('--vim_account',
1145 prompt=True, help='default VIM account id or name for the deployment')
1146 @click.option('--admin_status',
1147 default='ENABLED',
1148 help='administration status')
1149 @click.option('--ssh_keys',
1150 default=None,
1151 help='comma separated list of public key files to inject to vnfs')
1152 @click.option('--config',
1153 default=None,
1154 help='ns specific yaml configuration')
1155 @click.option('--config_file',
1156 default=None,
1157 help='ns specific yaml configuration file')
1158 @click.option('--wait',
1159 required=False,
1160 default=False,
1161 is_flag=True,
1162 help='do not return the control immediately, but keep it \
1163 until the operation is completed, or timeout')
1164 @click.pass_context
1165 def ns_create(ctx,
1166 nsd_name,
1167 ns_name,
1168 vim_account,
1169 admin_status,
1170 ssh_keys,
1171 config,
1172 config_file,
1173 wait):
1174 """creates a new NS instance"""
1175 try:
1176 if config_file:
1177 check_client_version(ctx.obj, '--config_file')
1178 if config:
1179 raise ClientException('"--config" option is incompatible with "--config_file" option')
1180 with open(config_file, 'r') as cf:
1181 config=cf.read()
1182 ctx.obj.ns.create(
1183 nsd_name,
1184 ns_name,
1185 config=config,
1186 ssh_keys=ssh_keys,
1187 account=vim_account,
1188 wait=wait)
1189 except ClientException as e:
1190 print(str(e))
1191 exit(1)
1192
1193
1194 def nst_create(ctx, filename, overwrite):
1195 try:
1196 check_client_version(ctx.obj, ctx.command.name)
1197 ctx.obj.nst.create(filename, overwrite)
1198 except ClientException as e:
1199 print(str(e))
1200 exit(1)
1201
1202
1203 @cli.command(name='nst-create', short_help='creates a new Network Slice Template (NST)')
1204 @click.argument('filename')
1205 @click.option('--overwrite', 'overwrite', default=None,
1206 help='overwrites deprecated use override')
1207 @click.option('--override', 'overwrite' ,default=None,
1208 help='overrides fields in descriptor, format: '
1209 '"key1.key2...=value[;key3...=value;...]"')
1210 @click.pass_context
1211 def nst_create1(ctx, filename, overwrite):
1212 """creates a new Network Slice Template (NST)
1213
1214 FILENAME: NST yaml file or NSTpkg tar.gz file
1215 """
1216 nst_create(ctx, filename, overwrite)
1217
1218
1219 @cli.command(name='netslice-template-create', short_help='creates a new Network Slice Template (NST)')
1220 @click.argument('filename')
1221 @click.option('--overwrite', 'overwrite', default=None,
1222 help='overwrites deprecated use override')
1223 @click.option('--override', 'overwrite', default=None,
1224 help='overrides fields in descriptor, format: '
1225 '"key1.key2...=value[;key3...=value;...]"')
1226 @click.pass_context
1227 def nst_create2(ctx, filename, overwrite):
1228 """creates a new Network Slice Template (NST)
1229
1230 FILENAME: NST yaml file or NSTpkg tar.gz file
1231 """
1232 nst_create(ctx, filename, overwrite)
1233
1234
1235 def nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1236 """creates a new Network Slice Instance (NSI)"""
1237 try:
1238 check_client_version(ctx.obj, ctx.command.name)
1239 if config_file:
1240 if config:
1241 raise ClientException('"--config" option is incompatible with "--config_file" option')
1242 with open(config_file, 'r') as cf:
1243 config=cf.read()
1244 ctx.obj.nsi.create(nst_name, nsi_name, config=config, ssh_keys=ssh_keys,
1245 account=vim_account, wait=wait)
1246 except ClientException as e:
1247 print(str(e))
1248 exit(1)
1249
1250
1251 @cli.command(name='nsi-create', short_help='creates a new Network Slice Instance')
1252 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1253 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1254 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1255 @click.option('--ssh_keys', default=None,
1256 help='comma separated list of keys to inject to vnfs')
1257 @click.option('--config', default=None,
1258 help='Netslice specific yaml configuration:\n'
1259 'netslice_subnet: [\n'
1260 'id: TEXT, vim_account: TEXT,\n'
1261 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1262 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1263 'additionalParamsForNsi: {param: value, ...}\n'
1264 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1265 '],\n'
1266 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1267 )
1268 @click.option('--config_file',
1269 default=None,
1270 help='nsi specific yaml configuration file')
1271 @click.option('--wait',
1272 required=False,
1273 default=False,
1274 is_flag=True,
1275 help='do not return the control immediately, but keep it \
1276 until the operation is completed, or timeout')
1277 @click.pass_context
1278 def nsi_create1(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1279 """creates a new Network Slice Instance (NSI)"""
1280 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1281
1282
1283 @cli.command(name='netslice-instance-create', short_help='creates a new Network Slice Instance')
1284 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1285 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1286 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1287 @click.option('--ssh_keys', default=None,
1288 help='comma separated list of keys to inject to vnfs')
1289 @click.option('--config', default=None,
1290 help='Netslice specific yaml configuration:\n'
1291 'netslice_subnet: [\n'
1292 'id: TEXT, vim_account: TEXT,\n'
1293 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1294 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1295 '],\n'
1296 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1297 )
1298 @click.option('--config_file',
1299 default=None,
1300 help='nsi specific yaml configuration file')
1301 @click.option('--wait',
1302 required=False,
1303 default=False,
1304 is_flag=True,
1305 help='do not return the control immediately, but keep it \
1306 until the operation is completed, or timeout')
1307 @click.pass_context
1308 def nsi_create2(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1309 """creates a new Network Slice Instance (NSI)"""
1310 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1311
1312
1313 @cli.command(name='pdu-create', short_help='adds a new Physical Deployment Unit to the catalog')
1314 @click.option('--name', help='name of the Physical Deployment Unit')
1315 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1316 @click.option('--interface',
1317 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1318 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1319 multiple=True)
1320 @click.option('--description', help='human readable description')
1321 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple=True)
1322 @click.option('--descriptor_file', default=None, help='PDU descriptor file (as an alternative to using the other arguments')
1323 @click.pass_context
1324 def pdu_create(ctx, name, pdu_type, interface, description, vim_account, descriptor_file):
1325 """creates a new Physical Deployment Unit (PDU)"""
1326 try:
1327 check_client_version(ctx.obj, ctx.command.name)
1328 pdu = {}
1329 if not descriptor_file:
1330 if not name:
1331 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1332 if not pdu_type:
1333 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1334 if not interface:
1335 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1336 if not vim_account:
1337 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1338 else:
1339 with open(descriptor_file, 'r') as df:
1340 pdu = yaml.safe_load(df.read())
1341 if name: pdu["name"] = name
1342 if pdu_type: pdu["type"] = pdu_type
1343 if description: pdu["description"] = description
1344 if vim_account: pdu["vim_accounts"] = vim_account
1345 if interface:
1346 ifaces_list = []
1347 for iface in interface:
1348 new_iface={k:v for k,v in [i.split('=') for i in iface.split(',')]}
1349 new_iface["mgmt"] = (new_iface.get("mgmt","false").lower() == "true")
1350 ifaces_list.append(new_iface)
1351 pdu["interfaces"] = ifaces_list
1352 ctx.obj.pdu.create(pdu)
1353 except ClientException as e:
1354 print(str(e))
1355 exit(1)
1356
1357 ####################
1358 # UPDATE operations
1359 ####################
1360
1361 def nsd_update(ctx, name, content):
1362 try:
1363 check_client_version(ctx.obj, ctx.command.name)
1364 ctx.obj.nsd.update(name, content)
1365 except ClientException as e:
1366 print(str(e))
1367 exit(1)
1368
1369
1370 @cli.command(name='nsd-update', short_help='updates a NSD/NSpkg')
1371 @click.argument('name')
1372 @click.option('--content', default=None,
1373 help='filename with the NSD/NSpkg replacing the current one')
1374 @click.pass_context
1375 def nsd_update1(ctx, name, content):
1376 """updates a NSD/NSpkg
1377
1378 NAME: name or ID of the NSD/NSpkg
1379 """
1380 nsd_update(ctx, name, content)
1381
1382
1383 @cli.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
1384 @click.argument('name')
1385 @click.option('--content', default=None,
1386 help='filename with the NSD/NSpkg replacing the current one')
1387 @click.pass_context
1388 def nsd_update2(ctx, name, content):
1389 """updates a NSD/NSpkg
1390
1391 NAME: name or ID of the NSD/NSpkg
1392 """
1393 nsd_update(ctx, name, content)
1394
1395
1396 def vnfd_update(ctx, name, content):
1397 try:
1398 check_client_version(ctx.obj, ctx.command.name)
1399 ctx.obj.vnfd.update(name, content)
1400 except ClientException as e:
1401 print(str(e))
1402 exit(1)
1403
1404
1405 @cli.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
1406 @click.argument('name')
1407 @click.option('--content', default=None,
1408 help='filename with the VNFD/VNFpkg replacing the current one')
1409 @click.pass_context
1410 def vnfd_update1(ctx, name, content):
1411 """updates a VNFD/VNFpkg
1412
1413 NAME: name or ID of the VNFD/VNFpkg
1414 """
1415 vnfd_update(ctx, name, content)
1416
1417
1418 @cli.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
1419 @click.argument('name')
1420 @click.option('--content', default=None,
1421 help='filename with the VNFD/VNFpkg replacing the current one')
1422 @click.pass_context
1423 def vnfd_update2(ctx, name, content):
1424 """updates a VNFD/VNFpkg
1425
1426 NAME: VNFD yaml file or VNFpkg tar.gz file
1427 """
1428 vnfd_update(ctx, name, content)
1429
1430
1431 @cli.command(name='nfpkg-update', short_help='updates a NFpkg')
1432 @click.argument('name')
1433 @click.option('--content', default=None,
1434 help='filename with the NFpkg replacing the current one')
1435 @click.pass_context
1436 def nfpkg_update(ctx, name, content):
1437 """updates a NFpkg
1438
1439 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1440 """
1441 vnfd_update(ctx, name, content)
1442
1443
1444 def nst_update(ctx, name, content):
1445 try:
1446 check_client_version(ctx.obj, ctx.command.name)
1447 ctx.obj.nst.update(name, content)
1448 except ClientException as e:
1449 print(str(e))
1450 exit(1)
1451
1452
1453 @cli.command(name='nst-update', short_help='updates a Network Slice Template (NST)')
1454 @click.argument('name')
1455 @click.option('--content', default=None,
1456 help='filename with the NST/NSTpkg replacing the current one')
1457 @click.pass_context
1458 def nst_update1(ctx, name, content):
1459 """updates a Network Slice Template (NST)
1460
1461 NAME: name or ID of the NSD/NSpkg
1462 """
1463 nst_update(ctx, name, content)
1464
1465
1466 @cli.command(name='netslice-template-update', short_help='updates a Network Slice Template (NST)')
1467 @click.argument('name')
1468 @click.option('--content', default=None,
1469 help='filename with the NST/NSTpkg replacing the current one')
1470 @click.pass_context
1471 def nst_update2(ctx, name, content):
1472 """updates a Network Slice Template (NST)
1473
1474 NAME: name or ID of the NSD/NSpkg
1475 """
1476 nst_update(ctx, name, content)
1477
1478
1479 ####################
1480 # DELETE operations
1481 ####################
1482
1483 def nsd_delete(ctx, name, force):
1484 try:
1485 if not force:
1486 ctx.obj.nsd.delete(name)
1487 else:
1488 check_client_version(ctx.obj, '--force')
1489 ctx.obj.nsd.delete(name, force)
1490 except ClientException as e:
1491 print(str(e))
1492 exit(1)
1493
1494
1495 @cli.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
1496 @click.argument('name')
1497 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1498 @click.pass_context
1499 def nsd_delete1(ctx, name, force):
1500 """deletes a NSD/NSpkg
1501
1502 NAME: name or ID of the NSD/NSpkg to be deleted
1503 """
1504 nsd_delete(ctx, name, force)
1505
1506
1507 @cli.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
1508 @click.argument('name')
1509 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1510 @click.pass_context
1511 def nsd_delete2(ctx, name, force):
1512 """deletes a NSD/NSpkg
1513
1514 NAME: name or ID of the NSD/NSpkg to be deleted
1515 """
1516 nsd_delete(ctx, name, force)
1517
1518
1519 def vnfd_delete(ctx, name, force):
1520 try:
1521 if not force:
1522 ctx.obj.vnfd.delete(name)
1523 else:
1524 check_client_version(ctx.obj, '--force')
1525 ctx.obj.vnfd.delete(name, force)
1526 except ClientException as e:
1527 print(str(e))
1528 exit(1)
1529
1530
1531 @cli.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
1532 @click.argument('name')
1533 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1534 @click.pass_context
1535 def vnfd_delete1(ctx, name, force):
1536 """deletes a VNFD/VNFpkg
1537
1538 NAME: name or ID of the VNFD/VNFpkg to be deleted
1539 """
1540 vnfd_delete(ctx, name, force)
1541
1542
1543 @cli.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
1544 @click.argument('name')
1545 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1546 @click.pass_context
1547 def vnfd_delete2(ctx, name, force):
1548 """deletes a VNFD/VNFpkg
1549
1550 NAME: name or ID of the VNFD/VNFpkg to be deleted
1551 """
1552 vnfd_delete(ctx, name, force)
1553
1554
1555 @cli.command(name='nfpkg-delete', short_help='deletes a NFpkg')
1556 @click.argument('name')
1557 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1558 @click.pass_context
1559 def nfpkg_delete(ctx, name, force):
1560 """deletes a NFpkg
1561
1562 NAME: name or ID of the NFpkg to be deleted
1563 """
1564 vnfd_delete(ctx, name, force)
1565
1566
1567 @cli.command(name='ns-delete', short_help='deletes a NS instance')
1568 @click.argument('name')
1569 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1570 @click.option('--wait',
1571 required=False,
1572 default=False,
1573 is_flag=True,
1574 help='do not return the control immediately, but keep it \
1575 until the operation is completed, or timeout')
1576 @click.pass_context
1577 def ns_delete(ctx, name, force, wait):
1578 """deletes a NS instance
1579
1580 NAME: name or ID of the NS instance to be deleted
1581 """
1582 try:
1583 if not force:
1584 ctx.obj.ns.delete(name, wait=wait)
1585 else:
1586 check_client_version(ctx.obj, '--force')
1587 ctx.obj.ns.delete(name, force, wait=wait)
1588 except ClientException as e:
1589 print(str(e))
1590 exit(1)
1591
1592
1593 def nst_delete(ctx, name, force):
1594 try:
1595 check_client_version(ctx.obj, ctx.command.name)
1596 ctx.obj.nst.delete(name, force)
1597 except ClientException as e:
1598 print(str(e))
1599 exit(1)
1600
1601
1602 @cli.command(name='nst-delete', short_help='deletes a Network Slice Template (NST)')
1603 @click.argument('name')
1604 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1605 @click.pass_context
1606 def nst_delete1(ctx, name, force):
1607 """deletes a Network Slice Template (NST)
1608
1609 NAME: name or ID of the NST/NSTpkg to be deleted
1610 """
1611 nst_delete(ctx, name, force)
1612
1613
1614 @cli.command(name='netslice-template-delete', short_help='deletes a Network Slice Template (NST)')
1615 @click.argument('name')
1616 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1617 @click.pass_context
1618 def nst_delete2(ctx, name, force):
1619 """deletes a Network Slice Template (NST)
1620
1621 NAME: name or ID of the NST/NSTpkg to be deleted
1622 """
1623 nst_delete(ctx, name, force)
1624
1625
1626 def nsi_delete(ctx, name, force, wait):
1627 try:
1628 check_client_version(ctx.obj, ctx.command.name)
1629 ctx.obj.nsi.delete(name, force, wait=wait)
1630 except ClientException as e:
1631 print(str(e))
1632 exit(1)
1633
1634
1635 @cli.command(name='nsi-delete', short_help='deletes a Network Slice Instance (NSI)')
1636 @click.argument('name')
1637 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1638 @click.option('--wait',
1639 required=False,
1640 default=False,
1641 is_flag=True,
1642 help='do not return the control immediately, but keep it \
1643 until the operation is completed, or timeout')
1644 @click.pass_context
1645 def nsi_delete1(ctx, name, force, wait):
1646 """deletes a Network Slice Instance (NSI)
1647
1648 NAME: name or ID of the Network Slice instance to be deleted
1649 """
1650 nsi_delete(ctx, name, force, wait=wait)
1651
1652
1653 @cli.command(name='netslice-instance-delete', short_help='deletes a Network Slice Instance (NSI)')
1654 @click.argument('name')
1655 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1656 @click.pass_context
1657 def nsi_delete2(ctx, name, force, wait):
1658 """deletes a Network Slice Instance (NSI)
1659
1660 NAME: name or ID of the Network Slice instance to be deleted
1661 """
1662 nsi_delete(ctx, name, force, wait=wait)
1663
1664
1665 @cli.command(name='pdu-delete', short_help='deletes a Physical Deployment Unit (PDU)')
1666 @click.argument('name')
1667 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1668 @click.pass_context
1669 def pdu_delete(ctx, name, force):
1670 """deletes a Physical Deployment Unit (PDU)
1671
1672 NAME: name or ID of the PDU to be deleted
1673 """
1674 try:
1675 check_client_version(ctx.obj, ctx.command.name)
1676 ctx.obj.pdu.delete(name, force)
1677 except ClientException as e:
1678 print(str(e))
1679 exit(1)
1680
1681
1682 #################
1683 # VIM operations
1684 #################
1685
1686 @cli.command(name='vim-create', short_help='creates a new VIM account')
1687 @click.option('--name',
1688 prompt=True,
1689 help='Name to create datacenter')
1690 @click.option('--user',
1691 prompt=True,
1692 help='VIM username')
1693 @click.option('--password',
1694 prompt=True,
1695 hide_input=True,
1696 confirmation_prompt=True,
1697 help='VIM password')
1698 @click.option('--auth_url',
1699 prompt=True,
1700 help='VIM url')
1701 @click.option('--tenant',
1702 prompt=True,
1703 help='VIM tenant name')
1704 @click.option('--config',
1705 default=None,
1706 help='VIM specific config parameters')
1707 @click.option('--account_type',
1708 default='openstack',
1709 help='VIM type')
1710 @click.option('--description',
1711 default='no description',
1712 help='human readable description')
1713 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1714 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1715 @click.option('--wait',
1716 required=False,
1717 default=False,
1718 is_flag=True,
1719 help='do not return the control immediately, but keep it \
1720 until the operation is completed, or timeout')
1721 @click.pass_context
1722 def vim_create(ctx,
1723 name,
1724 user,
1725 password,
1726 auth_url,
1727 tenant,
1728 config,
1729 account_type,
1730 description,
1731 sdn_controller,
1732 sdn_port_mapping,
1733 wait):
1734 """creates a new VIM account"""
1735 try:
1736 if sdn_controller:
1737 check_client_version(ctx.obj, '--sdn_controller')
1738 if sdn_port_mapping:
1739 check_client_version(ctx.obj, '--sdn_port_mapping')
1740 vim = {}
1741 vim['vim-username'] = user
1742 vim['vim-password'] = password
1743 vim['vim-url'] = auth_url
1744 vim['vim-tenant-name'] = tenant
1745 vim['vim-type'] = account_type
1746 vim['description'] = description
1747 vim['config'] = config
1748 if sdn_controller or sdn_port_mapping:
1749 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1750 else:
1751 ctx.obj.vim.create(name, vim, wait=wait)
1752 except ClientException as e:
1753 print(str(e))
1754 exit(1)
1755
1756
1757 @cli.command(name='vim-update', short_help='updates a VIM account')
1758 @click.argument('name')
1759 @click.option('--newname', help='New name for the VIM account')
1760 @click.option('--user', help='VIM username')
1761 @click.option('--password', help='VIM password')
1762 @click.option('--auth_url', help='VIM url')
1763 @click.option('--tenant', help='VIM tenant name')
1764 @click.option('--config', help='VIM specific config parameters')
1765 @click.option('--account_type', help='VIM type')
1766 @click.option('--description', help='human readable description')
1767 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1768 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1769 @click.option('--wait',
1770 required=False,
1771 default=False,
1772 is_flag=True,
1773 help='do not return the control immediately, but keep it \
1774 until the operation is completed, or timeout')
1775 @click.pass_context
1776 def vim_update(ctx,
1777 name,
1778 newname,
1779 user,
1780 password,
1781 auth_url,
1782 tenant,
1783 config,
1784 account_type,
1785 description,
1786 sdn_controller,
1787 sdn_port_mapping,
1788 wait):
1789 """updates a VIM account
1790
1791 NAME: name or ID of the VIM account
1792 """
1793 try:
1794 check_client_version(ctx.obj, ctx.command.name)
1795 vim = {}
1796 if newname: vim['name'] = newname
1797 if user: vim['vim_user'] = user
1798 if password: vim['vim_password'] = password
1799 if auth_url: vim['vim_url'] = auth_url
1800 if tenant: vim['vim-tenant-name'] = tenant
1801 if account_type: vim['vim_type'] = account_type
1802 if description: vim['description'] = description
1803 if config: vim['config'] = config
1804 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1805 except ClientException as e:
1806 print(str(e))
1807 exit(1)
1808
1809
1810 @cli.command(name='vim-delete', short_help='deletes a VIM account')
1811 @click.argument('name')
1812 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1813 @click.option('--wait',
1814 required=False,
1815 default=False,
1816 is_flag=True,
1817 help='do not return the control immediately, but keep it \
1818 until the operation is completed, or timeout')
1819 @click.pass_context
1820 def vim_delete(ctx, name, force, wait):
1821 """deletes a VIM account
1822
1823 NAME: name or ID of the VIM account to be deleted
1824 """
1825 try:
1826 if not force:
1827 ctx.obj.vim.delete(name, wait=wait)
1828 else:
1829 check_client_version(ctx.obj, '--force')
1830 ctx.obj.vim.delete(name, force, wait=wait)
1831 except ClientException as e:
1832 print(str(e))
1833 exit(1)
1834
1835
1836 @cli.command(name='vim-list', short_help='list all VIM accounts')
1837 #@click.option('--ro_update/--no_ro_update',
1838 # default=False,
1839 # help='update list from RO')
1840 @click.option('--filter', default=None,
1841 help='restricts the list to the VIM accounts matching the filter')
1842 @click.pass_context
1843 def vim_list(ctx, filter):
1844 """list all VIM accounts"""
1845 if filter:
1846 check_client_version(ctx.obj, '--filter')
1847 # if ro_update:
1848 # check_client_version(ctx.obj, '--ro_update', 'v1')
1849 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1850 if fullclassname == 'osmclient.sol005.client.Client':
1851 resp = ctx.obj.vim.list(filter)
1852 # else:
1853 # resp = ctx.obj.vim.list(ro_update)
1854 table = PrettyTable(['vim name', 'uuid'])
1855 for vim in resp:
1856 table.add_row([vim['name'], vim['uuid']])
1857 table.align = 'l'
1858 print(table)
1859
1860
1861 @cli.command(name='vim-show', short_help='shows the details of a VIM account')
1862 @click.argument('name')
1863 @click.pass_context
1864 def vim_show(ctx, name):
1865 """shows the details of a VIM account
1866
1867 NAME: name or ID of the VIM account
1868 """
1869 try:
1870 resp = ctx.obj.vim.get(name)
1871 if 'vim_password' in resp:
1872 resp['vim_password']='********'
1873 except ClientException as e:
1874 print(str(e))
1875 exit(1)
1876
1877 table = PrettyTable(['key', 'attribute'])
1878 for k, v in list(resp.items()):
1879 table.add_row([k, json.dumps(v, indent=2)])
1880 table.align = 'l'
1881 print(table)
1882
1883
1884 ####################
1885 # WIM operations
1886 ####################
1887
1888 @cli.command(name='wim-create', short_help='creates a new WIM account')
1889 @click.option('--name',
1890 prompt=True,
1891 help='Name for the WIM account')
1892 @click.option('--user',
1893 help='WIM username')
1894 @click.option('--password',
1895 help='WIM password')
1896 @click.option('--url',
1897 prompt=True,
1898 help='WIM url')
1899 # @click.option('--tenant',
1900 # help='wIM tenant name')
1901 @click.option('--config',
1902 default=None,
1903 help='WIM specific config parameters')
1904 @click.option('--wim_type',
1905 help='WIM type')
1906 @click.option('--description',
1907 default='no description',
1908 help='human readable description')
1909 @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)")
1910 @click.option('--wait',
1911 required=False,
1912 default=False,
1913 is_flag=True,
1914 help='do not return the control immediately, but keep it \
1915 until the operation is completed, or timeout')
1916 @click.pass_context
1917 def wim_create(ctx,
1918 name,
1919 user,
1920 password,
1921 url,
1922 # tenant,
1923 config,
1924 wim_type,
1925 description,
1926 wim_port_mapping,
1927 wait):
1928 """creates a new WIM account"""
1929 try:
1930 check_client_version(ctx.obj, ctx.command.name)
1931 # if sdn_controller:
1932 # check_client_version(ctx.obj, '--sdn_controller')
1933 # if sdn_port_mapping:
1934 # check_client_version(ctx.obj, '--sdn_port_mapping')
1935 wim = {}
1936 if user: wim['user'] = user
1937 if password: wim['password'] = password
1938 if url: wim['wim_url'] = url
1939 # if tenant: wim['tenant'] = tenant
1940 wim['wim_type'] = wim_type
1941 if description: wim['description'] = description
1942 if config: wim['config'] = config
1943 ctx.obj.wim.create(name, wim, wim_port_mapping, wait=wait)
1944 except ClientException as e:
1945 print(str(e))
1946 exit(1)
1947
1948
1949 @cli.command(name='wim-update', short_help='updates a WIM account')
1950 @click.argument('name')
1951 @click.option('--newname', help='New name for the WIM account')
1952 @click.option('--user', help='WIM username')
1953 @click.option('--password', help='WIM password')
1954 @click.option('--url', help='WIM url')
1955 @click.option('--config', help='WIM specific config parameters')
1956 @click.option('--wim_type', help='WIM type')
1957 @click.option('--description', help='human readable description')
1958 @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)")
1959 @click.option('--wait',
1960 required=False,
1961 default=False,
1962 is_flag=True,
1963 help='do not return the control immediately, but keep it \
1964 until the operation is completed, or timeout')
1965 @click.pass_context
1966 def wim_update(ctx,
1967 name,
1968 newname,
1969 user,
1970 password,
1971 url,
1972 config,
1973 wim_type,
1974 description,
1975 wim_port_mapping,
1976 wait):
1977 """updates a WIM account
1978
1979 NAME: name or ID of the WIM account
1980 """
1981 try:
1982 check_client_version(ctx.obj, ctx.command.name)
1983 wim = {}
1984 if newname: wim['name'] = newname
1985 if user: wim['user'] = user
1986 if password: wim['password'] = password
1987 if url: wim['url'] = url
1988 # if tenant: wim['tenant'] = tenant
1989 if wim_type: wim['wim_type'] = wim_type
1990 if description: wim['description'] = description
1991 if config: wim['config'] = config
1992 ctx.obj.wim.update(name, wim, wim_port_mapping, wait=wait)
1993 except ClientException as e:
1994 print(str(e))
1995 exit(1)
1996
1997
1998 @cli.command(name='wim-delete', short_help='deletes a WIM account')
1999 @click.argument('name')
2000 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2001 @click.option('--wait',
2002 required=False,
2003 default=False,
2004 is_flag=True,
2005 help='do not return the control immediately, but keep it \
2006 until the operation is completed, or timeout')
2007 @click.pass_context
2008 def wim_delete(ctx, name, force, wait):
2009 """deletes a WIM account
2010
2011 NAME: name or ID of the WIM account to be deleted
2012 """
2013 try:
2014 check_client_version(ctx.obj, ctx.command.name)
2015 ctx.obj.wim.delete(name, force, wait=wait)
2016 except ClientException as e:
2017 print(str(e))
2018 exit(1)
2019
2020
2021 @cli.command(name='wim-list', short_help='list all WIM accounts')
2022 @click.option('--filter', default=None,
2023 help='restricts the list to the WIM accounts matching the filter')
2024 @click.pass_context
2025 def wim_list(ctx, filter):
2026 """list all WIM accounts"""
2027 try:
2028 check_client_version(ctx.obj, ctx.command.name)
2029 resp = ctx.obj.wim.list(filter)
2030 table = PrettyTable(['wim name', 'uuid'])
2031 for wim in resp:
2032 table.add_row([wim['name'], wim['uuid']])
2033 table.align = 'l'
2034 print(table)
2035 except ClientException as e:
2036 print(str(e))
2037 exit(1)
2038
2039
2040 @cli.command(name='wim-show', short_help='shows the details of a WIM account')
2041 @click.argument('name')
2042 @click.pass_context
2043 def wim_show(ctx, name):
2044 """shows the details of a WIM account
2045
2046 NAME: name or ID of the WIM account
2047 """
2048 try:
2049 check_client_version(ctx.obj, ctx.command.name)
2050 resp = ctx.obj.wim.get(name)
2051 if 'password' in resp:
2052 resp['wim_password']='********'
2053 except ClientException as e:
2054 print(str(e))
2055 exit(1)
2056
2057 table = PrettyTable(['key', 'attribute'])
2058 for k, v in list(resp.items()):
2059 table.add_row([k, json.dumps(v, indent=2)])
2060 table.align = 'l'
2061 print(table)
2062
2063
2064 ####################
2065 # SDN controller operations
2066 ####################
2067
2068 @cli.command(name='sdnc-create', short_help='creates a new SDN controller')
2069 @click.option('--name',
2070 prompt=True,
2071 help='Name to create sdn controller')
2072 @click.option('--type',
2073 prompt=True,
2074 help='SDN controller type')
2075 @click.option('--sdn_controller_version',
2076 help='SDN controller version')
2077 @click.option('--ip_address',
2078 prompt=True,
2079 help='SDN controller IP address')
2080 @click.option('--port',
2081 prompt=True,
2082 help='SDN controller port')
2083 @click.option('--switch_dpid',
2084 prompt=True,
2085 help='Switch DPID (Openflow Datapath ID)')
2086 @click.option('--user',
2087 help='SDN controller username')
2088 @click.option('--password',
2089 hide_input=True,
2090 confirmation_prompt=True,
2091 help='SDN controller password')
2092 #@click.option('--description',
2093 # default='no description',
2094 # help='human readable description')
2095 @click.option('--wait',
2096 required=False,
2097 default=False,
2098 is_flag=True,
2099 help='do not return the control immediately, but keep it \
2100 until the operation is completed, or timeout')
2101 @click.pass_context
2102 def sdnc_create(ctx,
2103 name,
2104 type,
2105 sdn_controller_version,
2106 ip_address,
2107 port,
2108 switch_dpid,
2109 user,
2110 password,
2111 wait):
2112 """creates a new SDN controller"""
2113 sdncontroller = {}
2114 sdncontroller['name'] = name
2115 sdncontroller['type'] = type
2116 sdncontroller['ip'] = ip_address
2117 sdncontroller['port'] = int(port)
2118 sdncontroller['dpid'] = switch_dpid
2119 if sdn_controller_version:
2120 sdncontroller['version'] = sdn_controller_version
2121 if user:
2122 sdncontroller['user'] = user
2123 if password:
2124 sdncontroller['password'] = password
2125 # sdncontroller['description'] = description
2126 try:
2127 check_client_version(ctx.obj, ctx.command.name)
2128 ctx.obj.sdnc.create(name, sdncontroller, wait=wait)
2129 except ClientException as e:
2130 print(str(e))
2131 exit(1)
2132
2133 @cli.command(name='sdnc-update', short_help='updates an SDN controller')
2134 @click.argument('name')
2135 @click.option('--newname', help='New name for the SDN controller')
2136 @click.option('--type', help='SDN controller type')
2137 @click.option('--sdn_controller_version', help='SDN controller username')
2138 @click.option('--ip_address', help='SDN controller IP address')
2139 @click.option('--port', help='SDN controller port')
2140 @click.option('--switch_dpid', help='Switch DPID (Openflow Datapath ID)')
2141 @click.option('--user', help='SDN controller username')
2142 @click.option('--password', help='SDN controller password')
2143 #@click.option('--description', default=None, help='human readable description')
2144 @click.option('--wait',
2145 required=False,
2146 default=False,
2147 is_flag=True,
2148 help='do not return the control immediately, but keep it \
2149 until the operation is completed, or timeout')
2150 @click.pass_context
2151 def sdnc_update(ctx,
2152 name,
2153 newname,
2154 type,
2155 sdn_controller_version,
2156 ip_address,
2157 port,
2158 switch_dpid,
2159 user,
2160 password,
2161 wait):
2162 """updates an SDN controller
2163
2164 NAME: name or ID of the SDN controller
2165 """
2166 sdncontroller = {}
2167 if newname: sdncontroller['name'] = newname
2168 if type: sdncontroller['type'] = type
2169 if ip_address: sdncontroller['ip'] = ip_address
2170 if port: sdncontroller['port'] = int(port)
2171 if switch_dpid: sdncontroller['dpid'] = switch_dpid
2172 # sdncontroller['description'] = description
2173 if sdn_controller_version is not None:
2174 if sdn_controller_version=="":
2175 sdncontroller['version'] = None
2176 else:
2177 sdncontroller['version'] = sdn_controller_version
2178 if user is not None:
2179 if user=="":
2180 sdncontroller['user'] = None
2181 else:
2182 sdncontroller['user'] = user
2183 if password is not None:
2184 if password=="":
2185 sdncontroller['password'] = None
2186 else:
2187 sdncontroller['password'] = user
2188 try:
2189 check_client_version(ctx.obj, ctx.command.name)
2190 ctx.obj.sdnc.update(name, sdncontroller, wait=wait)
2191 except ClientException as e:
2192 print(str(e))
2193 exit(1)
2194
2195
2196 @cli.command(name='sdnc-delete', short_help='deletes an SDN controller')
2197 @click.argument('name')
2198 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2199 @click.option('--wait',
2200 required=False,
2201 default=False,
2202 is_flag=True,
2203 help='do not return the control immediately, but keep it \
2204 until the operation is completed, or timeout')
2205 @click.pass_context
2206 def sdnc_delete(ctx, name, force, wait):
2207 """deletes an SDN controller
2208
2209 NAME: name or ID of the SDN controller to be deleted
2210 """
2211 try:
2212 check_client_version(ctx.obj, ctx.command.name)
2213 ctx.obj.sdnc.delete(name, force, wait=wait)
2214 except ClientException as e:
2215 print(str(e))
2216 exit(1)
2217
2218
2219 @cli.command(name='sdnc-list', short_help='list all SDN controllers')
2220 @click.option('--filter', default=None,
2221 help='restricts the list to the SDN controllers matching the filter')
2222 @click.pass_context
2223 def sdnc_list(ctx, filter):
2224 """list all SDN controllers"""
2225 try:
2226 check_client_version(ctx.obj, ctx.command.name)
2227 resp = ctx.obj.sdnc.list(filter)
2228 except ClientException as e:
2229 print(str(e))
2230 exit(1)
2231 table = PrettyTable(['sdnc name', 'id'])
2232 for sdnc in resp:
2233 table.add_row([sdnc['name'], sdnc['_id']])
2234 table.align = 'l'
2235 print(table)
2236
2237
2238 @cli.command(name='sdnc-show', short_help='shows the details of an SDN controller')
2239 @click.argument('name')
2240 @click.pass_context
2241 def sdnc_show(ctx, name):
2242 """shows the details of an SDN controller
2243
2244 NAME: name or ID of the SDN controller
2245 """
2246 try:
2247 check_client_version(ctx.obj, ctx.command.name)
2248 resp = ctx.obj.sdnc.get(name)
2249 except ClientException as e:
2250 print(str(e))
2251 exit(1)
2252
2253 table = PrettyTable(['key', 'attribute'])
2254 for k, v in list(resp.items()):
2255 table.add_row([k, json.dumps(v, indent=2)])
2256 table.align = 'l'
2257 print(table)
2258
2259
2260 ####################
2261 # Project mgmt operations
2262 ####################
2263
2264 @cli.command(name='project-create', short_help='creates a new project')
2265 @click.argument('name')
2266 #@click.option('--description',
2267 # default='no description',
2268 # help='human readable description')
2269 @click.pass_context
2270 def project_create(ctx, name):
2271 """Creates a new project
2272
2273 NAME: name of the project
2274 """
2275 project = {}
2276 project['name'] = name
2277 try:
2278 check_client_version(ctx.obj, ctx.command.name)
2279 ctx.obj.project.create(name, project)
2280 except ClientException as e:
2281 print(str(e))
2282 exit(1)
2283
2284
2285 @cli.command(name='project-delete', short_help='deletes a project')
2286 @click.argument('name')
2287 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2288 @click.pass_context
2289 def project_delete(ctx, name):
2290 """deletes a project
2291
2292 NAME: name or ID of the project to be deleted
2293 """
2294 try:
2295 check_client_version(ctx.obj, ctx.command.name)
2296 ctx.obj.project.delete(name)
2297 except ClientException as e:
2298 print(str(e))
2299 exit(1)
2300
2301
2302 @cli.command(name='project-list', short_help='list all projects')
2303 @click.option('--filter', default=None,
2304 help='restricts the list to the projects matching the filter')
2305 @click.pass_context
2306 def project_list(ctx, filter):
2307 """list all projects"""
2308 try:
2309 check_client_version(ctx.obj, ctx.command.name)
2310 resp = ctx.obj.project.list(filter)
2311 except ClientException as e:
2312 print(str(e))
2313 exit(1)
2314 table = PrettyTable(['name', 'id'])
2315 for proj in resp:
2316 table.add_row([proj['name'], proj['_id']])
2317 table.align = 'l'
2318 print(table)
2319
2320
2321 @cli.command(name='project-show', short_help='shows the details of a project')
2322 @click.argument('name')
2323 @click.pass_context
2324 def project_show(ctx, name):
2325 """shows the details of a project
2326
2327 NAME: name or ID of the project
2328 """
2329 try:
2330 check_client_version(ctx.obj, ctx.command.name)
2331 resp = ctx.obj.project.get(name)
2332 except ClientException as e:
2333 print(str(e))
2334 exit(1)
2335
2336 table = PrettyTable(['key', 'attribute'])
2337 for k, v in resp.items():
2338 table.add_row([k, json.dumps(v, indent=2)])
2339 table.align = 'l'
2340 print(table)
2341
2342
2343 @cli.command(name='project-update', short_help='updates a project (only the name can be updated)')
2344 @click.argument('project')
2345 @click.option('--name',
2346 prompt=True,
2347 help='new name for the project')
2348
2349 @click.pass_context
2350 def project_update(ctx, project, name):
2351 """
2352 Update a project name
2353
2354 :param ctx:
2355 :param project: id or name of the project to modify
2356 :param name: new name for the project
2357 :return:
2358 """
2359
2360 project_changes = {}
2361 project_changes['name'] = name
2362
2363 try:
2364 check_client_version(ctx.obj, ctx.command.name)
2365 ctx.obj.project.update(project, project_changes)
2366 except ClientException as e:
2367 print(str(e))
2368
2369
2370 ####################
2371 # User mgmt operations
2372 ####################
2373
2374 @cli.command(name='user-create', short_help='creates a new user')
2375 @click.argument('username')
2376 @click.option('--password',
2377 prompt=True,
2378 hide_input=True,
2379 confirmation_prompt=True,
2380 help='user password')
2381 @click.option('--projects',
2382 # prompt="Comma separate list of projects",
2383 multiple=True,
2384 callback=lambda ctx, param, value: ''.join(value).split(',') if all(len(x)==1 for x in value) else value,
2385 help='list of project ids that the user belongs to')
2386 @click.option('--project-role-mappings', 'project_role_mappings',
2387 default=None, multiple=True,
2388 help='creating user project/role(s) mapping')
2389 @click.pass_context
2390 def user_create(ctx, username, password, projects, project_role_mappings):
2391 """Creates a new user
2392
2393 \b
2394 USERNAME: name of the user
2395 PASSWORD: password of the user
2396 PROJECTS: projects assigned to user (internal only)
2397 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
2398 """
2399 user = {}
2400 user['username'] = username
2401 user['password'] = password
2402 user['projects'] = projects
2403 user['project_role_mappings'] = project_role_mappings
2404
2405 try:
2406 check_client_version(ctx.obj, ctx.command.name)
2407 ctx.obj.user.create(username, user)
2408 except ClientException as e:
2409 print(str(e))
2410 exit(1)
2411
2412
2413 @cli.command(name='user-update', short_help='updates user information')
2414 @click.argument('username')
2415 @click.option('--password',
2416 # prompt=True,
2417 # hide_input=True,
2418 # confirmation_prompt=True,
2419 help='user password')
2420 @click.option('--set-username', 'set_username',
2421 default=None,
2422 help='change username')
2423 @click.option('--set-project', 'set_project',
2424 default=None, multiple=True,
2425 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
2426 @click.option('--remove-project', 'remove_project',
2427 default=None, multiple=True,
2428 help='removes project from user: \'project\'')
2429 @click.option('--add-project-role', 'add_project_role',
2430 default=None, multiple=True,
2431 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
2432 @click.option('--remove-project-role', 'remove_project_role',
2433 default=None, multiple=True,
2434 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
2435 @click.pass_context
2436 def user_update(ctx, username, password, set_username, set_project, remove_project,
2437 add_project_role, remove_project_role):
2438 """Update a user information
2439
2440 \b
2441 USERNAME: name of the user
2442 PASSWORD: new password
2443 SET_USERNAME: new username
2444 SET_PROJECT: creating mappings for project/role(s)
2445 REMOVE_PROJECT: deleting mappings for project/role(s)
2446 ADD_PROJECT_ROLE: adding mappings for project/role(s)
2447 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
2448 """
2449 user = {}
2450 user['password'] = password
2451 user['username'] = set_username
2452 user['set-project'] = set_project
2453 user['remove-project'] = remove_project
2454 user['add-project-role'] = add_project_role
2455 user['remove-project-role'] = remove_project_role
2456
2457 try:
2458 check_client_version(ctx.obj, ctx.command.name)
2459 ctx.obj.user.update(username, user)
2460 except ClientException as e:
2461 print(str(e))
2462 exit(1)
2463
2464
2465 @cli.command(name='user-delete', short_help='deletes a user')
2466 @click.argument('name')
2467 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2468 @click.pass_context
2469 def user_delete(ctx, name):
2470 """deletes a user
2471
2472 \b
2473 NAME: name or ID of the user to be deleted
2474 """
2475 try:
2476 check_client_version(ctx.obj, ctx.command.name)
2477 ctx.obj.user.delete(name)
2478 except ClientException as e:
2479 print(str(e))
2480 exit(1)
2481
2482
2483 @cli.command(name='user-list', short_help='list all users')
2484 @click.option('--filter', default=None,
2485 help='restricts the list to the users matching the filter')
2486 @click.pass_context
2487 def user_list(ctx, filter):
2488 """list all users"""
2489 try:
2490 check_client_version(ctx.obj, ctx.command.name)
2491 resp = ctx.obj.user.list(filter)
2492 except ClientException as e:
2493 print(str(e))
2494 exit(1)
2495 table = PrettyTable(['name', 'id'])
2496 for user in resp:
2497 table.add_row([user['username'], user['_id']])
2498 table.align = 'l'
2499 print(table)
2500
2501
2502 @cli.command(name='user-show', short_help='shows the details of a user')
2503 @click.argument('name')
2504 @click.pass_context
2505 def user_show(ctx, name):
2506 """shows the details of a user
2507
2508 NAME: name or ID of the user
2509 """
2510 try:
2511 check_client_version(ctx.obj, ctx.command.name)
2512 resp = ctx.obj.user.get(name)
2513 if 'password' in resp:
2514 resp['password']='********'
2515 except ClientException as e:
2516 print(str(e))
2517 exit(1)
2518
2519 table = PrettyTable(['key', 'attribute'])
2520 for k, v in resp.items():
2521 table.add_row([k, json.dumps(v, indent=2)])
2522 table.align = 'l'
2523 print(table)
2524
2525
2526 ####################
2527 # Fault Management operations
2528 ####################
2529
2530 @cli.command(name='ns-alarm-create')
2531 @click.argument('name')
2532 @click.option('--ns', prompt=True, help='NS instance id or name')
2533 @click.option('--vnf', prompt=True,
2534 help='VNF name (VNF member index as declared in the NSD)')
2535 @click.option('--vdu', prompt=True,
2536 help='VDU name (VDU name as declared in the VNFD)')
2537 @click.option('--metric', prompt=True,
2538 help='Name of the metric (e.g. cpu_utilization)')
2539 @click.option('--severity', default='WARNING',
2540 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
2541 @click.option('--threshold_value', prompt=True,
2542 help='threshold value that, when crossed, an alarm is triggered')
2543 @click.option('--threshold_operator', prompt=True,
2544 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
2545 @click.option('--statistic', default='AVERAGE',
2546 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
2547 @click.pass_context
2548 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
2549 threshold_value, threshold_operator, statistic):
2550 """creates a new alarm for a NS instance"""
2551 # TODO: Check how to validate threshold_value.
2552 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
2553 try:
2554 ns_instance = ctx.obj.ns.get(ns)
2555 alarm = {}
2556 alarm['alarm_name'] = name
2557 alarm['ns_id'] = ns_instance['_id']
2558 alarm['correlation_id'] = ns_instance['_id']
2559 alarm['vnf_member_index'] = vnf
2560 alarm['vdu_name'] = vdu
2561 alarm['metric_name'] = metric
2562 alarm['severity'] = severity
2563 alarm['threshold_value'] = int(threshold_value)
2564 alarm['operation'] = threshold_operator
2565 alarm['statistic'] = statistic
2566 check_client_version(ctx.obj, ctx.command.name)
2567 ctx.obj.ns.create_alarm(alarm)
2568 except ClientException as e:
2569 print(str(e))
2570 exit(1)
2571
2572
2573 #@cli.command(name='ns-alarm-delete')
2574 #@click.argument('name')
2575 #@click.pass_context
2576 #def ns_alarm_delete(ctx, name):
2577 # """deletes an alarm
2578 #
2579 # NAME: name of the alarm to be deleted
2580 # """
2581 # try:
2582 # check_client_version(ctx.obj, ctx.command.name)
2583 # ctx.obj.ns.delete_alarm(name)
2584 # except ClientException as e:
2585 # print(str(e))
2586 # exit(1)
2587
2588
2589 ####################
2590 # Performance Management operations
2591 ####################
2592
2593 @cli.command(name='ns-metric-export', short_help='exports a metric to the internal OSM bus, which can be read by other apps')
2594 @click.option('--ns', prompt=True, help='NS instance id or name')
2595 @click.option('--vnf', prompt=True,
2596 help='VNF name (VNF member index as declared in the NSD)')
2597 @click.option('--vdu', prompt=True,
2598 help='VDU name (VDU name as declared in the VNFD)')
2599 @click.option('--metric', prompt=True,
2600 help='name of the metric (e.g. cpu_utilization)')
2601 #@click.option('--period', default='1w',
2602 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
2603 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
2604 @click.pass_context
2605 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
2606 """exports a metric to the internal OSM bus, which can be read by other apps"""
2607 # TODO: Check how to validate interval.
2608 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
2609 try:
2610 ns_instance = ctx.obj.ns.get(ns)
2611 metric_data = {}
2612 metric_data['ns_id'] = ns_instance['_id']
2613 metric_data['correlation_id'] = ns_instance['_id']
2614 metric_data['vnf_member_index'] = vnf
2615 metric_data['vdu_name'] = vdu
2616 metric_data['metric_name'] = metric
2617 metric_data['collection_unit'] = 'WEEK'
2618 metric_data['collection_period'] = 1
2619 check_client_version(ctx.obj, ctx.command.name)
2620 if not interval:
2621 print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
2622 else:
2623 i = 1
2624 while True:
2625 print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
2626 time.sleep(int(interval))
2627 i+=1
2628 except ClientException as e:
2629 print(str(e))
2630 exit(1)
2631
2632
2633 ####################
2634 # Other operations
2635 ####################
2636
2637 @cli.command(name='upload-package', short_help='uploads a VNF package or NS package')
2638 @click.argument('filename')
2639 @click.pass_context
2640 def upload_package(ctx, filename):
2641 """uploads a VNF package or NS package
2642
2643 FILENAME: VNF or NS package file (tar.gz)
2644 """
2645 try:
2646 ctx.obj.package.upload(filename)
2647 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
2648 if fullclassname != 'osmclient.sol005.client.Client':
2649 ctx.obj.package.wait_for_upload(filename)
2650 except ClientException as e:
2651 print(str(e))
2652 exit(1)
2653
2654
2655 #@cli.command(name='ns-scaling-show')
2656 #@click.argument('ns_name')
2657 #@click.pass_context
2658 #def show_ns_scaling(ctx, ns_name):
2659 # """shows the status of a NS scaling operation
2660 #
2661 # NS_NAME: name of the NS instance being scaled
2662 # """
2663 # try:
2664 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2665 # resp = ctx.obj.ns.list()
2666 # except ClientException as e:
2667 # print(str(e))
2668 # exit(1)
2669 #
2670 # table = PrettyTable(
2671 # ['group-name',
2672 # 'instance-id',
2673 # 'operational status',
2674 # 'create-time',
2675 # 'vnfr ids'])
2676 #
2677 # for ns in resp:
2678 # if ns_name == ns['name']:
2679 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
2680 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
2681 # for record in scaling_records:
2682 # if 'instance' in record:
2683 # instances = record['instance']
2684 # for inst in instances:
2685 # table.add_row(
2686 # [record['scaling-group-name-ref'],
2687 # inst['instance-id'],
2688 # inst['op-status'],
2689 # time.strftime('%Y-%m-%d %H:%M:%S',
2690 # time.localtime(
2691 # inst['create-time'])),
2692 # inst['vnfrs']])
2693 # table.align = 'l'
2694 # print(table)
2695
2696
2697 #@cli.command(name='ns-scale')
2698 #@click.argument('ns_name')
2699 #@click.option('--ns_scale_group', prompt=True)
2700 #@click.option('--index', prompt=True)
2701 #@click.option('--wait',
2702 # required=False,
2703 # default=False,
2704 # is_flag=True,
2705 # help='do not return the control immediately, but keep it \
2706 # until the operation is completed, or timeout')
2707 #@click.pass_context
2708 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
2709 # """scales NS
2710 #
2711 # NS_NAME: name of the NS instance to be scaled
2712 # """
2713 # try:
2714 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2715 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
2716 # except ClientException as e:
2717 # print(str(e))
2718 # exit(1)
2719
2720
2721 #@cli.command(name='config-agent-list')
2722 #@click.pass_context
2723 #def config_agent_list(ctx):
2724 # """list config agents"""
2725 # try:
2726 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2727 # except ClientException as e:
2728 # print(str(e))
2729 # exit(1)
2730 # table = PrettyTable(['name', 'account-type', 'details'])
2731 # for account in ctx.obj.vca.list():
2732 # table.add_row(
2733 # [account['name'],
2734 # account['account-type'],
2735 # account['juju']])
2736 # table.align = 'l'
2737 # print(table)
2738
2739
2740 #@cli.command(name='config-agent-delete')
2741 #@click.argument('name')
2742 #@click.pass_context
2743 #def config_agent_delete(ctx, name):
2744 # """deletes a config agent
2745 #
2746 # NAME: name of the config agent to be deleted
2747 # """
2748 # try:
2749 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2750 # ctx.obj.vca.delete(name)
2751 # except ClientException as e:
2752 # print(str(e))
2753 # exit(1)
2754
2755
2756 #@cli.command(name='config-agent-add')
2757 #@click.option('--name',
2758 # prompt=True)
2759 #@click.option('--account_type',
2760 # prompt=True)
2761 #@click.option('--server',
2762 # prompt=True)
2763 #@click.option('--user',
2764 # prompt=True)
2765 #@click.option('--secret',
2766 # prompt=True,
2767 # hide_input=True,
2768 # confirmation_prompt=True)
2769 #@click.pass_context
2770 #def config_agent_add(ctx, name, account_type, server, user, secret):
2771 # """adds a config agent"""
2772 # try:
2773 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2774 # ctx.obj.vca.create(name, account_type, server, user, secret)
2775 # except ClientException as e:
2776 # print(str(e))
2777 # exit(1)
2778
2779
2780 #@cli.command(name='ro-dump')
2781 #@click.pass_context
2782 #def ro_dump(ctx):
2783 # """shows RO agent information"""
2784 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2785 # resp = ctx.obj.vim.get_resource_orchestrator()
2786 # table = PrettyTable(['key', 'attribute'])
2787 # for k, v in list(resp.items()):
2788 # table.add_row([k, json.dumps(v, indent=2)])
2789 # table.align = 'l'
2790 # print(table)
2791
2792
2793 #@cli.command(name='vcs-list')
2794 #@click.pass_context
2795 #def vcs_list(ctx):
2796 # check_client_version(ctx.obj, ctx.command.name, 'v1')
2797 # resp = ctx.obj.utils.get_vcs_info()
2798 # table = PrettyTable(['component name', 'state'])
2799 # for component in resp:
2800 # table.add_row([component['component_name'], component['state']])
2801 # table.align = 'l'
2802 # print(table)
2803
2804
2805 @cli.command(name='ns-action', short_help='executes an action/primitive over a NS instance')
2806 @click.argument('ns_name')
2807 @click.option('--vnf_name', default=None, help='member-vnf-index if the target is a vnf instead of a ns)')
2808 @click.option('--vdu_id', default=None, help='vdu-id if the target is a vdu o a vnf')
2809 @click.option('--vdu_count', default=None, help='number of vdu instance of this vdu_id')
2810 @click.option('--action_name', prompt=True)
2811 @click.option('--params', default=None)
2812 @click.option('--wait',
2813 required=False,
2814 default=False,
2815 is_flag=True,
2816 help='do not return the control immediately, but keep it \
2817 until the operation is completed, or timeout')
2818 @click.pass_context
2819 def ns_action(ctx,
2820 ns_name,
2821 vnf_name,
2822 vdu_id,
2823 vdu_count,
2824 action_name,
2825 params,
2826 wait):
2827 """executes an action/primitive over a NS instance
2828
2829 NS_NAME: name or ID of the NS instance
2830 """
2831 try:
2832 check_client_version(ctx.obj, ctx.command.name)
2833 op_data = {}
2834 if vnf_name:
2835 op_data['member_vnf_index'] = vnf_name
2836 if vdu_id:
2837 op_data['vdu_id'] = vdu_id
2838 if vdu_count:
2839 op_data['vdu_count_index'] = vdu_count
2840 op_data['primitive'] = action_name
2841 if params:
2842 op_data['primitive_params'] = yaml.safe_load(params)
2843 else:
2844 op_data['primitive_params'] = {}
2845 ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data, wait=wait)
2846
2847 except ClientException as e:
2848 print(str(e))
2849 exit(1)
2850
2851
2852 @cli.command(name='vnf-scale', short_help='executes a VNF scale (adding/removing VDUs)')
2853 @click.argument('ns_name')
2854 @click.argument('vnf_name')
2855 @click.option('--scaling-group', prompt=True, help="scaling-group-descriptor name to use")
2856 @click.option('--scale-in', default=False, is_flag=True, help="performs a scale in operation")
2857 @click.option('--scale-out', default=False, is_flag=True, help="performs a scale out operation (by default)")
2858 @click.pass_context
2859 def vnf_scale(ctx,
2860 ns_name,
2861 vnf_name,
2862 scaling_group,
2863 scale_in,
2864 scale_out):
2865 """
2866 Executes a VNF scale (adding/removing VDUs)
2867
2868 \b
2869 NS_NAME: name or ID of the NS instance.
2870 VNF_NAME: member-vnf-index in the NS to be scaled.
2871 """
2872 try:
2873 check_client_version(ctx.obj, ctx.command.name)
2874 if not scale_in and not scale_out:
2875 scale_out = True
2876 ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out)
2877 except ClientException as e:
2878 print(str(e))
2879 exit(1)
2880
2881
2882 ##############################
2883 # Role Management Operations #
2884 ##############################
2885
2886 @cli.command(name='role-create', short_help='creates a new role')
2887 @click.argument('name')
2888 @click.option('--permissions',
2889 default=None,
2890 help='role permissions using a dictionary')
2891 @click.pass_context
2892 def role_create(ctx, name, permissions):
2893 """
2894 Creates a new role.
2895
2896 \b
2897 NAME: Name or ID of the role.
2898 DEFINITION: Definition of grant/denial of access to resources.
2899 """
2900 try:
2901 check_client_version(ctx.obj, ctx.command.name)
2902 ctx.obj.role.create(name, permissions)
2903 except ClientException as e:
2904 print(str(e))
2905 exit(1)
2906
2907
2908 @cli.command(name='role-update', short_help='updates a role')
2909 @click.argument('name')
2910 @click.option('--set-name',
2911 default=None,
2912 help='change name of rle')
2913 # @click.option('--permissions',
2914 # default=None,
2915 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
2916 @click.option('--add',
2917 default=None,
2918 help='yaml format dictionary with permission: True/False to access grant/denial')
2919 @click.option('--remove',
2920 default=None,
2921 help='yaml format list to remove a permission')
2922 @click.pass_context
2923 def role_update(ctx, name, set_name, add, remove):
2924 """
2925 Updates a role.
2926
2927 \b
2928 NAME: Name or ID of the role.
2929 DEFINITION: Definition overwrites the old definition.
2930 ADD: Grant/denial of access to resource to add.
2931 REMOVE: Grant/denial of access to resource to remove.
2932 """
2933 try:
2934 check_client_version(ctx.obj, ctx.command.name)
2935 ctx.obj.role.update(name, set_name, None, add, remove)
2936 except ClientException as e:
2937 print(str(e))
2938 exit(1)
2939
2940
2941 @cli.command(name='role-delete', short_help='deletes a role')
2942 @click.argument('name')
2943 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2944 @click.pass_context
2945 def role_delete(ctx, name):
2946 """
2947 Deletes a role.
2948
2949 \b
2950 NAME: Name or ID of the role.
2951 """
2952 try:
2953 check_client_version(ctx.obj, ctx.command.name)
2954 ctx.obj.role.delete(name)
2955 except ClientException as e:
2956 print(str(e))
2957 exit(1)
2958
2959
2960 @cli.command(name='role-list', short_help='list all roles')
2961 @click.option('--filter', default=None,
2962 help='restricts the list to the projects matching the filter')
2963 @click.pass_context
2964 def role_list(ctx, filter):
2965 """
2966 List all roles.
2967 """
2968 try:
2969 check_client_version(ctx.obj, ctx.command.name)
2970 resp = ctx.obj.role.list(filter)
2971 except ClientException as e:
2972 print(str(e))
2973 exit(1)
2974 table = PrettyTable(['name', 'id'])
2975 for role in resp:
2976 table.add_row([role['name'], role['_id']])
2977 table.align = 'l'
2978 print(table)
2979
2980
2981 @cli.command(name='role-show', short_help='show specific role')
2982 @click.argument('name')
2983 @click.pass_context
2984 def role_show(ctx, name):
2985 """
2986 Shows the details of a role.
2987
2988 \b
2989 NAME: Name or ID of the role.
2990 """
2991 try:
2992 check_client_version(ctx.obj, ctx.command.name)
2993 resp = ctx.obj.role.get(name)
2994 except ClientException as e:
2995 print(str(e))
2996 exit(1)
2997
2998 table = PrettyTable(['key', 'attribute'])
2999 for k, v in resp.items():
3000 table.add_row([k, json.dumps(v, indent=2)])
3001 table.align = 'l'
3002 print(table)
3003
3004
3005 @cli.command(name='package-create',
3006 short_help='Create a package descriptor')
3007 @click.argument('package-type')
3008 @click.argument('package-name')
3009 @click.option('--base-directory',
3010 default='.',
3011 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
3012 @click.option('--image',
3013 default="image-name",
3014 help='(VNF) Set the name of the vdu image. Default "image-name"')
3015 @click.option('--vdus',
3016 default=1,
3017 help='(VNF) Set the number of vdus in a VNF. Default 1')
3018 @click.option('--vcpu',
3019 default=1,
3020 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
3021 @click.option('--memory',
3022 default=1024,
3023 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
3024 @click.option('--storage',
3025 default=10,
3026 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
3027 @click.option('--interfaces',
3028 default=0,
3029 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
3030 @click.option('--vendor',
3031 default="OSM",
3032 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
3033 @click.option('--override',
3034 default=False,
3035 is_flag=True,
3036 help='(NS/VNF/NST) Flag for overriding the package if exists.')
3037 @click.option('--detailed',
3038 is_flag=True,
3039 default=False,
3040 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
3041 @click.option('--netslice-subnets',
3042 default=1,
3043 help='(NST) Number of netslice subnets. Default 1')
3044 @click.option('--netslice-vlds',
3045 default=1,
3046 help='(NST) Number of netslice vlds. Default 1')
3047 @click.pass_context
3048 def package_create(ctx,
3049 package_type,
3050 base_directory,
3051 package_name,
3052 override,
3053 image,
3054 vdus,
3055 vcpu,
3056 memory,
3057 storage,
3058 interfaces,
3059 vendor,
3060 detailed,
3061 netslice_subnets,
3062 netslice_vlds):
3063 """
3064 Creates an OSM NS, VNF, NST package
3065
3066 \b
3067 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
3068 PACKAGE_NAME: Name of the package to create the folder with the content.
3069 """
3070
3071 try:
3072 check_client_version(ctx.obj, ctx.command.name)
3073 print("Creating the {} structure: {}/{}".format(package_type.upper(), base_directory, package_name))
3074 resp = ctx.obj.package_tool.create(package_type,
3075 base_directory,
3076 package_name,
3077 override=override,
3078 image=image,
3079 vdus=vdus,
3080 vcpu=vcpu,
3081 memory=memory,
3082 storage=storage,
3083 interfaces=interfaces,
3084 vendor=vendor,
3085 detailed=detailed,
3086 netslice_subnets=netslice_subnets,
3087 netslice_vlds=netslice_vlds)
3088 print(resp)
3089 except ClientException as inst:
3090 print("ERROR: {}".format(inst))
3091 exit(1)
3092
3093 @cli.command(name='package-validate',
3094 short_help='Validate a package descriptor')
3095 @click.argument('base-directory',
3096 default=".",
3097 required=False)
3098 @click.pass_context
3099 def package_validate(ctx,
3100 base_directory):
3101 """
3102 Validate descriptors given a base directory.
3103
3104 \b
3105 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
3106 """
3107 try:
3108 check_client_version(ctx.obj, ctx.command.name)
3109 results = ctx.obj.package_tool.validate(base_directory)
3110 table = PrettyTable()
3111 table.field_names = ["TYPE", "PATH", "VALID", "ERROR"]
3112 # Print the dictionary generated by the validation function
3113 for result in results:
3114 table.add_row([result["type"], result["path"], result["valid"], result["error"]])
3115 table.sortby = "VALID"
3116 table.align["PATH"] = "l"
3117 table.align["TYPE"] = "l"
3118 table.align["ERROR"] = "l"
3119 print(table)
3120 except ClientException as inst:
3121 print("ERROR: {}".format(inst))
3122 exit(1)
3123
3124 @cli.command(name='package-build',
3125 short_help='Build the tar.gz of the package')
3126 @click.argument('package-folder')
3127 @click.option('--skip-validation',
3128 default=False,
3129 is_flag=True,
3130 help='skip package validation')
3131 @click.pass_context
3132 def package_build(ctx,
3133 package_folder,
3134 skip_validation):
3135 """
3136 Build the package NS, VNF given the package_folder.
3137
3138 \b
3139 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
3140 """
3141 try:
3142 check_client_version(ctx.obj, ctx.command.name)
3143 results = ctx.obj.package_tool.build(package_folder, skip_validation)
3144 print(results)
3145 except ClientException as inst:
3146 print("ERROR: {}".format(inst))
3147 exit(1)
3148
3149
3150 if __name__ == '__main__':
3151 try:
3152 cli()
3153 except pycurl.error as e:
3154 print(e)
3155 print('Maybe "--hostname" option or OSM_HOSTNAME' +
3156 'environment variable needs to be specified')
3157 exit(1)