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