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