prompt a proper message when OSM server is not running
[osm/osmclient.git] / osmclient / scripts / osm.py
1 # Copyright 2017-2018 Sandvine
2 # Copyright 2018 Telefonica
3 #
4 # All Rights Reserved.
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
16 # under the License.
17 """
18 OSM shell/cli
19 """
20
21 import click
22 from osmclient import client
23 from osmclient.common.exceptions import ClientException
24 from prettytable import PrettyTable
25 import yaml
26 import json
27 import time
28 import pycurl
29 import os
30 import textwrap
31 import pkg_resources
32
33
34 def wrap_text(text, width):
35 wrapper = textwrap.TextWrapper(width=width)
36 lines = text.splitlines()
37 return "\n".join(map(wrapper.fill, lines))
38
39
40 def trunc_text(text, length):
41 if len(text) > length:
42 return text[:(length - 3)] + '...'
43 else:
44 return text
45
46
47 def check_client_version(obj, what, version='sol005'):
48 """
49 Checks the version of the client object and raises error if it not the expected.
50
51 :param obj: the client object
52 :what: the function or command under evaluation (used when an error is raised)
53 :return: -
54 :raises ClientError: if the specified version does not match the client version
55 """
56 fullclassname = obj.__module__ + "." + obj.__class__.__name__
57 message = 'The following commands or options are only supported with the option "--sol005": {}'.format(what)
58 if version == 'v1':
59 message = 'The following commands or options are not supported when using option "--sol005": {}'.format(what)
60 if fullclassname != 'osmclient.{}.client.Client'.format(version):
61 raise ClientException(message)
62 return
63
64
65 CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'], max_content_width=160)
66
67 @click.group(context_settings=CONTEXT_SETTINGS)
68 @click.option('--hostname',
69 default="127.0.0.1",
70 envvar='OSM_HOSTNAME',
71 help='hostname of server. ' +
72 'Also can set OSM_HOSTNAME in environment')
73 #@click.option('--sol005/--no-sol005',
74 # default=True,
75 # envvar='OSM_SOL005',
76 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
77 # 'Also can set OSM_SOL005 in environment')
78 @click.option('--user',
79 default=None,
80 envvar='OSM_USER',
81 help='user (defaults to admin). ' +
82 'Also can set OSM_USER in environment')
83 @click.option('--password',
84 default=None,
85 envvar='OSM_PASSWORD',
86 help='password (defaults to admin). ' +
87 'Also can set OSM_PASSWORD in environment')
88 @click.option('--project',
89 default=None,
90 envvar='OSM_PROJECT',
91 help='project (defaults to admin). ' +
92 'Also can set OSM_PROJECT in environment')
93 #@click.option('--so-port',
94 # default=None,
95 # envvar='OSM_SO_PORT',
96 # help='hostname of server. ' +
97 # 'Also can set OSM_SO_PORT in environment')
98 #@click.option('--so-project',
99 # default=None,
100 # envvar='OSM_SO_PROJECT',
101 # help='Project Name in SO. ' +
102 # 'Also can set OSM_SO_PROJECT in environment')
103 #@click.option('--ro-hostname',
104 # default=None,
105 # envvar='OSM_RO_HOSTNAME',
106 # help='hostname of RO server. ' +
107 # 'Also can set OSM_RO_HOSTNAME in environment')
108 #@click.option('--ro-port',
109 # default=None,
110 # envvar='OSM_RO_PORT',
111 # help='hostname of RO server. ' +
112 # 'Also can set OSM_RO_PORT in environment')
113 @click.pass_context
114 def cli_osm(ctx, hostname, user, password, project):
115 if hostname is None:
116 print((
117 "either hostname option or OSM_HOSTNAME " +
118 "environment variable needs to be specified"))
119 exit(1)
120 kwargs={}
121 # if so_port is not None:
122 # kwargs['so_port']=so_port
123 # if so_project is not None:
124 # kwargs['so_project']=so_project
125 # if ro_hostname is not None:
126 # kwargs['ro_host']=ro_hostname
127 # if ro_port is not None:
128 # kwargs['ro_port']=ro_port
129 sol005 = os.getenv('OSM_SOL005', True)
130 if user is not None:
131 kwargs['user']=user
132 if password is not None:
133 kwargs['password']=password
134 if project is not None:
135 kwargs['project']=project
136 ctx.obj = client.Client(host=hostname, sol005=sol005, **kwargs)
137
138
139 ####################
140 # LIST operations
141 ####################
142
143 @cli_osm.command(name='ns-list', short_help='list all NS instances')
144 @click.option('--filter', default=None,
145 help='restricts the list to the NS instances matching the filter.')
146 @click.pass_context
147 def ns_list(ctx, filter):
148 """list all NS instances
149
150 \b
151 Options:
152 --filter filterExpr Restricts the list to the NS instances matching the filter
153
154 \b
155 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
156 concatenated using the "&" character:
157
158 \b
159 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
160 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
161 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
162 attrName := string
163 value := scalar value
164
165 \b
166 where:
167 * zero or more occurrences
168 ? zero or one occurrence
169 [] grouping of expressions to be used with ? and *
170 "" quotation marks for marking string constants
171 <> name separator
172
173 \b
174 "AttrName" is the name of one attribute in the data type that defines the representation
175 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
176 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
177 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
178 entries, it means that the operator "op" is applied to the attribute addressed by the last
179 <attrName> entry included in the concatenation. All simple filter expressions are combined
180 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
181 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
182 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
183 prefix". If an attribute referenced in an expression is an array, an object that contains a
184 corresponding array shall be considered to match the expression if any of the elements in the
185 array matches all expressions that have the same attribute prefix.
186
187 \b
188 Filter examples:
189 --filter admin-status=ENABLED
190 --filter nsd-ref=<NSD_NAME>
191 --filter nsd.vendor=<VENDOR>
192 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
193 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
194 """
195 if filter:
196 check_client_version(ctx.obj, '--filter')
197 resp = ctx.obj.ns.list(filter)
198 else:
199 resp = ctx.obj.ns.list()
200 table = PrettyTable(
201 ['ns instance name',
202 'id',
203 'operational status',
204 'config status',
205 'detailed status'])
206 for ns in resp:
207 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
208 if fullclassname == 'osmclient.sol005.client.Client':
209 nsr = ns
210 nsr_name = nsr['name']
211 nsr_id = nsr['_id']
212 else:
213 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
214 nsr = nsopdata['nsr:nsr']
215 nsr_name = nsr['name-ref']
216 nsr_id = nsr['ns-instance-config-ref']
217 opstatus = nsr['operational-status'] if 'operational-status' in nsr else 'Not found'
218 configstatus = nsr['config-status'] if 'config-status' in nsr else 'Not found'
219 detailed_status = nsr['detailed-status'] if 'detailed-status' in nsr else 'Not found'
220 detailed_status = wrap_text(text=detailed_status,width=50)
221 if configstatus == "config_not_needed":
222 configstatus = "configured (no charms)"
223
224 table.add_row(
225 [nsr_name,
226 nsr_id,
227 opstatus,
228 configstatus,
229 detailed_status])
230 table.align = 'l'
231 print(table)
232
233
234 def nsd_list(ctx, filter):
235 if filter:
236 check_client_version(ctx.obj, '--filter')
237 resp = ctx.obj.nsd.list(filter)
238 else:
239 resp = ctx.obj.nsd.list()
240 # print(yaml.safe_dump(resp))
241 table = PrettyTable(['nsd name', 'id'])
242 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
243 if fullclassname == 'osmclient.sol005.client.Client':
244 for ns in resp:
245 name = ns['name'] if 'name' in ns else '-'
246 table.add_row([name, ns['_id']])
247 else:
248 for ns in resp:
249 table.add_row([ns['name'], ns['id']])
250 table.align = 'l'
251 print(table)
252
253
254 @cli_osm.command(name='nsd-list', short_help='list all NS packages')
255 @click.option('--filter', default=None,
256 help='restricts the list to the NSD/NSpkg matching the filter')
257 @click.pass_context
258 def nsd_list1(ctx, filter):
259 """list all NSD/NS pkg in the system"""
260 nsd_list(ctx, filter)
261
262
263 @cli_osm.command(name='nspkg-list', short_help='list all NS packages')
264 @click.option('--filter', default=None,
265 help='restricts the list to the NSD/NSpkg matching the filter')
266 @click.pass_context
267 def nsd_list2(ctx, filter):
268 """list all NS packages"""
269 nsd_list(ctx, filter)
270
271
272 def vnfd_list(ctx, nf_type, filter):
273 if nf_type:
274 check_client_version(ctx.obj, '--nf_type')
275 elif filter:
276 check_client_version(ctx.obj, '--filter')
277 if nf_type:
278 if nf_type == "vnf":
279 nf_filter = "_admin.type=vnfd"
280 elif nf_type == "pnf":
281 nf_filter = "_admin.type=pnfd"
282 elif nf_type == "hnf":
283 nf_filter = "_admin.type=hnfd"
284 else:
285 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
286 if filter:
287 filter = '{}&{}'.format(nf_filter, filter)
288 else:
289 filter = nf_filter
290 if filter:
291 resp = ctx.obj.vnfd.list(filter)
292 else:
293 resp = ctx.obj.vnfd.list()
294 # print(yaml.safe_dump(resp))
295 table = PrettyTable(['nfpkg name', 'id'])
296 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
297 if fullclassname == 'osmclient.sol005.client.Client':
298 for vnfd in resp:
299 name = vnfd['name'] if 'name' in vnfd else '-'
300 table.add_row([name, vnfd['_id']])
301 else:
302 for vnfd in resp:
303 table.add_row([vnfd['name'], vnfd['id']])
304 table.align = 'l'
305 print(table)
306
307
308 @cli_osm.command(name='vnfd-list', short_help='list all xNF packages (VNF, HNF, PNF)')
309 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
310 @click.option('--filter', default=None,
311 help='restricts the list to the NF pkg matching the filter')
312 @click.pass_context
313 def vnfd_list1(ctx, nf_type, filter):
314 """list all xNF packages (VNF, HNF, PNF)"""
315 vnfd_list(ctx, nf_type, filter)
316
317
318 @cli_osm.command(name='vnfpkg-list', short_help='list all xNF packages (VNF, HNF, PNF)')
319 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
320 @click.option('--filter', default=None,
321 help='restricts the list to the NFpkg matching the filter')
322 @click.pass_context
323 def vnfd_list2(ctx, nf_type, filter):
324 """list all xNF packages (VNF, HNF, PNF)"""
325 vnfd_list(ctx, nf_type, filter)
326
327
328 @cli_osm.command(name='nfpkg-list', short_help='list all xNF packages (VNF, HNF, PNF)')
329 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
330 @click.option('--filter', default=None,
331 help='restricts the list to the NFpkg matching the filter')
332 @click.pass_context
333 def nfpkg_list(ctx, nf_type, filter):
334 """list all xNF packages (VNF, HNF, PNF)"""
335 # try:
336 check_client_version(ctx.obj, ctx.command.name)
337 vnfd_list(ctx, nf_type, filter)
338 # except ClientException as e:
339 # print(str(e))
340 # exit(1)
341
342
343 def vnf_list(ctx, ns, filter):
344 # try:
345 if ns or filter:
346 if ns:
347 check_client_version(ctx.obj, '--ns')
348 if filter:
349 check_client_version(ctx.obj, '--filter')
350 resp = ctx.obj.vnf.list(ns, filter)
351 else:
352 resp = ctx.obj.vnf.list()
353 # except ClientException as e:
354 # print(str(e))
355 # exit(1)
356 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
357 if fullclassname == 'osmclient.sol005.client.Client':
358 table = PrettyTable(
359 ['vnf id',
360 'name',
361 'ns id',
362 'vnf member index',
363 'vnfd name',
364 'vim account id',
365 'ip address'])
366 for vnfr in resp:
367 name = vnfr['name'] if 'name' in vnfr else '-'
368 table.add_row(
369 [vnfr['_id'],
370 name,
371 vnfr['nsr-id-ref'],
372 vnfr['member-vnf-index-ref'],
373 vnfr['vnfd-ref'],
374 vnfr['vim-account-id'],
375 vnfr['ip-address']])
376 else:
377 table = PrettyTable(
378 ['vnf name',
379 'id',
380 'operational status',
381 'config status'])
382 for vnfr in resp:
383 if 'mgmt-interface' not in vnfr:
384 vnfr['mgmt-interface'] = {}
385 vnfr['mgmt-interface']['ip-address'] = None
386 table.add_row(
387 [vnfr['name'],
388 vnfr['id'],
389 vnfr['operational-status'],
390 vnfr['config-status']])
391 table.align = 'l'
392 print(table)
393
394
395 @cli_osm.command(name='vnf-list', short_help='list all NF instances')
396 @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list')
397 @click.option('--filter', default=None,
398 help='restricts the list to the NF instances matching the filter.')
399 @click.pass_context
400 def vnf_list1(ctx, ns, filter):
401 """list all NF instances"""
402 vnf_list(ctx, ns, filter)
403
404
405 @cli_osm.command(name='nf-list', short_help='list all NF instances')
406 @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list')
407 @click.option('--filter', default=None,
408 help='restricts the list to the NF instances matching the filter.')
409 @click.pass_context
410 def nf_list(ctx, ns, filter):
411 """list all NF instances
412
413 \b
414 Options:
415 --ns TEXT NS instance id or name to restrict the VNF list
416 --filter filterExpr Restricts the list to the VNF instances matching the filter
417
418 \b
419 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
420 concatenated using the "&" character:
421
422 \b
423 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
424 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
425 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
426 attrName := string
427 value := scalar value
428
429 \b
430 where:
431 * zero or more occurrences
432 ? zero or one occurrence
433 [] grouping of expressions to be used with ? and *
434 "" quotation marks for marking string constants
435 <> name separator
436
437 \b
438 "AttrName" is the name of one attribute in the data type that defines the representation
439 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
440 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
441 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
442 entries, it means that the operator "op" is applied to the attribute addressed by the last
443 <attrName> entry included in the concatenation. All simple filter expressions are combined
444 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
445 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
446 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
447 prefix". If an attribute referenced in an expression is an array, an object that contains a
448 corresponding array shall be considered to match the expression if any of the elements in the
449 array matches all expressions that have the same attribute prefix.
450
451 \b
452 Filter examples:
453 --filter vim-account-id=<VIM_ACCOUNT_ID>
454 --filter vnfd-ref=<VNFD_NAME>
455 --filter vdur.ip-address=<IP_ADDRESS>
456 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
457 """
458 vnf_list(ctx, ns, filter)
459
460
461 @cli_osm.command(name='ns-op-list', short_help='shows the history of operations over a NS instance')
462 @click.argument('name')
463 @click.pass_context
464 def ns_op_list(ctx, name):
465 """shows the history of operations over a NS instance
466
467 NAME: name or ID of the NS instance
468 """
469 # try:
470 check_client_version(ctx.obj, ctx.command.name)
471 resp = ctx.obj.ns.list_op(name)
472 # except ClientException as e:
473 # print(str(e))
474 # exit(1)
475
476 table = PrettyTable(['id', 'operation', 'action_name', 'status'])
477 #print(yaml.safe_dump(resp))
478 for op in resp:
479 action_name = "N/A"
480 if op['lcmOperationType']=='action':
481 action_name = op['operationParams']['primitive']
482 table.add_row([op['id'], op['lcmOperationType'], action_name,
483 op['operationState']])
484 table.align = 'l'
485 print(table)
486
487
488 def nsi_list(ctx, filter):
489 """list all Network Slice Instances"""
490 # try:
491 check_client_version(ctx.obj, ctx.command.name)
492 resp = ctx.obj.nsi.list(filter)
493 # except ClientException as e:
494 # print(str(e))
495 # exit(1)
496 table = PrettyTable(
497 ['netslice instance name',
498 'id',
499 'operational status',
500 'config status',
501 'detailed status'])
502 for nsi in resp:
503 nsi_name = nsi['name']
504 nsi_id = nsi['_id']
505 opstatus = nsi['operational-status'] if 'operational-status' in nsi else 'Not found'
506 configstatus = nsi['config-status'] if 'config-status' in nsi else 'Not found'
507 detailed_status = nsi['detailed-status'] if 'detailed-status' in nsi else 'Not found'
508 if configstatus == "config_not_needed":
509 configstatus = "configured (no charms)"
510 table.add_row(
511 [nsi_name,
512 nsi_id,
513 opstatus,
514 configstatus,
515 detailed_status])
516 table.align = 'l'
517 print(table)
518
519
520 @cli_osm.command(name='nsi-list', short_help='list all Network Slice Instances (NSI)')
521 @click.option('--filter', default=None,
522 help='restricts the list to the Network Slice Instances matching the filter')
523 @click.pass_context
524 def nsi_list1(ctx, filter):
525 """list all Network Slice Instances (NSI)"""
526 nsi_list(ctx, filter)
527
528
529 @cli_osm.command(name='netslice-instance-list', short_help='list all Network Slice Instances (NSI)')
530 @click.option('--filter', default=None,
531 help='restricts the list to the Network Slice Instances matching the filter')
532 @click.pass_context
533 def nsi_list2(ctx, filter):
534 """list all Network Slice Instances (NSI)"""
535 nsi_list(ctx, filter)
536
537
538 def nst_list(ctx, filter):
539 # try:
540 check_client_version(ctx.obj, ctx.command.name)
541 resp = ctx.obj.nst.list(filter)
542 # except ClientException as e:
543 # print(str(e))
544 # exit(1)
545 # print(yaml.safe_dump(resp))
546 table = PrettyTable(['nst name', 'id'])
547 for nst in resp:
548 name = nst['name'] if 'name' in nst else '-'
549 table.add_row([name, nst['_id']])
550 table.align = 'l'
551 print(table)
552
553
554 @cli_osm.command(name='nst-list', short_help='list all Network Slice Templates (NST)')
555 @click.option('--filter', default=None,
556 help='restricts the list to the NST matching the filter')
557 @click.pass_context
558 def nst_list1(ctx, filter):
559 """list all Network Slice Templates (NST) in the system"""
560 nst_list(ctx, filter)
561
562
563 @cli_osm.command(name='netslice-template-list', short_help='list all Network Slice Templates (NST)')
564 @click.option('--filter', default=None,
565 help='restricts the list to the NST matching the filter')
566 @click.pass_context
567 def nst_list2(ctx, filter):
568 """list all Network Slice Templates (NST) in the system"""
569 nst_list(ctx, filter)
570
571
572 def nsi_op_list(ctx, name):
573 # try:
574 check_client_version(ctx.obj, ctx.command.name)
575 resp = ctx.obj.nsi.list_op(name)
576 # except ClientException as e:
577 # print(str(e))
578 # exit(1)
579 table = PrettyTable(['id', 'operation', 'status'])
580 for op in resp:
581 table.add_row([op['id'], op['lcmOperationType'],
582 op['operationState']])
583 table.align = 'l'
584 print(table)
585
586
587 @cli_osm.command(name='nsi-op-list', short_help='shows the history of operations over a Network Slice Instance (NSI)')
588 @click.argument('name')
589 @click.pass_context
590 def nsi_op_list1(ctx, name):
591 """shows the history of operations over a Network Slice Instance (NSI)
592
593 NAME: name or ID of the Network Slice Instance
594 """
595 nsi_op_list(ctx, name)
596
597
598 @cli_osm.command(name='netslice-instance-op-list', short_help='shows the history of operations over a Network Slice Instance (NSI)')
599 @click.argument('name')
600 @click.pass_context
601 def nsi_op_list2(ctx, name):
602 """shows the history of operations over a Network Slice Instance (NSI)
603
604 NAME: name or ID of the Network Slice Instance
605 """
606 nsi_op_list(ctx, name)
607
608
609 @cli_osm.command(name='pdu-list', short_help='list all Physical Deployment Units (PDU)')
610 @click.option('--filter', default=None,
611 help='restricts the list to the Physical Deployment Units matching the filter')
612 @click.pass_context
613 def pdu_list(ctx, filter):
614 """list all Physical Deployment Units (PDU)"""
615 # try:
616 check_client_version(ctx.obj, ctx.command.name)
617 resp = ctx.obj.pdu.list(filter)
618 # except ClientException as e:
619 # print(str(e))
620 # exit(1)
621 table = PrettyTable(
622 ['pdu name',
623 'id',
624 'type',
625 'mgmt ip address'])
626 for pdu in resp:
627 pdu_name = pdu['name']
628 pdu_id = pdu['_id']
629 pdu_type = pdu['type']
630 pdu_ipaddress = "None"
631 for iface in pdu['interfaces']:
632 if iface['mgmt']:
633 pdu_ipaddress = iface['ip-address']
634 break
635 table.add_row(
636 [pdu_name,
637 pdu_id,
638 pdu_type,
639 pdu_ipaddress])
640 table.align = 'l'
641 print(table)
642
643
644 ####################
645 # SHOW operations
646 ####################
647
648 def nsd_show(ctx, name, literal):
649 # try:
650 resp = ctx.obj.nsd.get(name)
651 # resp = ctx.obj.nsd.get_individual(name)
652 # except ClientException as e:
653 # print(str(e))
654 # exit(1)
655
656 if literal:
657 print(yaml.safe_dump(resp))
658 return
659
660 table = PrettyTable(['field', 'value'])
661 for k, v in list(resp.items()):
662 table.add_row([k, json.dumps(v, indent=2)])
663 table.align = 'l'
664 print(table)
665
666
667 @cli_osm.command(name='nsd-show', short_help='shows the content of a NSD')
668 @click.option('--literal', is_flag=True,
669 help='print literally, no pretty table')
670 @click.argument('name')
671 @click.pass_context
672 def nsd_show1(ctx, name, literal):
673 """shows the content of a NSD
674
675 NAME: name or ID of the NSD/NSpkg
676 """
677 nsd_show(ctx, name, literal)
678
679
680 @cli_osm.command(name='nspkg-show', short_help='shows the content of a NSD')
681 @click.option('--literal', is_flag=True,
682 help='print literally, no pretty table')
683 @click.argument('name')
684 @click.pass_context
685 def nsd_show2(ctx, name, literal):
686 """shows the content of a NSD
687
688 NAME: name or ID of the NSD/NSpkg
689 """
690 nsd_show(ctx, name, literal)
691
692
693 def vnfd_show(ctx, name, literal):
694 # try:
695 resp = ctx.obj.vnfd.get(name)
696 # resp = ctx.obj.vnfd.get_individual(name)
697 # except ClientException as e:
698 # print(str(e))
699 # exit(1)
700
701 if literal:
702 print(yaml.safe_dump(resp))
703 return
704
705 table = PrettyTable(['field', 'value'])
706 for k, v in list(resp.items()):
707 table.add_row([k, json.dumps(v, indent=2)])
708 table.align = 'l'
709 print(table)
710
711
712 @cli_osm.command(name='vnfd-show', short_help='shows the content of a VNFD')
713 @click.option('--literal', is_flag=True,
714 help='print literally, no pretty table')
715 @click.argument('name')
716 @click.pass_context
717 def vnfd_show1(ctx, name, literal):
718 """shows the content of a VNFD
719
720 NAME: name or ID of the VNFD/VNFpkg
721 """
722 vnfd_show(ctx, name, literal)
723
724
725 @cli_osm.command(name='vnfpkg-show', short_help='shows the content of a VNFD')
726 @click.option('--literal', is_flag=True,
727 help='print literally, no pretty table')
728 @click.argument('name')
729 @click.pass_context
730 def vnfd_show2(ctx, name, literal):
731 """shows the content of a VNFD
732
733 NAME: name or ID of the VNFD/VNFpkg
734 """
735 vnfd_show(ctx, name, literal)
736
737
738 @cli_osm.command(name='nfpkg-show', short_help='shows the content of a NF Descriptor')
739 @click.option('--literal', is_flag=True,
740 help='print literally, no pretty table')
741 @click.argument('name')
742 @click.pass_context
743 def nfpkg_show(ctx, name, literal):
744 """shows the content of a NF Descriptor
745
746 NAME: name or ID of the NFpkg
747 """
748 vnfd_show(ctx, name, literal)
749
750
751 @cli_osm.command(name='ns-show', short_help='shows the info of a NS instance')
752 @click.argument('name')
753 @click.option('--literal', is_flag=True,
754 help='print literally, no pretty table')
755 @click.option('--filter', default=None)
756 @click.pass_context
757 def ns_show(ctx, name, literal, filter):
758 """shows the info of a NS instance
759
760 NAME: name or ID of the NS instance
761 """
762 # try:
763 ns = ctx.obj.ns.get(name)
764 # except ClientException as e:
765 # print(str(e))
766 # exit(1)
767
768 if literal:
769 print(yaml.safe_dump(ns))
770 return
771
772 table = PrettyTable(['field', 'value'])
773
774 for k, v in list(ns.items()):
775 if filter is None or filter in k:
776 table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
777
778 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
779 if fullclassname != 'osmclient.sol005.client.Client':
780 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
781 nsr_optdata = nsopdata['nsr:nsr']
782 for k, v in list(nsr_optdata.items()):
783 if filter is None or filter in k:
784 table.add_row([k, wrap_text(json.dumps(v, indent=2),width=100)])
785 table.align = 'l'
786 print(table)
787
788
789 @cli_osm.command(name='vnf-show', short_help='shows the info of a VNF instance')
790 @click.argument('name')
791 @click.option('--literal', is_flag=True,
792 help='print literally, no pretty table')
793 @click.option('--filter', default=None, help='restricts the information to the fields in the filter')
794 @click.option('--kdu', default=None, help='KDU name (whose status will be shown)')
795 @click.pass_context
796 def vnf_show(ctx, name, literal, filter, kdu):
797 """shows the info of a VNF instance
798
799 NAME: name or ID of the VNF instance
800 """
801 if kdu:
802 if literal:
803 raise ClientException('"--literal" option is incompatible with "--kdu" option')
804 if filter:
805 raise ClientException('"--filter" option is incompatible with "--kdu" option')
806
807 # try:
808 check_client_version(ctx.obj, ctx.command.name)
809 resp = ctx.obj.vnf.get(name)
810
811 if kdu:
812 ns_id = resp['nsr-id-ref']
813 op_data={}
814 op_data['member_vnf_index'] = resp['member-vnf-index-ref']
815 op_data['kdu_name'] = kdu
816 op_data['primitive'] = 'status'
817 op_data['primitive_params'] = {}
818 op_id = ctx.obj.ns.exec_op(ns_id, op_name='action', op_data=op_data, wait=False)
819 t = 0
820 while t<30:
821 op_info = ctx.obj.ns.get_op(op_id)
822 if op_info['operationState'] == 'COMPLETED':
823 print(op_info['detailed-status'])
824 return
825 time.sleep(5)
826 t += 5
827 print ("Could not determine KDU status")
828
829 if literal:
830 print(yaml.safe_dump(resp))
831 return
832
833 table = PrettyTable(['field', 'value'])
834
835 for k, v in list(resp.items()):
836 if filter is None or filter in k:
837 table.add_row([k, wrap_text(text=json.dumps(v,indent=2),width=100)])
838 table.align = 'l'
839 print(table)
840 # except ClientException as e:
841 # print(str(e))
842 # exit(1)
843
844
845 #@cli_osm.command(name='vnf-monitoring-show')
846 #@click.argument('vnf_name')
847 #@click.pass_context
848 #def vnf_monitoring_show(ctx, vnf_name):
849 # try:
850 # check_client_version(ctx.obj, ctx.command.name, 'v1')
851 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
852 # except ClientException as e:
853 # print(str(e))
854 # exit(1)
855 #
856 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
857 # if resp is not None:
858 # for monitor in resp:
859 # table.add_row(
860 # [vnf_name,
861 # monitor['name'],
862 # monitor['value-integer'],
863 # monitor['units']])
864 # table.align = 'l'
865 # print(table)
866
867
868 #@cli_osm.command(name='ns-monitoring-show')
869 #@click.argument('ns_name')
870 #@click.pass_context
871 #def ns_monitoring_show(ctx, ns_name):
872 # try:
873 # check_client_version(ctx.obj, ctx.command.name, 'v1')
874 # resp = ctx.obj.ns.get_monitoring(ns_name)
875 # except ClientException as e:
876 # print(str(e))
877 # exit(1)
878 #
879 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
880 # for key, val in list(resp.items()):
881 # for monitor in val:
882 # table.add_row(
883 # [key,
884 # monitor['name'],
885 # monitor['value-integer'],
886 # monitor['units']])
887 # table.align = 'l'
888 # print(table)
889
890
891 @cli_osm.command(name='ns-op-show', short_help='shows the info of a NS operation')
892 @click.argument('id')
893 @click.option('--filter', default=None)
894 @click.option('--literal', is_flag=True,
895 help='print literally, no pretty table')
896 @click.pass_context
897 def ns_op_show(ctx, id, filter, literal):
898 """shows the detailed info of a NS operation
899
900 ID: operation identifier
901 """
902 # try:
903 check_client_version(ctx.obj, ctx.command.name)
904 op_info = ctx.obj.ns.get_op(id)
905 # except ClientException as e:
906 # print(str(e))
907 # exit(1)
908
909 if literal:
910 print(yaml.safe_dump(op_info))
911 return
912
913 table = PrettyTable(['field', 'value'])
914 for k, v in list(op_info.items()):
915 if filter is None or filter in k:
916 table.add_row([k, wrap_text(json.dumps(v, indent=2), 100)])
917 table.align = 'l'
918 print(table)
919
920
921 def nst_show(ctx, name, literal):
922 # try:
923 check_client_version(ctx.obj, ctx.command.name)
924 resp = ctx.obj.nst.get(name)
925 #resp = ctx.obj.nst.get_individual(name)
926 # except ClientException as e:
927 # print(str(e))
928 # exit(1)
929
930 if literal:
931 print(yaml.safe_dump(resp))
932 return
933
934 table = PrettyTable(['field', 'value'])
935 for k, v in list(resp.items()):
936 table.add_row([k, wrap_text(json.dumps(v, indent=2), 100)])
937 table.align = 'l'
938 print(table)
939
940
941 @cli_osm.command(name='nst-show', short_help='shows the content of a Network Slice Template (NST)')
942 @click.option('--literal', is_flag=True,
943 help='print literally, no pretty table')
944 @click.argument('name')
945 @click.pass_context
946 def nst_show1(ctx, name, literal):
947 """shows the content of a Network Slice Template (NST)
948
949 NAME: name or ID of the NST
950 """
951 nst_show(ctx, name, literal)
952
953
954 @cli_osm.command(name='netslice-template-show', short_help='shows the content of a Network Slice Template (NST)')
955 @click.option('--literal', is_flag=True,
956 help='print literally, no pretty table')
957 @click.argument('name')
958 @click.pass_context
959 def nst_show2(ctx, name, literal):
960 """shows the content of a Network Slice Template (NST)
961
962 NAME: name or ID of the NST
963 """
964 nst_show(ctx, name, literal)
965
966
967 def nsi_show(ctx, name, literal, filter):
968 # try:
969 check_client_version(ctx.obj, ctx.command.name)
970 nsi = ctx.obj.nsi.get(name)
971 # except ClientException as e:
972 # print(str(e))
973 # exit(1)
974
975 if literal:
976 print(yaml.safe_dump(nsi))
977 return
978
979 table = PrettyTable(['field', 'value'])
980
981 for k, v in list(nsi.items()):
982 if filter is None or filter in k:
983 table.add_row([k, json.dumps(v, indent=2)])
984
985 table.align = 'l'
986 print(table)
987
988
989 @cli_osm.command(name='nsi-show', short_help='shows the content of a Network Slice Instance (NSI)')
990 @click.argument('name')
991 @click.option('--literal', is_flag=True,
992 help='print literally, no pretty table')
993 @click.option('--filter', default=None)
994 @click.pass_context
995 def nsi_show1(ctx, name, literal, filter):
996 """shows the content of a Network Slice Instance (NSI)
997
998 NAME: name or ID of the Network Slice Instance
999 """
1000 nsi_show(ctx, name, literal, filter)
1001
1002
1003 @cli_osm.command(name='netslice-instance-show', short_help='shows the content of a Network Slice Instance (NSI)')
1004 @click.argument('name')
1005 @click.option('--literal', is_flag=True,
1006 help='print literally, no pretty table')
1007 @click.option('--filter', default=None)
1008 @click.pass_context
1009 def nsi_show2(ctx, name, literal, filter):
1010 """shows the content of a Network Slice Instance (NSI)
1011
1012 NAME: name or ID of the Network Slice Instance
1013 """
1014 nsi_show(ctx, name, literal, filter)
1015
1016
1017 def nsi_op_show(ctx, id, filter):
1018 # try:
1019 check_client_version(ctx.obj, ctx.command.name)
1020 op_info = ctx.obj.nsi.get_op(id)
1021 # except ClientException as e:
1022 # print(str(e))
1023 # exit(1)
1024
1025 table = PrettyTable(['field', 'value'])
1026 for k, v in list(op_info.items()):
1027 if filter is None or filter in k:
1028 table.add_row([k, json.dumps(v, indent=2)])
1029 table.align = 'l'
1030 print(table)
1031
1032
1033 @cli_osm.command(name='nsi-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
1034 @click.argument('id')
1035 @click.option('--filter', default=None)
1036 @click.pass_context
1037 def nsi_op_show1(ctx, id, filter):
1038 """shows the info of an operation over a Network Slice Instance(NSI)
1039
1040 ID: operation identifier
1041 """
1042 nsi_op_show(ctx, id, filter)
1043
1044
1045 @cli_osm.command(name='netslice-instance-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
1046 @click.argument('id')
1047 @click.option('--filter', default=None)
1048 @click.pass_context
1049 def nsi_op_show2(ctx, id, filter):
1050 """shows the info of an operation over a Network Slice Instance(NSI)
1051
1052 ID: operation identifier
1053 """
1054 nsi_op_show(ctx, id, filter)
1055
1056
1057 @cli_osm.command(name='pdu-show', short_help='shows the content of a Physical Deployment Unit (PDU)')
1058 @click.argument('name')
1059 @click.option('--literal', is_flag=True,
1060 help='print literally, no pretty table')
1061 @click.option('--filter', default=None)
1062 @click.pass_context
1063 def pdu_show(ctx, name, literal, filter):
1064 """shows the content of a Physical Deployment Unit (PDU)
1065
1066 NAME: name or ID of the PDU
1067 """
1068 # try:
1069 check_client_version(ctx.obj, ctx.command.name)
1070 pdu = ctx.obj.pdu.get(name)
1071 # except ClientException as e:
1072 # print(str(e))
1073 # exit(1)
1074
1075 if literal:
1076 print(yaml.safe_dump(pdu))
1077 return
1078
1079 table = PrettyTable(['field', 'value'])
1080
1081 for k, v in list(pdu.items()):
1082 if filter is None or filter in k:
1083 table.add_row([k, json.dumps(v, indent=2)])
1084
1085 table.align = 'l'
1086 print(table)
1087
1088
1089 ####################
1090 # CREATE operations
1091 ####################
1092
1093 def nsd_create(ctx, filename, overwrite):
1094 # try:
1095 check_client_version(ctx.obj, ctx.command.name)
1096 ctx.obj.nsd.create(filename, overwrite)
1097 # except ClientException as e:
1098 # print(str(e))
1099 # exit(1)
1100
1101
1102 @cli_osm.command(name='nsd-create', short_help='creates a new NSD/NSpkg')
1103 @click.argument('filename')
1104 @click.option('--overwrite', 'overwrite', default=None, hidden=True,
1105 help='Deprecated. Use override')
1106 @click.option('--override', 'overwrite', default=None,
1107 help='overrides fields in descriptor, format: '
1108 '"key1.key2...=value[;key3...=value;...]"')
1109 @click.pass_context
1110 def nsd_create1(ctx, filename, overwrite):
1111 """creates a new NSD/NSpkg
1112
1113 FILENAME: NSD yaml file or NSpkg tar.gz file
1114 """
1115 nsd_create(ctx, filename, overwrite)
1116
1117
1118 @cli_osm.command(name='nspkg-create', short_help='creates a new NSD/NSpkg')
1119 @click.argument('filename')
1120 @click.option('--overwrite', 'overwrite', default=None, hidden=True,
1121 help='Deprecated. Use override')
1122 @click.option('--override', 'overwrite', default=None,
1123 help='overrides fields in descriptor, format: '
1124 '"key1.key2...=value[;key3...=value;...]"')
1125 @click.pass_context
1126 def nsd_create2(ctx, filename, overwrite):
1127 """creates a new NSD/NSpkg
1128
1129 FILENAME: NSD yaml file or NSpkg tar.gz file
1130 """
1131 nsd_create(ctx, filename, overwrite)
1132
1133
1134 def vnfd_create(ctx, filename, overwrite):
1135 # try:
1136 check_client_version(ctx.obj, ctx.command.name)
1137 ctx.obj.vnfd.create(filename, overwrite)
1138 # except ClientException as e:
1139 # print(str(e))
1140 # exit(1)
1141
1142
1143 @cli_osm.command(name='vnfd-create', short_help='creates a new VNFD/VNFpkg')
1144 @click.argument('filename')
1145 @click.option('--overwrite', 'overwrite', default=None,
1146 help='overwrite deprecated, use override')
1147 @click.option('--override', 'overwrite', default=None,
1148 help='overrides fields in descriptor, format: '
1149 '"key1.key2...=value[;key3...=value;...]"')
1150 @click.pass_context
1151 def vnfd_create1(ctx, filename, overwrite):
1152 """creates a new VNFD/VNFpkg
1153
1154 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1155 """
1156 vnfd_create(ctx, filename, overwrite)
1157
1158
1159 @cli_osm.command(name='vnfpkg-create', short_help='creates a new VNFD/VNFpkg')
1160 @click.argument('filename')
1161 @click.option('--overwrite', 'overwrite', default=None, hidden=True,
1162 help='Deprecated. Use override')
1163 @click.option('--override', 'overwrite', default=None,
1164 help='overrides fields in descriptor, format: '
1165 '"key1.key2...=value[;key3...=value;...]"')
1166 @click.pass_context
1167 def vnfd_create2(ctx, filename, overwrite):
1168 """creates a new VNFD/VNFpkg
1169
1170 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1171 """
1172 vnfd_create(ctx, filename, overwrite)
1173
1174
1175 @cli_osm.command(name='nfpkg-create', short_help='creates a new NFpkg')
1176 @click.argument('filename')
1177 @click.option('--overwrite', 'overwrite', default=None, hidden=True,
1178 help='Deprecated. Use override')
1179 @click.option('--override', 'overwrite', default=None,
1180 help='overrides fields in descriptor, format: '
1181 '"key1.key2...=value[;key3...=value;...]"')
1182 @click.pass_context
1183 def nfpkg_create(ctx, filename, overwrite):
1184 """creates a new NFpkg
1185
1186 FILENAME: NF Descriptor yaml file or NFpkg tar.gz file
1187 """
1188 vnfd_create(ctx, filename, overwrite)
1189
1190
1191 @cli_osm.command(name='ns-create', short_help='creates a new Network Service instance')
1192 @click.option('--ns_name',
1193 prompt=True, help='name of the NS instance')
1194 @click.option('--nsd_name',
1195 prompt=True, help='name of the NS descriptor')
1196 @click.option('--vim_account',
1197 prompt=True, help='default VIM account id or name for the deployment')
1198 @click.option('--admin_status',
1199 default='ENABLED',
1200 help='administration status')
1201 @click.option('--ssh_keys',
1202 default=None,
1203 help='comma separated list of public key files to inject to vnfs')
1204 @click.option('--config',
1205 default=None,
1206 help='ns specific yaml configuration')
1207 @click.option('--config_file',
1208 default=None,
1209 help='ns specific yaml configuration file')
1210 @click.option('--wait',
1211 required=False,
1212 default=False,
1213 is_flag=True,
1214 help='do not return the control immediately, but keep it '
1215 'until the operation is completed, or timeout')
1216 @click.pass_context
1217 def ns_create(ctx,
1218 nsd_name,
1219 ns_name,
1220 vim_account,
1221 admin_status,
1222 ssh_keys,
1223 config,
1224 config_file,
1225 wait):
1226 """creates a new NS instance"""
1227 # try:
1228 if config_file:
1229 check_client_version(ctx.obj, '--config_file')
1230 if config:
1231 raise ClientException('"--config" option is incompatible with "--config_file" option')
1232 with open(config_file, 'r') as cf:
1233 config=cf.read()
1234 ctx.obj.ns.create(
1235 nsd_name,
1236 ns_name,
1237 config=config,
1238 ssh_keys=ssh_keys,
1239 account=vim_account,
1240 wait=wait)
1241 # except ClientException as e:
1242 # print(str(e))
1243 # exit(1)
1244
1245
1246 def nst_create(ctx, filename, overwrite):
1247 # try:
1248 check_client_version(ctx.obj, ctx.command.name)
1249 ctx.obj.nst.create(filename, overwrite)
1250 # except ClientException as e:
1251 # print(str(e))
1252 # exit(1)
1253
1254
1255 @cli_osm.command(name='nst-create', short_help='creates a new Network Slice Template (NST)')
1256 @click.argument('filename')
1257 @click.option('--overwrite', 'overwrite', default=None, hidden=True,
1258 help='Deprecated. Use override')
1259 @click.option('--override', 'overwrite', default=None,
1260 help='overrides fields in descriptor, format: '
1261 '"key1.key2...=value[;key3...=value;...]"')
1262 @click.pass_context
1263 def nst_create1(ctx, filename, overwrite):
1264 """creates a new Network Slice Template (NST)
1265
1266 FILENAME: NST yaml file or NSTpkg tar.gz file
1267 """
1268 nst_create(ctx, filename, overwrite)
1269
1270
1271 @cli_osm.command(name='netslice-template-create', short_help='creates a new Network Slice Template (NST)')
1272 @click.argument('filename')
1273 @click.option('--overwrite', 'overwrite', default=None, hidden=True,
1274 help='Deprecated. Use override')
1275 @click.option('--override', 'overwrite', default=None,
1276 help='overrides fields in descriptor, format: '
1277 '"key1.key2...=value[;key3...=value;...]"')
1278 @click.pass_context
1279 def nst_create2(ctx, filename, overwrite):
1280 """creates a new Network Slice Template (NST)
1281
1282 FILENAME: NST yaml file or NSTpkg tar.gz file
1283 """
1284 nst_create(ctx, filename, overwrite)
1285
1286
1287 def nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1288 """creates a new Network Slice Instance (NSI)"""
1289 # try:
1290 check_client_version(ctx.obj, ctx.command.name)
1291 if config_file:
1292 if config:
1293 raise ClientException('"--config" option is incompatible with "--config_file" option')
1294 with open(config_file, 'r') as cf:
1295 config=cf.read()
1296 ctx.obj.nsi.create(nst_name, nsi_name, config=config, ssh_keys=ssh_keys,
1297 account=vim_account, wait=wait)
1298 # except ClientException as e:
1299 # print(str(e))
1300 # exit(1)
1301
1302
1303 @cli_osm.command(name='nsi-create', short_help='creates a new Network Slice Instance')
1304 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1305 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1306 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1307 @click.option('--ssh_keys', default=None,
1308 help='comma separated list of keys to inject to vnfs')
1309 @click.option('--config', default=None,
1310 help='Netslice specific yaml configuration:\n'
1311 'netslice_subnet: [\n'
1312 'id: TEXT, vim_account: TEXT,\n'
1313 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1314 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1315 'additionalParamsForNsi: {param: value, ...}\n'
1316 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1317 '],\n'
1318 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1319 )
1320 @click.option('--config_file',
1321 default=None,
1322 help='nsi specific yaml configuration file')
1323 @click.option('--wait',
1324 required=False,
1325 default=False,
1326 is_flag=True,
1327 help='do not return the control immediately, but keep it '
1328 'until the operation is completed, or timeout')
1329 @click.pass_context
1330 def nsi_create1(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1331 """creates a new Network Slice Instance (NSI)"""
1332 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1333
1334
1335 @cli_osm.command(name='netslice-instance-create', short_help='creates a new Network Slice Instance')
1336 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1337 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1338 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1339 @click.option('--ssh_keys', default=None,
1340 help='comma separated list of keys to inject to vnfs')
1341 @click.option('--config', default=None,
1342 help='Netslice specific yaml configuration:\n'
1343 'netslice_subnet: [\n'
1344 'id: TEXT, vim_account: TEXT,\n'
1345 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1346 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1347 '],\n'
1348 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1349 )
1350 @click.option('--config_file',
1351 default=None,
1352 help='nsi specific yaml configuration file')
1353 @click.option('--wait',
1354 required=False,
1355 default=False,
1356 is_flag=True,
1357 help='do not return the control immediately, but keep it '
1358 'until the operation is completed, or timeout')
1359 @click.pass_context
1360 def nsi_create2(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1361 """creates a new Network Slice Instance (NSI)"""
1362 nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1363
1364
1365 @cli_osm.command(name='pdu-create', short_help='adds a new Physical Deployment Unit to the catalog')
1366 @click.option('--name', help='name of the Physical Deployment Unit')
1367 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1368 @click.option('--interface',
1369 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1370 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1371 multiple=True)
1372 @click.option('--description', help='human readable description')
1373 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple=True)
1374 @click.option('--descriptor_file', default=None,
1375 help='PDU descriptor file (as an alternative to using the other arguments')
1376 @click.pass_context
1377 def pdu_create(ctx, name, pdu_type, interface, description, vim_account, descriptor_file):
1378 """creates a new Physical Deployment Unit (PDU)"""
1379 # try:
1380 check_client_version(ctx.obj, ctx.command.name)
1381 pdu = {}
1382 if not descriptor_file:
1383 if not name:
1384 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1385 if not pdu_type:
1386 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1387 if not interface:
1388 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1389 if not vim_account:
1390 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1391 else:
1392 with open(descriptor_file, 'r') as df:
1393 pdu = yaml.safe_load(df.read())
1394 if name: pdu["name"] = name
1395 if pdu_type: pdu["type"] = pdu_type
1396 if description: pdu["description"] = description
1397 if vim_account: pdu["vim_accounts"] = vim_account
1398 if interface:
1399 ifaces_list = []
1400 for iface in interface:
1401 new_iface={k:v for k,v in [i.split('=') for i in iface.split(',')]}
1402 new_iface["mgmt"] = (new_iface.get("mgmt","false").lower() == "true")
1403 ifaces_list.append(new_iface)
1404 pdu["interfaces"] = ifaces_list
1405 ctx.obj.pdu.create(pdu)
1406 # except ClientException as e:
1407 # print(str(e))
1408 # exit(1)
1409
1410 ####################
1411 # UPDATE operations
1412 ####################
1413
1414 def nsd_update(ctx, name, content):
1415 # try:
1416 check_client_version(ctx.obj, ctx.command.name)
1417 ctx.obj.nsd.update(name, content)
1418 # except ClientException as e:
1419 # print(str(e))
1420 # exit(1)
1421
1422
1423 @cli_osm.command(name='nsd-update', short_help='updates a NSD/NSpkg')
1424 @click.argument('name')
1425 @click.option('--content', default=None,
1426 help='filename with the NSD/NSpkg replacing the current one')
1427 @click.pass_context
1428 def nsd_update1(ctx, name, content):
1429 """updates a NSD/NSpkg
1430
1431 NAME: name or ID of the NSD/NSpkg
1432 """
1433 nsd_update(ctx, name, content)
1434
1435
1436 @cli_osm.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
1437 @click.argument('name')
1438 @click.option('--content', default=None,
1439 help='filename with the NSD/NSpkg replacing the current one')
1440 @click.pass_context
1441 def nsd_update2(ctx, name, content):
1442 """updates a NSD/NSpkg
1443
1444 NAME: name or ID of the NSD/NSpkg
1445 """
1446 nsd_update(ctx, name, content)
1447
1448
1449 def vnfd_update(ctx, name, content):
1450 # try:
1451 check_client_version(ctx.obj, ctx.command.name)
1452 ctx.obj.vnfd.update(name, content)
1453 # except ClientException as e:
1454 # print(str(e))
1455 # exit(1)
1456
1457
1458 @cli_osm.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
1459 @click.argument('name')
1460 @click.option('--content', default=None,
1461 help='filename with the VNFD/VNFpkg replacing the current one')
1462 @click.pass_context
1463 def vnfd_update1(ctx, name, content):
1464 """updates a VNFD/VNFpkg
1465
1466 NAME: name or ID of the VNFD/VNFpkg
1467 """
1468 vnfd_update(ctx, name, content)
1469
1470
1471 @cli_osm.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
1472 @click.argument('name')
1473 @click.option('--content', default=None,
1474 help='filename with the VNFD/VNFpkg replacing the current one')
1475 @click.pass_context
1476 def vnfd_update2(ctx, name, content):
1477 """updates a VNFD/VNFpkg
1478
1479 NAME: VNFD yaml file or VNFpkg tar.gz file
1480 """
1481 vnfd_update(ctx, name, content)
1482
1483
1484 @cli_osm.command(name='nfpkg-update', short_help='updates a NFpkg')
1485 @click.argument('name')
1486 @click.option('--content', default=None,
1487 help='filename with the NFpkg replacing the current one')
1488 @click.pass_context
1489 def nfpkg_update(ctx, name, content):
1490 """updates a NFpkg
1491
1492 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1493 """
1494 vnfd_update(ctx, name, content)
1495
1496
1497 def nst_update(ctx, name, content):
1498 # try:
1499 check_client_version(ctx.obj, ctx.command.name)
1500 ctx.obj.nst.update(name, content)
1501 # except ClientException as e:
1502 # print(str(e))
1503 # exit(1)
1504
1505
1506 @cli_osm.command(name='nst-update', short_help='updates a Network Slice Template (NST)')
1507 @click.argument('name')
1508 @click.option('--content', default=None,
1509 help='filename with the NST/NSTpkg replacing the current one')
1510 @click.pass_context
1511 def nst_update1(ctx, name, content):
1512 """updates a Network Slice Template (NST)
1513
1514 NAME: name or ID of the NSD/NSpkg
1515 """
1516 nst_update(ctx, name, content)
1517
1518
1519 @cli_osm.command(name='netslice-template-update', short_help='updates a Network Slice Template (NST)')
1520 @click.argument('name')
1521 @click.option('--content', default=None,
1522 help='filename with the NST/NSTpkg replacing the current one')
1523 @click.pass_context
1524 def nst_update2(ctx, name, content):
1525 """updates a Network Slice Template (NST)
1526
1527 NAME: name or ID of the NSD/NSpkg
1528 """
1529 nst_update(ctx, name, content)
1530
1531
1532 ####################
1533 # DELETE operations
1534 ####################
1535
1536 def nsd_delete(ctx, name, force):
1537 # try:
1538 if not force:
1539 ctx.obj.nsd.delete(name)
1540 else:
1541 check_client_version(ctx.obj, '--force')
1542 ctx.obj.nsd.delete(name, force)
1543 # except ClientException as e:
1544 # print(str(e))
1545 # exit(1)
1546
1547
1548 @cli_osm.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
1549 @click.argument('name')
1550 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1551 @click.pass_context
1552 def nsd_delete1(ctx, name, force):
1553 """deletes a NSD/NSpkg
1554
1555 NAME: name or ID of the NSD/NSpkg to be deleted
1556 """
1557 nsd_delete(ctx, name, force)
1558
1559
1560 @cli_osm.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
1561 @click.argument('name')
1562 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1563 @click.pass_context
1564 def nsd_delete2(ctx, name, force):
1565 """deletes a NSD/NSpkg
1566
1567 NAME: name or ID of the NSD/NSpkg to be deleted
1568 """
1569 nsd_delete(ctx, name, force)
1570
1571
1572 def vnfd_delete(ctx, name, force):
1573 # try:
1574 if not force:
1575 ctx.obj.vnfd.delete(name)
1576 else:
1577 check_client_version(ctx.obj, '--force')
1578 ctx.obj.vnfd.delete(name, force)
1579 # except ClientException as e:
1580 # print(str(e))
1581 # exit(1)
1582
1583
1584 @cli_osm.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
1585 @click.argument('name')
1586 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1587 @click.pass_context
1588 def vnfd_delete1(ctx, name, force):
1589 """deletes a VNFD/VNFpkg
1590
1591 NAME: name or ID of the VNFD/VNFpkg to be deleted
1592 """
1593 vnfd_delete(ctx, name, force)
1594
1595
1596 @cli_osm.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
1597 @click.argument('name')
1598 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1599 @click.pass_context
1600 def vnfd_delete2(ctx, name, force):
1601 """deletes a VNFD/VNFpkg
1602
1603 NAME: name or ID of the VNFD/VNFpkg to be deleted
1604 """
1605 vnfd_delete(ctx, name, force)
1606
1607
1608 @cli_osm.command(name='nfpkg-delete', short_help='deletes a NFpkg')
1609 @click.argument('name')
1610 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1611 @click.pass_context
1612 def nfpkg_delete(ctx, name, force):
1613 """deletes a NFpkg
1614
1615 NAME: name or ID of the NFpkg to be deleted
1616 """
1617 vnfd_delete(ctx, name, force)
1618
1619
1620 @cli_osm.command(name='ns-delete', short_help='deletes a NS instance')
1621 @click.argument('name')
1622 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1623 @click.option('--wait',
1624 required=False,
1625 default=False,
1626 is_flag=True,
1627 help='do not return the control immediately, but keep it '
1628 'until the operation is completed, or timeout')
1629 @click.pass_context
1630 def ns_delete(ctx, name, force, wait):
1631 """deletes a NS instance
1632
1633 NAME: name or ID of the NS instance to be deleted
1634 """
1635 # try:
1636 if not force:
1637 ctx.obj.ns.delete(name, wait=wait)
1638 else:
1639 check_client_version(ctx.obj, '--force')
1640 ctx.obj.ns.delete(name, force, wait=wait)
1641 # except ClientException as e:
1642 # print(str(e))
1643 # exit(1)
1644
1645
1646 def nst_delete(ctx, name, force):
1647 # try:
1648 check_client_version(ctx.obj, ctx.command.name)
1649 ctx.obj.nst.delete(name, force)
1650 # except ClientException as e:
1651 # print(str(e))
1652 # exit(1)
1653
1654
1655 @cli_osm.command(name='nst-delete', short_help='deletes a Network Slice Template (NST)')
1656 @click.argument('name')
1657 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1658 @click.pass_context
1659 def nst_delete1(ctx, name, force):
1660 """deletes a Network Slice Template (NST)
1661
1662 NAME: name or ID of the NST/NSTpkg to be deleted
1663 """
1664 nst_delete(ctx, name, force)
1665
1666
1667 @cli_osm.command(name='netslice-template-delete', short_help='deletes a Network Slice Template (NST)')
1668 @click.argument('name')
1669 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1670 @click.pass_context
1671 def nst_delete2(ctx, name, force):
1672 """deletes a Network Slice Template (NST)
1673
1674 NAME: name or ID of the NST/NSTpkg to be deleted
1675 """
1676 nst_delete(ctx, name, force)
1677
1678
1679 def nsi_delete(ctx, name, force, wait):
1680 # try:
1681 check_client_version(ctx.obj, ctx.command.name)
1682 ctx.obj.nsi.delete(name, force, wait=wait)
1683 # except ClientException as e:
1684 # print(str(e))
1685 # exit(1)
1686
1687
1688 @cli_osm.command(name='nsi-delete', short_help='deletes a Network Slice Instance (NSI)')
1689 @click.argument('name')
1690 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1691 @click.option('--wait',
1692 required=False,
1693 default=False,
1694 is_flag=True,
1695 help='do not return the control immediately, but keep it '
1696 'until the operation is completed, or timeout')
1697 @click.pass_context
1698 def nsi_delete1(ctx, name, force, wait):
1699 """deletes a Network Slice Instance (NSI)
1700
1701 NAME: name or ID of the Network Slice instance to be deleted
1702 """
1703 nsi_delete(ctx, name, force, wait=wait)
1704
1705
1706 @cli_osm.command(name='netslice-instance-delete', short_help='deletes a Network Slice Instance (NSI)')
1707 @click.argument('name')
1708 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1709 @click.pass_context
1710 def nsi_delete2(ctx, name, force, wait):
1711 """deletes a Network Slice Instance (NSI)
1712
1713 NAME: name or ID of the Network Slice instance to be deleted
1714 """
1715 nsi_delete(ctx, name, force, wait=wait)
1716
1717
1718 @cli_osm.command(name='pdu-delete', short_help='deletes a Physical Deployment Unit (PDU)')
1719 @click.argument('name')
1720 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1721 @click.pass_context
1722 def pdu_delete(ctx, name, force):
1723 """deletes a Physical Deployment Unit (PDU)
1724
1725 NAME: name or ID of the PDU to be deleted
1726 """
1727 # try:
1728 check_client_version(ctx.obj, ctx.command.name)
1729 ctx.obj.pdu.delete(name, force)
1730 # except ClientException as e:
1731 # print(str(e))
1732 # exit(1)
1733
1734
1735 #################
1736 # VIM operations
1737 #################
1738
1739 @cli_osm.command(name='vim-create', short_help='creates a new VIM account')
1740 @click.option('--name',
1741 prompt=True,
1742 help='Name to create datacenter')
1743 @click.option('--user',
1744 prompt=True,
1745 help='VIM username')
1746 @click.option('--password',
1747 prompt=True,
1748 hide_input=True,
1749 confirmation_prompt=True,
1750 help='VIM password')
1751 @click.option('--auth_url',
1752 prompt=True,
1753 help='VIM url')
1754 @click.option('--tenant',
1755 prompt=True,
1756 help='VIM tenant name')
1757 @click.option('--config',
1758 default=None,
1759 help='VIM specific config parameters')
1760 @click.option('--account_type',
1761 default='openstack',
1762 help='VIM type')
1763 @click.option('--description',
1764 default='no description',
1765 help='human readable description')
1766 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1767 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1768 @click.option('--wait',
1769 required=False,
1770 default=False,
1771 is_flag=True,
1772 help='do not return the control immediately, but keep it '
1773 'until the operation is completed, or timeout')
1774 @click.pass_context
1775 def vim_create(ctx,
1776 name,
1777 user,
1778 password,
1779 auth_url,
1780 tenant,
1781 config,
1782 account_type,
1783 description,
1784 sdn_controller,
1785 sdn_port_mapping,
1786 wait):
1787 """creates a new VIM account"""
1788 # try:
1789 if sdn_controller:
1790 check_client_version(ctx.obj, '--sdn_controller')
1791 if sdn_port_mapping:
1792 check_client_version(ctx.obj, '--sdn_port_mapping')
1793 vim = {}
1794 vim['vim-username'] = user
1795 vim['vim-password'] = password
1796 vim['vim-url'] = auth_url
1797 vim['vim-tenant-name'] = tenant
1798 vim['vim-type'] = account_type
1799 vim['description'] = description
1800 vim['config'] = config
1801 if sdn_controller or sdn_port_mapping:
1802 ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1803 else:
1804 ctx.obj.vim.create(name, vim, wait=wait)
1805 # except ClientException as e:
1806 # print(str(e))
1807 # exit(1)
1808
1809
1810 @cli_osm.command(name='vim-update', short_help='updates a VIM account')
1811 @click.argument('name')
1812 @click.option('--newname', help='New name for the VIM account')
1813 @click.option('--user', help='VIM username')
1814 @click.option('--password', help='VIM password')
1815 @click.option('--auth_url', help='VIM url')
1816 @click.option('--tenant', help='VIM tenant name')
1817 @click.option('--config', help='VIM specific config parameters')
1818 @click.option('--account_type', help='VIM type')
1819 @click.option('--description', help='human readable description')
1820 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
1821 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
1822 @click.option('--wait',
1823 required=False,
1824 default=False,
1825 is_flag=True,
1826 help='do not return the control immediately, but keep it '
1827 'until the operation is completed, or timeout')
1828 @click.pass_context
1829 def vim_update(ctx,
1830 name,
1831 newname,
1832 user,
1833 password,
1834 auth_url,
1835 tenant,
1836 config,
1837 account_type,
1838 description,
1839 sdn_controller,
1840 sdn_port_mapping,
1841 wait):
1842 """updates a VIM account
1843
1844 NAME: name or ID of the VIM account
1845 """
1846 # try:
1847 check_client_version(ctx.obj, ctx.command.name)
1848 vim = {}
1849 if newname: vim['name'] = newname
1850 if user: vim['vim_user'] = user
1851 if password: vim['vim_password'] = password
1852 if auth_url: vim['vim_url'] = auth_url
1853 if tenant: vim['vim-tenant-name'] = tenant
1854 if account_type: vim['vim_type'] = account_type
1855 if description: vim['description'] = description
1856 if config: vim['config'] = config
1857 ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
1858 # except ClientException as e:
1859 # print(str(e))
1860 # exit(1)
1861
1862
1863 @cli_osm.command(name='vim-delete', short_help='deletes a VIM account')
1864 @click.argument('name')
1865 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
1866 @click.option('--wait',
1867 required=False,
1868 default=False,
1869 is_flag=True,
1870 help='do not return the control immediately, but keep it '
1871 'until the operation is completed, or timeout')
1872 @click.pass_context
1873 def vim_delete(ctx, name, force, wait):
1874 """deletes a VIM account
1875
1876 NAME: name or ID of the VIM account to be deleted
1877 """
1878 # try:
1879 if not force:
1880 ctx.obj.vim.delete(name, wait=wait)
1881 else:
1882 check_client_version(ctx.obj, '--force')
1883 ctx.obj.vim.delete(name, force, wait=wait)
1884 # except ClientException as e:
1885 # print(str(e))
1886 # exit(1)
1887
1888
1889 @cli_osm.command(name='vim-list', short_help='list all VIM accounts')
1890 #@click.option('--ro_update/--no_ro_update',
1891 # default=False,
1892 # help='update list from RO')
1893 @click.option('--filter', default=None,
1894 help='restricts the list to the VIM accounts matching the filter')
1895 @click.pass_context
1896 def vim_list(ctx, filter):
1897 """list all VIM accounts"""
1898 if filter:
1899 check_client_version(ctx.obj, '--filter')
1900 # if ro_update:
1901 # check_client_version(ctx.obj, '--ro_update', 'v1')
1902 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1903 if fullclassname == 'osmclient.sol005.client.Client':
1904 resp = ctx.obj.vim.list(filter)
1905 # else:
1906 # resp = ctx.obj.vim.list(ro_update)
1907 table = PrettyTable(['vim name', 'uuid'])
1908 for vim in resp:
1909 table.add_row([vim['name'], vim['uuid']])
1910 table.align = 'l'
1911 print(table)
1912
1913
1914 @cli_osm.command(name='vim-show', short_help='shows the details of a VIM account')
1915 @click.argument('name')
1916 @click.pass_context
1917 def vim_show(ctx, name):
1918 """shows the details of a VIM account
1919
1920 NAME: name or ID of the VIM account
1921 """
1922 # try:
1923 resp = ctx.obj.vim.get(name)
1924 if 'vim_password' in resp:
1925 resp['vim_password']='********'
1926 # except ClientException as e:
1927 # print(str(e))
1928 # exit(1)
1929
1930 table = PrettyTable(['key', 'attribute'])
1931 for k, v in list(resp.items()):
1932 table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
1933 table.align = 'l'
1934 print(table)
1935
1936
1937 ####################
1938 # WIM operations
1939 ####################
1940
1941 @cli_osm.command(name='wim-create', short_help='creates a new WIM account')
1942 @click.option('--name',
1943 prompt=True,
1944 help='Name for the WIM account')
1945 @click.option('--user',
1946 help='WIM username')
1947 @click.option('--password',
1948 help='WIM password')
1949 @click.option('--url',
1950 prompt=True,
1951 help='WIM url')
1952 # @click.option('--tenant',
1953 # help='wIM tenant name')
1954 @click.option('--config',
1955 default=None,
1956 help='WIM specific config parameters')
1957 @click.option('--wim_type',
1958 help='WIM type')
1959 @click.option('--description',
1960 default='no description',
1961 help='human readable description')
1962 @click.option('--wim_port_mapping', default=None,
1963 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
1964 "(WAN service endpoint id and info)")
1965 @click.option('--wait',
1966 required=False,
1967 default=False,
1968 is_flag=True,
1969 help='do not return the control immediately, but keep it '
1970 'until the operation is completed, or timeout')
1971 @click.pass_context
1972 def wim_create(ctx,
1973 name,
1974 user,
1975 password,
1976 url,
1977 # tenant,
1978 config,
1979 wim_type,
1980 description,
1981 wim_port_mapping,
1982 wait):
1983 """creates a new WIM account"""
1984 # try:
1985 check_client_version(ctx.obj, ctx.command.name)
1986 # if sdn_controller:
1987 # check_client_version(ctx.obj, '--sdn_controller')
1988 # if sdn_port_mapping:
1989 # check_client_version(ctx.obj, '--sdn_port_mapping')
1990 wim = {}
1991 if user: wim['user'] = user
1992 if password: wim['password'] = password
1993 if url: wim['wim_url'] = url
1994 # if tenant: wim['tenant'] = tenant
1995 wim['wim_type'] = wim_type
1996 if description: wim['description'] = description
1997 if config: wim['config'] = config
1998 ctx.obj.wim.create(name, wim, wim_port_mapping, wait=wait)
1999 # except ClientException as e:
2000 # print(str(e))
2001 # exit(1)
2002
2003
2004 @cli_osm.command(name='wim-update', short_help='updates a WIM account')
2005 @click.argument('name')
2006 @click.option('--newname', help='New name for the WIM account')
2007 @click.option('--user', help='WIM username')
2008 @click.option('--password', help='WIM password')
2009 @click.option('--url', help='WIM url')
2010 @click.option('--config', help='WIM specific config parameters')
2011 @click.option('--wim_type', help='WIM type')
2012 @click.option('--description', help='human readable description')
2013 @click.option('--wim_port_mapping', default=None,
2014 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2015 "(WAN service endpoint id and info)")
2016 @click.option('--wait',
2017 required=False,
2018 default=False,
2019 is_flag=True,
2020 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2021 @click.pass_context
2022 def wim_update(ctx,
2023 name,
2024 newname,
2025 user,
2026 password,
2027 url,
2028 config,
2029 wim_type,
2030 description,
2031 wim_port_mapping,
2032 wait):
2033 """updates a WIM account
2034
2035 NAME: name or ID of the WIM account
2036 """
2037 # try:
2038 check_client_version(ctx.obj, ctx.command.name)
2039 wim = {}
2040 if newname: wim['name'] = newname
2041 if user: wim['user'] = user
2042 if password: wim['password'] = password
2043 if url: wim['url'] = url
2044 # if tenant: wim['tenant'] = tenant
2045 if wim_type: wim['wim_type'] = wim_type
2046 if description: wim['description'] = description
2047 if config: wim['config'] = config
2048 ctx.obj.wim.update(name, wim, wim_port_mapping, wait=wait)
2049 # except ClientException as e:
2050 # print(str(e))
2051 # exit(1)
2052
2053
2054 @cli_osm.command(name='wim-delete', short_help='deletes a WIM account')
2055 @click.argument('name')
2056 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2057 @click.option('--wait',
2058 required=False,
2059 default=False,
2060 is_flag=True,
2061 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2062 @click.pass_context
2063 def wim_delete(ctx, name, force, wait):
2064 """deletes a WIM account
2065
2066 NAME: name or ID of the WIM account to be deleted
2067 """
2068 # try:
2069 check_client_version(ctx.obj, ctx.command.name)
2070 ctx.obj.wim.delete(name, force, wait=wait)
2071 # except ClientException as e:
2072 # print(str(e))
2073 # exit(1)
2074
2075
2076 @cli_osm.command(name='wim-list', short_help='list all WIM accounts')
2077 @click.option('--filter', default=None,
2078 help='restricts the list to the WIM accounts matching the filter')
2079 @click.pass_context
2080 def wim_list(ctx, filter):
2081 """list all WIM accounts"""
2082 # try:
2083 check_client_version(ctx.obj, ctx.command.name)
2084 resp = ctx.obj.wim.list(filter)
2085 table = PrettyTable(['wim name', 'uuid'])
2086 for wim in resp:
2087 table.add_row([wim['name'], wim['uuid']])
2088 table.align = 'l'
2089 print(table)
2090 # except ClientException as e:
2091 # print(str(e))
2092 # exit(1)
2093
2094
2095 @cli_osm.command(name='wim-show', short_help='shows the details of a WIM account')
2096 @click.argument('name')
2097 @click.pass_context
2098 def wim_show(ctx, name):
2099 """shows the details of a WIM account
2100
2101 NAME: name or ID of the WIM account
2102 """
2103 # try:
2104 check_client_version(ctx.obj, ctx.command.name)
2105 resp = ctx.obj.wim.get(name)
2106 if 'password' in resp:
2107 resp['wim_password']='********'
2108 # except ClientException as e:
2109 # print(str(e))
2110 # exit(1)
2111
2112 table = PrettyTable(['key', 'attribute'])
2113 for k, v in list(resp.items()):
2114 table.add_row([k, json.dumps(v, indent=2)])
2115 table.align = 'l'
2116 print(table)
2117
2118
2119 ####################
2120 # SDN controller operations
2121 ####################
2122
2123 @cli_osm.command(name='sdnc-create', short_help='creates a new SDN controller')
2124 @click.option('--name',
2125 prompt=True,
2126 help='Name to create sdn controller')
2127 @click.option('--type',
2128 prompt=True,
2129 help='SDN controller type')
2130 @click.option('--sdn_controller_version', hidden=True,
2131 help='Deprecated. Use --config {version: sdn_controller_version}')
2132 @click.option('--url',
2133 help='URL in format http[s]://HOST:IP/')
2134 @click.option('--ip_address', hidden=True,
2135 help='Deprecated. Use --url')
2136 @click.option('--port', hidden=True,
2137 help='Deprecated. Use --url')
2138 @click.option('--switch_dpid', hidden=True,
2139 help='Deprecated. Use --config {dpid: DPID}')
2140 @click.option('--config',
2141 help='Extra information for SDN in yaml format, as {dpid: (Openflow Datapath ID), version: version}')
2142 @click.option('--user',
2143 help='SDN controller username')
2144 @click.option('--password',
2145 hide_input=True,
2146 confirmation_prompt=True,
2147 help='SDN controller password')
2148 @click.option('--description', default=None, help='human readable description')
2149 @click.option('--wait',
2150 required=False,
2151 default=False,
2152 is_flag=True,
2153 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2154 @click.pass_context
2155 def sdnc_create(ctx, **kwargs):
2156 """creates a new SDN controller"""
2157 sdncontroller = {x: kwargs[x] for x in kwargs if kwargs[x] and
2158 x not in ("wait", "ip_address", "port", "switch_dpid")}
2159 if kwargs.get("port"):
2160 print("option '--port' is deprecated, use '-url' instead")
2161 sdncontroller["port"] = int(kwargs["port"])
2162 if kwargs.get("ip_address"):
2163 print("option '--ip_address' is deprecated, use '-url' instead")
2164 sdncontroller["ip"] = kwargs["ip_address"]
2165 if kwargs.get("switch_dpid"):
2166 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2167 sdncontroller["dpid"] = kwargs["switch_dpid"]
2168 if kwargs.get("sdn_controller_version"):
2169 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2170 " instead")
2171 # try:
2172 check_client_version(ctx.obj, ctx.command.name)
2173 ctx.obj.sdnc.create(kwargs["name"], sdncontroller, wait=kwargs["wait"])
2174 # except ClientException as e:
2175 # print(str(e))
2176 # exit(1)
2177
2178 @cli_osm.command(name='sdnc-update', short_help='updates an SDN controller')
2179 @click.argument('name')
2180 @click.option('--newname', help='New name for the SDN controller')
2181 @click.option('--description', default=None, help='human readable description')
2182 @click.option('--type', help='SDN controller type')
2183 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2184 @click.option('--config', help='Extra information for SDN in yaml format, as '
2185 '{dpid: (Openflow Datapath ID), version: version}')
2186 @click.option('--user', help='SDN controller username')
2187 @click.option('--password', help='SDN controller password')
2188 @click.option('--ip_address', hidden=True, help='Deprecated. Use --url')
2189 @click.option('--port', hidden=True, help='Deprecated. Use --url')
2190 @click.option('--switch_dpid', hidden=True, help='Deprecated. Use --config {switch_dpid: DPID}')
2191 @click.option('--sdn_controller_version', hidden=True, help='Deprecated. Use --config {version: VERSION}')
2192 @click.option('--wait', required=False, default=False, is_flag=True,
2193 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2194 @click.pass_context
2195 def sdnc_update(ctx, **kwargs):
2196 """updates an SDN controller
2197
2198 NAME: name or ID of the SDN controller
2199 """
2200 sdncontroller = {x: kwargs[x] for x in kwargs if kwargs[x] and
2201 x not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2202 if kwargs.get("newname"):
2203 sdncontroller["name"] = kwargs["newname"]
2204 if kwargs.get("port"):
2205 print("option '--port' is deprecated, use '-url' instead")
2206 sdncontroller["port"] = int(kwargs["port"])
2207 if kwargs.get("ip_address"):
2208 print("option '--ip_address' is deprecated, use '-url' instead")
2209 sdncontroller["ip"] = kwargs["ip_address"]
2210 if kwargs.get("switch_dpid"):
2211 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2212 sdncontroller["dpid"] = kwargs["switch_dpid"]
2213 if kwargs.get("sdn_controller_version"):
2214 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2215 " instead")
2216
2217 # try:
2218 check_client_version(ctx.obj, ctx.command.name)
2219 ctx.obj.sdnc.update(kwargs["name"], sdncontroller, wait=kwargs["wait"])
2220 # except ClientException as e:
2221 # print(str(e))
2222 # exit(1)
2223
2224
2225 @cli_osm.command(name='sdnc-delete', short_help='deletes an SDN controller')
2226 @click.argument('name')
2227 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2228 @click.option('--wait', required=False, default=False, is_flag=True,
2229 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2230 @click.pass_context
2231 def sdnc_delete(ctx, name, force, wait):
2232 """deletes an SDN controller
2233
2234 NAME: name or ID of the SDN controller to be deleted
2235 """
2236 # try:
2237 check_client_version(ctx.obj, ctx.command.name)
2238 ctx.obj.sdnc.delete(name, force, wait=wait)
2239 # except ClientException as e:
2240 # print(str(e))
2241 # exit(1)
2242
2243
2244 @cli_osm.command(name='sdnc-list', short_help='list all SDN controllers')
2245 @click.option('--filter', default=None,
2246 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2247 @click.pass_context
2248 def sdnc_list(ctx, filter):
2249 """list all SDN controllers"""
2250 # try:
2251 check_client_version(ctx.obj, ctx.command.name)
2252 resp = ctx.obj.sdnc.list(filter)
2253 # except ClientException as e:
2254 # print(str(e))
2255 # exit(1)
2256 table = PrettyTable(['sdnc name', 'id'])
2257 for sdnc in resp:
2258 table.add_row([sdnc['name'], sdnc['_id']])
2259 table.align = 'l'
2260 print(table)
2261
2262
2263 @cli_osm.command(name='sdnc-show', short_help='shows the details of an SDN controller')
2264 @click.argument('name')
2265 @click.pass_context
2266 def sdnc_show(ctx, name):
2267 """shows the details of an SDN controller
2268
2269 NAME: name or ID of the SDN controller
2270 """
2271 # try:
2272 check_client_version(ctx.obj, ctx.command.name)
2273 resp = ctx.obj.sdnc.get(name)
2274 # except ClientException as e:
2275 # print(str(e))
2276 # exit(1)
2277
2278 table = PrettyTable(['key', 'attribute'])
2279 for k, v in list(resp.items()):
2280 table.add_row([k, json.dumps(v, indent=2)])
2281 table.align = 'l'
2282 print(table)
2283
2284
2285 ###########################
2286 # K8s cluster operations
2287 ###########################
2288
2289 @cli_osm.command(name='k8scluster-add')
2290 @click.argument('name')
2291 @click.option('--creds',
2292 prompt=True,
2293 help='credentials file, i.e. a valid `.kube/config` file')
2294 @click.option('--version',
2295 prompt=True,
2296 help='Kubernetes version')
2297 @click.option('--vim',
2298 prompt=True,
2299 help='VIM target, the VIM where the cluster resides')
2300 @click.option('--k8s-nets',
2301 prompt=True,
2302 help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"')
2303 @click.option('--description',
2304 default='',
2305 help='human readable description')
2306 @click.option('--namespace',
2307 default='kube-system',
2308 help='namespace to be used for its operation, defaults to `kube-system`')
2309 @click.option('--cni',
2310 default=None,
2311 help='list of CNI plugins, in JSON inline format, used in the cluster')
2312 #@click.option('--skip-init',
2313 # is_flag=True,
2314 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2315 #@click.option('--wait',
2316 # is_flag=True,
2317 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2318 @click.pass_context
2319 def k8scluster_add(ctx,
2320 name,
2321 creds,
2322 version,
2323 vim,
2324 k8s_nets,
2325 description,
2326 namespace,
2327 cni):
2328 """adds a K8s cluster to OSM
2329
2330 NAME: name of the K8s cluster
2331 """
2332 # try:
2333 check_client_version(ctx.obj, ctx.command.name)
2334 cluster = {}
2335 cluster['name'] = name
2336 with open(creds, 'r') as cf:
2337 cluster['credentials'] = yaml.safe_load(cf.read())
2338 cluster['k8s_version'] = version
2339 cluster['vim_account'] = vim
2340 cluster['nets'] = yaml.safe_load(k8s_nets)
2341 cluster['description'] = description
2342 if namespace: cluster['namespace'] = namespace
2343 if cni: cluster['cni'] = yaml.safe_load(cni)
2344 ctx.obj.k8scluster.create(name, cluster)
2345 # except ClientException as e:
2346 # print(str(e))
2347 # exit(1)
2348
2349
2350 @cli_osm.command(name='k8scluster-update', short_help='updates a K8s cluster')
2351 @click.argument('name')
2352 @click.option('--newname', help='New name for the K8s cluster')
2353 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
2354 @click.option('--version', help='Kubernetes version')
2355 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
2356 @click.option('--k8s-nets', help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"')
2357 @click.option('--description', help='human readable description')
2358 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
2359 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
2360 @click.pass_context
2361 def k8scluster_update(ctx,
2362 name,
2363 newname,
2364 creds,
2365 version,
2366 vim,
2367 k8s_nets,
2368 description,
2369 namespace,
2370 cni):
2371 """updates a K8s cluster
2372
2373 NAME: name or ID of the K8s cluster
2374 """
2375 # try:
2376 check_client_version(ctx.obj, ctx.command.name)
2377 cluster = {}
2378 if newname: cluster['name'] = newname
2379 if creds:
2380 with open(creds, 'r') as cf:
2381 cluster['credentials'] = yaml.safe_load(cf.read())
2382 if version: cluster['k8s_version'] = version
2383 if vim: cluster['vim_account'] = vim
2384 if k8s_nets: cluster['nets'] = yaml.safe_load(k8s_nets)
2385 if description: cluster['description'] = description
2386 if namespace: cluster['namespace'] = namespace
2387 if cni: cluster['cni'] = yaml.safe_load(cni)
2388 ctx.obj.k8scluster.update(name, cluster)
2389 # except ClientException as e:
2390 # print(str(e))
2391 # exit(1)
2392
2393
2394 @cli_osm.command(name='k8scluster-delete')
2395 @click.argument('name')
2396 @click.option('--force', is_flag=True, help='forces the deletion from the DB (not recommended)')
2397 #@click.option('--wait',
2398 # is_flag=True,
2399 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2400 @click.pass_context
2401 def k8scluster_delete(ctx, name, force):
2402 """deletes a K8s cluster
2403
2404 NAME: name or ID of the K8s cluster to be deleted
2405 """
2406 # try:
2407 check_client_version(ctx.obj, ctx.command.name)
2408 ctx.obj.k8scluster.delete(name, force=force)
2409 # except ClientException as e:
2410 # print(str(e))
2411 # exit(1)
2412
2413
2414 @cli_osm.command(name='k8scluster-list')
2415 @click.option('--filter', default=None,
2416 help='restricts the list to the K8s clusters matching the filter')
2417 @click.option('--literal', is_flag=True,
2418 help='print literally, no pretty table')
2419 @click.pass_context
2420 def k8scluster_list(ctx, filter, literal):
2421 """list all K8s clusters"""
2422 # try:
2423 check_client_version(ctx.obj, ctx.command.name)
2424 resp = ctx.obj.k8scluster.list(filter)
2425 if literal:
2426 print(yaml.safe_dump(resp))
2427 return
2428 table = PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
2429 for cluster in resp:
2430 table.add_row([cluster['name'], cluster['_id'], cluster['k8s_version'], cluster['vim_account'],
2431 json.dumps(cluster['nets']), cluster["_admin"]["operationalState"],
2432 trunc_text(cluster.get('description',''),40)])
2433 table.align = 'l'
2434 print(table)
2435 # except ClientException as e:
2436 # print(str(e))
2437 # exit(1)
2438
2439
2440 @cli_osm.command(name='k8scluster-show')
2441 @click.argument('name')
2442 @click.option('--literal', is_flag=True,
2443 help='print literally, no pretty table')
2444 @click.pass_context
2445 def k8scluster_show(ctx, name, literal):
2446 """shows the details of a K8s cluster
2447
2448 NAME: name or ID of the K8s cluster
2449 """
2450 # try:
2451 resp = ctx.obj.k8scluster.get(name)
2452 if literal:
2453 print(yaml.safe_dump(resp))
2454 return
2455 table = PrettyTable(['key', 'attribute'])
2456 for k, v in list(resp.items()):
2457 table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
2458 table.align = 'l'
2459 print(table)
2460 # except ClientException as e:
2461 # print(str(e))
2462 # exit(1)
2463
2464
2465
2466 ###########################
2467 # Repo operations
2468 ###########################
2469
2470 @cli_osm.command(name='repo-add')
2471 @click.argument('name')
2472 @click.argument('uri')
2473 @click.option('--type',
2474 type=click.Choice(['helm-chart', 'juju-bundle']),
2475 prompt=True,
2476 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2477 @click.option('--description',
2478 default='',
2479 help='human readable description')
2480 #@click.option('--wait',
2481 # is_flag=True,
2482 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2483 @click.pass_context
2484 def repo_add(ctx,
2485 name,
2486 uri,
2487 type,
2488 description):
2489 """adds a repo to OSM
2490
2491 NAME: name of the repo
2492 URI: URI of the repo
2493 """
2494 # try:
2495 check_client_version(ctx.obj, ctx.command.name)
2496 repo = {}
2497 repo['name'] = name
2498 repo['url'] = uri
2499 repo['type'] = type
2500 repo['description'] = description
2501 ctx.obj.repo.create(name, repo)
2502 # except ClientException as e:
2503 # print(str(e))
2504 # exit(1)
2505
2506
2507 @cli_osm.command(name='repo-update')
2508 @click.argument('name')
2509 @click.option('--newname', help='New name for the repo')
2510 @click.option('--uri', help='URI of the repo')
2511 @click.option('--type', type=click.Choice(['helm-chart', 'juju-bundle']),
2512 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2513 @click.option('--description', help='human readable description')
2514 #@click.option('--wait',
2515 # is_flag=True,
2516 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2517 @click.pass_context
2518 def repo_update(ctx,
2519 name,
2520 newname,
2521 uri,
2522 type,
2523 description):
2524 """updates a repo in OSM
2525
2526 NAME: name of the repo
2527 """
2528 # try:
2529 check_client_version(ctx.obj, ctx.command.name)
2530 repo = {}
2531 if newname: repo['name'] = newname
2532 if uri: repo['uri'] = uri
2533 if type: repo['type'] = type
2534 if description: repo['description'] = description
2535 ctx.obj.repo.update(name, repo)
2536 # except ClientException as e:
2537 # print(str(e))
2538 # exit(1)
2539
2540
2541 @cli_osm.command(name='repo-delete')
2542 @click.argument('name')
2543 @click.option('--force', is_flag=True, help='forces the deletion from the DB (not recommended)')
2544 #@click.option('--wait',
2545 # is_flag=True,
2546 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2547 @click.pass_context
2548 def repo_delete(ctx, name, force):
2549 """deletes a repo
2550
2551 NAME: name or ID of the repo to be deleted
2552 """
2553 # try:
2554 check_client_version(ctx.obj, ctx.command.name)
2555 ctx.obj.repo.delete(name, force=force)
2556 # except ClientException as e:
2557 # print(str(e))
2558 # exit(1)
2559
2560
2561 @cli_osm.command(name='repo-list')
2562 @click.option('--filter', default=None,
2563 help='restricts the list to the repos matching the filter')
2564 @click.option('--literal', is_flag=True,
2565 help='print literally, no pretty table')
2566 @click.pass_context
2567 def repo_list(ctx, filter, literal):
2568 """list all repos"""
2569 # try:
2570 check_client_version(ctx.obj, ctx.command.name)
2571 resp = ctx.obj.repo.list(filter)
2572 if literal:
2573 print(yaml.safe_dump(resp))
2574 return
2575 table = PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
2576 for repo in resp:
2577 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
2578 table.add_row([repo['name'], repo['_id'], repo['type'], repo['url'], trunc_text(repo.get('description',''),40)])
2579 table.align = 'l'
2580 print(table)
2581 # except ClientException as e:
2582 # print(str(e))
2583 # exit(1)
2584
2585
2586 @cli_osm.command(name='repo-show')
2587 @click.argument('name')
2588 @click.option('--literal', is_flag=True,
2589 help='print literally, no pretty table')
2590 @click.pass_context
2591 def repo_show(ctx, name, literal):
2592 """shows the details of a repo
2593
2594 NAME: name or ID of the repo
2595 """
2596 # try:
2597 resp = ctx.obj.repo.get(name)
2598 if literal:
2599 print(yaml.safe_dump(resp))
2600 return
2601 table = PrettyTable(['key', 'attribute'])
2602 for k, v in list(resp.items()):
2603 table.add_row([k, json.dumps(v, indent=2)])
2604 table.align = 'l'
2605 print(table)
2606 # except ClientException as e:
2607 # print(str(e))
2608 # exit(1)
2609
2610
2611
2612 ####################
2613 # Project mgmt operations
2614 ####################
2615
2616 @cli_osm.command(name='project-create', short_help='creates a new project')
2617 @click.argument('name')
2618 #@click.option('--description',
2619 # default='no description',
2620 # help='human readable description')
2621 @click.pass_context
2622 def project_create(ctx, name):
2623 """Creates a new project
2624
2625 NAME: name of the project
2626 """
2627 project = {}
2628 project['name'] = name
2629 # try:
2630 check_client_version(ctx.obj, ctx.command.name)
2631 ctx.obj.project.create(name, project)
2632 # except ClientException as e:
2633 # print(str(e))
2634 # exit(1)
2635
2636
2637 @cli_osm.command(name='project-delete', short_help='deletes a project')
2638 @click.argument('name')
2639 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2640 @click.pass_context
2641 def project_delete(ctx, name):
2642 """deletes a project
2643
2644 NAME: name or ID of the project to be deleted
2645 """
2646 # try:
2647 check_client_version(ctx.obj, ctx.command.name)
2648 ctx.obj.project.delete(name)
2649 # except ClientException as e:
2650 # print(str(e))
2651 # exit(1)
2652
2653
2654 @cli_osm.command(name='project-list', short_help='list all projects')
2655 @click.option('--filter', default=None,
2656 help='restricts the list to the projects matching the filter')
2657 @click.pass_context
2658 def project_list(ctx, filter):
2659 """list all projects"""
2660 # try:
2661 check_client_version(ctx.obj, ctx.command.name)
2662 resp = ctx.obj.project.list(filter)
2663 # except ClientException as e:
2664 # print(str(e))
2665 # exit(1)
2666 table = PrettyTable(['name', 'id'])
2667 for proj in resp:
2668 table.add_row([proj['name'], proj['_id']])
2669 table.align = 'l'
2670 print(table)
2671
2672
2673 @cli_osm.command(name='project-show', short_help='shows the details of a project')
2674 @click.argument('name')
2675 @click.pass_context
2676 def project_show(ctx, name):
2677 """shows the details of a project
2678
2679 NAME: name or ID of the project
2680 """
2681 # try:
2682 check_client_version(ctx.obj, ctx.command.name)
2683 resp = ctx.obj.project.get(name)
2684 # except ClientException as e:
2685 # print(str(e))
2686 # exit(1)
2687
2688 table = PrettyTable(['key', 'attribute'])
2689 for k, v in resp.items():
2690 table.add_row([k, json.dumps(v, indent=2)])
2691 table.align = 'l'
2692 print(table)
2693
2694
2695 @cli_osm.command(name='project-update', short_help='updates a project (only the name can be updated)')
2696 @click.argument('project')
2697 @click.option('--name',
2698 prompt=True,
2699 help='new name for the project')
2700
2701 @click.pass_context
2702 def project_update(ctx, project, name):
2703 """
2704 Update a project name
2705
2706 :param ctx:
2707 :param project: id or name of the project to modify
2708 :param name: new name for the project
2709 :return:
2710 """
2711
2712 project_changes = {}
2713 project_changes['name'] = name
2714
2715 # try:
2716 check_client_version(ctx.obj, ctx.command.name)
2717 ctx.obj.project.update(project, project_changes)
2718 # except ClientException as e:
2719 # print(str(e))
2720
2721
2722 ####################
2723 # User mgmt operations
2724 ####################
2725
2726 @cli_osm.command(name='user-create', short_help='creates a new user')
2727 @click.argument('username')
2728 @click.option('--password',
2729 prompt=True,
2730 hide_input=True,
2731 confirmation_prompt=True,
2732 help='user password')
2733 @click.option('--projects',
2734 # prompt="Comma separate list of projects",
2735 multiple=True,
2736 callback=lambda ctx, param, value: ''.join(value).split(',') if all(len(x)==1 for x in value) else value,
2737 help='list of project ids that the user belongs to')
2738 @click.option('--project-role-mappings', 'project_role_mappings',
2739 default=None, multiple=True,
2740 help='creating user project/role(s) mapping')
2741 @click.pass_context
2742 def user_create(ctx, username, password, projects, project_role_mappings):
2743 """Creates a new user
2744
2745 \b
2746 USERNAME: name of the user
2747 PASSWORD: password of the user
2748 PROJECTS: projects assigned to user (internal only)
2749 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
2750 """
2751 user = {}
2752 user['username'] = username
2753 user['password'] = password
2754 user['projects'] = projects
2755 user['project_role_mappings'] = project_role_mappings
2756
2757 # try:
2758 check_client_version(ctx.obj, ctx.command.name)
2759 ctx.obj.user.create(username, user)
2760 # except ClientException as e:
2761 # print(str(e))
2762 # exit(1)
2763
2764
2765 @cli_osm.command(name='user-update', short_help='updates user information')
2766 @click.argument('username')
2767 @click.option('--password',
2768 # prompt=True,
2769 # hide_input=True,
2770 # confirmation_prompt=True,
2771 help='user password')
2772 @click.option('--set-username', 'set_username',
2773 default=None,
2774 help='change username')
2775 @click.option('--set-project', 'set_project',
2776 default=None, multiple=True,
2777 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
2778 @click.option('--remove-project', 'remove_project',
2779 default=None, multiple=True,
2780 help='removes project from user: \'project\'')
2781 @click.option('--add-project-role', 'add_project_role',
2782 default=None, multiple=True,
2783 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
2784 @click.option('--remove-project-role', 'remove_project_role',
2785 default=None, multiple=True,
2786 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
2787 @click.pass_context
2788 def user_update(ctx, username, password, set_username, set_project, remove_project,
2789 add_project_role, remove_project_role):
2790 """Update a user information
2791
2792 \b
2793 USERNAME: name of the user
2794 PASSWORD: new password
2795 SET_USERNAME: new username
2796 SET_PROJECT: creating mappings for project/role(s)
2797 REMOVE_PROJECT: deleting mappings for project/role(s)
2798 ADD_PROJECT_ROLE: adding mappings for project/role(s)
2799 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
2800 """
2801 user = {}
2802 user['password'] = password
2803 user['username'] = set_username
2804 user['set-project'] = set_project
2805 user['remove-project'] = remove_project
2806 user['add-project-role'] = add_project_role
2807 user['remove-project-role'] = remove_project_role
2808
2809 # try:
2810 check_client_version(ctx.obj, ctx.command.name)
2811 ctx.obj.user.update(username, user)
2812 # except ClientException as e:
2813 # print(str(e))
2814 # exit(1)
2815
2816
2817 @cli_osm.command(name='user-delete', short_help='deletes a user')
2818 @click.argument('name')
2819 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2820 @click.pass_context
2821 def user_delete(ctx, name):
2822 """deletes a user
2823
2824 \b
2825 NAME: name or ID of the user to be deleted
2826 """
2827 # try:
2828 check_client_version(ctx.obj, ctx.command.name)
2829 ctx.obj.user.delete(name)
2830 # except ClientException as e:
2831 # print(str(e))
2832 # exit(1)
2833
2834
2835 @cli_osm.command(name='user-list', short_help='list all users')
2836 @click.option('--filter', default=None,
2837 help='restricts the list to the users matching the filter')
2838 @click.pass_context
2839 def user_list(ctx, filter):
2840 """list all users"""
2841 # try:
2842 check_client_version(ctx.obj, ctx.command.name)
2843 resp = ctx.obj.user.list(filter)
2844 # except ClientException as e:
2845 # print(str(e))
2846 # exit(1)
2847 table = PrettyTable(['name', 'id'])
2848 for user in resp:
2849 table.add_row([user['username'], user['_id']])
2850 table.align = 'l'
2851 print(table)
2852
2853
2854 @cli_osm.command(name='user-show', short_help='shows the details of a user')
2855 @click.argument('name')
2856 @click.pass_context
2857 def user_show(ctx, name):
2858 """shows the details of a user
2859
2860 NAME: name or ID of the user
2861 """
2862 # try:
2863 check_client_version(ctx.obj, ctx.command.name)
2864 resp = ctx.obj.user.get(name)
2865 if 'password' in resp:
2866 resp['password']='********'
2867 # except ClientException as e:
2868 # print(str(e))
2869 # exit(1)
2870
2871 table = PrettyTable(['key', 'attribute'])
2872 for k, v in resp.items():
2873 table.add_row([k, json.dumps(v, indent=2)])
2874 table.align = 'l'
2875 print(table)
2876
2877
2878 ####################
2879 # Fault Management operations
2880 ####################
2881
2882 @cli_osm.command(name='ns-alarm-create')
2883 @click.argument('name')
2884 @click.option('--ns', prompt=True, help='NS instance id or name')
2885 @click.option('--vnf', prompt=True,
2886 help='VNF name (VNF member index as declared in the NSD)')
2887 @click.option('--vdu', prompt=True,
2888 help='VDU name (VDU name as declared in the VNFD)')
2889 @click.option('--metric', prompt=True,
2890 help='Name of the metric (e.g. cpu_utilization)')
2891 @click.option('--severity', default='WARNING',
2892 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
2893 @click.option('--threshold_value', prompt=True,
2894 help='threshold value that, when crossed, an alarm is triggered')
2895 @click.option('--threshold_operator', prompt=True,
2896 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
2897 @click.option('--statistic', default='AVERAGE',
2898 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
2899 @click.pass_context
2900 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
2901 threshold_value, threshold_operator, statistic):
2902 """creates a new alarm for a NS instance"""
2903 # TODO: Check how to validate threshold_value.
2904 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
2905 # try:
2906 ns_instance = ctx.obj.ns.get(ns)
2907 alarm = {}
2908 alarm['alarm_name'] = name
2909 alarm['ns_id'] = ns_instance['_id']
2910 alarm['correlation_id'] = ns_instance['_id']
2911 alarm['vnf_member_index'] = vnf
2912 alarm['vdu_name'] = vdu
2913 alarm['metric_name'] = metric
2914 alarm['severity'] = severity
2915 alarm['threshold_value'] = int(threshold_value)
2916 alarm['operation'] = threshold_operator
2917 alarm['statistic'] = statistic
2918 check_client_version(ctx.obj, ctx.command.name)
2919 ctx.obj.ns.create_alarm(alarm)
2920 # except ClientException as e:
2921 # print(str(e))
2922 # exit(1)
2923
2924
2925 #@cli_osm.command(name='ns-alarm-delete')
2926 #@click.argument('name')
2927 #@click.pass_context
2928 #def ns_alarm_delete(ctx, name):
2929 # """deletes an alarm
2930 #
2931 # NAME: name of the alarm to be deleted
2932 # """
2933 # try:
2934 # check_client_version(ctx.obj, ctx.command.name)
2935 # ctx.obj.ns.delete_alarm(name)
2936 # except ClientException as e:
2937 # print(str(e))
2938 # exit(1)
2939
2940
2941 ####################
2942 # Performance Management operations
2943 ####################
2944
2945 @cli_osm.command(name='ns-metric-export', short_help='exports a metric to the internal OSM bus, which can be read by other apps')
2946 @click.option('--ns', prompt=True, help='NS instance id or name')
2947 @click.option('--vnf', prompt=True,
2948 help='VNF name (VNF member index as declared in the NSD)')
2949 @click.option('--vdu', prompt=True,
2950 help='VDU name (VDU name as declared in the VNFD)')
2951 @click.option('--metric', prompt=True,
2952 help='name of the metric (e.g. cpu_utilization)')
2953 #@click.option('--period', default='1w',
2954 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
2955 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
2956 @click.pass_context
2957 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
2958 """exports a metric to the internal OSM bus, which can be read by other apps"""
2959 # TODO: Check how to validate interval.
2960 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
2961 # try:
2962 ns_instance = ctx.obj.ns.get(ns)
2963 metric_data = {}
2964 metric_data['ns_id'] = ns_instance['_id']
2965 metric_data['correlation_id'] = ns_instance['_id']
2966 metric_data['vnf_member_index'] = vnf
2967 metric_data['vdu_name'] = vdu
2968 metric_data['metric_name'] = metric
2969 metric_data['collection_unit'] = 'WEEK'
2970 metric_data['collection_period'] = 1
2971 check_client_version(ctx.obj, ctx.command.name)
2972 if not interval:
2973 print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
2974 else:
2975 i = 1
2976 while True:
2977 print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
2978 time.sleep(int(interval))
2979 i+=1
2980 # except ClientException as e:
2981 # print(str(e))
2982 # exit(1)
2983
2984
2985 ####################
2986 # Other operations
2987 ####################
2988
2989 @cli_osm.command(name='version')
2990 @click.pass_context
2991 def get_version(ctx):
2992 # try:
2993 check_client_version(ctx.obj, "version")
2994 print ("Server version: {}".format(ctx.obj.get_version()))
2995 print ("Client version: {}".format(pkg_resources.get_distribution("osmclient").version))
2996 # except ClientException as e:
2997 # print(str(e))
2998 # exit(1)
2999
3000 @cli_osm.command(name='upload-package', short_help='uploads a VNF package or NS package')
3001 @click.argument('filename')
3002 @click.pass_context
3003 def upload_package(ctx, filename):
3004 """uploads a VNF package or NS package
3005
3006 FILENAME: VNF or NS package file (tar.gz)
3007 """
3008 # try:
3009 ctx.obj.package.upload(filename)
3010 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
3011 if fullclassname != 'osmclient.sol005.client.Client':
3012 ctx.obj.package.wait_for_upload(filename)
3013 # except ClientException as e:
3014 # print(str(e))
3015 # exit(1)
3016
3017
3018 #@cli_osm.command(name='ns-scaling-show')
3019 #@click.argument('ns_name')
3020 #@click.pass_context
3021 #def show_ns_scaling(ctx, ns_name):
3022 # """shows the status of a NS scaling operation
3023 #
3024 # NS_NAME: name of the NS instance being scaled
3025 # """
3026 # try:
3027 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3028 # resp = ctx.obj.ns.list()
3029 # except ClientException as e:
3030 # print(str(e))
3031 # exit(1)
3032 #
3033 # table = PrettyTable(
3034 # ['group-name',
3035 # 'instance-id',
3036 # 'operational status',
3037 # 'create-time',
3038 # 'vnfr ids'])
3039 #
3040 # for ns in resp:
3041 # if ns_name == ns['name']:
3042 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3043 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3044 # for record in scaling_records:
3045 # if 'instance' in record:
3046 # instances = record['instance']
3047 # for inst in instances:
3048 # table.add_row(
3049 # [record['scaling-group-name-ref'],
3050 # inst['instance-id'],
3051 # inst['op-status'],
3052 # time.strftime('%Y-%m-%d %H:%M:%S',
3053 # time.localtime(
3054 # inst['create-time'])),
3055 # inst['vnfrs']])
3056 # table.align = 'l'
3057 # print(table)
3058
3059
3060 #@cli_osm.command(name='ns-scale')
3061 #@click.argument('ns_name')
3062 #@click.option('--ns_scale_group', prompt=True)
3063 #@click.option('--index', prompt=True)
3064 #@click.option('--wait',
3065 # required=False,
3066 # default=False,
3067 # is_flag=True,
3068 # help='do not return the control immediately, but keep it \
3069 # until the operation is completed, or timeout')
3070 #@click.pass_context
3071 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3072 # """scales NS
3073 #
3074 # NS_NAME: name of the NS instance to be scaled
3075 # """
3076 # try:
3077 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3078 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3079 # except ClientException as e:
3080 # print(str(e))
3081 # exit(1)
3082
3083
3084 #@cli_osm.command(name='config-agent-list')
3085 #@click.pass_context
3086 #def config_agent_list(ctx):
3087 # """list config agents"""
3088 # try:
3089 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3090 # except ClientException as e:
3091 # print(str(e))
3092 # exit(1)
3093 # table = PrettyTable(['name', 'account-type', 'details'])
3094 # for account in ctx.obj.vca.list():
3095 # table.add_row(
3096 # [account['name'],
3097 # account['account-type'],
3098 # account['juju']])
3099 # table.align = 'l'
3100 # print(table)
3101
3102
3103 #@cli_osm.command(name='config-agent-delete')
3104 #@click.argument('name')
3105 #@click.pass_context
3106 #def config_agent_delete(ctx, name):
3107 # """deletes a config agent
3108 #
3109 # NAME: name of the config agent to be deleted
3110 # """
3111 # try:
3112 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3113 # ctx.obj.vca.delete(name)
3114 # except ClientException as e:
3115 # print(str(e))
3116 # exit(1)
3117
3118
3119 #@cli_osm.command(name='config-agent-add')
3120 #@click.option('--name',
3121 # prompt=True)
3122 #@click.option('--account_type',
3123 # prompt=True)
3124 #@click.option('--server',
3125 # prompt=True)
3126 #@click.option('--user',
3127 # prompt=True)
3128 #@click.option('--secret',
3129 # prompt=True,
3130 # hide_input=True,
3131 # confirmation_prompt=True)
3132 #@click.pass_context
3133 #def config_agent_add(ctx, name, account_type, server, user, secret):
3134 # """adds a config agent"""
3135 # try:
3136 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3137 # ctx.obj.vca.create(name, account_type, server, user, secret)
3138 # except ClientException as e:
3139 # print(str(e))
3140 # exit(1)
3141
3142
3143 #@cli_osm.command(name='ro-dump')
3144 #@click.pass_context
3145 #def ro_dump(ctx):
3146 # """shows RO agent information"""
3147 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3148 # resp = ctx.obj.vim.get_resource_orchestrator()
3149 # table = PrettyTable(['key', 'attribute'])
3150 # for k, v in list(resp.items()):
3151 # table.add_row([k, json.dumps(v, indent=2)])
3152 # table.align = 'l'
3153 # print(table)
3154
3155
3156 #@cli_osm.command(name='vcs-list')
3157 #@click.pass_context
3158 #def vcs_list(ctx):
3159 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3160 # resp = ctx.obj.utils.get_vcs_info()
3161 # table = PrettyTable(['component name', 'state'])
3162 # for component in resp:
3163 # table.add_row([component['component_name'], component['state']])
3164 # table.align = 'l'
3165 # print(table)
3166
3167
3168 @cli_osm.command(name='ns-action', short_help='executes an action/primitive over a NS instance')
3169 @click.argument('ns_name')
3170 @click.option('--vnf_name', default=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3171 @click.option('--kdu_name', default=None, help='kdu-name if the target is a kdu)')
3172 @click.option('--vdu_id', default=None, help='vdu-id if the target is a vdu')
3173 @click.option('--vdu_count', default=None, help='number of vdu instance of this vdu_id')
3174 @click.option('--action_name', prompt=True, help='action name')
3175 @click.option('--params', default=None, help='action params in YAML/JSON inline string')
3176 @click.option('--params_file', default=None, help='YAML/JSON file with action params')
3177 @click.option('--wait',
3178 required=False,
3179 default=False,
3180 is_flag=True,
3181 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3182 @click.pass_context
3183 def ns_action(ctx,
3184 ns_name,
3185 vnf_name,
3186 kdu_name,
3187 vdu_id,
3188 vdu_count,
3189 action_name,
3190 params,
3191 params_file,
3192 wait):
3193 """executes an action/primitive over a NS instance
3194
3195 NS_NAME: name or ID of the NS instance
3196 """
3197 # try:
3198 check_client_version(ctx.obj, ctx.command.name)
3199 op_data = {}
3200 if vnf_name:
3201 op_data['member_vnf_index'] = vnf_name
3202 if kdu_name:
3203 op_data['kdu_name'] = kdu_name
3204 if vdu_id:
3205 op_data['vdu_id'] = vdu_id
3206 if vdu_count:
3207 op_data['vdu_count_index'] = vdu_count
3208 op_data['primitive'] = action_name
3209 if params_file:
3210 with open(params_file, 'r') as pf:
3211 params = pf.read()
3212 if params:
3213 op_data['primitive_params'] = yaml.safe_load(params)
3214 else:
3215 op_data['primitive_params'] = {}
3216 print(ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data, wait=wait))
3217
3218 # except ClientException as e:
3219 # print(str(e))
3220 # exit(1)
3221
3222
3223 @cli_osm.command(name='vnf-scale', short_help='executes a VNF scale (adding/removing VDUs)')
3224 @click.argument('ns_name')
3225 @click.argument('vnf_name')
3226 @click.option('--scaling-group', prompt=True, help="scaling-group-descriptor name to use")
3227 @click.option('--scale-in', default=False, is_flag=True, help="performs a scale in operation")
3228 @click.option('--scale-out', default=False, is_flag=True, help="performs a scale out operation (by default)")
3229 @click.pass_context
3230 def vnf_scale(ctx,
3231 ns_name,
3232 vnf_name,
3233 scaling_group,
3234 scale_in,
3235 scale_out):
3236 """
3237 Executes a VNF scale (adding/removing VDUs)
3238
3239 \b
3240 NS_NAME: name or ID of the NS instance.
3241 VNF_NAME: member-vnf-index in the NS to be scaled.
3242 """
3243 # try:
3244 check_client_version(ctx.obj, ctx.command.name)
3245 if not scale_in and not scale_out:
3246 scale_out = True
3247 ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out)
3248 # except ClientException as e:
3249 # print(str(e))
3250 # exit(1)
3251
3252
3253 ##############################
3254 # Role Management Operations #
3255 ##############################
3256
3257 @cli_osm.command(name='role-create', short_help='creates a new role')
3258 @click.argument('name')
3259 @click.option('--permissions',
3260 default=None,
3261 help='role permissions using a dictionary')
3262 @click.pass_context
3263 def role_create(ctx, name, permissions):
3264 """
3265 Creates a new role.
3266
3267 \b
3268 NAME: Name or ID of the role.
3269 DEFINITION: Definition of grant/denial of access to resources.
3270 """
3271 # try:
3272 check_client_version(ctx.obj, ctx.command.name)
3273 ctx.obj.role.create(name, permissions)
3274 # except ClientException as e:
3275 # print(str(e))
3276 # exit(1)
3277
3278
3279 @cli_osm.command(name='role-update', short_help='updates a role')
3280 @click.argument('name')
3281 @click.option('--set-name',
3282 default=None,
3283 help='change name of rle')
3284 # @click.option('--permissions',
3285 # default=None,
3286 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
3287 @click.option('--add',
3288 default=None,
3289 help='yaml format dictionary with permission: True/False to access grant/denial')
3290 @click.option('--remove',
3291 default=None,
3292 help='yaml format list to remove a permission')
3293 @click.pass_context
3294 def role_update(ctx, name, set_name, add, remove):
3295 """
3296 Updates a role.
3297
3298 \b
3299 NAME: Name or ID of the role.
3300 DEFINITION: Definition overwrites the old definition.
3301 ADD: Grant/denial of access to resource to add.
3302 REMOVE: Grant/denial of access to resource to remove.
3303 """
3304 # try:
3305 check_client_version(ctx.obj, ctx.command.name)
3306 ctx.obj.role.update(name, set_name, None, add, remove)
3307 # except ClientException as e:
3308 # print(str(e))
3309 # exit(1)
3310
3311
3312 @cli_osm.command(name='role-delete', short_help='deletes a role')
3313 @click.argument('name')
3314 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3315 @click.pass_context
3316 def role_delete(ctx, name):
3317 """
3318 Deletes a role.
3319
3320 \b
3321 NAME: Name or ID of the role.
3322 """
3323 # try:
3324 check_client_version(ctx.obj, ctx.command.name)
3325 ctx.obj.role.delete(name)
3326 # except ClientException as e:
3327 # print(str(e))
3328 # exit(1)
3329
3330
3331 @cli_osm.command(name='role-list', short_help='list all roles')
3332 @click.option('--filter', default=None,
3333 help='restricts the list to the projects matching the filter')
3334 @click.pass_context
3335 def role_list(ctx, filter):
3336 """
3337 List all roles.
3338 """
3339 # try:
3340 check_client_version(ctx.obj, ctx.command.name)
3341 resp = ctx.obj.role.list(filter)
3342 # except ClientException as e:
3343 # print(str(e))
3344 # exit(1)
3345 table = PrettyTable(['name', 'id'])
3346 for role in resp:
3347 table.add_row([role['name'], role['_id']])
3348 table.align = 'l'
3349 print(table)
3350
3351
3352 @cli_osm.command(name='role-show', short_help='show specific role')
3353 @click.argument('name')
3354 @click.pass_context
3355 def role_show(ctx, name):
3356 """
3357 Shows the details of a role.
3358
3359 \b
3360 NAME: Name or ID of the role.
3361 """
3362 # try:
3363 check_client_version(ctx.obj, ctx.command.name)
3364 resp = ctx.obj.role.get(name)
3365 # except ClientException as e:
3366 # print(str(e))
3367 # exit(1)
3368
3369 table = PrettyTable(['key', 'attribute'])
3370 for k, v in resp.items():
3371 table.add_row([k, json.dumps(v, indent=2)])
3372 table.align = 'l'
3373 print(table)
3374
3375
3376 @cli_osm.command(name='package-create',
3377 short_help='Create a package descriptor')
3378 @click.argument('package-type')
3379 @click.argument('package-name')
3380 @click.option('--base-directory',
3381 default='.',
3382 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
3383 @click.option('--image',
3384 default="image-name",
3385 help='(VNF) Set the name of the vdu image. Default "image-name"')
3386 @click.option('--vdus',
3387 default=1,
3388 help='(VNF) Set the number of vdus in a VNF. Default 1')
3389 @click.option('--vcpu',
3390 default=1,
3391 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
3392 @click.option('--memory',
3393 default=1024,
3394 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
3395 @click.option('--storage',
3396 default=10,
3397 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
3398 @click.option('--interfaces',
3399 default=0,
3400 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
3401 @click.option('--vendor',
3402 default="OSM",
3403 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
3404 @click.option('--override',
3405 default=False,
3406 is_flag=True,
3407 help='(NS/VNF/NST) Flag for overriding the package if exists.')
3408 @click.option('--detailed',
3409 is_flag=True,
3410 default=False,
3411 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
3412 @click.option('--netslice-subnets',
3413 default=1,
3414 help='(NST) Number of netslice subnets. Default 1')
3415 @click.option('--netslice-vlds',
3416 default=1,
3417 help='(NST) Number of netslice vlds. Default 1')
3418 @click.pass_context
3419 def package_create(ctx,
3420 package_type,
3421 base_directory,
3422 package_name,
3423 override,
3424 image,
3425 vdus,
3426 vcpu,
3427 memory,
3428 storage,
3429 interfaces,
3430 vendor,
3431 detailed,
3432 netslice_subnets,
3433 netslice_vlds):
3434 """
3435 Creates an OSM NS, VNF, NST package
3436
3437 \b
3438 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
3439 PACKAGE_NAME: Name of the package to create the folder with the content.
3440 """
3441
3442 # try:
3443 check_client_version(ctx.obj, ctx.command.name)
3444 print("Creating the {} structure: {}/{}".format(package_type.upper(), base_directory, package_name))
3445 resp = ctx.obj.package_tool.create(package_type,
3446 base_directory,
3447 package_name,
3448 override=override,
3449 image=image,
3450 vdus=vdus,
3451 vcpu=vcpu,
3452 memory=memory,
3453 storage=storage,
3454 interfaces=interfaces,
3455 vendor=vendor,
3456 detailed=detailed,
3457 netslice_subnets=netslice_subnets,
3458 netslice_vlds=netslice_vlds)
3459 print(resp)
3460 # except ClientException as inst:
3461 # print("ERROR: {}".format(inst))
3462 # exit(1)
3463
3464 @cli_osm.command(name='package-validate',
3465 short_help='Validate a package descriptor')
3466 @click.argument('base-directory',
3467 default=".",
3468 required=False)
3469 @click.pass_context
3470 def package_validate(ctx,
3471 base_directory):
3472 """
3473 Validate descriptors given a base directory.
3474
3475 \b
3476 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
3477 """
3478 # try:
3479 check_client_version(ctx.obj, ctx.command.name)
3480 results = ctx.obj.package_tool.validate(base_directory)
3481 table = PrettyTable()
3482 table.field_names = ["TYPE", "PATH", "VALID", "ERROR"]
3483 # Print the dictionary generated by the validation function
3484 for result in results:
3485 table.add_row([result["type"], result["path"], result["valid"], result["error"]])
3486 table.sortby = "VALID"
3487 table.align["PATH"] = "l"
3488 table.align["TYPE"] = "l"
3489 table.align["ERROR"] = "l"
3490 print(table)
3491 # except ClientException as inst:
3492 # print("ERROR: {}".format(inst))
3493 # exit(1)
3494
3495 @cli_osm.command(name='package-build',
3496 short_help='Build the tar.gz of the package')
3497 @click.argument('package-folder')
3498 @click.option('--skip-validation',
3499 default=False,
3500 is_flag=True,
3501 help='skip package validation')
3502 @click.pass_context
3503 def package_build(ctx,
3504 package_folder,
3505 skip_validation):
3506 """
3507 Build the package NS, VNF given the package_folder.
3508
3509 \b
3510 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
3511 """
3512 # try:
3513 check_client_version(ctx.obj, ctx.command.name)
3514 results = ctx.obj.package_tool.build(package_folder, skip_validation)
3515 print(results)
3516 # except ClientException as inst:
3517 # print("ERROR: {}".format(inst))
3518 # exit(1)
3519
3520
3521 def cli():
3522 try:
3523 cli_osm()
3524 except pycurl.error as exc:
3525 print(exc)
3526 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
3527 exit(1)
3528 except ClientException as exc:
3529 print("ERROR: {}".format(exc))
3530 exit(1)
3531 # TODO capture other controlled exceptions here
3532 # TODO remove the ClientException captures from all places, unless they do something different
3533
3534
3535 if __name__ == '__main__':
3536 cli()