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