2c151ffeca03ef16ce48f6d14f610d9326914aea
[osm/osmclient.git] / osmclient / scripts / osm.py
1 # Copyright 2017-2018 Sandvine
2 # Copyright 2018 Telefonica
3 #
4 # All Rights Reserved.
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
16 # under the License.
17 """
18 OSM shell/cli
19 """
20
21 import click
22 from osmclient import client
23 from osmclient.common.exceptions import ClientException
24 from prettytable import PrettyTable
25 import yaml
26 import json
27 import time
28 import pycurl
29
30 def check_client_version(obj, what, version='sol005'):
31 '''
32 Checks the version of the client object and raises error if it not the expected.
33
34 :param obj: the client object
35 :what: the function or command under evaluation (used when an error is raised)
36 :return: -
37 :raises ClientError: if the specified version does not match the client version
38 '''
39 fullclassname = obj.__module__ + "." + obj.__class__.__name__
40 message = 'The following commands or options are only supported with the option "--sol005": {}'.format(what)
41 if version == 'v1':
42 message = 'The following commands or options are not supported when using option "--sol005": {}'.format(what)
43 if fullclassname != 'osmclient.{}.client.Client'.format(version):
44 raise ClientException(message)
45 return
46
47 @click.group()
48 @click.option('--hostname',
49 default="127.0.0.1",
50 envvar='OSM_HOSTNAME',
51 help='hostname of server. ' +
52 'Also can set OSM_HOSTNAME in environment')
53 @click.option('--sol005/--no-sol005',
54 default=True,
55 envvar='OSM_SOL005',
56 help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
57 'Also can set OSM_SOL005 in environment')
58 @click.option('--user',
59 default=None,
60 envvar='OSM_USER',
61 help='user (only from Release FOUR, defaults to admin). ' +
62 'Also can set OSM_USER in environment')
63 @click.option('--password',
64 default=None,
65 envvar='OSM_PASSWORD',
66 help='password (only from Release FOUR, defaults to admin). ' +
67 'Also can set OSM_PASSWORD in environment')
68 @click.option('--project',
69 default=None,
70 envvar='OSM_PROJECT',
71 help='project (only from Release FOUR, defaults to admin). ' +
72 'Also can set OSM_PROJECT in environment')
73 @click.option('--so-port',
74 default=None,
75 envvar='OSM_SO_PORT',
76 help='hostname of server. ' +
77 'Also can set OSM_SO_PORT in environment')
78 @click.option('--so-project',
79 default=None,
80 envvar='OSM_SO_PROJECT',
81 help='Project Name in SO. ' +
82 'Also can set OSM_SO_PROJECT in environment')
83 @click.option('--ro-hostname',
84 default=None,
85 envvar='OSM_RO_HOSTNAME',
86 help='hostname of RO server. ' +
87 'Also can set OSM_RO_HOSTNAME in environment')
88 @click.option('--ro-port',
89 default=None,
90 envvar='OSM_RO_PORT',
91 help='hostname of RO server. ' +
92 'Also can set OSM_RO_PORT in environment')
93 @click.pass_context
94 def cli(ctx, hostname, sol005, user, password, project, so_port, so_project, ro_hostname, ro_port):
95 if hostname is None:
96 print((
97 "either hostname option or OSM_HOSTNAME " +
98 "environment variable needs to be specified"))
99 exit(1)
100 kwargs={}
101 if so_port is not None:
102 kwargs['so_port']=so_port
103 if so_project is not None:
104 kwargs['so_project']=so_project
105 if ro_hostname is not None:
106 kwargs['ro_host']=ro_hostname
107 if ro_port is not None:
108 kwargs['ro_port']=ro_port
109 if user is not None:
110 kwargs['user']=user
111 if password is not None:
112 kwargs['password']=password
113 if project is not None:
114 kwargs['project']=project
115
116 ctx.obj = client.Client(host=hostname, sol005=sol005, **kwargs)
117
118
119 ####################
120 # LIST operations
121 ####################
122
123 @cli.command(name='ns-list')
124 @click.option('--filter', default=None,
125 help='restricts the list to the NS instances matching the filter.')
126 @click.pass_context
127 def ns_list(ctx, filter):
128 '''list all NS instances
129
130 \b
131 Options:
132 --filter filterExpr Restricts the list to the NS instances matching the filter
133
134 \b
135 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
136 concatenated using the "&" character:
137
138 \b
139 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
140 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
141 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
142 attrName := string
143 value := scalar value
144
145 \b
146 where:
147 * zero or more occurrences
148 ? zero or one occurrence
149 [] grouping of expressions to be used with ? and *
150 "" quotation marks for marking string constants
151 <> name separator
152
153 \b
154 "AttrName" is the name of one attribute in the data type that defines the representation
155 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
156 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
157 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
158 entries, it means that the operator "op" is applied to the attribute addressed by the last
159 <attrName> entry included in the concatenation. All simple filter expressions are combined
160 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
161 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
162 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
163 prefix". If an attribute referenced in an expression is an array, an object that contains a
164 corresponding array shall be considered to match the expression if any of the elements in the
165 array matches all expressions that have the same attribute prefix.
166
167 \b
168 Filter examples:
169 --filter admin-status=ENABLED
170 --filter nsd-ref=<NSD_NAME>
171 --filter nsd.vendor=<VENDOR>
172 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
173 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
174 '''
175 if filter:
176 check_client_version(ctx.obj, '--filter')
177 resp = ctx.obj.ns.list(filter)
178 else:
179 resp = ctx.obj.ns.list()
180 table = PrettyTable(
181 ['ns instance name',
182 'id',
183 'operational status',
184 'config status',
185 'detailed status'])
186 for ns in resp:
187 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
188 if fullclassname == 'osmclient.sol005.client.Client':
189 nsr = ns
190 nsr_name = nsr['name']
191 nsr_id = nsr['_id']
192 else:
193 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
194 nsr = nsopdata['nsr:nsr']
195 nsr_name = nsr['name-ref']
196 nsr_id = nsr['ns-instance-config-ref']
197 opstatus = nsr['operational-status'] if 'operational-status' in nsr else 'Not found'
198 configstatus = nsr['config-status'] if 'config-status' in nsr else 'Not found'
199 detailed_status = nsr['detailed-status'] if 'detailed-status' in nsr else 'Not found'
200 if configstatus == "config_not_needed":
201 configstatus = "configured (no charms)"
202 table.add_row(
203 [nsr_name,
204 nsr_id,
205 opstatus,
206 configstatus,
207 detailed_status])
208 table.align = 'l'
209 print(table)
210
211
212 def nsd_list(ctx, filter):
213 if filter:
214 check_client_version(ctx.obj, '--filter')
215 resp = ctx.obj.nsd.list(filter)
216 else:
217 resp = ctx.obj.nsd.list()
218 #print yaml.safe_dump(resp)
219 table = PrettyTable(['nsd name', 'id'])
220 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
221 if fullclassname == 'osmclient.sol005.client.Client':
222 for ns in resp:
223 name = ns['name'] if 'name' in ns else '-'
224 table.add_row([name, ns['_id']])
225 else:
226 for ns in resp:
227 table.add_row([ns['name'], ns['id']])
228 table.align = 'l'
229 print(table)
230
231
232 @cli.command(name='nsd-list')
233 @click.option('--filter', default=None,
234 help='restricts the list to the NSD/NSpkg matching the filter')
235 @click.pass_context
236 def nsd_list1(ctx, filter):
237 '''list all NSD/NSpkg in the system'''
238 nsd_list(ctx,filter)
239
240
241 @cli.command(name='nspkg-list')
242 @click.option('--filter', default=None,
243 help='restricts the list to the NSD/NSpkg matching the filter')
244 @click.pass_context
245 def nsd_list2(ctx, filter):
246 '''list all NSD/NSpkg in the system'''
247 nsd_list(ctx,filter)
248
249
250 def vnfd_list(ctx, nf_type, filter):
251 if nf_type:
252 check_client_version(ctx.obj, '--nf_type')
253 elif filter:
254 check_client_version(ctx.obj, '--filter')
255 if nf_type:
256 if nf_type == "vnf":
257 nf_filter = "_admin.type=vnfd"
258 elif nf_type == "pnf":
259 nf_filter = "_admin.type=pnfd"
260 elif nf_type == "hnf":
261 nf_filter = "_admin.type=hnfd"
262 else:
263 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
264 if filter:
265 filter = '{}&{}'.format(nf_filter, filter)
266 else:
267 filter = nf_filter
268 if filter:
269 resp = ctx.obj.vnfd.list(filter)
270 else:
271 resp = ctx.obj.vnfd.list()
272 #print yaml.safe_dump(resp)
273 table = PrettyTable(['vnfd name', 'id'])
274 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
275 if fullclassname == 'osmclient.sol005.client.Client':
276 for vnfd in resp:
277 name = vnfd['name'] if 'name' in vnfd else '-'
278 table.add_row([name, vnfd['_id']])
279 else:
280 for vnfd in resp:
281 table.add_row([vnfd['name'], vnfd['id']])
282 table.align = 'l'
283 print(table)
284
285
286 @cli.command(name='vnfd-list')
287 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
288 @click.option('--filter', default=None,
289 help='restricts the list to the NFpkg matching the filter')
290 @click.pass_context
291 def vnfd_list1(ctx, nf_type, filter):
292 '''list all VNFD/VNFpkg in the system'''
293 vnfd_list(ctx, nf_type, filter)
294
295
296 @cli.command(name='vnfpkg-list')
297 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
298 @click.option('--filter', default=None,
299 help='restricts the list to the NFpkg matching the filter')
300 @click.pass_context
301 def vnfd_list2(ctx, nf_type, filter):
302 '''list all VNFD/VNFpkg in the system'''
303 vnfd_list(ctx, nf_type, filter)
304
305
306 @cli.command(name='nfpkg-list')
307 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
308 @click.option('--filter', default=None,
309 help='restricts the list to the NFpkg matching the filter')
310 @click.pass_context
311 def nfpkg_list(ctx, nf_type, filter):
312 '''list all NFpkg (VNFpkg, PNFpkg, HNFpkg) in the system'''
313 try:
314 check_client_version(ctx.obj, ctx.command.name)
315 vnfd_list(ctx,nf_type,filter)
316 except ClientException as inst:
317 print((inst.message))
318 exit(1)
319
320
321 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]'
1228 '],\n'
1229 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1230 )
1231 @click.option('--config_file',
1232 default=None,
1233 help='nsi specific yaml configuration file')
1234 @click.pass_context
1235 def nsi_create1(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file):
1236 '''creates a new Network Slice Instance (NSI)'''
1237 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file)
1238
1239
1240 @cli.command(name='netslice-instance-create', short_help='creates a new Network Slice Instance')
1241 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1242 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1243 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1244 @click.option('--ssh_keys', default=None,
1245 help='comma separated list of keys to inject to vnfs')
1246 @click.option('--config', default=None,
1247 help='Netslice specific yaml configuration:\n'
1248 'netslice_subnet: [\n'
1249 'id: TEXT, vim_account: TEXT,\n'
1250 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1251 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1252 '],\n'
1253 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1254 )
1255 @click.option('--config_file',
1256 default=None,
1257 help='nsi specific yaml configuration file')
1258 @click.pass_context
1259 def nsi_create2(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file):
1260 '''creates a new Network Slice Instance (NSI)'''
1261 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file)
1262
1263
1264 @cli.command(name='pdu-create', short_help='adds a new Physical Deployment Unit to the catalog')
1265 @click.option('--name', help='name of the Physical Deployment Unit')
1266 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1267 @click.option('--interface',
1268 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1269 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1270 multiple=True)
1271 @click.option('--description', help='human readable description')
1272 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple=True)
1273 @click.option('--descriptor_file', default=None, help='PDU descriptor file (as an alternative to using the other arguments')
1274 @click.pass_context
1275 def pdu_create(ctx, name, pdu_type, interface, description, vim_account, descriptor_file):
1276 '''creates a new Physical Deployment Unit (PDU)'''
1277 try:
1278 check_client_version(ctx.obj, ctx.command.name)
1279 pdu = {}
1280 if not descriptor_file:
1281 if not name:
1282 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1283 if not pdu_type:
1284 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1285 if not interface:
1286 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1287 if not vim_account:
1288 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1289 else:
1290 with open(descriptor_file, 'r') as df:
1291 pdu = yaml.load(df.read())
1292 if name: pdu["name"] = name
1293 if pdu_type: pdu["type"] = pdu_type
1294 if description: pdu["description"] = description
1295 if vim_account: pdu["vim_accounts"] = vim_account
1296 if interface:
1297 ifaces_list = []
1298 for iface in interface:
1299 new_iface={k:v for k,v in [i.split('=') for i in iface.split(',')]}
1300 new_iface["mgmt"] = (new_iface.get("mgmt","false").lower() == "true")
1301 ifaces_list.append(new_iface)
1302 pdu["interfaces"] = ifaces_list
1303 ctx.obj.pdu.create(pdu)
1304 except ClientException as inst:
1305 print((inst.message))
1306 exit(1)
1307
1308
1309 ####################
1310 # UPDATE operations
1311 ####################
1312
1313 def nsd_update(ctx, name, content):
1314 try:
1315 check_client_version(ctx.obj, ctx.command.name)
1316 ctx.obj.nsd.update(name, content)
1317 except ClientException as inst:
1318 print((inst.message))
1319 exit(1)
1320
1321
1322 @cli.command(name='nsd-update', short_help='updates a NSD/NSpkg')
1323 @click.argument('name')
1324 @click.option('--content', default=None,
1325 help='filename with the NSD/NSpkg replacing the current one')
1326 @click.pass_context
1327 def nsd_update1(ctx, name, content):
1328 '''updates a NSD/NSpkg
1329
1330 NAME: name or ID of the NSD/NSpkg
1331 '''
1332 nsd_update(ctx, name, content)
1333
1334
1335 @cli.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
1336 @click.argument('name')
1337 @click.option('--content', default=None,
1338 help='filename with the NSD/NSpkg replacing the current one')
1339 @click.pass_context
1340 def nsd_update2(ctx, name, content):
1341 '''updates a NSD/NSpkg
1342
1343 NAME: name or ID of the NSD/NSpkg
1344 '''
1345 nsd_update(ctx, name, content)
1346
1347
1348 def vnfd_update(ctx, name, content):
1349 try:
1350 check_client_version(ctx.obj, ctx.command.name)
1351 ctx.obj.vnfd.update(name, content)
1352 except ClientException as inst:
1353 print((inst.message))
1354 exit(1)
1355
1356
1357 @cli.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
1358 @click.argument('name')
1359 @click.option('--content', default=None,
1360 help='filename with the VNFD/VNFpkg replacing the current one')
1361 @click.pass_context
1362 def vnfd_update1(ctx, name, content):
1363 '''updates a VNFD/VNFpkg
1364
1365 NAME: name or ID of the VNFD/VNFpkg
1366 '''
1367 vnfd_update(ctx, name, content)
1368
1369
1370 @cli.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
1371 @click.argument('name')
1372 @click.option('--content', default=None,
1373 help='filename with the VNFD/VNFpkg replacing the current one')
1374 @click.pass_context
1375 def vnfd_update2(ctx, name, content):
1376 '''updates a VNFD/VNFpkg
1377
1378 NAME: VNFD yaml file or VNFpkg tar.gz file
1379 '''
1380 vnfd_update(ctx, name, content)
1381
1382
1383 @cli.command(name='nfpkg-update', short_help='updates a NFpkg')
1384 @click.argument('name')
1385 @click.option('--content', default=None,
1386 help='filename with the NFpkg replacing the current one')
1387 @click.pass_context
1388 def nfpkg_update(ctx, name, content):
1389 '''updates a NFpkg
1390
1391 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1392 '''
1393 vnfd_update(ctx, name, content)
1394
1395
1396 def nst_update(ctx, name, content):
1397 try:
1398 check_client_version(ctx.obj, ctx.command.name)
1399 ctx.obj.nst.update(name, content)
1400 except ClientException as inst:
1401 print((inst.message))
1402 exit(1)
1403
1404
1405 @cli.command(name='nst-update', short_help='updates a Network Slice Template (NST)')
1406 @click.argument('name')
1407 @click.option('--content', default=None,
1408 help='filename with the NST/NSTpkg replacing the current one')
1409 @click.pass_context
1410 def nst_update1(ctx, name, content):
1411 '''updates a Network Slice Template (NST)
1412
1413 NAME: name or ID of the NSD/NSpkg
1414 '''
1415 nst_update(ctx, name, content)
1416
1417
1418 @cli.command(name='netslice-template-update', short_help='updates a Network Slice Template (NST)')
1419 @click.argument('name')
1420 @click.option('--content', default=None,
1421 help='filename with the NST/NSTpkg replacing the current one')
1422 @click.pass_context
1423 def nst_update2(ctx, name, content):
1424 '''updates a Network Slice Template (NST)
1425
1426 NAME: name or ID of the NSD/NSpkg
1427 '''
1428 nst_update(ctx, name, content)
1429
1430
1431 ####################
1432 # DELETE operations
1433 ####################
1434
1435 def nsd_delete(ctx, name, force):
1436 try:
1437 if not force:
1438 ctx.obj.nsd.delete(name)
1439 else:
1440 check_client_version(ctx.obj, '--force')
1441 ctx.obj.nsd.delete(name, force)
1442 except ClientException as inst:
1443 print((inst.message))
1444 exit(1)
1445
1446
1447 @cli.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
1448 @click.argument('name')
1449 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1450 @click.pass_context
1451 def nsd_delete1(ctx, name, force):
1452 '''deletes a NSD/NSpkg
1453
1454 NAME: name or ID of the NSD/NSpkg to be deleted
1455 '''
1456 nsd_delete(ctx, name, force)
1457
1458
1459 @cli.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
1460 @click.argument('name')
1461 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1462 @click.pass_context
1463 def nsd_delete2(ctx, name, force):
1464 '''deletes a NSD/NSpkg
1465
1466 NAME: name or ID of the NSD/NSpkg to be deleted
1467 '''
1468 nsd_delete(ctx, name, force)
1469
1470
1471 def vnfd_delete(ctx, name, force):
1472 try:
1473 if not force:
1474 ctx.obj.vnfd.delete(name)
1475 else:
1476 check_client_version(ctx.obj, '--force')
1477 ctx.obj.vnfd.delete(name, force)
1478 except ClientException as inst:
1479 print((inst.message))
1480 exit(1)
1481
1482
1483 @cli.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
1484 @click.argument('name')
1485 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1486 @click.pass_context
1487 def vnfd_delete1(ctx, name, force):
1488 '''deletes a VNFD/VNFpkg
1489
1490 NAME: name or ID of the VNFD/VNFpkg to be deleted
1491 '''
1492 vnfd_delete(ctx, name, force)
1493
1494
1495 @cli.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
1496 @click.argument('name')
1497 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1498 @click.pass_context
1499 def vnfd_delete2(ctx, name, force):
1500 '''deletes a VNFD/VNFpkg
1501
1502 NAME: name or ID of the VNFD/VNFpkg to be deleted
1503 '''
1504 vnfd_delete(ctx, name, force)
1505
1506
1507 @cli.command(name='nfpkg-delete', short_help='deletes a NFpkg')
1508 @click.argument('name')
1509 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1510 @click.pass_context
1511 def nfpkg_delete(ctx, name, force):
1512 '''deletes a NFpkg
1513
1514 NAME: name or ID of the NFpkg to be deleted
1515 '''
1516 vnfd_delete(ctx, name, force)
1517
1518
1519 @cli.command(name='ns-delete', short_help='deletes a NS instance')
1520 @click.argument('name')
1521 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1522 @click.pass_context
1523 def ns_delete(ctx, name, force):
1524 '''deletes a NS instance
1525
1526 NAME: name or ID of the NS instance to be deleted
1527 '''
1528 try:
1529 if not force:
1530 ctx.obj.ns.delete(name)
1531 else:
1532 check_client_version(ctx.obj, '--force')
1533 ctx.obj.ns.delete(name, force)
1534 except ClientException as inst:
1535 print((inst.message))
1536 exit(1)
1537
1538
1539 def nst_delete(ctx, name, force):
1540 try:
1541 check_client_version(ctx.obj, ctx.command.name)
1542 ctx.obj.nst.delete(name, force)
1543 except ClientException as inst:
1544 print((inst.message))
1545 exit(1)
1546
1547
1548 @cli.command(name='nst-delete', short_help='deletes a Network Slice Template (NST)')
1549 @click.argument('name')
1550 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1551 @click.pass_context
1552 def nst_delete1(ctx, name, force):
1553 '''deletes a Network Slice Template (NST)
1554
1555 NAME: name or ID of the NST/NSTpkg to be deleted
1556 '''
1557 nst_delete(ctx, name, force)
1558
1559
1560 @cli.command(name='netslice-template-delete', short_help='deletes a Network Slice Template (NST)')
1561 @click.argument('name')
1562 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1563 @click.pass_context
1564 def nst_delete2(ctx, name, force):
1565 '''deletes a Network Slice Template (NST)
1566
1567 NAME: name or ID of the NST/NSTpkg to be deleted
1568 '''
1569 nst_delete(ctx, name, force)
1570
1571
1572 def nsi_delete(ctx, name, force):
1573 try:
1574 check_client_version(ctx.obj, ctx.command.name)
1575 ctx.obj.nsi.delete(name, force)
1576 except ClientException as inst:
1577 print((inst.message))
1578 exit(1)
1579
1580
1581 @cli.command(name='nsi-delete', short_help='deletes a Network Slice Instance (NSI)')
1582 @click.argument('name')
1583 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1584 @click.pass_context
1585 def nsi_delete1(ctx, name, force):
1586 '''deletes a Network Slice Instance (NSI)
1587
1588 NAME: name or ID of the Network Slice instance to be deleted
1589 '''
1590 nsi_delete(ctx, name, force)
1591
1592
1593 @cli.command(name='netslice-instance-delete', short_help='deletes a Network Slice Instance (NSI)')
1594 @click.argument('name')
1595 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1596 @click.pass_context
1597 def nsi_delete2(ctx, name, force):
1598 '''deletes a Network Slice Instance (NSI)
1599
1600 NAME: name or ID of the Network Slice instance to be deleted
1601 '''
1602 nsi_delete(ctx, name, force)
1603
1604
1605 @cli.command(name='pdu-delete', short_help='deletes a Physical Deployment Unit (PDU)')
1606 @click.argument('name')
1607 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1608 @click.pass_context
1609 def pdu_delete(ctx, name, force):
1610 '''deletes a Physical Deployment Unit (PDU)
1611
1612 NAME: name or ID of the PDU to be deleted
1613 '''
1614 try:
1615 check_client_version(ctx.obj, ctx.command.name)
1616 ctx.obj.pdu.delete(name, force)
1617 except ClientException as inst:
1618 print((inst.message))
1619 exit(1)
1620
1621
1622 ####################
1623 # VIM operations
1624 ####################
1625
1626 @cli.command(name='vim-create')
1627 @click.option('--name',
1628 prompt=True,
1629 help='Name to create datacenter')
1630 @click.option('--user',
1631 prompt=True,
1632 help='VIM username')
1633 @click.option('--password',
1634 prompt=True,
1635 hide_input=True,
1636 confirmation_prompt=True,
1637 help='VIM password')
1638 @click.option('--auth_url',
1639 prompt=True,
1640 help='VIM url')
1641 @click.option('--tenant',
1642 prompt=True,
1643 help='VIM tenant name')
1644 @click.option('--config',
1645 default=None,
1646 help='VIM specific config parameters')
1647 @click.option('--account_type',
1648 default='openstack',
1649 help='VIM type')
1650 @click.option('--description',
1651 default='no description',
1652 help='human readable description')
1653 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1654 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1655 @click.pass_context
1656 def vim_create(ctx,
1657 name,
1658 user,
1659 password,
1660 auth_url,
1661 tenant,
1662 config,
1663 account_type,
1664 description,
1665 sdn_controller,
1666 sdn_port_mapping):
1667 '''creates a new VIM account
1668 '''
1669 try:
1670 if sdn_controller:
1671 check_client_version(ctx.obj, '--sdn_controller')
1672 if sdn_port_mapping:
1673 check_client_version(ctx.obj, '--sdn_port_mapping')
1674 vim = {}
1675 vim['vim-username'] = user
1676 vim['vim-password'] = password
1677 vim['vim-url'] = auth_url
1678 vim['vim-tenant-name'] = tenant
1679 vim['vim-type'] = account_type
1680 vim['description'] = description
1681 vim['config'] = config
1682 if sdn_controller or sdn_port_mapping:
1683 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping)
1684 else:
1685 ctx.obj.vim.create(name, vim)
1686 except ClientException as inst:
1687 print((inst.message))
1688 exit(1)
1689
1690
1691 @cli.command(name='vim-update', short_help='updates a VIM account')
1692 @click.argument('name')
1693 @click.option('--newname', help='New name for the VIM account')
1694 @click.option('--user', help='VIM username')
1695 @click.option('--password', help='VIM password')
1696 @click.option('--auth_url', help='VIM url')
1697 @click.option('--tenant', help='VIM tenant name')
1698 @click.option('--config', help='VIM specific config parameters')
1699 @click.option('--account_type', help='VIM type')
1700 @click.option('--description', help='human readable description')
1701 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1702 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1703 @click.pass_context
1704 def vim_update(ctx,
1705 name,
1706 newname,
1707 user,
1708 password,
1709 auth_url,
1710 tenant,
1711 config,
1712 account_type,
1713 description,
1714 sdn_controller,
1715 sdn_port_mapping):
1716 '''updates a VIM account
1717
1718 NAME: name or ID of the VIM account
1719 '''
1720 try:
1721 check_client_version(ctx.obj, ctx.command.name)
1722 vim = {}
1723 if newname: vim['name'] = newname
1724 if user: vim['vim_user'] = user
1725 if password: vim['vim_password'] = password
1726 if auth_url: vim['vim_url'] = auth_url
1727 if tenant: vim['vim-tenant-name'] = tenant
1728 if account_type: vim['vim_type'] = account_type
1729 if description: vim['description'] = description
1730 if config: vim['config'] = config
1731 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping)
1732 except ClientException as inst:
1733 print((inst.message))
1734 exit(1)
1735
1736
1737 @cli.command(name='vim-delete')
1738 @click.argument('name')
1739 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1740 @click.pass_context
1741 def vim_delete(ctx, name, force):
1742 '''deletes a VIM account
1743
1744 NAME: name or ID of the VIM account to be deleted
1745 '''
1746 try:
1747 if not force:
1748 ctx.obj.vim.delete(name)
1749 else:
1750 check_client_version(ctx.obj, '--force')
1751 ctx.obj.vim.delete(name, force)
1752 except ClientException as inst:
1753 print((inst.message))
1754 exit(1)
1755
1756
1757 @cli.command(name='vim-list')
1758 @click.option('--ro_update/--no_ro_update',
1759 default=False,
1760 help='update list from RO')
1761 @click.option('--filter', default=None,
1762 help='restricts the list to the VIM accounts matching the filter')
1763 @click.pass_context
1764 def vim_list(ctx, ro_update, filter):
1765 '''list all VIM accounts'''
1766 if filter:
1767 check_client_version(ctx.obj, '--filter')
1768 if ro_update:
1769 check_client_version(ctx.obj, '--ro_update', 'v1')
1770 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1771 if fullclassname == 'osmclient.sol005.client.Client':
1772 resp = ctx.obj.vim.list(filter)
1773 else:
1774 resp = ctx.obj.vim.list(ro_update)
1775 table = PrettyTable(['vim name', 'uuid'])
1776 for vim in resp:
1777 table.add_row([vim['name'], vim['uuid']])
1778 table.align = 'l'
1779 print(table)
1780
1781
1782 @cli.command(name='vim-show')
1783 @click.argument('name')
1784 @click.pass_context
1785 def vim_show(ctx, name):
1786 '''shows the details of a VIM account
1787
1788 NAME: name or ID of the VIM account
1789 '''
1790 try:
1791 resp = ctx.obj.vim.get(name)
1792 if 'vim_password' in resp:
1793 resp['vim_password']='********'
1794 except ClientException as inst:
1795 print((inst.message))
1796 exit(1)
1797
1798 table = PrettyTable(['key', 'attribute'])
1799 for k, v in list(resp.items()):
1800 table.add_row([k, json.dumps(v, indent=2)])
1801 table.align = 'l'
1802 print(table)
1803
1804
1805 ####################
1806 # WIM operations
1807 ####################
1808
1809 @cli.command(name='wim-create')
1810 @click.option('--name',
1811 prompt=True,
1812 help='Name for the WIM account')
1813 @click.option('--user',
1814 help='WIM username')
1815 @click.option('--password',
1816 help='WIM password')
1817 @click.option('--url',
1818 prompt=True,
1819 help='WIM url')
1820 # @click.option('--tenant',
1821 # help='wIM tenant name')
1822 @click.option('--config',
1823 default=None,
1824 help='WIM specific config parameters')
1825 @click.option('--wim_type',
1826 help='WIM type')
1827 @click.option('--description',
1828 default='no description',
1829 help='human readable description')
1830 @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)")
1831 @click.pass_context
1832 def wim_create(ctx,
1833 name,
1834 user,
1835 password,
1836 url,
1837 # tenant,
1838 config,
1839 wim_type,
1840 description,
1841 wim_port_mapping):
1842 '''creates a new WIM account
1843 '''
1844 try:
1845 check_client_version(ctx.obj, ctx.command.name)
1846 # if sdn_controller:
1847 # check_client_version(ctx.obj, '--sdn_controller')
1848 # if sdn_port_mapping:
1849 # check_client_version(ctx.obj, '--sdn_port_mapping')
1850 wim = {}
1851 if user: wim['user'] = user
1852 if password: wim['password'] = password
1853 if url: wim['wim_url'] = url
1854 # if tenant: wim['tenant'] = tenant
1855 wim['wim_type'] = wim_type
1856 if description: wim['description'] = description
1857 if config: wim['config'] = config
1858 ctx.obj.wim.create(name, wim, wim_port_mapping)
1859 except ClientException as inst:
1860 print((inst.message))
1861 exit(1)
1862
1863
1864 @cli.command(name='wim-update', short_help='updates a WIM account')
1865 @click.argument('name')
1866 @click.option('--newname', help='New name for the WIM account')
1867 @click.option('--user', help='WIM username')
1868 @click.option('--password', help='WIM password')
1869 @click.option('--url', help='WIM url')
1870 @click.option('--config', help='WIM specific config parameters')
1871 @click.option('--wim_type', help='WIM type')
1872 @click.option('--description', help='human readable description')
1873 @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)")
1874 @click.pass_context
1875 def wim_update(ctx,
1876 name,
1877 newname,
1878 user,
1879 password,
1880 url,
1881 config,
1882 wim_type,
1883 description,
1884 wim_port_mapping):
1885 '''updates a WIM account
1886
1887 NAME: name or ID of the WIM account
1888 '''
1889 try:
1890 check_client_version(ctx.obj, ctx.command.name)
1891 wim = {}
1892 if newname: wim['name'] = newname
1893 if user: wim['user'] = user
1894 if password: wim['password'] = password
1895 if url: wim['url'] = url
1896 # if tenant: wim['tenant'] = tenant
1897 if wim_type: wim['wim_type'] = wim_type
1898 if description: wim['description'] = description
1899 if config: wim['config'] = config
1900 ctx.obj.wim.update(name, wim, wim_port_mapping)
1901 except ClientException as inst:
1902 print((inst.message))
1903 exit(1)
1904
1905
1906 @cli.command(name='wim-delete')
1907 @click.argument('name')
1908 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1909 @click.pass_context
1910 def wim_delete(ctx, name, force):
1911 '''deletes a WIM account
1912
1913 NAME: name or ID of the WIM account to be deleted
1914 '''
1915 try:
1916 check_client_version(ctx.obj, ctx.command.name)
1917 ctx.obj.wim.delete(name, force)
1918 except ClientException as inst:
1919 print((inst.message))
1920 exit(1)
1921
1922
1923 @cli.command(name='wim-list')
1924 @click.option('--filter', default=None,
1925 help='restricts the list to the WIM accounts matching the filter')
1926 @click.pass_context
1927 def wim_list(ctx, filter):
1928 '''list all WIM accounts'''
1929 try:
1930 check_client_version(ctx.obj, ctx.command.name)
1931 resp = ctx.obj.wim.list(filter)
1932 table = PrettyTable(['wim name', 'uuid'])
1933 for wim in resp:
1934 table.add_row([wim['name'], wim['uuid']])
1935 table.align = 'l'
1936 print(table)
1937 except ClientException as inst:
1938 print((inst.message))
1939 exit(1)
1940
1941
1942 @cli.command(name='wim-show')
1943 @click.argument('name')
1944 @click.pass_context
1945 def wim_show(ctx, name):
1946 '''shows the details of a WIM account
1947
1948 NAME: name or ID of the WIM account
1949 '''
1950 try:
1951 check_client_version(ctx.obj, ctx.command.name)
1952 resp = ctx.obj.wim.get(name)
1953 if 'password' in resp:
1954 resp['wim_password']='********'
1955 except ClientException as inst:
1956 print((inst.message))
1957 exit(1)
1958
1959 table = PrettyTable(['key', 'attribute'])
1960 for k, v in list(resp.items()):
1961 table.add_row([k, json.dumps(v, indent=2)])
1962 table.align = 'l'
1963 print(table)
1964
1965
1966 ####################
1967 # SDN controller operations
1968 ####################
1969
1970 @cli.command(name='sdnc-create')
1971 @click.option('--name',
1972 prompt=True,
1973 help='Name to create sdn controller')
1974 @click.option('--type',
1975 prompt=True,
1976 help='SDN controller type')
1977 @click.option('--sdn_controller_version',
1978 help='SDN controller username')
1979 @click.option('--ip_address',
1980 prompt=True,
1981 help='SDN controller IP address')
1982 @click.option('--port',
1983 prompt=True,
1984 help='SDN controller port')
1985 @click.option('--switch_dpid',
1986 prompt=True,
1987 help='Switch DPID (Openflow Datapath ID)')
1988 @click.option('--user',
1989 help='SDN controller username')
1990 @click.option('--password',
1991 hide_input=True,
1992 confirmation_prompt=True,
1993 help='SDN controller password')
1994 #@click.option('--description',
1995 # default='no description',
1996 # help='human readable description')
1997 @click.pass_context
1998 def sdnc_create(ctx,
1999 name,
2000 type,
2001 sdn_controller_version,
2002 ip_address,
2003 port,
2004 switch_dpid,
2005 user,
2006 password):
2007 '''creates a new SDN controller
2008 '''
2009 sdncontroller = {}
2010 sdncontroller['name'] = name
2011 sdncontroller['type'] = type
2012 sdncontroller['ip'] = ip_address
2013 sdncontroller['port'] = int(port)
2014 sdncontroller['dpid'] = switch_dpid
2015 if sdn_controller_version:
2016 sdncontroller['version'] = sdn_controller_version
2017 if user:
2018 sdncontroller['user'] = user
2019 if password:
2020 sdncontroller['password'] = password
2021 # sdncontroller['description'] = description
2022 try:
2023 check_client_version(ctx.obj, ctx.command.name)
2024 ctx.obj.sdnc.create(name, sdncontroller)
2025 except ClientException as inst:
2026 print((inst.message))
2027
2028
2029 @cli.command(name='sdnc-update', short_help='updates an SDN controller')
2030 @click.argument('name')
2031 @click.option('--newname', help='New name for the SDN controller')
2032 @click.option('--type', help='SDN controller type')
2033 @click.option('--sdn_controller_version', help='SDN controller username')
2034 @click.option('--ip_address', help='SDN controller IP address')
2035 @click.option('--port', help='SDN controller port')
2036 @click.option('--switch_dpid', help='Switch DPID (Openflow Datapath ID)')
2037 @click.option('--user', help='SDN controller username')
2038 @click.option('--password', help='SDN controller password')
2039 #@click.option('--description', default=None, help='human readable description')
2040 @click.pass_context
2041 def sdnc_update(ctx,
2042 name,
2043 newname,
2044 type,
2045 sdn_controller_version,
2046 ip_address,
2047 port,
2048 switch_dpid,
2049 user,
2050 password):
2051 '''updates an SDN controller
2052
2053 NAME: name or ID of the SDN controller
2054 '''
2055 sdncontroller = {}
2056 if newname: sdncontroller['name'] = newname
2057 if type: sdncontroller['type'] = type
2058 if ip_address: sdncontroller['ip'] = ip_address
2059 if port: sdncontroller['port'] = int(port)
2060 if switch_dpid: sdncontroller['dpid'] = switch_dpid
2061 # sdncontroller['description'] = description
2062 if sdn_controller_version is not None:
2063 if sdn_controller_version=="":
2064 sdncontroller['version'] = None
2065 else:
2066 sdncontroller['version'] = sdn_controller_version
2067 if user is not None:
2068 if user=="":
2069 sdncontroller['user'] = None
2070 else:
2071 sdncontroller['user'] = user
2072 if password is not None:
2073 if password=="":
2074 sdncontroller['password'] = None
2075 else:
2076 sdncontroller['password'] = user
2077 try:
2078 check_client_version(ctx.obj, ctx.command.name)
2079 ctx.obj.sdnc.update(name, sdncontroller)
2080 except ClientException as inst:
2081 print((inst.message))
2082 exit(1)
2083
2084
2085 @cli.command(name='sdnc-delete')
2086 @click.argument('name')
2087 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2088 @click.pass_context
2089 def sdnc_delete(ctx, name, force):
2090 '''deletes an SDN controller
2091
2092 NAME: name or ID of the SDN controller to be deleted
2093 '''
2094 try:
2095 check_client_version(ctx.obj, ctx.command.name)
2096 ctx.obj.sdnc.delete(name, force)
2097 except ClientException as inst:
2098 print((inst.message))
2099 exit(1)
2100
2101
2102 @cli.command(name='sdnc-list')
2103 @click.option('--filter', default=None,
2104 help='restricts the list to the SDN controllers matching the filter')
2105 @click.pass_context
2106 def sdnc_list(ctx, filter):
2107 '''list all SDN controllers'''
2108 try:
2109 check_client_version(ctx.obj, ctx.command.name)
2110 resp = ctx.obj.sdnc.list(filter)
2111 except ClientException as inst:
2112 print((inst.message))
2113 exit(1)
2114 table = PrettyTable(['name', 'id'])
2115 for sdnc in resp:
2116 table.add_row([sdnc['name'], sdnc['_id']])
2117 table.align = 'l'
2118 print(table)
2119
2120
2121 @cli.command(name='sdnc-show')
2122 @click.argument('name')
2123 @click.pass_context
2124 def sdnc_show(ctx, name):
2125 '''shows the details of an SDN controller
2126
2127 NAME: name or ID of the SDN controller
2128 '''
2129 try:
2130 check_client_version(ctx.obj, ctx.command.name)
2131 resp = ctx.obj.sdnc.get(name)
2132 except ClientException as inst:
2133 print((inst.message))
2134 exit(1)
2135
2136 table = PrettyTable(['key', 'attribute'])
2137 for k, v in list(resp.items()):
2138 table.add_row([k, json.dumps(v, indent=2)])
2139 table.align = 'l'
2140 print(table)
2141
2142
2143 ####################
2144 # Project mgmt operations
2145 ####################
2146
2147 @cli.command(name='project-create')
2148 @click.argument('name')
2149 #@click.option('--description',
2150 # default='no description',
2151 # help='human readable description')
2152 @click.pass_context
2153 def project_create(ctx, name):
2154 '''Creates a new project
2155
2156 NAME: name of the project
2157 '''
2158 project = {}
2159 project['name'] = name
2160 try:
2161 check_client_version(ctx.obj, ctx.command.name)
2162 ctx.obj.project.create(name, project)
2163 except ClientException as inst:
2164 print(inst.message)
2165
2166
2167 @cli.command(name='project-delete')
2168 @click.argument('name')
2169 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2170 @click.pass_context
2171 def project_delete(ctx, name):
2172 '''deletes a project
2173
2174 NAME: name or ID of the project to be deleted
2175 '''
2176 try:
2177 check_client_version(ctx.obj, ctx.command.name)
2178 ctx.obj.project.delete(name)
2179 except ClientException as inst:
2180 print(inst.message)
2181 exit(1)
2182
2183
2184 @cli.command(name='project-list')
2185 @click.option('--filter', default=None,
2186 help='restricts the list to the projects matching the filter')
2187 @click.pass_context
2188 def project_list(ctx, filter):
2189 '''list all projects'''
2190 try:
2191 check_client_version(ctx.obj, ctx.command.name)
2192 resp = ctx.obj.project.list(filter)
2193 except ClientException as inst:
2194 print(inst.message)
2195 exit(1)
2196 table = PrettyTable(['name', 'id'])
2197 for proj in resp:
2198 table.add_row([proj['name'], proj['_id']])
2199 table.align = 'l'
2200 print(table)
2201
2202
2203 @cli.command(name='project-show')
2204 @click.argument('name')
2205 @click.pass_context
2206 def project_show(ctx, name):
2207 '''shows the details of a project
2208
2209 NAME: name or ID of the project
2210 '''
2211 try:
2212 check_client_version(ctx.obj, ctx.command.name)
2213 resp = ctx.obj.project.get(name)
2214 except ClientException as inst:
2215 print(inst.message)
2216 exit(1)
2217
2218 table = PrettyTable(['key', 'attribute'])
2219 for k, v in resp.items():
2220 table.add_row([k, json.dumps(v, indent=2)])
2221 table.align = 'l'
2222 print(table)
2223
2224
2225 ####################
2226 # User mgmt operations
2227 ####################
2228
2229 @cli.command(name='user-create')
2230 @click.argument('username')
2231 @click.option('--password',
2232 prompt=True,
2233 hide_input=True,
2234 confirmation_prompt=True,
2235 help='user password')
2236 @click.option('--projects',
2237 default=None,
2238 help='list of project ids that the user belongs to')
2239 #@click.option('--description',
2240 # default='no description',
2241 # help='human readable description')
2242 @click.pass_context
2243 def user_create(ctx, username, password, projects):
2244 '''Creates a new user
2245
2246 USERNAME: name of the user
2247 '''
2248 user = {}
2249 user['username'] = username
2250 user['password'] = password
2251 user['projects'] = projects
2252 try:
2253 check_client_version(ctx.obj, ctx.command.name)
2254 ctx.obj.user.create(username, user)
2255 except ClientException as inst:
2256 print(inst.message)
2257
2258
2259 @cli.command(name='user-delete')
2260 @click.argument('name')
2261 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2262 @click.pass_context
2263 def user_delete(ctx, name):
2264 '''deletes a user
2265
2266 NAME: name or ID of the user to be deleted
2267 '''
2268 try:
2269 check_client_version(ctx.obj, ctx.command.name)
2270 ctx.obj.user.delete(name)
2271 except ClientException as inst:
2272 print(inst.message)
2273 exit(1)
2274
2275
2276 @cli.command(name='user-list')
2277 @click.option('--filter', default=None,
2278 help='restricts the list to the users matching the filter')
2279 @click.pass_context
2280 def user_list(ctx, filter):
2281 '''list all users'''
2282 try:
2283 check_client_version(ctx.obj, ctx.command.name)
2284 resp = ctx.obj.user.list(filter)
2285 except ClientException as inst:
2286 print(inst.message)
2287 exit(1)
2288 table = PrettyTable(['name', 'id'])
2289 for user in resp:
2290 table.add_row([user['name'], user['_id']])
2291 table.align = 'l'
2292 print(table)
2293
2294
2295 @cli.command(name='user-show')
2296 @click.argument('name')
2297 @click.pass_context
2298 def user_show(ctx, name):
2299 '''shows the details of a user
2300
2301 NAME: name or ID of the user
2302 '''
2303 try:
2304 check_client_version(ctx.obj, ctx.command.name)
2305 resp = ctx.obj.user.get(name)
2306 if 'password' in resp:
2307 resp['password']='********'
2308 except ClientException as inst:
2309 print(inst.message)
2310 exit(1)
2311
2312 table = PrettyTable(['key', 'attribute'])
2313 for k, v in resp.items():
2314 table.add_row([k, json.dumps(v, indent=2)])
2315 table.align = 'l'
2316 print(table)
2317
2318
2319 ####################
2320 # Fault Management operations
2321 ####################
2322
2323 @cli.command(name='ns-alarm-create')
2324 @click.argument('name')
2325 @click.option('--ns', prompt=True, help='NS instance id or name')
2326 @click.option('--vnf', prompt=True,
2327 help='VNF name (VNF member index as declared in the NSD)')
2328 @click.option('--vdu', prompt=True,
2329 help='VDU name (VDU name as declared in the VNFD)')
2330 @click.option('--metric', prompt=True,
2331 help='Name of the metric (e.g. cpu_utilization)')
2332 @click.option('--severity', default='WARNING',
2333 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
2334 @click.option('--threshold_value', prompt=True,
2335 help='threshold value that, when crossed, an alarm is triggered')
2336 @click.option('--threshold_operator', prompt=True,
2337 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
2338 @click.option('--statistic', default='AVERAGE',
2339 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
2340 @click.pass_context
2341 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
2342 threshold_value, threshold_operator, statistic):
2343 '''creates a new alarm for a NS instance'''
2344 ns_instance = ctx.obj.ns.get(ns)
2345 alarm = {}
2346 alarm['alarm_name'] = name
2347 alarm['ns_id'] = ns_instance['_id']
2348 alarm['correlation_id'] = ns_instance['_id']
2349 alarm['vnf_member_index'] = vnf
2350 alarm['vdu_name'] = vdu
2351 alarm['metric_name'] = metric
2352 alarm['severity'] = severity
2353 alarm['threshold_value'] = int(threshold_value)
2354 alarm['operation'] = threshold_operator
2355 alarm['statistic'] = statistic
2356 try:
2357 check_client_version(ctx.obj, ctx.command.name)
2358 ctx.obj.ns.create_alarm(alarm)
2359 except ClientException as inst:
2360 print((inst.message))
2361 exit(1)
2362
2363
2364 #@cli.command(name='ns-alarm-delete')
2365 #@click.argument('name')
2366 #@click.pass_context
2367 #def ns_alarm_delete(ctx, name):
2368 # '''deletes an alarm
2369 #
2370 # NAME: name of the alarm to be deleted
2371 # '''
2372 # try:
2373 # check_client_version(ctx.obj, ctx.command.name)
2374 # ctx.obj.ns.delete_alarm(name)
2375 # except ClientException as inst:
2376 # print(inst.message)
2377 # exit(1)
2378
2379
2380 ####################
2381 # Performance Management operations
2382 ####################
2383
2384 @cli.command(name='ns-metric-export')
2385 @click.option('--ns', prompt=True, help='NS instance id or name')
2386 @click.option('--vnf', prompt=True,
2387 help='VNF name (VNF member index as declared in the NSD)')
2388 @click.option('--vdu', prompt=True,
2389 help='VDU name (VDU name as declared in the VNFD)')
2390 @click.option('--metric', prompt=True,
2391 help='name of the metric (e.g. cpu_utilization)')
2392 #@click.option('--period', default='1w',
2393 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
2394 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
2395 @click.pass_context
2396 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
2397 '''exports a metric to the internal OSM bus, which can be read by other apps
2398 '''
2399 ns_instance = ctx.obj.ns.get(ns)
2400 metric_data = {}
2401 metric_data['ns_id'] = ns_instance['_id']
2402 metric_data['correlation_id'] = ns_instance['_id']
2403 metric_data['vnf_member_index'] = vnf
2404 metric_data['vdu_name'] = vdu
2405 metric_data['metric_name'] = metric
2406 metric_data['collection_unit'] = 'WEEK'
2407 metric_data['collection_period'] = 1
2408 try:
2409 check_client_version(ctx.obj, ctx.command.name)
2410 if not interval:
2411 print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
2412 else:
2413 i = 1
2414 while True:
2415 print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
2416 time.sleep(int(interval))
2417 i+=1
2418 except ClientException as inst:
2419 print((inst.message))
2420 exit(1)
2421
2422
2423 ####################
2424 # Other operations
2425 ####################
2426
2427 @cli.command(name='upload-package')
2428 @click.argument('filename')
2429 @click.pass_context
2430 def upload_package(ctx, filename):
2431 '''uploads a VNF package or NS package
2432
2433 FILENAME: VNF or NS package file (tar.gz)
2434 '''
2435 try:
2436 ctx.obj.package.upload(filename)
2437 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
2438 if fullclassname != 'osmclient.sol005.client.Client':
2439 ctx.obj.package.wait_for_upload(filename)
2440 except ClientException as inst:
2441 print((inst.message))
2442 exit(1)
2443
2444
2445 @cli.command(name='ns-scaling-show')
2446 @click.argument('ns_name')
2447 @click.pass_context
2448 def show_ns_scaling(ctx, ns_name):
2449 '''shows the status of a NS scaling operation
2450
2451 NS_NAME: name of the NS instance being scaled
2452 '''
2453 try:
2454 check_client_version(ctx.obj, ctx.command.name, 'v1')
2455 resp = ctx.obj.ns.list()
2456 except ClientException as inst:
2457 print((inst.message))
2458 exit(1)
2459
2460 table = PrettyTable(
2461 ['group-name',
2462 'instance-id',
2463 'operational status',
2464 'create-time',
2465 'vnfr ids'])
2466
2467 for ns in resp:
2468 if ns_name == ns['name']:
2469 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
2470 scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
2471 for record in scaling_records:
2472 if 'instance' in record:
2473 instances = record['instance']
2474 for inst in instances:
2475 table.add_row(
2476 [record['scaling-group-name-ref'],
2477 inst['instance-id'],
2478 inst['op-status'],
2479 time.strftime('%Y-%m-%d %H:%M:%S',
2480 time.localtime(
2481 inst['create-time'])),
2482 inst['vnfrs']])
2483 table.align = 'l'
2484 print(table)
2485
2486
2487 @cli.command(name='ns-scale')
2488 @click.argument('ns_name')
2489 @click.option('--ns_scale_group', prompt=True)
2490 @click.option('--index', prompt=True)
2491 @click.pass_context
2492 def ns_scale(ctx, ns_name, ns_scale_group, index):
2493 '''scales NS
2494
2495 NS_NAME: name of the NS instance to be scaled
2496 '''
2497 try:
2498 check_client_version(ctx.obj, ctx.command.name, 'v1')
2499 ctx.obj.ns.scale(ns_name, ns_scale_group, index)
2500 except ClientException as inst:
2501 print((inst.message))
2502 exit(1)
2503
2504
2505 @cli.command(name='config-agent-list')
2506 @click.pass_context
2507 def config_agent_list(ctx):
2508 '''list config agents'''
2509 try:
2510 check_client_version(ctx.obj, ctx.command.name, 'v1')
2511 except ClientException as inst:
2512 print((inst.message))
2513 exit(1)
2514 table = PrettyTable(['name', 'account-type', 'details'])
2515 for account in ctx.obj.vca.list():
2516 table.add_row(
2517 [account['name'],
2518 account['account-type'],
2519 account['juju']])
2520 table.align = 'l'
2521 print(table)
2522
2523
2524 @cli.command(name='config-agent-delete')
2525 @click.argument('name')
2526 @click.pass_context
2527 def config_agent_delete(ctx, name):
2528 '''deletes a config agent
2529
2530 NAME: name of the config agent to be deleted
2531 '''
2532 try:
2533 check_client_version(ctx.obj, ctx.command.name, 'v1')
2534 ctx.obj.vca.delete(name)
2535 except ClientException as inst:
2536 print((inst.message))
2537 exit(1)
2538
2539
2540 @cli.command(name='config-agent-add')
2541 @click.option('--name',
2542 prompt=True)
2543 @click.option('--account_type',
2544 prompt=True)
2545 @click.option('--server',
2546 prompt=True)
2547 @click.option('--user',
2548 prompt=True)
2549 @click.option('--secret',
2550 prompt=True,
2551 hide_input=True,
2552 confirmation_prompt=True)
2553 @click.pass_context
2554 def config_agent_add(ctx, name, account_type, server, user, secret):
2555 '''adds a config agent'''
2556 try:
2557 check_client_version(ctx.obj, ctx.command.name, 'v1')
2558 ctx.obj.vca.create(name, account_type, server, user, secret)
2559 except ClientException as inst:
2560 print((inst.message))
2561 exit(1)
2562
2563 @cli.command(name='ro-dump')
2564 @click.pass_context
2565 def ro_dump(ctx):
2566 '''shows RO agent information'''
2567 check_client_version(ctx.obj, ctx.command.name, 'v1')
2568 resp = ctx.obj.vim.get_resource_orchestrator()
2569 table = PrettyTable(['key', 'attribute'])
2570 for k, v in list(resp.items()):
2571 table.add_row([k, json.dumps(v, indent=2)])
2572 table.align = 'l'
2573 print(table)
2574
2575
2576 @cli.command(name='vcs-list')
2577 @click.pass_context
2578 def vcs_list(ctx):
2579 check_client_version(ctx.obj, ctx.command.name, 'v1')
2580 resp = ctx.obj.utils.get_vcs_info()
2581 table = PrettyTable(['component name', 'state'])
2582 for component in resp:
2583 table.add_row([component['component_name'], component['state']])
2584 table.align = 'l'
2585 print(table)
2586
2587
2588 @cli.command(name='ns-action')
2589 @click.argument('ns_name')
2590 @click.option('--vnf_name', default=None)
2591 @click.option('--action_name', prompt=True)
2592 @click.option('--params', prompt=True)
2593 @click.pass_context
2594 def ns_action(ctx,
2595 ns_name,
2596 vnf_name,
2597 action_name,
2598 params):
2599 '''executes an action/primitive over a NS instance
2600
2601 NS_NAME: name or ID of the NS instance
2602 '''
2603 try:
2604 check_client_version(ctx.obj, ctx.command.name)
2605 op_data={}
2606 if vnf_name:
2607 op_data['vnf_member_index'] = vnf_name
2608 op_data['primitive'] = action_name
2609 op_data['primitive_params'] = yaml.load(params)
2610 ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data)
2611
2612 except ClientException as inst:
2613 print((inst.message))
2614 exit(1)
2615
2616
2617 @cli.command(name='vnf-scale')
2618 @click.argument('ns_name')
2619 @click.argument('vnf_name')
2620 @click.option('--scaling-group', prompt=True, help="scaling-group-descriptor name to use")
2621 @click.option('--scale-in', default=False, is_flag=True, help="performs a scale in operation")
2622 @click.option('--scale-out', default=False, is_flag=True, help="performs a scale out operation (by default)")
2623 @click.pass_context
2624 def vnf_scale(ctx,
2625 ns_name,
2626 vnf_name,
2627 scaling_group,
2628 scale_in,
2629 scale_out):
2630 '''executes a VNF scale (adding/removing VDUs)
2631
2632 \b
2633 NS_NAME: name or ID of the NS instance.
2634 VNF_NAME: member-vnf-index in the NS to be scaled.
2635 '''
2636 try:
2637 check_client_version(ctx.obj, ctx.command.name)
2638 if not scale_in and not scale_out:
2639 scale_out = True
2640 ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out)
2641 except ClientException as inst:
2642 print((inst.message))
2643 exit(1)
2644
2645
2646 if __name__ == '__main__':
2647 try:
2648 cli()
2649 except pycurl.error as e:
2650 print(e)
2651 print('Maybe "--hostname" option or OSM_HOSTNAME' +
2652 'environment variable needs to be specified')
2653 exit(1)
2654