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