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):
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':
553 name
= vnfr
['name'] if 'name' in vnfr
else '-'
558 vnfr
['member-vnf-index-ref'],
560 vnfr
['vim-account-id'],
566 'operational status',
569 if 'mgmt-interface' not in vnfr
:
570 vnfr
['mgmt-interface'] = {}
571 vnfr
['mgmt-interface']['ip-address'] = None
575 vnfr
['operational-status'],
576 vnfr
['config-status']])
581 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
582 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
583 @click.option('--filter', default
=None,
584 help='restricts the list to the NF instances matching the filter.')
586 def vnf_list1(ctx
, ns
, filter):
587 """list all NF instances"""
589 vnf_list(ctx
, ns
, filter)
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.')
597 def nf_list(ctx
, ns
, filter):
598 """list all NF instances
602 --ns TEXT NS instance id or name to restrict the VNF list
603 --filter filterExpr Restricts the list to the VNF instances matching the filter
606 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
607 concatenated using the "&" character:
610 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
611 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
612 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
614 value := scalar value
618 * zero or more occurrences
619 ? zero or one occurrence
620 [] grouping of expressions to be used with ? and *
621 "" quotation marks for marking string constants
625 "AttrName" is the name of one attribute in the data type that defines the representation
626 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
627 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
628 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
629 entries, it means that the operator "op" is applied to the attribute addressed by the last
630 <attrName> entry included in the concatenation. All simple filter expressions are combined
631 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
632 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
633 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
634 prefix". If an attribute referenced in an expression is an array, an object that contains a
635 corresponding array shall be considered to match the expression if any of the elements in the
636 array matches all expressions that have the same attribute prefix.
640 --filter vim-account-id=<VIM_ACCOUNT_ID>
641 --filter vnfd-ref=<VNFD_NAME>
642 --filter vdur.ip-address=<IP_ADDRESS>
643 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
646 vnf_list(ctx
, ns
, filter)
649 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
650 @click.argument('name')
651 @click.option('--long', is_flag
=True,
652 help='get more details of the NS operation (date, ).')
654 def ns_op_list(ctx
, name
, long):
655 """shows the history of operations over a NS instance
657 NAME: name or ID of the NS instance
659 def formatParams(params
):
660 if params
['lcmOperationType']=='instantiate':
661 params
.pop('nsDescription')
665 elif params
['lcmOperationType']=='action':
666 params
.pop('primitive')
667 params
.pop('lcmOperationType')
668 params
.pop('nsInstanceId')
673 check_client_version(ctx
.obj
, ctx
.command
.name
)
674 resp
= ctx
.obj
.ns
.list_op(name
)
675 # except ClientException as e:
680 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
682 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
684 #print(yaml.safe_dump(resp))
687 if op
['lcmOperationType']=='action':
688 action_name
= op
['operationParams']['primitive']
690 if op
['operationState']=='PROCESSING':
691 if op
['lcmOperationType']=='instantiate':
695 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
696 elif op
['operationState']=='FAILED' or op
['operationState']=='FAILED_TEMP':
697 detail
= op
['errorMessage']
698 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
699 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
701 table
.add_row([op
['id'],
702 op
['lcmOperationType'],
704 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
705 op
['operationState'],
708 wrap_text(text
=detail
,width
=50)])
710 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
711 op
['operationState'], date
, wrap_text(text
=detail
,width
=50)])
716 def nsi_list(ctx
, filter):
717 """list all Network Slice Instances"""
720 check_client_version(ctx
.obj
, ctx
.command
.name
)
721 resp
= ctx
.obj
.nsi
.list(filter)
722 # except ClientException as e:
726 ['netslice instance name',
728 'operational status',
732 nsi_name
= nsi
['name']
734 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
735 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
736 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
737 if configstatus
== "config_not_needed":
738 configstatus
= "configured (no charms)"
749 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
750 @click.option('--filter', default
=None,
751 help='restricts the list to the Network Slice Instances matching the filter')
753 def nsi_list1(ctx
, filter):
754 """list all Network Slice Instances (NSI)"""
756 nsi_list(ctx
, filter)
759 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
760 @click.option('--filter', default
=None,
761 help='restricts the list to the Network Slice Instances matching the filter')
763 def nsi_list2(ctx
, filter):
764 """list all Network Slice Instances (NSI)"""
766 nsi_list(ctx
, filter)
769 def nst_list(ctx
, filter):
772 check_client_version(ctx
.obj
, ctx
.command
.name
)
773 resp
= ctx
.obj
.nst
.list(filter)
774 # except ClientException as e:
777 # print(yaml.safe_dump(resp))
778 table
= PrettyTable(['nst name', 'id'])
780 name
= nst
['name'] if 'name' in nst
else '-'
781 table
.add_row([name
, nst
['_id']])
786 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
787 @click.option('--filter', default
=None,
788 help='restricts the list to the NST matching the filter')
790 def nst_list1(ctx
, filter):
791 """list all Network Slice Templates (NST) in the system"""
793 nst_list(ctx
, filter)
796 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
797 @click.option('--filter', default
=None,
798 help='restricts the list to the NST matching the filter')
800 def nst_list2(ctx
, filter):
801 """list all Network Slice Templates (NST) in the system"""
803 nst_list(ctx
, filter)
806 def nsi_op_list(ctx
, name
):
809 check_client_version(ctx
.obj
, ctx
.command
.name
)
810 resp
= ctx
.obj
.nsi
.list_op(name
)
811 # except ClientException as e:
814 table
= PrettyTable(['id', 'operation', 'status'])
816 table
.add_row([op
['id'], op
['lcmOperationType'],
817 op
['operationState']])
822 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
823 @click.argument('name')
825 def nsi_op_list1(ctx
, name
):
826 """shows the history of operations over a Network Slice Instance (NSI)
828 NAME: name or ID of the Network Slice Instance
831 nsi_op_list(ctx
, name
)
834 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
835 @click.argument('name')
837 def nsi_op_list2(ctx
, name
):
838 """shows the history of operations over a Network Slice Instance (NSI)
840 NAME: name or ID of the Network Slice Instance
843 nsi_op_list(ctx
, name
)
846 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
847 @click.option('--filter', default
=None,
848 help='restricts the list to the Physical Deployment Units matching the filter')
850 def pdu_list(ctx
, filter):
851 """list all Physical Deployment Units (PDU)"""
854 check_client_version(ctx
.obj
, ctx
.command
.name
)
855 resp
= ctx
.obj
.pdu
.list(filter)
856 # except ClientException as e:
865 pdu_name
= pdu
['name']
867 pdu_type
= pdu
['type']
868 pdu_ipaddress
= "None"
869 for iface
in pdu
['interfaces']:
871 pdu_ipaddress
= iface
['ip-address']
886 def nsd_show(ctx
, name
, literal
):
889 resp
= ctx
.obj
.nsd
.get(name
)
890 # resp = ctx.obj.nsd.get_individual(name)
891 # except ClientException as e:
896 print(yaml
.safe_dump(resp
))
899 table
= PrettyTable(['field', 'value'])
900 for k
, v
in list(resp
.items()):
901 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
906 @cli_osm.command(name
='nsd-show', short_help
='shows the content of a NSD')
907 @click.option('--literal', is_flag
=True,
908 help='print literally, no pretty table')
909 @click.argument('name')
911 def nsd_show1(ctx
, name
, literal
):
912 """shows the content of a NSD
914 NAME: name or ID of the NSD/NSpkg
917 nsd_show(ctx
, name
, literal
)
920 @cli_osm.command(name
='nspkg-show', short_help
='shows the content of a NSD')
921 @click.option('--literal', is_flag
=True,
922 help='print literally, no pretty table')
923 @click.argument('name')
925 def nsd_show2(ctx
, name
, literal
):
926 """shows the content of a NSD
928 NAME: name or ID of the NSD/NSpkg
931 nsd_show(ctx
, name
, literal
)
934 def vnfd_show(ctx
, name
, literal
):
937 resp
= ctx
.obj
.vnfd
.get(name
)
938 # resp = ctx.obj.vnfd.get_individual(name)
939 # except ClientException as e:
944 print(yaml
.safe_dump(resp
))
947 table
= PrettyTable(['field', 'value'])
948 for k
, v
in list(resp
.items()):
949 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
954 @cli_osm.command(name
='vnfd-show', short_help
='shows the content of a VNFD')
955 @click.option('--literal', is_flag
=True,
956 help='print literally, no pretty table')
957 @click.argument('name')
959 def vnfd_show1(ctx
, name
, literal
):
960 """shows the content of a VNFD
962 NAME: name or ID of the VNFD/VNFpkg
965 vnfd_show(ctx
, name
, literal
)
968 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the content of a VNFD')
969 @click.option('--literal', is_flag
=True,
970 help='print literally, no pretty table')
971 @click.argument('name')
973 def vnfd_show2(ctx
, name
, literal
):
974 """shows the content of a VNFD
976 NAME: name or ID of the VNFD/VNFpkg
979 vnfd_show(ctx
, name
, literal
)
982 @cli_osm.command(name
='nfpkg-show', short_help
='shows the content of a NF Descriptor')
983 @click.option('--literal', is_flag
=True,
984 help='print literally, no pretty table')
985 @click.argument('name')
987 def nfpkg_show(ctx
, name
, literal
):
988 """shows the content of a NF Descriptor
990 NAME: name or ID of the NFpkg
993 vnfd_show(ctx
, name
, literal
)
996 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
997 @click.argument('name')
998 @click.option('--literal', is_flag
=True,
999 help='print literally, no pretty table')
1000 @click.option('--filter', default
=None)
1002 def ns_show(ctx
, name
, literal
, filter):
1003 """shows the info of a NS instance
1005 NAME: name or ID of the NS instance
1009 ns
= ctx
.obj
.ns
.get(name
)
1010 # except ClientException as e:
1015 print(yaml
.safe_dump(ns
))
1018 table
= PrettyTable(['field', 'value'])
1020 for k
, v
in list(ns
.items()):
1021 if filter is None or filter in k
:
1022 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1024 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1025 if fullclassname
!= 'osmclient.sol005.client.Client':
1026 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1027 nsr_optdata
= nsopdata
['nsr:nsr']
1028 for k
, v
in list(nsr_optdata
.items()):
1029 if filter is None or filter in k
:
1030 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1035 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1036 @click.argument('name')
1037 @click.option('--literal', is_flag
=True,
1038 help='print literally, no pretty table')
1039 @click.option('--filter', default
=None, help='restricts the information to the fields in the filter')
1040 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1042 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1043 """shows the info of a VNF instance
1045 NAME: name or ID of the VNF instance
1047 def print_kdu_status(op_info_status
):
1048 """print KDU status properly formatted
1051 op_status
= yaml
.safe_load(op_info_status
)
1052 if "namespace" in op_status
and "info" in op_status
and \
1053 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1054 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1055 "notes" in op_status
["info"]["status"] and "seconds" in op_status
["info"]["last_deployed"]:
1056 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1057 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1058 print("NAMESPACE: {}".format(op_status
["namespace"]))
1059 status_code
= "UNKNOWN"
1060 if op_status
["info"]["status"]["code"]==1:
1061 status_code
= "DEPLOYED"
1062 print("STATUS: {}".format(status_code
))
1065 print(op_status
["info"]["status"]["resources"])
1067 print(op_status
["info"]["status"]["notes"])
1069 print(op_info_status
)
1071 print(op_info_status
)
1076 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1078 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1081 check_client_version(ctx
.obj
, ctx
.command
.name
)
1082 resp
= ctx
.obj
.vnf
.get(name
)
1085 ns_id
= resp
['nsr-id-ref']
1087 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1088 op_data
['kdu_name'] = kdu
1089 op_data
['primitive'] = 'status'
1090 op_data
['primitive_params'] = {}
1091 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1094 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1095 if op_info
['operationState'] == 'COMPLETED':
1096 print_kdu_status(op_info
['detailed-status'])
1100 print ("Could not determine KDU status")
1103 print(yaml
.safe_dump(resp
))
1106 table
= PrettyTable(['field', 'value'])
1108 for k
, v
in list(resp
.items()):
1109 if filter is None or filter in k
:
1110 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1113 # except ClientException as e:
1118 #@cli_osm.command(name='vnf-monitoring-show')
1119 #@click.argument('vnf_name')
1120 #@click.pass_context
1121 #def vnf_monitoring_show(ctx, vnf_name):
1123 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1124 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1125 # except ClientException as e:
1129 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1130 # if resp is not None:
1131 # for monitor in resp:
1135 # monitor['value-integer'],
1136 # monitor['units']])
1141 #@cli_osm.command(name='ns-monitoring-show')
1142 #@click.argument('ns_name')
1143 #@click.pass_context
1144 #def ns_monitoring_show(ctx, ns_name):
1146 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1147 # resp = ctx.obj.ns.get_monitoring(ns_name)
1148 # except ClientException as e:
1152 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1153 # for key, val in list(resp.items()):
1154 # for monitor in val:
1158 # monitor['value-integer'],
1159 # monitor['units']])
1164 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1165 @click.argument('id')
1166 @click.option('--filter', default
=None)
1167 @click.option('--literal', is_flag
=True,
1168 help='print literally, no pretty table')
1170 def ns_op_show(ctx
, id, filter, literal
):
1171 """shows the detailed info of a NS operation
1173 ID: operation identifier
1177 check_client_version(ctx
.obj
, ctx
.command
.name
)
1178 op_info
= ctx
.obj
.ns
.get_op(id)
1179 # except ClientException as e:
1184 print(yaml
.safe_dump(op_info
))
1187 table
= PrettyTable(['field', 'value'])
1188 for k
, v
in list(op_info
.items()):
1189 if filter is None or filter in k
:
1190 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1195 def nst_show(ctx
, name
, literal
):
1198 check_client_version(ctx
.obj
, ctx
.command
.name
)
1199 resp
= ctx
.obj
.nst
.get(name
)
1200 #resp = ctx.obj.nst.get_individual(name)
1201 # except ClientException as e:
1206 print(yaml
.safe_dump(resp
))
1209 table
= PrettyTable(['field', 'value'])
1210 for k
, v
in list(resp
.items()):
1211 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1216 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1217 @click.option('--literal', is_flag
=True,
1218 help='print literally, no pretty table')
1219 @click.argument('name')
1221 def nst_show1(ctx
, name
, literal
):
1222 """shows the content of a Network Slice Template (NST)
1224 NAME: name or ID of the NST
1227 nst_show(ctx
, name
, literal
)
1230 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1231 @click.option('--literal', is_flag
=True,
1232 help='print literally, no pretty table')
1233 @click.argument('name')
1235 def nst_show2(ctx
, name
, literal
):
1236 """shows the content of a Network Slice Template (NST)
1238 NAME: name or ID of the NST
1241 nst_show(ctx
, name
, literal
)
1244 def nsi_show(ctx
, name
, literal
, filter):
1247 check_client_version(ctx
.obj
, ctx
.command
.name
)
1248 nsi
= ctx
.obj
.nsi
.get(name
)
1249 # except ClientException as e:
1254 print(yaml
.safe_dump(nsi
))
1257 table
= PrettyTable(['field', 'value'])
1259 for k
, v
in list(nsi
.items()):
1260 if filter is None or filter in k
:
1261 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1267 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1268 @click.argument('name')
1269 @click.option('--literal', is_flag
=True,
1270 help='print literally, no pretty table')
1271 @click.option('--filter', default
=None)
1273 def nsi_show1(ctx
, name
, literal
, filter):
1274 """shows the content of a Network Slice Instance (NSI)
1276 NAME: name or ID of the Network Slice Instance
1279 nsi_show(ctx
, name
, literal
, filter)
1282 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1283 @click.argument('name')
1284 @click.option('--literal', is_flag
=True,
1285 help='print literally, no pretty table')
1286 @click.option('--filter', default
=None)
1288 def nsi_show2(ctx
, name
, literal
, filter):
1289 """shows the content of a Network Slice Instance (NSI)
1291 NAME: name or ID of the Network Slice Instance
1294 nsi_show(ctx
, name
, literal
, filter)
1297 def nsi_op_show(ctx
, id, filter):
1300 check_client_version(ctx
.obj
, ctx
.command
.name
)
1301 op_info
= ctx
.obj
.nsi
.get_op(id)
1302 # except ClientException as e:
1306 table
= PrettyTable(['field', 'value'])
1307 for k
, v
in list(op_info
.items()):
1308 if filter is None or filter in k
:
1309 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1314 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1315 @click.argument('id')
1316 @click.option('--filter', default
=None)
1318 def nsi_op_show1(ctx
, id, filter):
1319 """shows the info of an operation over a Network Slice Instance(NSI)
1321 ID: operation identifier
1324 nsi_op_show(ctx
, id, filter)
1327 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1328 @click.argument('id')
1329 @click.option('--filter', default
=None)
1331 def nsi_op_show2(ctx
, id, filter):
1332 """shows the info of an operation over a Network Slice Instance(NSI)
1334 ID: operation identifier
1337 nsi_op_show(ctx
, id, filter)
1340 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1341 @click.argument('name')
1342 @click.option('--literal', is_flag
=True,
1343 help='print literally, no pretty table')
1344 @click.option('--filter', default
=None)
1346 def pdu_show(ctx
, name
, literal
, filter):
1347 """shows the content of a Physical Deployment Unit (PDU)
1349 NAME: name or ID of the PDU
1353 check_client_version(ctx
.obj
, ctx
.command
.name
)
1354 pdu
= ctx
.obj
.pdu
.get(name
)
1355 # except ClientException as e:
1360 print(yaml
.safe_dump(pdu
))
1363 table
= PrettyTable(['field', 'value'])
1365 for k
, v
in list(pdu
.items()):
1366 if filter is None or filter in k
:
1367 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1373 ####################
1375 ####################
1377 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
):
1380 check_client_version(ctx
.obj
, ctx
.command
.name
)
1381 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1382 # except ClientException as e:
1387 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1388 @click.argument('filename')
1389 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1390 help='Deprecated. Use override')
1391 @click.option('--override', 'overwrite', default
=None,
1392 help='overrides fields in descriptor, format: '
1393 '"key1.key2...=value[;key3...=value;...]"')
1394 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1395 help='The charm will not be compiled, it is assumed to already exist')
1397 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
):
1398 """creates a new NSD/NSpkg
1400 FILENAME: NSD yaml file or NSpkg tar.gz file
1403 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1406 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1407 @click.argument('filename')
1408 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1409 help='Deprecated. Use override')
1410 @click.option('--override', 'overwrite', default
=None,
1411 help='overrides fields in descriptor, format: '
1412 '"key1.key2...=value[;key3...=value;...]"')
1413 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1414 help='The charm will not be compiled, it is assumed to already exist')
1416 def nsd_create2(ctx
, charm_folder
, overwrite
, skip_charm_build
):
1417 """creates a new NSD/NSpkg
1419 FILENAME: NSD folder, NSD yaml file or NSpkg tar.gz file
1422 nsd_create(ctx
, charm_folder
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1425 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
):
1428 check_client_version(ctx
.obj
, ctx
.command
.name
)
1429 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1430 # except ClientException as e:
1435 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1436 @click.argument('filename')
1437 @click.option('--overwrite', 'overwrite', default
=None,
1438 help='overwrite deprecated, use override')
1439 @click.option('--override', 'overwrite', default
=None,
1440 help='overrides fields in descriptor, format: '
1441 '"key1.key2...=value[;key3...=value;...]"')
1442 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1443 help='The charm will not be compiled, it is assumed to already exist')
1445 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
):
1446 """creates a new VNFD/VNFpkg
1448 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1451 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1454 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1455 @click.argument('filename')
1456 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1457 help='Deprecated. Use override')
1458 @click.option('--override', 'overwrite', default
=None,
1459 help='overrides fields in descriptor, format: '
1460 '"key1.key2...=value[;key3...=value;...]"')
1461 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1462 help='The charm will not be compiled, it is assumed to already exist')
1464 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
):
1465 """creates a new VNFD/VNFpkg
1467 FILENAME: NF Package Folder, NF Descriptor yaml file or NFpkg tar.gz file
1470 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1473 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1474 @click.argument('filename')
1475 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1476 help='Deprecated. Use override')
1477 @click.option('--override', 'overwrite', default
=None,
1478 help='overrides fields in descriptor, format: '
1479 '"key1.key2...=value[;key3...=value;...]"')
1480 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1481 help='The charm will not be compiled, it is assumed to already exist')
1483 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
):
1484 """creates a new NFpkg
1486 FILENAME: NF Package Folder, NF Descriptor yaml file or NFpkg tar.gz filems to build
1489 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1492 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1493 @click.option('--ns_name',
1494 prompt
=True, help='name of the NS instance')
1495 @click.option('--nsd_name',
1496 prompt
=True, help='name of the NS descriptor')
1497 @click.option('--vim_account',
1498 prompt
=True, help='default VIM account id or name for the deployment')
1499 @click.option('--admin_status',
1501 help='administration status')
1502 @click.option('--ssh_keys',
1504 help='comma separated list of public key files to inject to vnfs')
1505 @click.option('--config',
1507 help='ns specific yaml configuration')
1508 @click.option('--config_file',
1510 help='ns specific yaml configuration file')
1511 @click.option('--wait',
1515 help='do not return the control immediately, but keep it '
1516 'until the operation is completed, or timeout')
1527 """creates a new NS instance"""
1531 check_client_version(ctx
.obj
, '--config_file')
1533 raise ClientException('"--config" option is incompatible with "--config_file" option')
1534 with
open(config_file
, 'r') as cf
:
1541 account
=vim_account
,
1543 # except ClientException as e:
1548 def nst_create(ctx
, filename
, overwrite
):
1551 check_client_version(ctx
.obj
, ctx
.command
.name
)
1552 ctx
.obj
.nst
.create(filename
, overwrite
)
1553 # except ClientException as e:
1558 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1559 @click.argument('filename')
1560 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1561 help='Deprecated. Use override')
1562 @click.option('--override', 'overwrite', default
=None,
1563 help='overrides fields in descriptor, format: '
1564 '"key1.key2...=value[;key3...=value;...]"')
1566 def nst_create1(ctx
, charm_folder
, overwrite
):
1567 """creates a new Network Slice Template (NST)
1569 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1572 nst_create(ctx
, charm_folder
, overwrite
)
1575 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1576 @click.argument('filename')
1577 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1578 help='Deprecated. Use override')
1579 @click.option('--override', 'overwrite', default
=None,
1580 help='overrides fields in descriptor, format: '
1581 '"key1.key2...=value[;key3...=value;...]"')
1583 def nst_create2(ctx
, filename
, overwrite
):
1584 """creates a new Network Slice Template (NST)
1586 FILENAME: NST yaml file or NSTpkg tar.gz file
1589 nst_create(ctx
, filename
, overwrite
)
1592 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1593 """creates a new Network Slice Instance (NSI)"""
1596 check_client_version(ctx
.obj
, ctx
.command
.name
)
1599 raise ClientException('"--config" option is incompatible with "--config_file" option')
1600 with
open(config_file
, 'r') as cf
:
1602 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1603 account
=vim_account
, wait
=wait
)
1604 # except ClientException as e:
1609 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1610 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1611 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1612 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1613 @click.option('--ssh_keys', default
=None,
1614 help='comma separated list of keys to inject to vnfs')
1615 @click.option('--config', default
=None,
1616 help='Netslice specific yaml configuration:\n'
1617 'netslice_subnet: [\n'
1618 'id: TEXT, vim_account: TEXT,\n'
1619 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1620 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1621 'additionalParamsForNsi: {param: value, ...}\n'
1622 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1624 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1626 @click.option('--config_file',
1628 help='nsi specific yaml configuration file')
1629 @click.option('--wait',
1633 help='do not return the control immediately, but keep it '
1634 'until the operation is completed, or timeout')
1636 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1637 """creates a new Network Slice Instance (NSI)"""
1639 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1642 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1643 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1644 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1645 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1646 @click.option('--ssh_keys', default
=None,
1647 help='comma separated list of keys to inject to vnfs')
1648 @click.option('--config', default
=None,
1649 help='Netslice specific yaml configuration:\n'
1650 'netslice_subnet: [\n'
1651 'id: TEXT, vim_account: TEXT,\n'
1652 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1653 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1655 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1657 @click.option('--config_file',
1659 help='nsi specific yaml configuration file')
1660 @click.option('--wait',
1664 help='do not return the control immediately, but keep it '
1665 'until the operation is completed, or timeout')
1667 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1668 """creates a new Network Slice Instance (NSI)"""
1670 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1673 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1674 @click.option('--name', help='name of the Physical Deployment Unit')
1675 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1676 @click.option('--interface',
1677 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1678 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1680 @click.option('--description', help='human readable description')
1681 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
1682 @click.option('--descriptor_file', default
=None,
1683 help='PDU descriptor file (as an alternative to using the other arguments')
1685 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
1686 """creates a new Physical Deployment Unit (PDU)"""
1689 check_client_version(ctx
.obj
, ctx
.command
.name
)
1691 if not descriptor_file
:
1693 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1695 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1697 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1699 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1701 with
open(descriptor_file
, 'r') as df
:
1702 pdu
= yaml
.safe_load(df
.read())
1703 if name
: pdu
["name"] = name
1704 if pdu_type
: pdu
["type"] = pdu_type
1705 if description
: pdu
["description"] = description
1706 if vim_account
: pdu
["vim_accounts"] = vim_account
1709 for iface
in interface
:
1710 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
1711 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
1712 ifaces_list
.append(new_iface
)
1713 pdu
["interfaces"] = ifaces_list
1714 ctx
.obj
.pdu
.create(pdu
)
1715 # except ClientException as e:
1720 ####################
1722 ####################
1724 def nsd_update(ctx
, name
, content
):
1727 check_client_version(ctx
.obj
, ctx
.command
.name
)
1728 ctx
.obj
.nsd
.update(name
, content
)
1729 # except ClientException as e:
1734 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
1735 @click.argument('name')
1736 @click.option('--content', default
=None,
1737 help='filename with the NSD/NSpkg replacing the current one')
1739 def nsd_update1(ctx
, name
, content
):
1740 """updates a NSD/NSpkg
1742 NAME: name or ID of the NSD/NSpkg
1745 nsd_update(ctx
, name
, content
)
1748 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
1749 @click.argument('name')
1750 @click.option('--content', default
=None,
1751 help='filename with the NSD/NSpkg replacing the current one')
1753 def nsd_update2(ctx
, name
, content
):
1754 """updates a NSD/NSpkg
1756 NAME: name or ID of the NSD/NSpkg
1759 nsd_update(ctx
, name
, content
)
1762 def vnfd_update(ctx
, name
, content
):
1765 check_client_version(ctx
.obj
, ctx
.command
.name
)
1766 ctx
.obj
.vnfd
.update(name
, content
)
1767 # except ClientException as e:
1772 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
1773 @click.argument('name')
1774 @click.option('--content', default
=None,
1775 help='filename with the VNFD/VNFpkg replacing the current one')
1777 def vnfd_update1(ctx
, name
, content
):
1778 """updates a VNFD/VNFpkg
1780 NAME: name or ID of the VNFD/VNFpkg
1783 vnfd_update(ctx
, name
, content
)
1786 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
1787 @click.argument('name')
1788 @click.option('--content', default
=None,
1789 help='filename with the VNFD/VNFpkg replacing the current one')
1791 def vnfd_update2(ctx
, name
, content
):
1792 """updates a VNFD/VNFpkg
1794 NAME: VNFD yaml file or VNFpkg tar.gz file
1797 vnfd_update(ctx
, name
, content
)
1800 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
1801 @click.argument('name')
1802 @click.option('--content', default
=None,
1803 help='filename with the NFpkg replacing the current one')
1805 def nfpkg_update(ctx
, name
, content
):
1808 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1811 vnfd_update(ctx
, name
, content
)
1814 def nst_update(ctx
, name
, content
):
1817 check_client_version(ctx
.obj
, ctx
.command
.name
)
1818 ctx
.obj
.nst
.update(name
, content
)
1819 # except ClientException as e:
1824 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
1825 @click.argument('name')
1826 @click.option('--content', default
=None,
1827 help='filename with the NST/NSTpkg replacing the current one')
1829 def nst_update1(ctx
, name
, content
):
1830 """updates a Network Slice Template (NST)
1832 NAME: name or ID of the NSD/NSpkg
1835 nst_update(ctx
, name
, content
)
1838 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
1839 @click.argument('name')
1840 @click.option('--content', default
=None,
1841 help='filename with the NST/NSTpkg replacing the current one')
1843 def nst_update2(ctx
, name
, content
):
1844 """updates a Network Slice Template (NST)
1846 NAME: name or ID of the NSD/NSpkg
1849 nst_update(ctx
, name
, content
)
1852 ####################
1854 ####################
1856 def nsd_delete(ctx
, name
, force
):
1860 ctx
.obj
.nsd
.delete(name
)
1862 check_client_version(ctx
.obj
, '--force')
1863 ctx
.obj
.nsd
.delete(name
, force
)
1864 # except ClientException as e:
1869 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
1870 @click.argument('name')
1871 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1873 def nsd_delete1(ctx
, name
, force
):
1874 """deletes a NSD/NSpkg
1876 NAME: name or ID of the NSD/NSpkg to be deleted
1879 nsd_delete(ctx
, name
, force
)
1882 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
1883 @click.argument('name')
1884 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1886 def nsd_delete2(ctx
, name
, force
):
1887 """deletes a NSD/NSpkg
1889 NAME: name or ID of the NSD/NSpkg to be deleted
1892 nsd_delete(ctx
, name
, force
)
1895 def vnfd_delete(ctx
, name
, force
):
1899 ctx
.obj
.vnfd
.delete(name
)
1901 check_client_version(ctx
.obj
, '--force')
1902 ctx
.obj
.vnfd
.delete(name
, force
)
1903 # except ClientException as e:
1908 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
1909 @click.argument('name')
1910 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1912 def vnfd_delete1(ctx
, name
, force
):
1913 """deletes a VNFD/VNFpkg
1915 NAME: name or ID of the VNFD/VNFpkg to be deleted
1918 vnfd_delete(ctx
, name
, force
)
1921 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
1922 @click.argument('name')
1923 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1925 def vnfd_delete2(ctx
, name
, force
):
1926 """deletes a VNFD/VNFpkg
1928 NAME: name or ID of the VNFD/VNFpkg to be deleted
1931 vnfd_delete(ctx
, name
, force
)
1934 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
1935 @click.argument('name')
1936 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1938 def nfpkg_delete(ctx
, name
, force
):
1941 NAME: name or ID of the NFpkg to be deleted
1944 vnfd_delete(ctx
, name
, force
)
1947 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
1948 @click.argument('name')
1949 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1950 @click.option('--wait',
1954 help='do not return the control immediately, but keep it '
1955 'until the operation is completed, or timeout')
1957 def ns_delete(ctx
, name
, force
, wait
):
1958 """deletes a NS instance
1960 NAME: name or ID of the NS instance to be deleted
1965 ctx
.obj
.ns
.delete(name
, wait
=wait
)
1967 check_client_version(ctx
.obj
, '--force')
1968 ctx
.obj
.ns
.delete(name
, force
, wait
=wait
)
1969 # except ClientException as e:
1974 def nst_delete(ctx
, name
, force
):
1977 check_client_version(ctx
.obj
, ctx
.command
.name
)
1978 ctx
.obj
.nst
.delete(name
, force
)
1979 # except ClientException as e:
1984 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
1985 @click.argument('name')
1986 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1988 def nst_delete1(ctx
, name
, force
):
1989 """deletes a Network Slice Template (NST)
1991 NAME: name or ID of the NST/NSTpkg to be deleted
1994 nst_delete(ctx
, name
, force
)
1997 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
1998 @click.argument('name')
1999 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2001 def nst_delete2(ctx
, name
, force
):
2002 """deletes a Network Slice Template (NST)
2004 NAME: name or ID of the NST/NSTpkg to be deleted
2007 nst_delete(ctx
, name
, force
)
2010 def nsi_delete(ctx
, name
, force
, wait
):
2013 check_client_version(ctx
.obj
, ctx
.command
.name
)
2014 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2015 # except ClientException as e:
2020 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2021 @click.argument('name')
2022 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2023 @click.option('--wait',
2027 help='do not return the control immediately, but keep it '
2028 'until the operation is completed, or timeout')
2030 def nsi_delete1(ctx
, name
, force
, wait
):
2031 """deletes a Network Slice Instance (NSI)
2033 NAME: name or ID of the Network Slice instance to be deleted
2036 nsi_delete(ctx
, name
, force
, wait
=wait
)
2039 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2040 @click.argument('name')
2041 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2043 def nsi_delete2(ctx
, name
, force
, wait
):
2044 """deletes a Network Slice Instance (NSI)
2046 NAME: name or ID of the Network Slice instance to be deleted
2049 nsi_delete(ctx
, name
, force
, wait
=wait
)
2052 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2053 @click.argument('name')
2054 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2056 def pdu_delete(ctx
, name
, force
):
2057 """deletes a Physical Deployment Unit (PDU)
2059 NAME: name or ID of the PDU to be deleted
2063 check_client_version(ctx
.obj
, ctx
.command
.name
)
2064 ctx
.obj
.pdu
.delete(name
, force
)
2065 # except ClientException as e:
2074 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2075 @click.option('--name',
2077 help='Name to create datacenter')
2078 @click.option('--user',
2080 help='VIM username')
2081 @click.option('--password',
2084 confirmation_prompt
=True,
2085 help='VIM password')
2086 @click.option('--auth_url',
2089 @click.option('--tenant',
2091 help='VIM tenant name')
2092 @click.option('--config',
2094 help='VIM specific config parameters')
2095 @click.option('--account_type',
2096 default
='openstack',
2098 @click.option('--description',
2100 help='human readable description')
2101 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2102 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2103 @click.option('--wait',
2107 help='do not return the control immediately, but keep it '
2108 'until the operation is completed, or timeout')
2122 """creates a new VIM account"""
2126 check_client_version(ctx
.obj
, '--sdn_controller')
2127 if sdn_port_mapping
:
2128 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2130 vim
['vim-username'] = user
2131 vim
['vim-password'] = password
2132 vim
['vim-url'] = auth_url
2133 vim
['vim-tenant-name'] = tenant
2134 vim
['vim-type'] = account_type
2135 vim
['description'] = description
2136 vim
['config'] = config
2137 if sdn_controller
or sdn_port_mapping
:
2138 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2140 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2141 # except ClientException as e:
2146 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2147 @click.argument('name')
2148 @click.option('--newname', help='New name for the VIM account')
2149 @click.option('--user', help='VIM username')
2150 @click.option('--password', help='VIM password')
2151 @click.option('--auth_url', help='VIM url')
2152 @click.option('--tenant', help='VIM tenant name')
2153 @click.option('--config', help='VIM specific config parameters')
2154 @click.option('--account_type', help='VIM type')
2155 @click.option('--description', help='human readable description')
2156 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2157 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2158 @click.option('--wait',
2162 help='do not return the control immediately, but keep it '
2163 'until the operation is completed, or timeout')
2178 """updates a VIM account
2180 NAME: name or ID of the VIM account
2184 check_client_version(ctx
.obj
, ctx
.command
.name
)
2186 if newname
: vim
['name'] = newname
2187 if user
: vim
['vim_user'] = user
2188 if password
: vim
['vim_password'] = password
2189 if auth_url
: vim
['vim_url'] = auth_url
2190 if tenant
: vim
['vim-tenant-name'] = tenant
2191 if account_type
: vim
['vim_type'] = account_type
2192 if description
: vim
['description'] = description
2193 if config
: vim
['config'] = config
2194 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2195 # except ClientException as e:
2200 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2201 @click.argument('name')
2202 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2203 @click.option('--wait',
2207 help='do not return the control immediately, but keep it '
2208 'until the operation is completed, or timeout')
2210 def vim_delete(ctx
, name
, force
, wait
):
2211 """deletes a VIM account
2213 NAME: name or ID of the VIM account to be deleted
2218 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2220 check_client_version(ctx
.obj
, '--force')
2221 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2222 # except ClientException as e:
2227 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2228 #@click.option('--ro_update/--no_ro_update',
2230 # help='update list from RO')
2231 @click.option('--filter', default
=None,
2232 help='restricts the list to the VIM accounts matching the filter')
2234 def vim_list(ctx
, filter):
2235 """list all VIM accounts"""
2238 check_client_version(ctx
.obj
, '--filter')
2240 # check_client_version(ctx.obj, '--ro_update', 'v1')
2241 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2242 if fullclassname
== 'osmclient.sol005.client.Client':
2243 resp
= ctx
.obj
.vim
.list(filter)
2245 # resp = ctx.obj.vim.list(ro_update)
2246 table
= PrettyTable(['vim name', 'uuid'])
2248 table
.add_row([vim
['name'], vim
['uuid']])
2253 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2254 @click.argument('name')
2256 def vim_show(ctx
, name
):
2257 """shows the details of a VIM account
2259 NAME: name or ID of the VIM account
2263 resp
= ctx
.obj
.vim
.get(name
)
2264 if 'vim_password' in resp
:
2265 resp
['vim_password']='********'
2266 # except ClientException as e:
2270 table
= PrettyTable(['key', 'attribute'])
2271 for k
, v
in list(resp
.items()):
2272 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2277 ####################
2279 ####################
2281 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2282 @click.option('--name',
2284 help='Name for the WIM account')
2285 @click.option('--user',
2286 help='WIM username')
2287 @click.option('--password',
2288 help='WIM password')
2289 @click.option('--url',
2292 # @click.option('--tenant',
2293 # help='wIM tenant name')
2294 @click.option('--config',
2296 help='WIM specific config parameters')
2297 @click.option('--wim_type',
2299 @click.option('--description',
2301 help='human readable description')
2302 @click.option('--wim_port_mapping', default
=None,
2303 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2304 "(WAN service endpoint id and info)")
2305 @click.option('--wait',
2309 help='do not return the control immediately, but keep it '
2310 'until the operation is completed, or timeout')
2323 """creates a new WIM account"""
2326 check_client_version(ctx
.obj
, ctx
.command
.name
)
2327 # if sdn_controller:
2328 # check_client_version(ctx.obj, '--sdn_controller')
2329 # if sdn_port_mapping:
2330 # check_client_version(ctx.obj, '--sdn_port_mapping')
2332 if user
: wim
['user'] = user
2333 if password
: wim
['password'] = password
2334 if url
: wim
['wim_url'] = url
2335 # if tenant: wim['tenant'] = tenant
2336 wim
['wim_type'] = wim_type
2337 if description
: wim
['description'] = description
2338 if config
: wim
['config'] = config
2339 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2340 # except ClientException as e:
2345 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2346 @click.argument('name')
2347 @click.option('--newname', help='New name for the WIM account')
2348 @click.option('--user', help='WIM username')
2349 @click.option('--password', help='WIM password')
2350 @click.option('--url', help='WIM url')
2351 @click.option('--config', help='WIM specific config parameters')
2352 @click.option('--wim_type', help='WIM type')
2353 @click.option('--description', help='human readable description')
2354 @click.option('--wim_port_mapping', default
=None,
2355 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2356 "(WAN service endpoint id and info)")
2357 @click.option('--wait',
2361 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2374 """updates a WIM account
2376 NAME: name or ID of the WIM account
2380 check_client_version(ctx
.obj
, ctx
.command
.name
)
2382 if newname
: wim
['name'] = newname
2383 if user
: wim
['user'] = user
2384 if password
: wim
['password'] = password
2385 if url
: wim
['url'] = url
2386 # if tenant: wim['tenant'] = tenant
2387 if wim_type
: wim
['wim_type'] = wim_type
2388 if description
: wim
['description'] = description
2389 if config
: wim
['config'] = config
2390 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2391 # except ClientException as e:
2396 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2397 @click.argument('name')
2398 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2399 @click.option('--wait',
2403 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2405 def wim_delete(ctx
, name
, force
, wait
):
2406 """deletes a WIM account
2408 NAME: name or ID of the WIM account to be deleted
2412 check_client_version(ctx
.obj
, ctx
.command
.name
)
2413 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2414 # except ClientException as e:
2419 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2420 @click.option('--filter', default
=None,
2421 help='restricts the list to the WIM accounts matching the filter')
2423 def wim_list(ctx
, filter):
2424 """list all WIM accounts"""
2427 check_client_version(ctx
.obj
, ctx
.command
.name
)
2428 resp
= ctx
.obj
.wim
.list(filter)
2429 table
= PrettyTable(['wim name', 'uuid'])
2431 table
.add_row([wim
['name'], wim
['uuid']])
2434 # except ClientException as e:
2439 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2440 @click.argument('name')
2442 def wim_show(ctx
, name
):
2443 """shows the details of a WIM account
2445 NAME: name or ID of the WIM account
2449 check_client_version(ctx
.obj
, ctx
.command
.name
)
2450 resp
= ctx
.obj
.wim
.get(name
)
2451 if 'password' in resp
:
2452 resp
['wim_password']='********'
2453 # except ClientException as e:
2457 table
= PrettyTable(['key', 'attribute'])
2458 for k
, v
in list(resp
.items()):
2459 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2464 ####################
2465 # SDN controller operations
2466 ####################
2468 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2469 @click.option('--name',
2471 help='Name to create sdn controller')
2472 @click.option('--type',
2474 help='SDN controller type')
2475 @click.option('--sdn_controller_version', # hidden=True,
2476 help='Deprecated. Use --config {version: sdn_controller_version}')
2477 @click.option('--url',
2478 help='URL in format http[s]://HOST:IP/')
2479 @click.option('--ip_address', # hidden=True,
2480 help='Deprecated. Use --url')
2481 @click.option('--port', # hidden=True,
2482 help='Deprecated. Use --url')
2483 @click.option('--switch_dpid', # hidden=True,
2484 help='Deprecated. Use --config {dpid: DPID}')
2485 @click.option('--config',
2486 help='Extra information for SDN in yaml format, as {dpid: (Openflow Datapath ID), version: version}')
2487 @click.option('--user',
2488 help='SDN controller username')
2489 @click.option('--password',
2491 confirmation_prompt
=True,
2492 help='SDN controller password')
2493 @click.option('--description', default
=None, help='human readable description')
2494 @click.option('--wait',
2498 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2500 def sdnc_create(ctx
, **kwargs
):
2501 """creates a new SDN controller"""
2503 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2504 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2505 if kwargs
.get("port"):
2506 print("option '--port' is deprecated, use '-url' instead")
2507 sdncontroller
["port"] = int(kwargs
["port"])
2508 if kwargs
.get("ip_address"):
2509 print("option '--ip_address' is deprecated, use '-url' instead")
2510 sdncontroller
["ip"] = kwargs
["ip_address"]
2511 if kwargs
.get("switch_dpid"):
2512 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2513 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2514 if kwargs
.get("sdn_controller_version"):
2515 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2518 check_client_version(ctx
.obj
, ctx
.command
.name
)
2519 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2520 # except ClientException as e:
2524 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2525 @click.argument('name')
2526 @click.option('--newname', help='New name for the SDN controller')
2527 @click.option('--description', default
=None, help='human readable description')
2528 @click.option('--type', help='SDN controller type')
2529 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2530 @click.option('--config', help='Extra information for SDN in yaml format, as '
2531 '{dpid: (Openflow Datapath ID), version: version}')
2532 @click.option('--user', help='SDN controller username')
2533 @click.option('--password', help='SDN controller password')
2534 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2535 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2536 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2537 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2538 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2539 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2541 def sdnc_update(ctx
, **kwargs
):
2542 """updates an SDN controller
2544 NAME: name or ID of the SDN controller
2547 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2548 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2549 if kwargs
.get("newname"):
2550 sdncontroller
["name"] = kwargs
["newname"]
2551 if kwargs
.get("port"):
2552 print("option '--port' is deprecated, use '-url' instead")
2553 sdncontroller
["port"] = int(kwargs
["port"])
2554 if kwargs
.get("ip_address"):
2555 print("option '--ip_address' is deprecated, use '-url' instead")
2556 sdncontroller
["ip"] = kwargs
["ip_address"]
2557 if kwargs
.get("switch_dpid"):
2558 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2559 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2560 if kwargs
.get("sdn_controller_version"):
2561 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2565 check_client_version(ctx
.obj
, ctx
.command
.name
)
2566 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2567 # except ClientException as e:
2572 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2573 @click.argument('name')
2574 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2575 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2576 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2578 def sdnc_delete(ctx
, name
, force
, wait
):
2579 """deletes an SDN controller
2581 NAME: name or ID of the SDN controller to be deleted
2585 check_client_version(ctx
.obj
, ctx
.command
.name
)
2586 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2587 # except ClientException as e:
2592 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2593 @click.option('--filter', default
=None,
2594 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2596 def sdnc_list(ctx
, filter):
2597 """list all SDN controllers"""
2600 check_client_version(ctx
.obj
, ctx
.command
.name
)
2601 resp
= ctx
.obj
.sdnc
.list(filter)
2602 # except ClientException as e:
2605 table
= PrettyTable(['sdnc name', 'id'])
2607 table
.add_row([sdnc
['name'], sdnc
['_id']])
2612 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2613 @click.argument('name')
2615 def sdnc_show(ctx
, name
):
2616 """shows the details of an SDN controller
2618 NAME: name or ID of the SDN controller
2622 check_client_version(ctx
.obj
, ctx
.command
.name
)
2623 resp
= ctx
.obj
.sdnc
.get(name
)
2624 # except ClientException as e:
2628 table
= PrettyTable(['key', 'attribute'])
2629 for k
, v
in list(resp
.items()):
2630 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2635 ###########################
2636 # K8s cluster operations
2637 ###########################
2639 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2640 @click.argument('name')
2641 @click.option('--creds',
2643 help='credentials file, i.e. a valid `.kube/config` file')
2644 @click.option('--version',
2646 help='Kubernetes version')
2647 @click.option('--vim',
2649 help='VIM target, the VIM where the cluster resides')
2650 @click.option('--k8s-nets',
2652 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) ...]}"')
2653 @click.option('--description',
2655 help='human readable description')
2656 @click.option('--namespace',
2657 default
='kube-system',
2658 help='namespace to be used for its operation, defaults to `kube-system`')
2659 @click.option('--cni',
2661 help='list of CNI plugins, in JSON inline format, used in the cluster')
2662 #@click.option('--skip-init',
2664 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2665 #@click.option('--wait',
2667 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2669 def k8scluster_add(ctx
,
2678 """adds a K8s cluster to OSM
2680 NAME: name of the K8s cluster
2683 check_client_version(ctx
.obj
, ctx
.command
.name
)
2685 cluster
['name'] = name
2686 with
open(creds
, 'r') as cf
:
2687 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2688 cluster
['k8s_version'] = version
2689 cluster
['vim_account'] = vim
2690 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2691 cluster
['description'] = description
2692 if namespace
: cluster
['namespace'] = namespace
2693 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2694 ctx
.obj
.k8scluster
.create(name
, cluster
)
2695 # except ClientException as e:
2700 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
2701 @click.argument('name')
2702 @click.option('--newname', help='New name for the K8s cluster')
2703 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
2704 @click.option('--version', help='Kubernetes version')
2705 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
2706 @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) ...]}"')
2707 @click.option('--description', help='human readable description')
2708 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
2709 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
2711 def k8scluster_update(ctx
,
2721 """updates a K8s cluster
2723 NAME: name or ID of the K8s cluster
2726 check_client_version(ctx
.obj
, ctx
.command
.name
)
2728 if newname
: cluster
['name'] = newname
2730 with
open(creds
, 'r') as cf
:
2731 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2732 if version
: cluster
['k8s_version'] = version
2733 if vim
: cluster
['vim_account'] = vim
2734 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2735 if description
: cluster
['description'] = description
2736 if namespace
: cluster
['namespace'] = namespace
2737 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2738 ctx
.obj
.k8scluster
.update(name
, cluster
)
2739 # except ClientException as e:
2744 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
2745 @click.argument('name')
2746 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2747 #@click.option('--wait',
2749 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2751 def k8scluster_delete(ctx
, name
, force
):
2752 """deletes a K8s cluster
2754 NAME: name or ID of the K8s cluster to be deleted
2757 check_client_version(ctx
.obj
, ctx
.command
.name
)
2758 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
2759 # except ClientException as e:
2764 @cli_osm.command(name
='k8scluster-list')
2765 @click.option('--filter', default
=None,
2766 help='restricts the list to the K8s clusters matching the filter')
2767 @click.option('--literal', is_flag
=True,
2768 help='print literally, no pretty table')
2770 def k8scluster_list(ctx
, filter, literal
):
2771 """list all K8s clusters"""
2773 check_client_version(ctx
.obj
, ctx
.command
.name
)
2774 resp
= ctx
.obj
.k8scluster
.list(filter)
2776 print(yaml
.safe_dump(resp
))
2778 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
2779 for cluster
in resp
:
2780 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
2781 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
2782 trunc_text(cluster
.get('description',''),40)])
2785 # except ClientException as e:
2790 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
2791 @click.argument('name')
2792 @click.option('--literal', is_flag
=True,
2793 help='print literally, no pretty table')
2795 def k8scluster_show(ctx
, name
, literal
):
2796 """shows the details of a K8s cluster
2798 NAME: name or ID of the K8s cluster
2801 resp
= ctx
.obj
.k8scluster
.get(name
)
2803 print(yaml
.safe_dump(resp
))
2805 table
= PrettyTable(['key', 'attribute'])
2806 for k
, v
in list(resp
.items()):
2807 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2810 # except ClientException as e:
2816 ###########################
2818 ###########################
2820 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
2821 @click.argument('name')
2822 @click.argument('uri')
2823 @click.option('--type',
2824 type=click
.Choice(['helm-chart', 'juju-bundle']),
2826 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2827 @click.option('--description',
2829 help='human readable description')
2830 #@click.option('--wait',
2832 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2839 """adds a repo to OSM
2841 NAME: name of the repo
2842 URI: URI of the repo
2845 check_client_version(ctx
.obj
, ctx
.command
.name
)
2850 repo
['description'] = description
2851 ctx
.obj
.repo
.create(name
, repo
)
2852 # except ClientException as e:
2857 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
2858 @click.argument('name')
2859 @click.option('--newname', help='New name for the repo')
2860 @click.option('--uri', help='URI of the repo')
2861 @click.option('--type', type=click
.Choice(['helm-chart', 'juju-bundle']),
2862 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2863 @click.option('--description', help='human readable description')
2864 #@click.option('--wait',
2866 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2868 def repo_update(ctx
,
2874 """updates a repo in OSM
2876 NAME: name of the repo
2879 check_client_version(ctx
.obj
, ctx
.command
.name
)
2881 if newname
: repo
['name'] = newname
2882 if uri
: repo
['uri'] = uri
2883 if type: repo
['type'] = type
2884 if description
: repo
['description'] = description
2885 ctx
.obj
.repo
.update(name
, repo
)
2886 # except ClientException as e:
2891 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
2892 @click.argument('name')
2893 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2894 #@click.option('--wait',
2896 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2898 def repo_delete(ctx
, name
, force
):
2901 NAME: name or ID of the repo to be deleted
2904 check_client_version(ctx
.obj
, ctx
.command
.name
)
2905 ctx
.obj
.repo
.delete(name
, force
=force
)
2906 # except ClientException as e:
2911 @cli_osm.command(name
='repo-list')
2912 @click.option('--filter', default
=None,
2913 help='restricts the list to the repos matching the filter')
2914 @click.option('--literal', is_flag
=True,
2915 help='print literally, no pretty table')
2917 def repo_list(ctx
, filter, literal
):
2918 """list all repos"""
2920 check_client_version(ctx
.obj
, ctx
.command
.name
)
2921 resp
= ctx
.obj
.repo
.list(filter)
2923 print(yaml
.safe_dump(resp
))
2925 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
2927 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
2928 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description',''),40)])
2931 # except ClientException as e:
2936 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
2937 @click.argument('name')
2938 @click.option('--literal', is_flag
=True,
2939 help='print literally, no pretty table')
2941 def repo_show(ctx
, name
, literal
):
2942 """shows the details of a repo
2944 NAME: name or ID of the repo
2947 resp
= ctx
.obj
.repo
.get(name
)
2949 print(yaml
.safe_dump(resp
))
2951 table
= PrettyTable(['key', 'attribute'])
2952 for k
, v
in list(resp
.items()):
2953 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2956 # except ClientException as e:
2962 ####################
2963 # Project mgmt operations
2964 ####################
2966 @cli_osm.command(name
='project-create', short_help
='creates a new project')
2967 @click.argument('name')
2968 #@click.option('--description',
2969 # default='no description',
2970 # help='human readable description')
2972 def project_create(ctx
, name
):
2973 """Creates a new project
2975 NAME: name of the project
2979 project
['name'] = name
2981 check_client_version(ctx
.obj
, ctx
.command
.name
)
2982 ctx
.obj
.project
.create(name
, project
)
2983 # except ClientException as e:
2988 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
2989 @click.argument('name')
2990 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2992 def project_delete(ctx
, name
):
2993 """deletes a project
2995 NAME: name or ID of the project to be deleted
2999 check_client_version(ctx
.obj
, ctx
.command
.name
)
3000 ctx
.obj
.project
.delete(name
)
3001 # except ClientException as e:
3006 @cli_osm.command(name
='project-list', short_help
='list all projects')
3007 @click.option('--filter', default
=None,
3008 help='restricts the list to the projects matching the filter')
3010 def project_list(ctx
, filter):
3011 """list all projects"""
3014 check_client_version(ctx
.obj
, ctx
.command
.name
)
3015 resp
= ctx
.obj
.project
.list(filter)
3016 # except ClientException as e:
3019 table
= PrettyTable(['name', 'id'])
3021 table
.add_row([proj
['name'], proj
['_id']])
3026 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3027 @click.argument('name')
3029 def project_show(ctx
, name
):
3030 """shows the details of a project
3032 NAME: name or ID of the project
3036 check_client_version(ctx
.obj
, ctx
.command
.name
)
3037 resp
= ctx
.obj
.project
.get(name
)
3038 # except ClientException as e:
3042 table
= PrettyTable(['key', 'attribute'])
3043 for k
, v
in resp
.items():
3044 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3049 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3050 @click.argument('project')
3051 @click.option('--name',
3053 help='new name for the project')
3056 def project_update(ctx
, project
, name
):
3058 Update a project name
3061 :param project: id or name of the project to modify
3062 :param name: new name for the project
3066 project_changes
= {}
3067 project_changes
['name'] = name
3070 check_client_version(ctx
.obj
, ctx
.command
.name
)
3071 ctx
.obj
.project
.update(project
, project_changes
)
3072 # except ClientException as e:
3076 ####################
3077 # User mgmt operations
3078 ####################
3080 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3081 @click.argument('username')
3082 @click.option('--password',
3085 confirmation_prompt
=True,
3086 help='user password')
3087 @click.option('--projects',
3088 # prompt="Comma separate list of projects",
3090 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3091 help='list of project ids that the user belongs to')
3092 @click.option('--project-role-mappings', 'project_role_mappings',
3093 default
=None, multiple
=True,
3094 help='creating user project/role(s) mapping')
3096 def user_create(ctx
, username
, password
, projects
, project_role_mappings
):
3097 """Creates a new user
3100 USERNAME: name of the user
3101 PASSWORD: password of the user
3102 PROJECTS: projects assigned to user (internal only)
3103 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3107 user
['username'] = username
3108 user
['password'] = password
3109 user
['projects'] = projects
3110 user
['project_role_mappings'] = project_role_mappings
3113 check_client_version(ctx
.obj
, ctx
.command
.name
)
3114 ctx
.obj
.user
.create(username
, user
)
3115 # except ClientException as e:
3120 @cli_osm.command(name
='user-update', short_help
='updates user information')
3121 @click.argument('username')
3122 @click.option('--password',
3125 # confirmation_prompt=True,
3126 help='user password')
3127 @click.option('--set-username', 'set_username',
3129 help='change username')
3130 @click.option('--set-project', 'set_project',
3131 default
=None, multiple
=True,
3132 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
3133 @click.option('--remove-project', 'remove_project',
3134 default
=None, multiple
=True,
3135 help='removes project from user: \'project\'')
3136 @click.option('--add-project-role', 'add_project_role',
3137 default
=None, multiple
=True,
3138 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
3139 @click.option('--remove-project-role', 'remove_project_role',
3140 default
=None, multiple
=True,
3141 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
3143 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3144 add_project_role
, remove_project_role
):
3145 """Update a user information
3148 USERNAME: name of the user
3149 PASSWORD: new password
3150 SET_USERNAME: new username
3151 SET_PROJECT: creating mappings for project/role(s)
3152 REMOVE_PROJECT: deleting mappings for project/role(s)
3153 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3154 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3158 user
['password'] = password
3159 user
['username'] = set_username
3160 user
['set-project'] = set_project
3161 user
['remove-project'] = remove_project
3162 user
['add-project-role'] = add_project_role
3163 user
['remove-project-role'] = remove_project_role
3166 check_client_version(ctx
.obj
, ctx
.command
.name
)
3167 ctx
.obj
.user
.update(username
, user
)
3168 # except ClientException as e:
3173 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3174 @click.argument('name')
3175 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3177 def user_delete(ctx
, name
):
3181 NAME: name or ID of the user to be deleted
3185 check_client_version(ctx
.obj
, ctx
.command
.name
)
3186 ctx
.obj
.user
.delete(name
)
3187 # except ClientException as e:
3192 @cli_osm.command(name
='user-list', short_help
='list all users')
3193 @click.option('--filter', default
=None,
3194 help='restricts the list to the users matching the filter')
3196 def user_list(ctx
, filter):
3197 """list all users"""
3199 check_client_version(ctx
.obj
, ctx
.command
.name
)
3200 resp
= ctx
.obj
.user
.list(filter)
3201 # except ClientException as e:
3204 table
= PrettyTable(['name', 'id'])
3206 table
.add_row([user
['username'], user
['_id']])
3211 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3212 @click.argument('name')
3214 def user_show(ctx
, name
):
3215 """shows the details of a user
3217 NAME: name or ID of the user
3221 check_client_version(ctx
.obj
, ctx
.command
.name
)
3222 resp
= ctx
.obj
.user
.get(name
)
3223 if 'password' in resp
:
3224 resp
['password']='********'
3225 # except ClientException as e:
3229 table
= PrettyTable(['key', 'attribute'])
3230 for k
, v
in resp
.items():
3231 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3236 ####################
3237 # Fault Management operations
3238 ####################
3240 @cli_osm.command(name
='ns-alarm-create')
3241 @click.argument('name')
3242 @click.option('--ns', prompt
=True, help='NS instance id or name')
3243 @click.option('--vnf', prompt
=True,
3244 help='VNF name (VNF member index as declared in the NSD)')
3245 @click.option('--vdu', prompt
=True,
3246 help='VDU name (VDU name as declared in the VNFD)')
3247 @click.option('--metric', prompt
=True,
3248 help='Name of the metric (e.g. cpu_utilization)')
3249 @click.option('--severity', default
='WARNING',
3250 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3251 @click.option('--threshold_value', prompt
=True,
3252 help='threshold value that, when crossed, an alarm is triggered')
3253 @click.option('--threshold_operator', prompt
=True,
3254 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3255 @click.option('--statistic', default
='AVERAGE',
3256 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3258 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3259 threshold_value
, threshold_operator
, statistic
):
3260 """creates a new alarm for a NS instance"""
3261 # TODO: Check how to validate threshold_value.
3262 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3265 ns_instance
= ctx
.obj
.ns
.get(ns
)
3267 alarm
['alarm_name'] = name
3268 alarm
['ns_id'] = ns_instance
['_id']
3269 alarm
['correlation_id'] = ns_instance
['_id']
3270 alarm
['vnf_member_index'] = vnf
3271 alarm
['vdu_name'] = vdu
3272 alarm
['metric_name'] = metric
3273 alarm
['severity'] = severity
3274 alarm
['threshold_value'] = int(threshold_value
)
3275 alarm
['operation'] = threshold_operator
3276 alarm
['statistic'] = statistic
3277 check_client_version(ctx
.obj
, ctx
.command
.name
)
3278 ctx
.obj
.ns
.create_alarm(alarm
)
3279 # except ClientException as e:
3284 #@cli_osm.command(name='ns-alarm-delete')
3285 #@click.argument('name')
3286 #@click.pass_context
3287 #def ns_alarm_delete(ctx, name):
3288 # """deletes an alarm
3290 # NAME: name of the alarm to be deleted
3293 # check_client_version(ctx.obj, ctx.command.name)
3294 # ctx.obj.ns.delete_alarm(name)
3295 # except ClientException as e:
3300 ####################
3301 # Performance Management operations
3302 ####################
3304 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3305 @click.option('--ns', prompt
=True, help='NS instance id or name')
3306 @click.option('--vnf', prompt
=True,
3307 help='VNF name (VNF member index as declared in the NSD)')
3308 @click.option('--vdu', prompt
=True,
3309 help='VDU name (VDU name as declared in the VNFD)')
3310 @click.option('--metric', prompt
=True,
3311 help='name of the metric (e.g. cpu_utilization)')
3312 #@click.option('--period', default='1w',
3313 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3314 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3316 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3317 """exports a metric to the internal OSM bus, which can be read by other apps"""
3318 # TODO: Check how to validate interval.
3319 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3322 ns_instance
= ctx
.obj
.ns
.get(ns
)
3324 metric_data
['ns_id'] = ns_instance
['_id']
3325 metric_data
['correlation_id'] = ns_instance
['_id']
3326 metric_data
['vnf_member_index'] = vnf
3327 metric_data
['vdu_name'] = vdu
3328 metric_data
['metric_name'] = metric
3329 metric_data
['collection_unit'] = 'WEEK'
3330 metric_data
['collection_period'] = 1
3331 check_client_version(ctx
.obj
, ctx
.command
.name
)
3333 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3337 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3338 time
.sleep(int(interval
))
3340 # except ClientException as e:
3345 ####################
3347 ####################
3349 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3351 def get_version(ctx
):
3352 """shows client and server versions"""
3354 check_client_version(ctx
.obj
, "version")
3355 print ("Server version: {}".format(ctx
.obj
.get_version()))
3356 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3357 # except ClientException as e:
3361 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3362 @click.argument('filename')
3363 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3364 help='the charm will not be compiled, it is assumed to already exist')
3366 def upload_package(ctx
, filename
, skip_charm_build
):
3367 """uploads a vnf package or ns package
3369 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3373 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3374 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3375 if fullclassname
!= 'osmclient.sol005.client.Client':
3376 ctx
.obj
.package
.wait_for_upload(filename
)
3377 # except ClientException as e:
3382 #@cli_osm.command(name='ns-scaling-show')
3383 #@click.argument('ns_name')
3384 #@click.pass_context
3385 #def show_ns_scaling(ctx, ns_name):
3386 # """shows the status of a NS scaling operation
3388 # NS_NAME: name of the NS instance being scaled
3391 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3392 # resp = ctx.obj.ns.list()
3393 # except ClientException as e:
3397 # table = PrettyTable(
3400 # 'operational status',
3405 # if ns_name == ns['name']:
3406 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3407 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3408 # for record in scaling_records:
3409 # if 'instance' in record:
3410 # instances = record['instance']
3411 # for inst in instances:
3413 # [record['scaling-group-name-ref'],
3414 # inst['instance-id'],
3415 # inst['op-status'],
3416 # time.strftime('%Y-%m-%d %H:%M:%S',
3418 # inst['create-time'])),
3424 #@cli_osm.command(name='ns-scale')
3425 #@click.argument('ns_name')
3426 #@click.option('--ns_scale_group', prompt=True)
3427 #@click.option('--index', prompt=True)
3428 #@click.option('--wait',
3432 # help='do not return the control immediately, but keep it \
3433 # until the operation is completed, or timeout')
3434 #@click.pass_context
3435 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3438 # NS_NAME: name of the NS instance to be scaled
3441 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3442 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3443 # except ClientException as e:
3448 #@cli_osm.command(name='config-agent-list')
3449 #@click.pass_context
3450 #def config_agent_list(ctx):
3451 # """list config agents"""
3453 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3454 # except ClientException as e:
3457 # table = PrettyTable(['name', 'account-type', 'details'])
3458 # for account in ctx.obj.vca.list():
3461 # account['account-type'],
3467 #@cli_osm.command(name='config-agent-delete')
3468 #@click.argument('name')
3469 #@click.pass_context
3470 #def config_agent_delete(ctx, name):
3471 # """deletes a config agent
3473 # NAME: name of the config agent to be deleted
3476 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3477 # ctx.obj.vca.delete(name)
3478 # except ClientException as e:
3483 #@cli_osm.command(name='config-agent-add')
3484 #@click.option('--name',
3486 #@click.option('--account_type',
3488 #@click.option('--server',
3490 #@click.option('--user',
3492 #@click.option('--secret',
3495 # confirmation_prompt=True)
3496 #@click.pass_context
3497 #def config_agent_add(ctx, name, account_type, server, user, secret):
3498 # """adds a config agent"""
3500 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3501 # ctx.obj.vca.create(name, account_type, server, user, secret)
3502 # except ClientException as e:
3507 #@cli_osm.command(name='ro-dump')
3508 #@click.pass_context
3510 # """shows RO agent information"""
3511 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3512 # resp = ctx.obj.vim.get_resource_orchestrator()
3513 # table = PrettyTable(['key', 'attribute'])
3514 # for k, v in list(resp.items()):
3515 # table.add_row([k, json.dumps(v, indent=2)])
3520 #@cli_osm.command(name='vcs-list')
3521 #@click.pass_context
3523 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3524 # resp = ctx.obj.utils.get_vcs_info()
3525 # table = PrettyTable(['component name', 'state'])
3526 # for component in resp:
3527 # table.add_row([component['component_name'], component['state']])
3532 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3533 @click.argument('ns_name')
3534 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3535 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3536 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3537 @click.option('--vdu_count', default
=None, help='number of vdu instance of this vdu_id')
3538 @click.option('--action_name', prompt
=True, help='action name')
3539 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3540 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3541 @click.option('--wait',
3545 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3557 """executes an action/primitive over a NS instance
3559 NS_NAME: name or ID of the NS instance
3563 check_client_version(ctx
.obj
, ctx
.command
.name
)
3566 op_data
['member_vnf_index'] = vnf_name
3568 op_data
['kdu_name'] = kdu_name
3570 op_data
['vdu_id'] = vdu_id
3572 op_data
['vdu_count_index'] = vdu_count
3573 op_data
['primitive'] = action_name
3575 with
open(params_file
, 'r') as pf
:
3578 op_data
['primitive_params'] = yaml
.safe_load(params
)
3580 op_data
['primitive_params'] = {}
3581 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
3583 # except ClientException as e:
3588 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
3589 @click.argument('ns_name')
3590 @click.argument('vnf_name')
3591 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
3592 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
3593 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
3602 Executes a VNF scale (adding/removing VDUs)
3605 NS_NAME: name or ID of the NS instance.
3606 VNF_NAME: member-vnf-index in the NS to be scaled.
3610 check_client_version(ctx
.obj
, ctx
.command
.name
)
3611 if not scale_in
and not scale_out
:
3613 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
)
3614 # except ClientException as e:
3619 ##############################
3620 # Role Management Operations #
3621 ##############################
3623 @cli_osm.command(name
='role-create', short_help
='creates a new role')
3624 @click.argument('name')
3625 @click.option('--permissions',
3627 help='role permissions using a dictionary')
3629 def role_create(ctx
, name
, permissions
):
3634 NAME: Name or ID of the role.
3635 DEFINITION: Definition of grant/denial of access to resources.
3639 check_client_version(ctx
.obj
, ctx
.command
.name
)
3640 ctx
.obj
.role
.create(name
, permissions
)
3641 # except ClientException as e:
3646 @cli_osm.command(name
='role-update', short_help
='updates a role')
3647 @click.argument('name')
3648 @click.option('--set-name',
3650 help='change name of rle')
3651 # @click.option('--permissions',
3653 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
3654 @click.option('--add',
3656 help='yaml format dictionary with permission: True/False to access grant/denial')
3657 @click.option('--remove',
3659 help='yaml format list to remove a permission')
3661 def role_update(ctx
, name
, set_name
, add
, remove
):
3666 NAME: Name or ID of the role.
3667 DEFINITION: Definition overwrites the old definition.
3668 ADD: Grant/denial of access to resource to add.
3669 REMOVE: Grant/denial of access to resource to remove.
3673 check_client_version(ctx
.obj
, ctx
.command
.name
)
3674 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
3675 # except ClientException as e:
3680 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
3681 @click.argument('name')
3682 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3684 def role_delete(ctx
, name
):
3689 NAME: Name or ID of the role.
3693 check_client_version(ctx
.obj
, ctx
.command
.name
)
3694 ctx
.obj
.role
.delete(name
)
3695 # except ClientException as e:
3700 @cli_osm.command(name
='role-list', short_help
='list all roles')
3701 @click.option('--filter', default
=None,
3702 help='restricts the list to the projects matching the filter')
3704 def role_list(ctx
, filter):
3710 check_client_version(ctx
.obj
, ctx
.command
.name
)
3711 resp
= ctx
.obj
.role
.list(filter)
3712 # except ClientException as e:
3715 table
= PrettyTable(['name', 'id'])
3717 table
.add_row([role
['name'], role
['_id']])
3722 @cli_osm.command(name
='role-show', short_help
='show specific role')
3723 @click.argument('name')
3725 def role_show(ctx
, name
):
3727 Shows the details of a role.
3730 NAME: Name or ID of the role.
3734 check_client_version(ctx
.obj
, ctx
.command
.name
)
3735 resp
= ctx
.obj
.role
.get(name
)
3736 # except ClientException as e:
3740 table
= PrettyTable(['key', 'attribute'])
3741 for k
, v
in resp
.items():
3742 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3747 @cli_osm.command(name
='package-create',
3748 short_help
='Create a package descriptor')
3749 @click.argument('package-type')
3750 @click.argument('package-name')
3751 @click.option('--base-directory',
3753 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
3754 @click.option('--image',
3755 default
="image-name",
3756 help='(VNF) Set the name of the vdu image. Default "image-name"')
3757 @click.option('--vdus',
3759 help='(VNF) Set the number of vdus in a VNF. Default 1')
3760 @click.option('--vcpu',
3762 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
3763 @click.option('--memory',
3765 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
3766 @click.option('--storage',
3768 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
3769 @click.option('--interfaces',
3771 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
3772 @click.option('--vendor',
3774 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
3775 @click.option('--override',
3778 help='(NS/VNF/NST) Flag for overriding the package if exists.')
3779 @click.option('--detailed',
3782 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
3783 @click.option('--netslice-subnets',
3785 help='(NST) Number of netslice subnets. Default 1')
3786 @click.option('--netslice-vlds',
3788 help='(NST) Number of netslice vlds. Default 1')
3790 def package_create(ctx
,
3806 Creates an OSM NS, VNF, NST package
3809 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
3810 PACKAGE_NAME: Name of the package to create the folder with the content.
3814 check_client_version(ctx
.obj
, ctx
.command
.name
)
3815 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
3816 resp
= ctx
.obj
.package_tool
.create(package_type
,
3825 interfaces
=interfaces
,
3828 netslice_subnets
=netslice_subnets
,
3829 netslice_vlds
=netslice_vlds
)
3831 # except ClientException as inst:
3832 # print("ERROR: {}".format(inst))
3835 @cli_osm.command(name
='package-validate',
3836 short_help
='Validate a package descriptor')
3837 @click.argument('base-directory',
3840 @click.option('--recursive/--no-recursive',
3842 help='The activated recursive option will validate the yaml files'
3843 ' within the indicated directory and in its subdirectories')
3845 def package_validate(ctx
,
3849 Validate descriptors given a base directory.
3852 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
3855 check_client_version(ctx
.obj
, ctx
.command
.name
)
3856 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
3857 table
= PrettyTable()
3858 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
3859 # Print the dictionary generated by the validation function
3860 for result
in results
:
3861 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
3862 table
.sortby
= "VALID"
3863 table
.align
["PATH"] = "l"
3864 table
.align
["TYPE"] = "l"
3865 table
.align
["ERROR"] = "l"
3867 # except ClientException as inst:
3868 # print("ERROR: {}".format(inst))
3871 @cli_osm.command(name
='package-build',
3872 short_help
='Build the tar.gz of the package')
3873 @click.argument('package-folder')
3874 @click.option('--skip-validation',
3877 help='skip package validation')
3878 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3879 help='the charm will not be compiled, it is assumed to already exist')
3881 def package_build(ctx
,
3886 Build the package NS, VNF given the package_folder.
3889 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
3892 check_client_version(ctx
.obj
, ctx
.command
.name
)
3893 results
= ctx
.obj
.package_tool
.build(package_folder
,
3894 skip_validation
=skip_validation
,
3895 skip_charm_build
=skip_charm_build
)
3897 # except ClientException as inst:
3898 # print("ERROR: {}".format(inst))
3906 except pycurl
.error
as exc
:
3908 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
3909 except ClientException
as exc
:
3910 print("ERROR: {}".format(exc
))
3911 except (FileNotFoundError
, PermissionError
) as exc
:
3912 print("Cannot open file: {}".format(exc
))
3913 except yaml
.YAMLError
as exc
:
3914 print("Invalid YAML format: {}".format(exc
))
3916 # TODO capture other controlled exceptions here
3917 # TODO remove the ClientException captures from all places, unless they do something different
3920 if __name__
== '__main__':