5c6d3badf53c0b1b8a1413219cf527467708dc80
1 # Copyright 2017-2018 Sandvine
2 # Copyright 2018 Telefonica
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
10 # http://www.apache.org/licenses/LICENSE-2.0
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
22 from osmclient
import client
23 from osmclient
.common
.exceptions
import ClientException
24 from prettytable
import PrettyTable
33 from datetime
import datetime
38 CONTEXT_SETTINGS
= dict(help_option_names
=['-h', '--help'], max_content_width
=160)
40 def wrap_text(text
, width
):
41 wrapper
= textwrap
.TextWrapper(width
=width
)
42 lines
= text
.splitlines()
43 return "\n".join(map(wrapper
.fill
, lines
))
46 def trunc_text(text
, length
):
47 if len(text
) > length
:
48 return text
[:(length
- 3)] + '...'
53 def check_client_version(obj
, what
, version
='sol005'):
55 Checks the version of the client object and raises error if it not the expected.
57 :param obj: the client object
58 :what: the function or command under evaluation (used when an error is raised)
60 :raises ClientError: if the specified version does not match the client version
63 fullclassname
= obj
.__module
__ + "." + obj
.__class
__.__name
__
64 message
= 'The following commands or options are only supported with the option "--sol005": {}'.format(what
)
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
)
72 @click.group(context_settings
=dict(help_option_names
=['-h', '--help'], max_content_width
=160))
73 @click.option('--hostname',
75 envvar
='OSM_HOSTNAME',
76 help='hostname of server. ' +
77 'Also can set OSM_HOSTNAME in environment')
78 #@click.option('--sol005/--no-sol005',
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',
86 help='user (defaults to admin). ' +
87 'Also can set OSM_USER in environment')
88 @click.option('--password',
90 envvar
='OSM_PASSWORD',
91 help='password (defaults to admin). ' +
92 'Also can set OSM_PASSWORD in environment')
93 @click.option('--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',
102 # envvar='OSM_SO_PORT',
103 # help='hostname of server. ' +
104 # 'Also can set OSM_SO_PORT in environment')
105 #@click.option('--so-project',
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',
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',
117 # envvar='OSM_RO_PORT',
118 # help='hostname of RO server. ' +
119 # 'Also can set OSM_RO_PORT in environment')
121 def cli_osm(ctx
, hostname
, user
, password
, project
, verbose
):
125 "either hostname option or OSM_HOSTNAME " +
126 "environment variable needs to be specified"))
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)
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')
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.option('--long', is_flag
=True,
156 help='get more details of the NS (project, vim, deployment status, configuration status.')
158 def ns_list(ctx
, filter, long):
159 """list all NS instances
163 --filter filterExpr Restricts the list to the NS instances matching the filter
166 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
167 concatenated using the "&" character:
170 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
171 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
172 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
174 value := scalar value
178 * zero or more occurrences
179 ? zero or one occurrence
180 [] grouping of expressions to be used with ? and *
181 "" quotation marks for marking string constants
185 "AttrName" is the name of one attribute in the data type that defines the representation
186 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
187 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
188 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
189 entries, it means that the operator "op" is applied to the attribute addressed by the last
190 <attrName> entry included in the concatenation. All simple filter expressions are combined
191 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
192 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
193 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
194 prefix". If an attribute referenced in an expression is an array, an object that contains a
195 corresponding array shall be considered to match the expression if any of the elements in the
196 array matches all expressions that have the same attribute prefix.
200 --filter admin-status=ENABLED
201 --filter nsd-ref=<NSD_NAME>
202 --filter nsd.vendor=<VENDOR>
203 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
204 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
206 def summarize_deployment_status(status_dict
):
211 net_list
= status_dict
['nets']
214 if net
['status'] not in status_nets
:
215 status_nets
[net
['status']] = 1
217 status_nets
[net
['status']] +=1
219 for k
,v
in status_nets
.items():
220 message
+= "{}:{},".format(k
,v
)
221 message
+= "TOTAL:{}".format(n_nets
)
222 summary
+= "{}".format(message
)
227 vnf_list
= status_dict
['vnfs']
229 member_vnf_index
= vnf
['member_vnf_index']
230 if member_vnf_index
not in status_vnfs
:
231 status_vnfs
[member_vnf_index
] = {}
232 for vm
in vnf
['vms']:
234 if vm
['status'] not in status_vms
:
235 status_vms
[vm
['status']] = 1
237 status_vms
[vm
['status']] +=1
238 if vm
['status'] not in status_vnfs
[member_vnf_index
]:
239 status_vnfs
[member_vnf_index
][vm
['status']] = 1
241 status_vnfs
[member_vnf_index
][vm
['status']] += 1
243 for k
,v
in status_vms
.items():
244 message
+= "{}:{},".format(k
,v
)
245 message
+= "TOTAL:{}".format(n_vms
)
246 summary
+= "\n{}".format(message
)
248 for k
,v
in status_vnfs
.items():
250 message
= "\n {} VMs: ".format(k
)
251 for k2
,v2
in v
.items():
252 message
+= "{}:{},".format(k2
,v2
)
254 message
+= "TOTAL:{}".format(total
)
258 def summarize_config_status(ee_list
):
263 if ee
['elementType'] not in status_ee
:
264 status_ee
[ee
['elementType']] = {}
265 status_ee
[ee
['elementType']][ee
['status']] = 1
267 if ee
['status'] in status_ee
[ee
['elementType']]:
268 status_ee
[ee
['elementType']][ee
['status']] += 1
270 status_ee
[ee
['elementType']][ee
['status']] = 1
272 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
273 if elementType
in status_ee
:
276 for k
,v
in status_ee
[elementType
].items():
277 message
+= "{}:{},".format(k
,v
)
279 message
+= "TOTAL:{}\n".format(total
)
280 summary
+= "{}: {}".format(elementType
, message
)
281 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
285 check_client_version(ctx
.obj
, '--filter')
286 resp
= ctx
.obj
.ns
.list(filter)
288 resp
= ctx
.obj
.ns
.list()
300 'configuration status'])
301 project_list
= ctx
.obj
.project
.list()
302 vim_list
= ctx
.obj
.vim
.list()
312 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
313 if fullclassname
== 'osmclient.sol005.client.Client':
315 nsr_name
= nsr
['name']
317 date
= datetime
.fromtimestamp(nsr
['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
318 ns_state
= nsr
['nsState']
320 deployment_status
= summarize_deployment_status(nsr
['deploymentStatus'])
321 config_status
= summarize_config_status(nsr
['configurationStatus'])
322 project_id
= nsr
.get('_admin').get('projects_read')[0]
324 for p
in project_list
:
325 if p
['_id'] == project_id
:
326 project_name
= p
['name']
328 #project = '{} ({})'.format(project_name, project_id)
329 project
= project_name
330 vim_id
= nsr
.get('datacenter')
333 if v
['uuid'] == vim_id
:
336 #vim = '{} ({})'.format(vim_name, vim_id)
338 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
339 error_details
= "N/A"
340 if ns_state
== "BROKEN" or ns_state
== "DEGRADED":
341 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'],nsr
['errorDetail'])
343 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
344 nsr
= nsopdata
['nsr:nsr']
345 nsr_name
= nsr
['name-ref']
346 nsr_id
= nsr
['ns-instance-config-ref']
349 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
350 ns_state
= deployment_status
351 config_status
= nsr
['config-status'] if 'config-status' in nsr
else 'Not found'
352 current_operation
= "Unknown"
353 error_details
= nsr
['detailed-status'] if 'detailed-status' in nsr
else 'Not found'
354 if config_status
== "config_not_needed":
355 config_status
= "configured (no charms)"
364 wrap_text(text
=error_details
,width
=40),
376 wrap_text(text
=error_details
,width
=40)])
379 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
380 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
382 def nsd_list(ctx
, filter, long):
385 check_client_version(ctx
.obj
, '--filter')
386 resp
= ctx
.obj
.nsd
.list(filter)
388 resp
= ctx
.obj
.nsd
.list()
389 # print(yaml.safe_dump(resp))
390 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
391 if fullclassname
== 'osmclient.sol005.client.Client':
393 table
= PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state',
394 'usage state', 'date', 'last update'])
396 table
= PrettyTable(['nsd name', 'id'])
398 name
= nsd
.get('name','-')
400 onb_state
= nsd
['_admin'].get('onboardingState','-')
401 op_state
= nsd
['_admin'].get('operationalState','-')
402 usage_state
= nsd
['_admin'].get('usageState','-')
403 date
= datetime
.fromtimestamp(nsd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
404 last_update
= datetime
.fromtimestamp(nsd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
405 table
.add_row([name
, nsd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
407 table
.add_row([name
, nsd
['_id']])
409 table
= PrettyTable(['nsd name', 'id'])
411 table
.add_row([nsd
['name'], nsd
['id']])
416 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
417 @click.option('--filter', default
=None,
418 help='restricts the list to the NSD/NSpkg matching the filter')
419 @click.option('--long', is_flag
=True, help='get more details')
421 def nsd_list1(ctx
, filter, long):
422 """list all NSD/NS pkg in the system"""
424 nsd_list(ctx
, filter, long)
427 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
428 @click.option('--filter', default
=None,
429 help='restricts the list to the NSD/NSpkg matching the filter')
430 @click.option('--long', is_flag
=True, help='get more details')
432 def nsd_list2(ctx
, filter, long):
433 """list all NS packages"""
435 nsd_list(ctx
, filter, long)
438 def vnfd_list(ctx
, nf_type
, filter, long):
441 check_client_version(ctx
.obj
, '--nf_type')
443 check_client_version(ctx
.obj
, '--filter')
446 nf_filter
= "_admin.type=vnfd"
447 elif nf_type
== "pnf":
448 nf_filter
= "_admin.type=pnfd"
449 elif nf_type
== "hnf":
450 nf_filter
= "_admin.type=hnfd"
452 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
454 filter = '{}&{}'.format(nf_filter
, filter)
458 resp
= ctx
.obj
.vnfd
.list(filter)
460 resp
= ctx
.obj
.vnfd
.list()
461 # print(yaml.safe_dump(resp))
462 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
463 if fullclassname
== 'osmclient.sol005.client.Client':
465 table
= PrettyTable(['nfpkg name', 'id', 'onboarding state', 'operational state',
466 'usage state', 'date', 'last update'])
468 table
= PrettyTable(['nfpkg name', 'id'])
470 name
= vnfd
['name'] if 'name' in vnfd
else '-'
472 onb_state
= vnfd
['_admin'].get('onboardingState','-')
473 op_state
= vnfd
['_admin'].get('operationalState','-')
474 usage_state
= vnfd
['_admin'].get('usageState','-')
475 date
= datetime
.fromtimestamp(vnfd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
476 last_update
= datetime
.fromtimestamp(vnfd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
477 table
.add_row([name
, vnfd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
479 table
.add_row([name
, vnfd
['_id']])
481 table
= PrettyTable(['nfpkg name', 'id'])
483 table
.add_row([vnfd
['name'], vnfd
['id']])
488 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
489 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
490 @click.option('--filter', default
=None,
491 help='restricts the list to the NF pkg matching the filter')
492 @click.option('--long', is_flag
=True, help='get more details')
494 def vnfd_list1(ctx
, nf_type
, filter, long):
495 """list all xNF packages (VNF, HNF, PNF)"""
497 vnfd_list(ctx
, nf_type
, filter, long)
500 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
501 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
502 @click.option('--filter', default
=None,
503 help='restricts the list to the NFpkg matching the filter')
504 @click.option('--long', is_flag
=True, help='get more details')
506 def vnfd_list2(ctx
, nf_type
, filter, long):
507 """list all xNF packages (VNF, HNF, PNF)"""
509 vnfd_list(ctx
, nf_type
, filter, long)
512 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
513 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
514 @click.option('--filter', default
=None,
515 help='restricts the list to the NFpkg matching the filter')
516 @click.option('--long', is_flag
=True, help='get more details')
518 def nfpkg_list(ctx
, nf_type
, filter, long):
519 """list all xNF packages (VNF, HNF, PNF)"""
522 check_client_version(ctx
.obj
, ctx
.command
.name
)
523 vnfd_list(ctx
, nf_type
, filter, long)
524 # except ClientException as e:
529 def vnf_list(ctx
, ns
, filter, long):
533 check_client_version(ctx
.obj
, '--ns')
535 check_client_version(ctx
.obj
, '--filter')
536 resp
= ctx
.obj
.vnf
.list(ns
, filter)
538 resp
= ctx
.obj
.vnf
.list()
539 # except ClientException as e:
542 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
543 if fullclassname
== 'osmclient.sol005.client.Client':
544 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
545 'vnfd name', 'vim account id', 'ip address']
547 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
548 'vnfd name', 'vim account id', 'ip address',
549 'date', 'last update']
550 table
= PrettyTable(field_names
)
552 name
= vnfr
['name'] if 'name' in vnfr
else '-'
553 new_row
= [vnfr
['_id'], name
, vnfr
['nsr-id-ref'],
554 vnfr
['member-vnf-index-ref'], vnfr
['vnfd-ref'],
555 vnfr
['vim-account-id'], vnfr
['ip-address']]
557 date
= datetime
.fromtimestamp(vnfr
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
558 last_update
= datetime
.fromtimestamp(vnfr
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
559 new_row
.extend([date
, last_update
])
560 table
.add_row(new_row
)
565 'operational status',
568 if 'mgmt-interface' not in vnfr
:
569 vnfr
['mgmt-interface'] = {}
570 vnfr
['mgmt-interface']['ip-address'] = None
574 vnfr
['operational-status'],
575 vnfr
['config-status']])
580 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
581 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
582 @click.option('--filter', default
=None,
583 help='restricts the list to the NF instances matching the filter.')
584 @click.option('--long', is_flag
=True, help='get more details')
586 def vnf_list1(ctx
, ns
, filter, long):
587 """list all NF instances"""
589 vnf_list(ctx
, ns
, filter, long)
592 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
593 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
594 @click.option('--filter', default
=None,
595 help='restricts the list to the NF instances matching the filter.')
596 @click.option('--long', is_flag
=True, help='get more details')
598 def nf_list(ctx
, ns
, filter, long):
599 """list all NF instances
603 --ns TEXT NS instance id or name to restrict the VNF list
604 --filter filterExpr Restricts the list to the VNF instances matching the filter
607 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
608 concatenated using the "&" character:
611 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
612 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
613 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
615 value := scalar value
619 * zero or more occurrences
620 ? zero or one occurrence
621 [] grouping of expressions to be used with ? and *
622 "" quotation marks for marking string constants
626 "AttrName" is the name of one attribute in the data type that defines the representation
627 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
628 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
629 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
630 entries, it means that the operator "op" is applied to the attribute addressed by the last
631 <attrName> entry included in the concatenation. All simple filter expressions are combined
632 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
633 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
634 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
635 prefix". If an attribute referenced in an expression is an array, an object that contains a
636 corresponding array shall be considered to match the expression if any of the elements in the
637 array matches all expressions that have the same attribute prefix.
641 --filter vim-account-id=<VIM_ACCOUNT_ID>
642 --filter vnfd-ref=<VNFD_NAME>
643 --filter vdur.ip-address=<IP_ADDRESS>
644 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
647 vnf_list(ctx
, ns
, filter)
650 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
651 @click.argument('name')
652 @click.option('--long', is_flag
=True,
653 help='get more details of the NS operation (date, ).')
655 def ns_op_list(ctx
, name
, long):
656 """shows the history of operations over a NS instance
658 NAME: name or ID of the NS instance
660 def formatParams(params
):
661 if params
['lcmOperationType']=='instantiate':
662 params
.pop('nsDescription')
666 elif params
['lcmOperationType']=='action':
667 params
.pop('primitive')
668 params
.pop('lcmOperationType')
669 params
.pop('nsInstanceId')
674 check_client_version(ctx
.obj
, ctx
.command
.name
)
675 resp
= ctx
.obj
.ns
.list_op(name
)
676 # except ClientException as e:
681 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
683 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
685 #print(yaml.safe_dump(resp))
688 if op
['lcmOperationType']=='action':
689 action_name
= op
['operationParams']['primitive']
691 if op
['operationState']=='PROCESSING':
692 if op
['lcmOperationType']=='instantiate':
696 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
697 elif op
['operationState']=='FAILED' or op
['operationState']=='FAILED_TEMP':
698 detail
= op
['errorMessage']
699 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
700 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
702 table
.add_row([op
['id'],
703 op
['lcmOperationType'],
705 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
706 op
['operationState'],
709 wrap_text(text
=detail
,width
=50)])
711 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
712 op
['operationState'], date
, wrap_text(text
=detail
,width
=50)])
717 def nsi_list(ctx
, filter):
718 """list all Network Slice Instances"""
721 check_client_version(ctx
.obj
, ctx
.command
.name
)
722 resp
= ctx
.obj
.nsi
.list(filter)
723 # except ClientException as e:
727 ['netslice instance name',
729 'operational status',
733 nsi_name
= nsi
['name']
735 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
736 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
737 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
738 if configstatus
== "config_not_needed":
739 configstatus
= "configured (no charms)"
750 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
751 @click.option('--filter', default
=None,
752 help='restricts the list to the Network Slice Instances matching the filter')
754 def nsi_list1(ctx
, filter):
755 """list all Network Slice Instances (NSI)"""
757 nsi_list(ctx
, filter)
760 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
761 @click.option('--filter', default
=None,
762 help='restricts the list to the Network Slice Instances matching the filter')
764 def nsi_list2(ctx
, filter):
765 """list all Network Slice Instances (NSI)"""
767 nsi_list(ctx
, filter)
770 def nst_list(ctx
, filter):
773 check_client_version(ctx
.obj
, ctx
.command
.name
)
774 resp
= ctx
.obj
.nst
.list(filter)
775 # except ClientException as e:
778 # print(yaml.safe_dump(resp))
779 table
= PrettyTable(['nst name', 'id'])
781 name
= nst
['name'] if 'name' in nst
else '-'
782 table
.add_row([name
, nst
['_id']])
787 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
788 @click.option('--filter', default
=None,
789 help='restricts the list to the NST matching the filter')
791 def nst_list1(ctx
, filter):
792 """list all Network Slice Templates (NST) in the system"""
794 nst_list(ctx
, filter)
797 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
798 @click.option('--filter', default
=None,
799 help='restricts the list to the NST matching the filter')
801 def nst_list2(ctx
, filter):
802 """list all Network Slice Templates (NST) in the system"""
804 nst_list(ctx
, filter)
807 def nsi_op_list(ctx
, name
):
810 check_client_version(ctx
.obj
, ctx
.command
.name
)
811 resp
= ctx
.obj
.nsi
.list_op(name
)
812 # except ClientException as e:
815 table
= PrettyTable(['id', 'operation', 'status'])
817 table
.add_row([op
['id'], op
['lcmOperationType'],
818 op
['operationState']])
823 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
824 @click.argument('name')
826 def nsi_op_list1(ctx
, name
):
827 """shows the history of operations over a Network Slice Instance (NSI)
829 NAME: name or ID of the Network Slice Instance
832 nsi_op_list(ctx
, name
)
835 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
836 @click.argument('name')
838 def nsi_op_list2(ctx
, name
):
839 """shows the history of operations over a Network Slice Instance (NSI)
841 NAME: name or ID of the Network Slice Instance
844 nsi_op_list(ctx
, name
)
847 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
848 @click.option('--filter', default
=None,
849 help='restricts the list to the Physical Deployment Units matching the filter')
851 def pdu_list(ctx
, filter):
852 """list all Physical Deployment Units (PDU)"""
855 check_client_version(ctx
.obj
, ctx
.command
.name
)
856 resp
= ctx
.obj
.pdu
.list(filter)
857 # except ClientException as e:
866 pdu_name
= pdu
['name']
868 pdu_type
= pdu
['type']
869 pdu_ipaddress
= "None"
870 for iface
in pdu
['interfaces']:
872 pdu_ipaddress
= iface
['ip-address']
887 def nsd_show(ctx
, name
, literal
):
890 resp
= ctx
.obj
.nsd
.get(name
)
891 # resp = ctx.obj.nsd.get_individual(name)
892 # except ClientException as e:
897 print(yaml
.safe_dump(resp
))
900 table
= PrettyTable(['field', 'value'])
901 for k
, v
in list(resp
.items()):
902 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
907 @cli_osm.command(name
='nsd-show', short_help
='shows the content of a NSD')
908 @click.option('--literal', is_flag
=True,
909 help='print literally, no pretty table')
910 @click.argument('name')
912 def nsd_show1(ctx
, name
, literal
):
913 """shows the content of a NSD
915 NAME: name or ID of the NSD/NSpkg
918 nsd_show(ctx
, name
, literal
)
921 @cli_osm.command(name
='nspkg-show', short_help
='shows the content of a NSD')
922 @click.option('--literal', is_flag
=True,
923 help='print literally, no pretty table')
924 @click.argument('name')
926 def nsd_show2(ctx
, name
, literal
):
927 """shows the content of a NSD
929 NAME: name or ID of the NSD/NSpkg
932 nsd_show(ctx
, name
, literal
)
935 def vnfd_show(ctx
, name
, literal
):
938 resp
= ctx
.obj
.vnfd
.get(name
)
939 # resp = ctx.obj.vnfd.get_individual(name)
940 # except ClientException as e:
945 print(yaml
.safe_dump(resp
))
948 table
= PrettyTable(['field', 'value'])
949 for k
, v
in list(resp
.items()):
950 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
955 @cli_osm.command(name
='vnfd-show', short_help
='shows the content of a VNFD')
956 @click.option('--literal', is_flag
=True,
957 help='print literally, no pretty table')
958 @click.argument('name')
960 def vnfd_show1(ctx
, name
, literal
):
961 """shows the content of a VNFD
963 NAME: name or ID of the VNFD/VNFpkg
966 vnfd_show(ctx
, name
, literal
)
969 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the content of a VNFD')
970 @click.option('--literal', is_flag
=True,
971 help='print literally, no pretty table')
972 @click.argument('name')
974 def vnfd_show2(ctx
, name
, literal
):
975 """shows the content of a VNFD
977 NAME: name or ID of the VNFD/VNFpkg
980 vnfd_show(ctx
, name
, literal
)
983 @cli_osm.command(name
='nfpkg-show', short_help
='shows the content of a NF Descriptor')
984 @click.option('--literal', is_flag
=True,
985 help='print literally, no pretty table')
986 @click.argument('name')
988 def nfpkg_show(ctx
, name
, literal
):
989 """shows the content of a NF Descriptor
991 NAME: name or ID of the NFpkg
994 vnfd_show(ctx
, name
, literal
)
997 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
998 @click.argument('name')
999 @click.option('--literal', is_flag
=True,
1000 help='print literally, no pretty table')
1001 @click.option('--filter', default
=None)
1003 def ns_show(ctx
, name
, literal
, filter):
1004 """shows the info of a NS instance
1006 NAME: name or ID of the NS instance
1010 ns
= ctx
.obj
.ns
.get(name
)
1011 # except ClientException as e:
1016 print(yaml
.safe_dump(ns
))
1019 table
= PrettyTable(['field', 'value'])
1021 for k
, v
in list(ns
.items()):
1022 if filter is None or filter in k
:
1023 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1025 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1026 if fullclassname
!= 'osmclient.sol005.client.Client':
1027 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1028 nsr_optdata
= nsopdata
['nsr:nsr']
1029 for k
, v
in list(nsr_optdata
.items()):
1030 if filter is None or filter in k
:
1031 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1036 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1037 @click.argument('name')
1038 @click.option('--literal', is_flag
=True,
1039 help='print literally, no pretty table')
1040 @click.option('--filter', default
=None, help='restricts the information to the fields in the filter')
1041 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1043 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1044 """shows the info of a VNF instance
1046 NAME: name or ID of the VNF instance
1048 def print_kdu_status(op_info_status
):
1049 """print KDU status properly formatted
1052 op_status
= yaml
.safe_load(op_info_status
)
1053 if "namespace" in op_status
and "info" in op_status
and \
1054 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1055 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1056 "notes" in op_status
["info"]["status"] and "seconds" in op_status
["info"]["last_deployed"]:
1057 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1058 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1059 print("NAMESPACE: {}".format(op_status
["namespace"]))
1060 status_code
= "UNKNOWN"
1061 if op_status
["info"]["status"]["code"]==1:
1062 status_code
= "DEPLOYED"
1063 print("STATUS: {}".format(status_code
))
1066 print(op_status
["info"]["status"]["resources"])
1068 print(op_status
["info"]["status"]["notes"])
1070 print(op_info_status
)
1072 print(op_info_status
)
1077 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1079 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1082 check_client_version(ctx
.obj
, ctx
.command
.name
)
1083 resp
= ctx
.obj
.vnf
.get(name
)
1086 ns_id
= resp
['nsr-id-ref']
1088 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1089 op_data
['kdu_name'] = kdu
1090 op_data
['primitive'] = 'status'
1091 op_data
['primitive_params'] = {}
1092 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1095 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1096 if op_info
['operationState'] == 'COMPLETED':
1097 print_kdu_status(op_info
['detailed-status'])
1101 print ("Could not determine KDU status")
1104 print(yaml
.safe_dump(resp
))
1107 table
= PrettyTable(['field', 'value'])
1109 for k
, v
in list(resp
.items()):
1110 if filter is None or filter in k
:
1111 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1114 # except ClientException as e:
1119 #@cli_osm.command(name='vnf-monitoring-show')
1120 #@click.argument('vnf_name')
1121 #@click.pass_context
1122 #def vnf_monitoring_show(ctx, vnf_name):
1124 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1125 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1126 # except ClientException as e:
1130 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1131 # if resp is not None:
1132 # for monitor in resp:
1136 # monitor['value-integer'],
1137 # monitor['units']])
1142 #@cli_osm.command(name='ns-monitoring-show')
1143 #@click.argument('ns_name')
1144 #@click.pass_context
1145 #def ns_monitoring_show(ctx, ns_name):
1147 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1148 # resp = ctx.obj.ns.get_monitoring(ns_name)
1149 # except ClientException as e:
1153 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1154 # for key, val in list(resp.items()):
1155 # for monitor in val:
1159 # monitor['value-integer'],
1160 # monitor['units']])
1165 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1166 @click.argument('id')
1167 @click.option('--filter', default
=None)
1168 @click.option('--literal', is_flag
=True,
1169 help='print literally, no pretty table')
1171 def ns_op_show(ctx
, id, filter, literal
):
1172 """shows the detailed info of a NS operation
1174 ID: operation identifier
1178 check_client_version(ctx
.obj
, ctx
.command
.name
)
1179 op_info
= ctx
.obj
.ns
.get_op(id)
1180 # except ClientException as e:
1185 print(yaml
.safe_dump(op_info
))
1188 table
= PrettyTable(['field', 'value'])
1189 for k
, v
in list(op_info
.items()):
1190 if filter is None or filter in k
:
1191 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1196 def nst_show(ctx
, name
, literal
):
1199 check_client_version(ctx
.obj
, ctx
.command
.name
)
1200 resp
= ctx
.obj
.nst
.get(name
)
1201 #resp = ctx.obj.nst.get_individual(name)
1202 # except ClientException as e:
1207 print(yaml
.safe_dump(resp
))
1210 table
= PrettyTable(['field', 'value'])
1211 for k
, v
in list(resp
.items()):
1212 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1217 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1218 @click.option('--literal', is_flag
=True,
1219 help='print literally, no pretty table')
1220 @click.argument('name')
1222 def nst_show1(ctx
, name
, literal
):
1223 """shows the content of a Network Slice Template (NST)
1225 NAME: name or ID of the NST
1228 nst_show(ctx
, name
, literal
)
1231 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1232 @click.option('--literal', is_flag
=True,
1233 help='print literally, no pretty table')
1234 @click.argument('name')
1236 def nst_show2(ctx
, name
, literal
):
1237 """shows the content of a Network Slice Template (NST)
1239 NAME: name or ID of the NST
1242 nst_show(ctx
, name
, literal
)
1245 def nsi_show(ctx
, name
, literal
, filter):
1248 check_client_version(ctx
.obj
, ctx
.command
.name
)
1249 nsi
= ctx
.obj
.nsi
.get(name
)
1250 # except ClientException as e:
1255 print(yaml
.safe_dump(nsi
))
1258 table
= PrettyTable(['field', 'value'])
1260 for k
, v
in list(nsi
.items()):
1261 if filter is None or filter in k
:
1262 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1268 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1269 @click.argument('name')
1270 @click.option('--literal', is_flag
=True,
1271 help='print literally, no pretty table')
1272 @click.option('--filter', default
=None)
1274 def nsi_show1(ctx
, name
, literal
, filter):
1275 """shows the content of a Network Slice Instance (NSI)
1277 NAME: name or ID of the Network Slice Instance
1280 nsi_show(ctx
, name
, literal
, filter)
1283 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1284 @click.argument('name')
1285 @click.option('--literal', is_flag
=True,
1286 help='print literally, no pretty table')
1287 @click.option('--filter', default
=None)
1289 def nsi_show2(ctx
, name
, literal
, filter):
1290 """shows the content of a Network Slice Instance (NSI)
1292 NAME: name or ID of the Network Slice Instance
1295 nsi_show(ctx
, name
, literal
, filter)
1298 def nsi_op_show(ctx
, id, filter):
1301 check_client_version(ctx
.obj
, ctx
.command
.name
)
1302 op_info
= ctx
.obj
.nsi
.get_op(id)
1303 # except ClientException as e:
1307 table
= PrettyTable(['field', 'value'])
1308 for k
, v
in list(op_info
.items()):
1309 if filter is None or filter in k
:
1310 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1315 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1316 @click.argument('id')
1317 @click.option('--filter', default
=None)
1319 def nsi_op_show1(ctx
, id, filter):
1320 """shows the info of an operation over a Network Slice Instance(NSI)
1322 ID: operation identifier
1325 nsi_op_show(ctx
, id, filter)
1328 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1329 @click.argument('id')
1330 @click.option('--filter', default
=None)
1332 def nsi_op_show2(ctx
, id, filter):
1333 """shows the info of an operation over a Network Slice Instance(NSI)
1335 ID: operation identifier
1338 nsi_op_show(ctx
, id, filter)
1341 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1342 @click.argument('name')
1343 @click.option('--literal', is_flag
=True,
1344 help='print literally, no pretty table')
1345 @click.option('--filter', default
=None)
1347 def pdu_show(ctx
, name
, literal
, filter):
1348 """shows the content of a Physical Deployment Unit (PDU)
1350 NAME: name or ID of the PDU
1354 check_client_version(ctx
.obj
, ctx
.command
.name
)
1355 pdu
= ctx
.obj
.pdu
.get(name
)
1356 # except ClientException as e:
1361 print(yaml
.safe_dump(pdu
))
1364 table
= PrettyTable(['field', 'value'])
1366 for k
, v
in list(pdu
.items()):
1367 if filter is None or filter in k
:
1368 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1374 ####################
1376 ####################
1378 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
):
1381 check_client_version(ctx
.obj
, ctx
.command
.name
)
1382 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1383 # except ClientException as e:
1388 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1389 @click.argument('filename')
1390 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1391 help='Deprecated. Use override')
1392 @click.option('--override', 'overwrite', default
=None,
1393 help='overrides fields in descriptor, format: '
1394 '"key1.key2...=value[;key3...=value;...]"')
1395 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1396 help='The charm will not be compiled, it is assumed to already exist')
1398 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
):
1399 """creates a new NSD/NSpkg
1401 FILENAME: NSD yaml file or NSpkg tar.gz file
1404 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1407 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1408 @click.argument('filename')
1409 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1410 help='Deprecated. Use override')
1411 @click.option('--override', 'overwrite', default
=None,
1412 help='overrides fields in descriptor, format: '
1413 '"key1.key2...=value[;key3...=value;...]"')
1414 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1415 help='The charm will not be compiled, it is assumed to already exist')
1417 def nsd_create2(ctx
, filename
, overwrite
, skip_charm_build
):
1418 """creates a new NSD/NSpkg
1420 FILENAME: NSD folder, NSD yaml file or NSpkg tar.gz file
1423 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1426 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
):
1429 check_client_version(ctx
.obj
, ctx
.command
.name
)
1430 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1431 # except ClientException as e:
1436 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1437 @click.argument('filename')
1438 @click.option('--overwrite', 'overwrite', default
=None,
1439 help='overwrite deprecated, use override')
1440 @click.option('--override', 'overwrite', default
=None,
1441 help='overrides fields in descriptor, format: '
1442 '"key1.key2...=value[;key3...=value;...]"')
1443 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1444 help='The charm will not be compiled, it is assumed to already exist')
1446 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
):
1447 """creates a new VNFD/VNFpkg
1449 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1452 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1455 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1456 @click.argument('filename')
1457 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1458 help='Deprecated. Use override')
1459 @click.option('--override', 'overwrite', default
=None,
1460 help='overrides fields in descriptor, format: '
1461 '"key1.key2...=value[;key3...=value;...]"')
1462 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1463 help='The charm will not be compiled, it is assumed to already exist')
1465 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
):
1466 """creates a new VNFD/VNFpkg
1468 FILENAME: NF Package Folder, NF Descriptor yaml file or NFpkg tar.gz file
1471 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1474 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1475 @click.argument('filename')
1476 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1477 help='Deprecated. Use override')
1478 @click.option('--override', 'overwrite', default
=None,
1479 help='overrides fields in descriptor, format: '
1480 '"key1.key2...=value[;key3...=value;...]"')
1481 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1482 help='The charm will not be compiled, it is assumed to already exist')
1484 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
):
1485 """creates a new NFpkg
1487 FILENAME: NF Package Folder, NF Descriptor yaml file or NFpkg tar.gz filems to build
1490 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1493 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1494 @click.option('--ns_name',
1495 prompt
=True, help='name of the NS instance')
1496 @click.option('--nsd_name',
1497 prompt
=True, help='name of the NS descriptor')
1498 @click.option('--vim_account',
1499 prompt
=True, help='default VIM account id or name for the deployment')
1500 @click.option('--admin_status',
1502 help='administration status')
1503 @click.option('--ssh_keys',
1505 help='comma separated list of public key files to inject to vnfs')
1506 @click.option('--config',
1508 help='ns specific yaml configuration')
1509 @click.option('--config_file',
1511 help='ns specific yaml configuration file')
1512 @click.option('--wait',
1516 help='do not return the control immediately, but keep it '
1517 'until the operation is completed, or timeout')
1528 """creates a new NS instance"""
1532 check_client_version(ctx
.obj
, '--config_file')
1534 raise ClientException('"--config" option is incompatible with "--config_file" option')
1535 with
open(config_file
, 'r') as cf
:
1542 account
=vim_account
,
1544 # except ClientException as e:
1549 def nst_create(ctx
, filename
, overwrite
):
1552 check_client_version(ctx
.obj
, ctx
.command
.name
)
1553 ctx
.obj
.nst
.create(filename
, overwrite
)
1554 # except ClientException as e:
1559 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1560 @click.argument('filename')
1561 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1562 help='Deprecated. Use override')
1563 @click.option('--override', 'overwrite', default
=None,
1564 help='overrides fields in descriptor, format: '
1565 '"key1.key2...=value[;key3...=value;...]"')
1567 def nst_create1(ctx
, charm_folder
, overwrite
):
1568 """creates a new Network Slice Template (NST)
1570 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1573 nst_create(ctx
, charm_folder
, overwrite
)
1576 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1577 @click.argument('filename')
1578 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1579 help='Deprecated. Use override')
1580 @click.option('--override', 'overwrite', default
=None,
1581 help='overrides fields in descriptor, format: '
1582 '"key1.key2...=value[;key3...=value;...]"')
1584 def nst_create2(ctx
, filename
, overwrite
):
1585 """creates a new Network Slice Template (NST)
1587 FILENAME: NST yaml file or NSTpkg tar.gz file
1590 nst_create(ctx
, filename
, overwrite
)
1593 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1594 """creates a new Network Slice Instance (NSI)"""
1597 check_client_version(ctx
.obj
, ctx
.command
.name
)
1600 raise ClientException('"--config" option is incompatible with "--config_file" option')
1601 with
open(config_file
, 'r') as cf
:
1603 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1604 account
=vim_account
, wait
=wait
)
1605 # except ClientException as e:
1610 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1611 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1612 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1613 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1614 @click.option('--ssh_keys', default
=None,
1615 help='comma separated list of keys to inject to vnfs')
1616 @click.option('--config', default
=None,
1617 help='Netslice specific yaml configuration:\n'
1618 'netslice_subnet: [\n'
1619 'id: TEXT, vim_account: TEXT,\n'
1620 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1621 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1622 'additionalParamsForNsi: {param: value, ...}\n'
1623 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1625 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1627 @click.option('--config_file',
1629 help='nsi specific yaml configuration file')
1630 @click.option('--wait',
1634 help='do not return the control immediately, but keep it '
1635 'until the operation is completed, or timeout')
1637 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1638 """creates a new Network Slice Instance (NSI)"""
1640 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1643 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1644 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1645 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1646 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1647 @click.option('--ssh_keys', default
=None,
1648 help='comma separated list of keys to inject to vnfs')
1649 @click.option('--config', default
=None,
1650 help='Netslice specific yaml configuration:\n'
1651 'netslice_subnet: [\n'
1652 'id: TEXT, vim_account: TEXT,\n'
1653 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1654 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1656 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1658 @click.option('--config_file',
1660 help='nsi specific yaml configuration file')
1661 @click.option('--wait',
1665 help='do not return the control immediately, but keep it '
1666 'until the operation is completed, or timeout')
1668 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1669 """creates a new Network Slice Instance (NSI)"""
1671 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1674 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1675 @click.option('--name', help='name of the Physical Deployment Unit')
1676 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1677 @click.option('--interface',
1678 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1679 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1681 @click.option('--description', help='human readable description')
1682 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
1683 @click.option('--descriptor_file', default
=None,
1684 help='PDU descriptor file (as an alternative to using the other arguments')
1686 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
1687 """creates a new Physical Deployment Unit (PDU)"""
1690 check_client_version(ctx
.obj
, ctx
.command
.name
)
1692 if not descriptor_file
:
1694 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1696 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1698 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1700 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1702 with
open(descriptor_file
, 'r') as df
:
1703 pdu
= yaml
.safe_load(df
.read())
1704 if name
: pdu
["name"] = name
1705 if pdu_type
: pdu
["type"] = pdu_type
1706 if description
: pdu
["description"] = description
1707 if vim_account
: pdu
["vim_accounts"] = vim_account
1710 for iface
in interface
:
1711 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
1712 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
1713 ifaces_list
.append(new_iface
)
1714 pdu
["interfaces"] = ifaces_list
1715 ctx
.obj
.pdu
.create(pdu
)
1716 # except ClientException as e:
1721 ####################
1723 ####################
1725 def nsd_update(ctx
, name
, content
):
1728 check_client_version(ctx
.obj
, ctx
.command
.name
)
1729 ctx
.obj
.nsd
.update(name
, content
)
1730 # except ClientException as e:
1735 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
1736 @click.argument('name')
1737 @click.option('--content', default
=None,
1738 help='filename with the NSD/NSpkg replacing the current one')
1740 def nsd_update1(ctx
, name
, content
):
1741 """updates a NSD/NSpkg
1743 NAME: name or ID of the NSD/NSpkg
1746 nsd_update(ctx
, name
, content
)
1749 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
1750 @click.argument('name')
1751 @click.option('--content', default
=None,
1752 help='filename with the NSD/NSpkg replacing the current one')
1754 def nsd_update2(ctx
, name
, content
):
1755 """updates a NSD/NSpkg
1757 NAME: name or ID of the NSD/NSpkg
1760 nsd_update(ctx
, name
, content
)
1763 def vnfd_update(ctx
, name
, content
):
1766 check_client_version(ctx
.obj
, ctx
.command
.name
)
1767 ctx
.obj
.vnfd
.update(name
, content
)
1768 # except ClientException as e:
1773 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
1774 @click.argument('name')
1775 @click.option('--content', default
=None,
1776 help='filename with the VNFD/VNFpkg replacing the current one')
1778 def vnfd_update1(ctx
, name
, content
):
1779 """updates a VNFD/VNFpkg
1781 NAME: name or ID of the VNFD/VNFpkg
1784 vnfd_update(ctx
, name
, content
)
1787 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
1788 @click.argument('name')
1789 @click.option('--content', default
=None,
1790 help='filename with the VNFD/VNFpkg replacing the current one')
1792 def vnfd_update2(ctx
, name
, content
):
1793 """updates a VNFD/VNFpkg
1795 NAME: VNFD yaml file or VNFpkg tar.gz file
1798 vnfd_update(ctx
, name
, content
)
1801 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
1802 @click.argument('name')
1803 @click.option('--content', default
=None,
1804 help='filename with the NFpkg replacing the current one')
1806 def nfpkg_update(ctx
, name
, content
):
1809 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1812 vnfd_update(ctx
, name
, content
)
1815 def nst_update(ctx
, name
, content
):
1818 check_client_version(ctx
.obj
, ctx
.command
.name
)
1819 ctx
.obj
.nst
.update(name
, content
)
1820 # except ClientException as e:
1825 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
1826 @click.argument('name')
1827 @click.option('--content', default
=None,
1828 help='filename with the NST/NSTpkg replacing the current one')
1830 def nst_update1(ctx
, name
, content
):
1831 """updates a Network Slice Template (NST)
1833 NAME: name or ID of the NSD/NSpkg
1836 nst_update(ctx
, name
, content
)
1839 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
1840 @click.argument('name')
1841 @click.option('--content', default
=None,
1842 help='filename with the NST/NSTpkg replacing the current one')
1844 def nst_update2(ctx
, name
, content
):
1845 """updates a Network Slice Template (NST)
1847 NAME: name or ID of the NSD/NSpkg
1850 nst_update(ctx
, name
, content
)
1853 ####################
1855 ####################
1857 def nsd_delete(ctx
, name
, force
):
1861 ctx
.obj
.nsd
.delete(name
)
1863 check_client_version(ctx
.obj
, '--force')
1864 ctx
.obj
.nsd
.delete(name
, force
)
1865 # except ClientException as e:
1870 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
1871 @click.argument('name')
1872 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1874 def nsd_delete1(ctx
, name
, force
):
1875 """deletes a NSD/NSpkg
1877 NAME: name or ID of the NSD/NSpkg to be deleted
1880 nsd_delete(ctx
, name
, force
)
1883 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
1884 @click.argument('name')
1885 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1887 def nsd_delete2(ctx
, name
, force
):
1888 """deletes a NSD/NSpkg
1890 NAME: name or ID of the NSD/NSpkg to be deleted
1893 nsd_delete(ctx
, name
, force
)
1896 def vnfd_delete(ctx
, name
, force
):
1900 ctx
.obj
.vnfd
.delete(name
)
1902 check_client_version(ctx
.obj
, '--force')
1903 ctx
.obj
.vnfd
.delete(name
, force
)
1904 # except ClientException as e:
1909 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
1910 @click.argument('name')
1911 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1913 def vnfd_delete1(ctx
, name
, force
):
1914 """deletes a VNFD/VNFpkg
1916 NAME: name or ID of the VNFD/VNFpkg to be deleted
1919 vnfd_delete(ctx
, name
, force
)
1922 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
1923 @click.argument('name')
1924 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1926 def vnfd_delete2(ctx
, name
, force
):
1927 """deletes a VNFD/VNFpkg
1929 NAME: name or ID of the VNFD/VNFpkg to be deleted
1932 vnfd_delete(ctx
, name
, force
)
1935 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
1936 @click.argument('name')
1937 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1939 def nfpkg_delete(ctx
, name
, force
):
1942 NAME: name or ID of the NFpkg to be deleted
1945 vnfd_delete(ctx
, name
, force
)
1948 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
1949 @click.argument('name')
1950 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1951 @click.option('--wait',
1955 help='do not return the control immediately, but keep it '
1956 'until the operation is completed, or timeout')
1958 def ns_delete(ctx
, name
, force
, wait
):
1959 """deletes a NS instance
1961 NAME: name or ID of the NS instance to be deleted
1966 ctx
.obj
.ns
.delete(name
, wait
=wait
)
1968 check_client_version(ctx
.obj
, '--force')
1969 ctx
.obj
.ns
.delete(name
, force
, wait
=wait
)
1970 # except ClientException as e:
1975 def nst_delete(ctx
, name
, force
):
1978 check_client_version(ctx
.obj
, ctx
.command
.name
)
1979 ctx
.obj
.nst
.delete(name
, force
)
1980 # except ClientException as e:
1985 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
1986 @click.argument('name')
1987 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1989 def nst_delete1(ctx
, name
, force
):
1990 """deletes a Network Slice Template (NST)
1992 NAME: name or ID of the NST/NSTpkg to be deleted
1995 nst_delete(ctx
, name
, force
)
1998 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
1999 @click.argument('name')
2000 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2002 def nst_delete2(ctx
, name
, force
):
2003 """deletes a Network Slice Template (NST)
2005 NAME: name or ID of the NST/NSTpkg to be deleted
2008 nst_delete(ctx
, name
, force
)
2011 def nsi_delete(ctx
, name
, force
, wait
):
2014 check_client_version(ctx
.obj
, ctx
.command
.name
)
2015 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2016 # except ClientException as e:
2021 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2022 @click.argument('name')
2023 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2024 @click.option('--wait',
2028 help='do not return the control immediately, but keep it '
2029 'until the operation is completed, or timeout')
2031 def nsi_delete1(ctx
, name
, force
, wait
):
2032 """deletes a Network Slice Instance (NSI)
2034 NAME: name or ID of the Network Slice instance to be deleted
2037 nsi_delete(ctx
, name
, force
, wait
=wait
)
2040 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2041 @click.argument('name')
2042 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2044 def nsi_delete2(ctx
, name
, force
, wait
):
2045 """deletes a Network Slice Instance (NSI)
2047 NAME: name or ID of the Network Slice instance to be deleted
2050 nsi_delete(ctx
, name
, force
, wait
=wait
)
2053 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2054 @click.argument('name')
2055 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2057 def pdu_delete(ctx
, name
, force
):
2058 """deletes a Physical Deployment Unit (PDU)
2060 NAME: name or ID of the PDU to be deleted
2064 check_client_version(ctx
.obj
, ctx
.command
.name
)
2065 ctx
.obj
.pdu
.delete(name
, force
)
2066 # except ClientException as e:
2075 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2076 @click.option('--name',
2078 help='Name to create datacenter')
2079 @click.option('--user',
2081 help='VIM username')
2082 @click.option('--password',
2085 confirmation_prompt
=True,
2086 help='VIM password')
2087 @click.option('--auth_url',
2090 @click.option('--tenant',
2092 help='VIM tenant name')
2093 @click.option('--config',
2095 help='VIM specific config parameters')
2096 @click.option('--account_type',
2097 default
='openstack',
2099 @click.option('--description',
2101 help='human readable description')
2102 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2103 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2104 @click.option('--wait',
2108 help='do not return the control immediately, but keep it '
2109 'until the operation is completed, or timeout')
2123 """creates a new VIM account"""
2127 check_client_version(ctx
.obj
, '--sdn_controller')
2128 if sdn_port_mapping
:
2129 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2131 vim
['vim-username'] = user
2132 vim
['vim-password'] = password
2133 vim
['vim-url'] = auth_url
2134 vim
['vim-tenant-name'] = tenant
2135 vim
['vim-type'] = account_type
2136 vim
['description'] = description
2137 vim
['config'] = config
2138 if sdn_controller
or sdn_port_mapping
:
2139 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2141 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2142 # except ClientException as e:
2147 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2148 @click.argument('name')
2149 @click.option('--newname', help='New name for the VIM account')
2150 @click.option('--user', help='VIM username')
2151 @click.option('--password', help='VIM password')
2152 @click.option('--auth_url', help='VIM url')
2153 @click.option('--tenant', help='VIM tenant name')
2154 @click.option('--config', help='VIM specific config parameters')
2155 @click.option('--account_type', help='VIM type')
2156 @click.option('--description', help='human readable description')
2157 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2158 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2159 @click.option('--wait',
2163 help='do not return the control immediately, but keep it '
2164 'until the operation is completed, or timeout')
2179 """updates a VIM account
2181 NAME: name or ID of the VIM account
2185 check_client_version(ctx
.obj
, ctx
.command
.name
)
2187 if newname
: vim
['name'] = newname
2188 if user
: vim
['vim_user'] = user
2189 if password
: vim
['vim_password'] = password
2190 if auth_url
: vim
['vim_url'] = auth_url
2191 if tenant
: vim
['vim-tenant-name'] = tenant
2192 if account_type
: vim
['vim_type'] = account_type
2193 if description
: vim
['description'] = description
2194 if config
: vim
['config'] = config
2195 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2196 # except ClientException as e:
2201 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2202 @click.argument('name')
2203 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2204 @click.option('--wait',
2208 help='do not return the control immediately, but keep it '
2209 'until the operation is completed, or timeout')
2211 def vim_delete(ctx
, name
, force
, wait
):
2212 """deletes a VIM account
2214 NAME: name or ID of the VIM account to be deleted
2219 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2221 check_client_version(ctx
.obj
, '--force')
2222 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2223 # except ClientException as e:
2228 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2229 #@click.option('--ro_update/--no_ro_update',
2231 # help='update list from RO')
2232 @click.option('--filter', default
=None,
2233 help='restricts the list to the VIM accounts matching the filter')
2235 def vim_list(ctx
, filter):
2236 """list all VIM accounts"""
2239 check_client_version(ctx
.obj
, '--filter')
2241 # check_client_version(ctx.obj, '--ro_update', 'v1')
2242 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2243 if fullclassname
== 'osmclient.sol005.client.Client':
2244 resp
= ctx
.obj
.vim
.list(filter)
2246 # resp = ctx.obj.vim.list(ro_update)
2247 table
= PrettyTable(['vim name', 'uuid'])
2249 table
.add_row([vim
['name'], vim
['uuid']])
2254 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2255 @click.argument('name')
2257 def vim_show(ctx
, name
):
2258 """shows the details of a VIM account
2260 NAME: name or ID of the VIM account
2264 resp
= ctx
.obj
.vim
.get(name
)
2265 if 'vim_password' in resp
:
2266 resp
['vim_password']='********'
2267 # except ClientException as e:
2271 table
= PrettyTable(['key', 'attribute'])
2272 for k
, v
in list(resp
.items()):
2273 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2278 ####################
2280 ####################
2282 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2283 @click.option('--name',
2285 help='Name for the WIM account')
2286 @click.option('--user',
2287 help='WIM username')
2288 @click.option('--password',
2289 help='WIM password')
2290 @click.option('--url',
2293 # @click.option('--tenant',
2294 # help='wIM tenant name')
2295 @click.option('--config',
2297 help='WIM specific config parameters')
2298 @click.option('--wim_type',
2300 @click.option('--description',
2302 help='human readable description')
2303 @click.option('--wim_port_mapping', default
=None,
2304 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2305 "(WAN service endpoint id and info)")
2306 @click.option('--wait',
2310 help='do not return the control immediately, but keep it '
2311 'until the operation is completed, or timeout')
2324 """creates a new WIM account"""
2327 check_client_version(ctx
.obj
, ctx
.command
.name
)
2328 # if sdn_controller:
2329 # check_client_version(ctx.obj, '--sdn_controller')
2330 # if sdn_port_mapping:
2331 # check_client_version(ctx.obj, '--sdn_port_mapping')
2333 if user
: wim
['user'] = user
2334 if password
: wim
['password'] = password
2335 if url
: wim
['wim_url'] = url
2336 # if tenant: wim['tenant'] = tenant
2337 wim
['wim_type'] = wim_type
2338 if description
: wim
['description'] = description
2339 if config
: wim
['config'] = config
2340 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2341 # except ClientException as e:
2346 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2347 @click.argument('name')
2348 @click.option('--newname', help='New name for the WIM account')
2349 @click.option('--user', help='WIM username')
2350 @click.option('--password', help='WIM password')
2351 @click.option('--url', help='WIM url')
2352 @click.option('--config', help='WIM specific config parameters')
2353 @click.option('--wim_type', help='WIM type')
2354 @click.option('--description', help='human readable description')
2355 @click.option('--wim_port_mapping', default
=None,
2356 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2357 "(WAN service endpoint id and info)")
2358 @click.option('--wait',
2362 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2375 """updates a WIM account
2377 NAME: name or ID of the WIM account
2381 check_client_version(ctx
.obj
, ctx
.command
.name
)
2383 if newname
: wim
['name'] = newname
2384 if user
: wim
['user'] = user
2385 if password
: wim
['password'] = password
2386 if url
: wim
['url'] = url
2387 # if tenant: wim['tenant'] = tenant
2388 if wim_type
: wim
['wim_type'] = wim_type
2389 if description
: wim
['description'] = description
2390 if config
: wim
['config'] = config
2391 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2392 # except ClientException as e:
2397 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2398 @click.argument('name')
2399 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2400 @click.option('--wait',
2404 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2406 def wim_delete(ctx
, name
, force
, wait
):
2407 """deletes a WIM account
2409 NAME: name or ID of the WIM account to be deleted
2413 check_client_version(ctx
.obj
, ctx
.command
.name
)
2414 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2415 # except ClientException as e:
2420 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2421 @click.option('--filter', default
=None,
2422 help='restricts the list to the WIM accounts matching the filter')
2424 def wim_list(ctx
, filter):
2425 """list all WIM accounts"""
2428 check_client_version(ctx
.obj
, ctx
.command
.name
)
2429 resp
= ctx
.obj
.wim
.list(filter)
2430 table
= PrettyTable(['wim name', 'uuid'])
2432 table
.add_row([wim
['name'], wim
['uuid']])
2435 # except ClientException as e:
2440 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2441 @click.argument('name')
2443 def wim_show(ctx
, name
):
2444 """shows the details of a WIM account
2446 NAME: name or ID of the WIM account
2450 check_client_version(ctx
.obj
, ctx
.command
.name
)
2451 resp
= ctx
.obj
.wim
.get(name
)
2452 if 'password' in resp
:
2453 resp
['wim_password']='********'
2454 # except ClientException as e:
2458 table
= PrettyTable(['key', 'attribute'])
2459 for k
, v
in list(resp
.items()):
2460 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2465 ####################
2466 # SDN controller operations
2467 ####################
2469 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2470 @click.option('--name',
2472 help='Name to create sdn controller')
2473 @click.option('--type',
2475 help='SDN controller type')
2476 @click.option('--sdn_controller_version', # hidden=True,
2477 help='Deprecated. Use --config {version: sdn_controller_version}')
2478 @click.option('--url',
2479 help='URL in format http[s]://HOST:IP/')
2480 @click.option('--ip_address', # hidden=True,
2481 help='Deprecated. Use --url')
2482 @click.option('--port', # hidden=True,
2483 help='Deprecated. Use --url')
2484 @click.option('--switch_dpid', # hidden=True,
2485 help='Deprecated. Use --config {dpid: DPID}')
2486 @click.option('--config',
2487 help='Extra information for SDN in yaml format, as {dpid: (Openflow Datapath ID), version: version}')
2488 @click.option('--user',
2489 help='SDN controller username')
2490 @click.option('--password',
2492 confirmation_prompt
=True,
2493 help='SDN controller password')
2494 @click.option('--description', default
=None, help='human readable description')
2495 @click.option('--wait',
2499 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2501 def sdnc_create(ctx
, **kwargs
):
2502 """creates a new SDN controller"""
2504 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2505 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2506 if kwargs
.get("port"):
2507 print("option '--port' is deprecated, use '-url' instead")
2508 sdncontroller
["port"] = int(kwargs
["port"])
2509 if kwargs
.get("ip_address"):
2510 print("option '--ip_address' is deprecated, use '-url' instead")
2511 sdncontroller
["ip"] = kwargs
["ip_address"]
2512 if kwargs
.get("switch_dpid"):
2513 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2514 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2515 if kwargs
.get("sdn_controller_version"):
2516 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2519 check_client_version(ctx
.obj
, ctx
.command
.name
)
2520 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2521 # except ClientException as e:
2525 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2526 @click.argument('name')
2527 @click.option('--newname', help='New name for the SDN controller')
2528 @click.option('--description', default
=None, help='human readable description')
2529 @click.option('--type', help='SDN controller type')
2530 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2531 @click.option('--config', help='Extra information for SDN in yaml format, as '
2532 '{dpid: (Openflow Datapath ID), version: version}')
2533 @click.option('--user', help='SDN controller username')
2534 @click.option('--password', help='SDN controller password')
2535 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2536 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2537 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2538 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2539 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2540 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2542 def sdnc_update(ctx
, **kwargs
):
2543 """updates an SDN controller
2545 NAME: name or ID of the SDN controller
2548 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2549 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2550 if kwargs
.get("newname"):
2551 sdncontroller
["name"] = kwargs
["newname"]
2552 if kwargs
.get("port"):
2553 print("option '--port' is deprecated, use '-url' instead")
2554 sdncontroller
["port"] = int(kwargs
["port"])
2555 if kwargs
.get("ip_address"):
2556 print("option '--ip_address' is deprecated, use '-url' instead")
2557 sdncontroller
["ip"] = kwargs
["ip_address"]
2558 if kwargs
.get("switch_dpid"):
2559 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2560 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2561 if kwargs
.get("sdn_controller_version"):
2562 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2566 check_client_version(ctx
.obj
, ctx
.command
.name
)
2567 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2568 # except ClientException as e:
2573 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2574 @click.argument('name')
2575 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2576 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2577 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2579 def sdnc_delete(ctx
, name
, force
, wait
):
2580 """deletes an SDN controller
2582 NAME: name or ID of the SDN controller to be deleted
2586 check_client_version(ctx
.obj
, ctx
.command
.name
)
2587 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2588 # except ClientException as e:
2593 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2594 @click.option('--filter', default
=None,
2595 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2597 def sdnc_list(ctx
, filter):
2598 """list all SDN controllers"""
2601 check_client_version(ctx
.obj
, ctx
.command
.name
)
2602 resp
= ctx
.obj
.sdnc
.list(filter)
2603 # except ClientException as e:
2606 table
= PrettyTable(['sdnc name', 'id'])
2608 table
.add_row([sdnc
['name'], sdnc
['_id']])
2613 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2614 @click.argument('name')
2616 def sdnc_show(ctx
, name
):
2617 """shows the details of an SDN controller
2619 NAME: name or ID of the SDN controller
2623 check_client_version(ctx
.obj
, ctx
.command
.name
)
2624 resp
= ctx
.obj
.sdnc
.get(name
)
2625 # except ClientException as e:
2629 table
= PrettyTable(['key', 'attribute'])
2630 for k
, v
in list(resp
.items()):
2631 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2636 ###########################
2637 # K8s cluster operations
2638 ###########################
2640 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2641 @click.argument('name')
2642 @click.option('--creds',
2644 help='credentials file, i.e. a valid `.kube/config` file')
2645 @click.option('--version',
2647 help='Kubernetes version')
2648 @click.option('--vim',
2650 help='VIM target, the VIM where the cluster resides')
2651 @click.option('--k8s-nets',
2653 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) ...]}"')
2654 @click.option('--description',
2656 help='human readable description')
2657 @click.option('--namespace',
2658 default
='kube-system',
2659 help='namespace to be used for its operation, defaults to `kube-system`')
2660 @click.option('--cni',
2662 help='list of CNI plugins, in JSON inline format, used in the cluster')
2663 #@click.option('--skip-init',
2665 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2666 #@click.option('--wait',
2668 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2670 def k8scluster_add(ctx
,
2679 """adds a K8s cluster to OSM
2681 NAME: name of the K8s cluster
2684 check_client_version(ctx
.obj
, ctx
.command
.name
)
2686 cluster
['name'] = name
2687 with
open(creds
, 'r') as cf
:
2688 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2689 cluster
['k8s_version'] = version
2690 cluster
['vim_account'] = vim
2691 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2692 cluster
['description'] = description
2693 if namespace
: cluster
['namespace'] = namespace
2694 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2695 ctx
.obj
.k8scluster
.create(name
, cluster
)
2696 # except ClientException as e:
2701 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
2702 @click.argument('name')
2703 @click.option('--newname', help='New name for the K8s cluster')
2704 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
2705 @click.option('--version', help='Kubernetes version')
2706 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
2707 @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) ...]}"')
2708 @click.option('--description', help='human readable description')
2709 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
2710 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
2712 def k8scluster_update(ctx
,
2722 """updates a K8s cluster
2724 NAME: name or ID of the K8s cluster
2727 check_client_version(ctx
.obj
, ctx
.command
.name
)
2729 if newname
: cluster
['name'] = newname
2731 with
open(creds
, 'r') as cf
:
2732 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2733 if version
: cluster
['k8s_version'] = version
2734 if vim
: cluster
['vim_account'] = vim
2735 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2736 if description
: cluster
['description'] = description
2737 if namespace
: cluster
['namespace'] = namespace
2738 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2739 ctx
.obj
.k8scluster
.update(name
, cluster
)
2740 # except ClientException as e:
2745 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
2746 @click.argument('name')
2747 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2748 #@click.option('--wait',
2750 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2752 def k8scluster_delete(ctx
, name
, force
):
2753 """deletes a K8s cluster
2755 NAME: name or ID of the K8s cluster to be deleted
2758 check_client_version(ctx
.obj
, ctx
.command
.name
)
2759 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
2760 # except ClientException as e:
2765 @cli_osm.command(name
='k8scluster-list')
2766 @click.option('--filter', default
=None,
2767 help='restricts the list to the K8s clusters matching the filter')
2768 @click.option('--literal', is_flag
=True,
2769 help='print literally, no pretty table')
2771 def k8scluster_list(ctx
, filter, literal
):
2772 """list all K8s clusters"""
2774 check_client_version(ctx
.obj
, ctx
.command
.name
)
2775 resp
= ctx
.obj
.k8scluster
.list(filter)
2777 print(yaml
.safe_dump(resp
))
2779 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
2780 for cluster
in resp
:
2781 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
2782 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
2783 trunc_text(cluster
.get('description',''),40)])
2786 # except ClientException as e:
2791 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
2792 @click.argument('name')
2793 @click.option('--literal', is_flag
=True,
2794 help='print literally, no pretty table')
2796 def k8scluster_show(ctx
, name
, literal
):
2797 """shows the details of a K8s cluster
2799 NAME: name or ID of the K8s cluster
2802 resp
= ctx
.obj
.k8scluster
.get(name
)
2804 print(yaml
.safe_dump(resp
))
2806 table
= PrettyTable(['key', 'attribute'])
2807 for k
, v
in list(resp
.items()):
2808 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2811 # except ClientException as e:
2817 ###########################
2819 ###########################
2821 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
2822 @click.argument('name')
2823 @click.argument('uri')
2824 @click.option('--type',
2825 type=click
.Choice(['helm-chart', 'juju-bundle']),
2827 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2828 @click.option('--description',
2830 help='human readable description')
2831 #@click.option('--wait',
2833 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2840 """adds a repo to OSM
2842 NAME: name of the repo
2843 URI: URI of the repo
2846 check_client_version(ctx
.obj
, ctx
.command
.name
)
2851 repo
['description'] = description
2852 ctx
.obj
.repo
.create(name
, repo
)
2853 # except ClientException as e:
2858 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
2859 @click.argument('name')
2860 @click.option('--newname', help='New name for the repo')
2861 @click.option('--uri', help='URI of the repo')
2862 @click.option('--type', type=click
.Choice(['helm-chart', 'juju-bundle']),
2863 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2864 @click.option('--description', help='human readable description')
2865 #@click.option('--wait',
2867 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2869 def repo_update(ctx
,
2875 """updates a repo in OSM
2877 NAME: name of the repo
2880 check_client_version(ctx
.obj
, ctx
.command
.name
)
2882 if newname
: repo
['name'] = newname
2883 if uri
: repo
['uri'] = uri
2884 if type: repo
['type'] = type
2885 if description
: repo
['description'] = description
2886 ctx
.obj
.repo
.update(name
, repo
)
2887 # except ClientException as e:
2892 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
2893 @click.argument('name')
2894 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2895 #@click.option('--wait',
2897 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2899 def repo_delete(ctx
, name
, force
):
2902 NAME: name or ID of the repo to be deleted
2905 check_client_version(ctx
.obj
, ctx
.command
.name
)
2906 ctx
.obj
.repo
.delete(name
, force
=force
)
2907 # except ClientException as e:
2912 @cli_osm.command(name
='repo-list')
2913 @click.option('--filter', default
=None,
2914 help='restricts the list to the repos matching the filter')
2915 @click.option('--literal', is_flag
=True,
2916 help='print literally, no pretty table')
2918 def repo_list(ctx
, filter, literal
):
2919 """list all repos"""
2921 check_client_version(ctx
.obj
, ctx
.command
.name
)
2922 resp
= ctx
.obj
.repo
.list(filter)
2924 print(yaml
.safe_dump(resp
))
2926 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
2928 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
2929 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description',''),40)])
2932 # except ClientException as e:
2937 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
2938 @click.argument('name')
2939 @click.option('--literal', is_flag
=True,
2940 help='print literally, no pretty table')
2942 def repo_show(ctx
, name
, literal
):
2943 """shows the details of a repo
2945 NAME: name or ID of the repo
2948 resp
= ctx
.obj
.repo
.get(name
)
2950 print(yaml
.safe_dump(resp
))
2952 table
= PrettyTable(['key', 'attribute'])
2953 for k
, v
in list(resp
.items()):
2954 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2957 # except ClientException as e:
2963 ####################
2964 # Project mgmt operations
2965 ####################
2967 @cli_osm.command(name
='project-create', short_help
='creates a new project')
2968 @click.argument('name')
2969 #@click.option('--description',
2970 # default='no description',
2971 # help='human readable description')
2973 def project_create(ctx
, name
):
2974 """Creates a new project
2976 NAME: name of the project
2980 project
['name'] = name
2982 check_client_version(ctx
.obj
, ctx
.command
.name
)
2983 ctx
.obj
.project
.create(name
, project
)
2984 # except ClientException as e:
2989 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
2990 @click.argument('name')
2991 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2993 def project_delete(ctx
, name
):
2994 """deletes a project
2996 NAME: name or ID of the project to be deleted
3000 check_client_version(ctx
.obj
, ctx
.command
.name
)
3001 ctx
.obj
.project
.delete(name
)
3002 # except ClientException as e:
3007 @cli_osm.command(name
='project-list', short_help
='list all projects')
3008 @click.option('--filter', default
=None,
3009 help='restricts the list to the projects matching the filter')
3011 def project_list(ctx
, filter):
3012 """list all projects"""
3015 check_client_version(ctx
.obj
, ctx
.command
.name
)
3016 resp
= ctx
.obj
.project
.list(filter)
3017 # except ClientException as e:
3020 table
= PrettyTable(['name', 'id'])
3022 table
.add_row([proj
['name'], proj
['_id']])
3027 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3028 @click.argument('name')
3030 def project_show(ctx
, name
):
3031 """shows the details of a project
3033 NAME: name or ID of the project
3037 check_client_version(ctx
.obj
, ctx
.command
.name
)
3038 resp
= ctx
.obj
.project
.get(name
)
3039 # except ClientException as e:
3043 table
= PrettyTable(['key', 'attribute'])
3044 for k
, v
in resp
.items():
3045 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3050 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3051 @click.argument('project')
3052 @click.option('--name',
3054 help='new name for the project')
3057 def project_update(ctx
, project
, name
):
3059 Update a project name
3062 :param project: id or name of the project to modify
3063 :param name: new name for the project
3067 project_changes
= {}
3068 project_changes
['name'] = name
3071 check_client_version(ctx
.obj
, ctx
.command
.name
)
3072 ctx
.obj
.project
.update(project
, project_changes
)
3073 # except ClientException as e:
3077 ####################
3078 # User mgmt operations
3079 ####################
3081 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3082 @click.argument('username')
3083 @click.option('--password',
3086 confirmation_prompt
=True,
3087 help='user password')
3088 @click.option('--projects',
3089 # prompt="Comma separate list of projects",
3091 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3092 help='list of project ids that the user belongs to')
3093 @click.option('--project-role-mappings', 'project_role_mappings',
3094 default
=None, multiple
=True,
3095 help='creating user project/role(s) mapping')
3097 def user_create(ctx
, username
, password
, projects
, project_role_mappings
):
3098 """Creates a new user
3101 USERNAME: name of the user
3102 PASSWORD: password of the user
3103 PROJECTS: projects assigned to user (internal only)
3104 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3108 user
['username'] = username
3109 user
['password'] = password
3110 user
['projects'] = projects
3111 user
['project_role_mappings'] = project_role_mappings
3114 check_client_version(ctx
.obj
, ctx
.command
.name
)
3115 ctx
.obj
.user
.create(username
, user
)
3116 # except ClientException as e:
3121 @cli_osm.command(name
='user-update', short_help
='updates user information')
3122 @click.argument('username')
3123 @click.option('--password',
3126 # confirmation_prompt=True,
3127 help='user password')
3128 @click.option('--set-username', 'set_username',
3130 help='change username')
3131 @click.option('--set-project', 'set_project',
3132 default
=None, multiple
=True,
3133 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
3134 @click.option('--remove-project', 'remove_project',
3135 default
=None, multiple
=True,
3136 help='removes project from user: \'project\'')
3137 @click.option('--add-project-role', 'add_project_role',
3138 default
=None, multiple
=True,
3139 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
3140 @click.option('--remove-project-role', 'remove_project_role',
3141 default
=None, multiple
=True,
3142 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
3144 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3145 add_project_role
, remove_project_role
):
3146 """Update a user information
3149 USERNAME: name of the user
3150 PASSWORD: new password
3151 SET_USERNAME: new username
3152 SET_PROJECT: creating mappings for project/role(s)
3153 REMOVE_PROJECT: deleting mappings for project/role(s)
3154 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3155 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3159 user
['password'] = password
3160 user
['username'] = set_username
3161 user
['set-project'] = set_project
3162 user
['remove-project'] = remove_project
3163 user
['add-project-role'] = add_project_role
3164 user
['remove-project-role'] = remove_project_role
3167 check_client_version(ctx
.obj
, ctx
.command
.name
)
3168 ctx
.obj
.user
.update(username
, user
)
3169 # except ClientException as e:
3174 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3175 @click.argument('name')
3176 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3178 def user_delete(ctx
, name
):
3182 NAME: name or ID of the user to be deleted
3186 check_client_version(ctx
.obj
, ctx
.command
.name
)
3187 ctx
.obj
.user
.delete(name
)
3188 # except ClientException as e:
3193 @cli_osm.command(name
='user-list', short_help
='list all users')
3194 @click.option('--filter', default
=None,
3195 help='restricts the list to the users matching the filter')
3197 def user_list(ctx
, filter):
3198 """list all users"""
3200 check_client_version(ctx
.obj
, ctx
.command
.name
)
3201 resp
= ctx
.obj
.user
.list(filter)
3202 # except ClientException as e:
3205 table
= PrettyTable(['name', 'id'])
3207 table
.add_row([user
['username'], user
['_id']])
3212 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3213 @click.argument('name')
3215 def user_show(ctx
, name
):
3216 """shows the details of a user
3218 NAME: name or ID of the user
3222 check_client_version(ctx
.obj
, ctx
.command
.name
)
3223 resp
= ctx
.obj
.user
.get(name
)
3224 if 'password' in resp
:
3225 resp
['password']='********'
3226 # except ClientException as e:
3230 table
= PrettyTable(['key', 'attribute'])
3231 for k
, v
in resp
.items():
3232 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3237 ####################
3238 # Fault Management operations
3239 ####################
3241 @cli_osm.command(name
='ns-alarm-create')
3242 @click.argument('name')
3243 @click.option('--ns', prompt
=True, help='NS instance id or name')
3244 @click.option('--vnf', prompt
=True,
3245 help='VNF name (VNF member index as declared in the NSD)')
3246 @click.option('--vdu', prompt
=True,
3247 help='VDU name (VDU name as declared in the VNFD)')
3248 @click.option('--metric', prompt
=True,
3249 help='Name of the metric (e.g. cpu_utilization)')
3250 @click.option('--severity', default
='WARNING',
3251 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3252 @click.option('--threshold_value', prompt
=True,
3253 help='threshold value that, when crossed, an alarm is triggered')
3254 @click.option('--threshold_operator', prompt
=True,
3255 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3256 @click.option('--statistic', default
='AVERAGE',
3257 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3259 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3260 threshold_value
, threshold_operator
, statistic
):
3261 """creates a new alarm for a NS instance"""
3262 # TODO: Check how to validate threshold_value.
3263 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3266 ns_instance
= ctx
.obj
.ns
.get(ns
)
3268 alarm
['alarm_name'] = name
3269 alarm
['ns_id'] = ns_instance
['_id']
3270 alarm
['correlation_id'] = ns_instance
['_id']
3271 alarm
['vnf_member_index'] = vnf
3272 alarm
['vdu_name'] = vdu
3273 alarm
['metric_name'] = metric
3274 alarm
['severity'] = severity
3275 alarm
['threshold_value'] = int(threshold_value
)
3276 alarm
['operation'] = threshold_operator
3277 alarm
['statistic'] = statistic
3278 check_client_version(ctx
.obj
, ctx
.command
.name
)
3279 ctx
.obj
.ns
.create_alarm(alarm
)
3280 # except ClientException as e:
3285 #@cli_osm.command(name='ns-alarm-delete')
3286 #@click.argument('name')
3287 #@click.pass_context
3288 #def ns_alarm_delete(ctx, name):
3289 # """deletes an alarm
3291 # NAME: name of the alarm to be deleted
3294 # check_client_version(ctx.obj, ctx.command.name)
3295 # ctx.obj.ns.delete_alarm(name)
3296 # except ClientException as e:
3301 ####################
3302 # Performance Management operations
3303 ####################
3305 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3306 @click.option('--ns', prompt
=True, help='NS instance id or name')
3307 @click.option('--vnf', prompt
=True,
3308 help='VNF name (VNF member index as declared in the NSD)')
3309 @click.option('--vdu', prompt
=True,
3310 help='VDU name (VDU name as declared in the VNFD)')
3311 @click.option('--metric', prompt
=True,
3312 help='name of the metric (e.g. cpu_utilization)')
3313 #@click.option('--period', default='1w',
3314 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3315 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3317 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3318 """exports a metric to the internal OSM bus, which can be read by other apps"""
3319 # TODO: Check how to validate interval.
3320 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3323 ns_instance
= ctx
.obj
.ns
.get(ns
)
3325 metric_data
['ns_id'] = ns_instance
['_id']
3326 metric_data
['correlation_id'] = ns_instance
['_id']
3327 metric_data
['vnf_member_index'] = vnf
3328 metric_data
['vdu_name'] = vdu
3329 metric_data
['metric_name'] = metric
3330 metric_data
['collection_unit'] = 'WEEK'
3331 metric_data
['collection_period'] = 1
3332 check_client_version(ctx
.obj
, ctx
.command
.name
)
3334 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3338 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3339 time
.sleep(int(interval
))
3341 # except ClientException as e:
3346 ####################
3348 ####################
3350 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3352 def get_version(ctx
):
3353 """shows client and server versions"""
3355 check_client_version(ctx
.obj
, "version")
3356 print ("Server version: {}".format(ctx
.obj
.get_version()))
3357 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3358 # except ClientException as e:
3362 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3363 @click.argument('filename')
3364 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3365 help='the charm will not be compiled, it is assumed to already exist')
3367 def upload_package(ctx
, filename
, skip_charm_build
):
3368 """uploads a vnf package or ns package
3370 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3374 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3375 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3376 if fullclassname
!= 'osmclient.sol005.client.Client':
3377 ctx
.obj
.package
.wait_for_upload(filename
)
3378 # except ClientException as e:
3383 #@cli_osm.command(name='ns-scaling-show')
3384 #@click.argument('ns_name')
3385 #@click.pass_context
3386 #def show_ns_scaling(ctx, ns_name):
3387 # """shows the status of a NS scaling operation
3389 # NS_NAME: name of the NS instance being scaled
3392 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3393 # resp = ctx.obj.ns.list()
3394 # except ClientException as e:
3398 # table = PrettyTable(
3401 # 'operational status',
3406 # if ns_name == ns['name']:
3407 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3408 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3409 # for record in scaling_records:
3410 # if 'instance' in record:
3411 # instances = record['instance']
3412 # for inst in instances:
3414 # [record['scaling-group-name-ref'],
3415 # inst['instance-id'],
3416 # inst['op-status'],
3417 # time.strftime('%Y-%m-%d %H:%M:%S',
3419 # inst['create-time'])),
3425 #@cli_osm.command(name='ns-scale')
3426 #@click.argument('ns_name')
3427 #@click.option('--ns_scale_group', prompt=True)
3428 #@click.option('--index', prompt=True)
3429 #@click.option('--wait',
3433 # help='do not return the control immediately, but keep it \
3434 # until the operation is completed, or timeout')
3435 #@click.pass_context
3436 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3439 # NS_NAME: name of the NS instance to be scaled
3442 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3443 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3444 # except ClientException as e:
3449 #@cli_osm.command(name='config-agent-list')
3450 #@click.pass_context
3451 #def config_agent_list(ctx):
3452 # """list config agents"""
3454 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3455 # except ClientException as e:
3458 # table = PrettyTable(['name', 'account-type', 'details'])
3459 # for account in ctx.obj.vca.list():
3462 # account['account-type'],
3468 #@cli_osm.command(name='config-agent-delete')
3469 #@click.argument('name')
3470 #@click.pass_context
3471 #def config_agent_delete(ctx, name):
3472 # """deletes a config agent
3474 # NAME: name of the config agent to be deleted
3477 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3478 # ctx.obj.vca.delete(name)
3479 # except ClientException as e:
3484 #@cli_osm.command(name='config-agent-add')
3485 #@click.option('--name',
3487 #@click.option('--account_type',
3489 #@click.option('--server',
3491 #@click.option('--user',
3493 #@click.option('--secret',
3496 # confirmation_prompt=True)
3497 #@click.pass_context
3498 #def config_agent_add(ctx, name, account_type, server, user, secret):
3499 # """adds a config agent"""
3501 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3502 # ctx.obj.vca.create(name, account_type, server, user, secret)
3503 # except ClientException as e:
3508 #@cli_osm.command(name='ro-dump')
3509 #@click.pass_context
3511 # """shows RO agent information"""
3512 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3513 # resp = ctx.obj.vim.get_resource_orchestrator()
3514 # table = PrettyTable(['key', 'attribute'])
3515 # for k, v in list(resp.items()):
3516 # table.add_row([k, json.dumps(v, indent=2)])
3521 #@cli_osm.command(name='vcs-list')
3522 #@click.pass_context
3524 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3525 # resp = ctx.obj.utils.get_vcs_info()
3526 # table = PrettyTable(['component name', 'state'])
3527 # for component in resp:
3528 # table.add_row([component['component_name'], component['state']])
3533 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3534 @click.argument('ns_name')
3535 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3536 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3537 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3538 @click.option('--vdu_count', default
=None, help='number of vdu instance of this vdu_id')
3539 @click.option('--action_name', prompt
=True, help='action name')
3540 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3541 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3542 @click.option('--wait',
3546 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3558 """executes an action/primitive over a NS instance
3560 NS_NAME: name or ID of the NS instance
3564 check_client_version(ctx
.obj
, ctx
.command
.name
)
3567 op_data
['member_vnf_index'] = vnf_name
3569 op_data
['kdu_name'] = kdu_name
3571 op_data
['vdu_id'] = vdu_id
3573 op_data
['vdu_count_index'] = vdu_count
3574 op_data
['primitive'] = action_name
3576 with
open(params_file
, 'r') as pf
:
3579 op_data
['primitive_params'] = yaml
.safe_load(params
)
3581 op_data
['primitive_params'] = {}
3582 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
3584 # except ClientException as e:
3589 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
3590 @click.argument('ns_name')
3591 @click.argument('vnf_name')
3592 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
3593 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
3594 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
3603 Executes a VNF scale (adding/removing VDUs)
3606 NS_NAME: name or ID of the NS instance.
3607 VNF_NAME: member-vnf-index in the NS to be scaled.
3611 check_client_version(ctx
.obj
, ctx
.command
.name
)
3612 if not scale_in
and not scale_out
:
3614 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
)
3615 # except ClientException as e:
3620 ##############################
3621 # Role Management Operations #
3622 ##############################
3624 @cli_osm.command(name
='role-create', short_help
='creates a new role')
3625 @click.argument('name')
3626 @click.option('--permissions',
3628 help='role permissions using a dictionary')
3630 def role_create(ctx
, name
, permissions
):
3635 NAME: Name or ID of the role.
3636 DEFINITION: Definition of grant/denial of access to resources.
3640 check_client_version(ctx
.obj
, ctx
.command
.name
)
3641 ctx
.obj
.role
.create(name
, permissions
)
3642 # except ClientException as e:
3647 @cli_osm.command(name
='role-update', short_help
='updates a role')
3648 @click.argument('name')
3649 @click.option('--set-name',
3651 help='change name of rle')
3652 # @click.option('--permissions',
3654 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
3655 @click.option('--add',
3657 help='yaml format dictionary with permission: True/False to access grant/denial')
3658 @click.option('--remove',
3660 help='yaml format list to remove a permission')
3662 def role_update(ctx
, name
, set_name
, add
, remove
):
3667 NAME: Name or ID of the role.
3668 DEFINITION: Definition overwrites the old definition.
3669 ADD: Grant/denial of access to resource to add.
3670 REMOVE: Grant/denial of access to resource to remove.
3674 check_client_version(ctx
.obj
, ctx
.command
.name
)
3675 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
3676 # except ClientException as e:
3681 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
3682 @click.argument('name')
3683 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3685 def role_delete(ctx
, name
):
3690 NAME: Name or ID of the role.
3694 check_client_version(ctx
.obj
, ctx
.command
.name
)
3695 ctx
.obj
.role
.delete(name
)
3696 # except ClientException as e:
3701 @cli_osm.command(name
='role-list', short_help
='list all roles')
3702 @click.option('--filter', default
=None,
3703 help='restricts the list to the projects matching the filter')
3705 def role_list(ctx
, filter):
3711 check_client_version(ctx
.obj
, ctx
.command
.name
)
3712 resp
= ctx
.obj
.role
.list(filter)
3713 # except ClientException as e:
3716 table
= PrettyTable(['name', 'id'])
3718 table
.add_row([role
['name'], role
['_id']])
3723 @cli_osm.command(name
='role-show', short_help
='show specific role')
3724 @click.argument('name')
3726 def role_show(ctx
, name
):
3728 Shows the details of a role.
3731 NAME: Name or ID of the role.
3735 check_client_version(ctx
.obj
, ctx
.command
.name
)
3736 resp
= ctx
.obj
.role
.get(name
)
3737 # except ClientException as e:
3741 table
= PrettyTable(['key', 'attribute'])
3742 for k
, v
in resp
.items():
3743 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3748 @cli_osm.command(name
='package-create',
3749 short_help
='Create a package descriptor')
3750 @click.argument('package-type')
3751 @click.argument('package-name')
3752 @click.option('--base-directory',
3754 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
3755 @click.option('--image',
3756 default
="image-name",
3757 help='(VNF) Set the name of the vdu image. Default "image-name"')
3758 @click.option('--vdus',
3760 help='(VNF) Set the number of vdus in a VNF. Default 1')
3761 @click.option('--vcpu',
3763 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
3764 @click.option('--memory',
3766 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
3767 @click.option('--storage',
3769 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
3770 @click.option('--interfaces',
3772 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
3773 @click.option('--vendor',
3775 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
3776 @click.option('--override',
3779 help='(NS/VNF/NST) Flag for overriding the package if exists.')
3780 @click.option('--detailed',
3783 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
3784 @click.option('--netslice-subnets',
3786 help='(NST) Number of netslice subnets. Default 1')
3787 @click.option('--netslice-vlds',
3789 help='(NST) Number of netslice vlds. Default 1')
3791 def package_create(ctx
,
3807 Creates an OSM NS, VNF, NST package
3810 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
3811 PACKAGE_NAME: Name of the package to create the folder with the content.
3815 check_client_version(ctx
.obj
, ctx
.command
.name
)
3816 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
3817 resp
= ctx
.obj
.package_tool
.create(package_type
,
3826 interfaces
=interfaces
,
3829 netslice_subnets
=netslice_subnets
,
3830 netslice_vlds
=netslice_vlds
)
3832 # except ClientException as inst:
3833 # print("ERROR: {}".format(inst))
3836 @cli_osm.command(name
='package-validate',
3837 short_help
='Validate a package descriptor')
3838 @click.argument('base-directory',
3841 @click.option('--recursive/--no-recursive',
3843 help='The activated recursive option will validate the yaml files'
3844 ' within the indicated directory and in its subdirectories')
3846 def package_validate(ctx
,
3850 Validate descriptors given a base directory.
3853 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
3856 check_client_version(ctx
.obj
, ctx
.command
.name
)
3857 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
3858 table
= PrettyTable()
3859 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
3860 # Print the dictionary generated by the validation function
3861 for result
in results
:
3862 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
3863 table
.sortby
= "VALID"
3864 table
.align
["PATH"] = "l"
3865 table
.align
["TYPE"] = "l"
3866 table
.align
["ERROR"] = "l"
3868 # except ClientException as inst:
3869 # print("ERROR: {}".format(inst))
3872 @cli_osm.command(name
='package-build',
3873 short_help
='Build the tar.gz of the package')
3874 @click.argument('package-folder')
3875 @click.option('--skip-validation',
3878 help='skip package validation')
3879 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3880 help='the charm will not be compiled, it is assumed to already exist')
3882 def package_build(ctx
,
3887 Build the package NS, VNF given the package_folder.
3890 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
3893 check_client_version(ctx
.obj
, ctx
.command
.name
)
3894 results
= ctx
.obj
.package_tool
.build(package_folder
,
3895 skip_validation
=skip_validation
,
3896 skip_charm_build
=skip_charm_build
)
3898 # except ClientException as inst:
3899 # print("ERROR: {}".format(inst))
3907 except pycurl
.error
as exc
:
3909 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
3910 except ClientException
as exc
:
3911 print("ERROR: {}".format(exc
))
3912 except (FileNotFoundError
, PermissionError
) as exc
:
3913 print("Cannot open file: {}".format(exc
))
3914 except yaml
.YAMLError
as exc
:
3915 print("Invalid YAML format: {}".format(exc
))
3917 # TODO capture other controlled exceptions here
3918 # TODO remove the ClientException captures from all places, unless they do something different
3921 if __name__
== '__main__':