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('--all-projects',
103 help='include all projects')
104 @click.option('--public/--no-public', default
=None,
105 help='flag for public items (packages, instances, VIM accounts, etc.)')
106 #@click.option('--so-port',
108 # envvar='OSM_SO_PORT',
109 # help='hostname of server. ' +
110 # 'Also can set OSM_SO_PORT in environment')
111 #@click.option('--so-project',
113 # envvar='OSM_SO_PROJECT',
114 # help='Project Name in SO. ' +
115 # 'Also can set OSM_SO_PROJECT in environment')
116 #@click.option('--ro-hostname',
118 # envvar='OSM_RO_HOSTNAME',
119 # help='hostname of RO server. ' +
120 # 'Also can set OSM_RO_HOSTNAME in environment')
121 #@click.option('--ro-port',
123 # envvar='OSM_RO_PORT',
124 # help='hostname of RO server. ' +
125 # 'Also can set OSM_RO_PORT in environment')
127 def cli_osm(ctx
, hostname
, user
, password
, project
, verbose
, all_projects
, public
):
131 "either hostname option or OSM_HOSTNAME " +
132 "environment variable needs to be specified"))
134 kwargs
= {'verbose': verbose
}
135 # if so_port is not None:
136 # kwargs['so_port']=so_port
137 # if so_project is not None:
138 # kwargs['so_project']=so_project
139 # if ro_hostname is not None:
140 # kwargs['ro_host']=ro_hostname
141 # if ro_port is not None:
142 # kwargs['ro_port']=ro_port
143 sol005
= os
.getenv('OSM_SOL005', True)
146 if password
is not None:
147 kwargs
['password']=password
148 if project
is not None:
149 kwargs
['project']=project
151 kwargs
['all_projects']=all_projects
152 if public
is not None:
153 kwargs
['public']=public
154 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
155 logger
= logging
.getLogger('osmclient')
162 @cli_osm.command(name
='ns-list', short_help
='list all NS instances')
163 @click.option('--filter', default
=None,
164 help='restricts the list to the NS instances matching the filter.')
165 @click.option('--long', is_flag
=True,
166 help='get more details of the NS (project, vim, deployment status, configuration status.')
168 def ns_list(ctx
, filter, long):
169 """list all NS instances
173 --filter filterExpr Restricts the list to the NS instances matching the filter
176 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
177 concatenated using the "&" character:
180 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
181 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
182 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
184 value := scalar value
188 * zero or more occurrences
189 ? zero or one occurrence
190 [] grouping of expressions to be used with ? and *
191 "" quotation marks for marking string constants
195 "AttrName" is the name of one attribute in the data type that defines the representation
196 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
197 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
198 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
199 entries, it means that the operator "op" is applied to the attribute addressed by the last
200 <attrName> entry included in the concatenation. All simple filter expressions are combined
201 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
202 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
203 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
204 prefix". If an attribute referenced in an expression is an array, an object that contains a
205 corresponding array shall be considered to match the expression if any of the elements in the
206 array matches all expressions that have the same attribute prefix.
210 --filter admin-status=ENABLED
211 --filter nsd-ref=<NSD_NAME>
212 --filter nsd.vendor=<VENDOR>
213 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
214 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
216 def summarize_deployment_status(status_dict
):
221 net_list
= status_dict
['nets']
224 if net
['status'] not in status_nets
:
225 status_nets
[net
['status']] = 1
227 status_nets
[net
['status']] +=1
229 for k
,v
in status_nets
.items():
230 message
+= "{}:{},".format(k
,v
)
231 message
+= "TOTAL:{}".format(n_nets
)
232 summary
+= "{}".format(message
)
237 vnf_list
= status_dict
['vnfs']
239 member_vnf_index
= vnf
['member_vnf_index']
240 if member_vnf_index
not in status_vnfs
:
241 status_vnfs
[member_vnf_index
] = {}
242 for vm
in vnf
['vms']:
244 if vm
['status'] not in status_vms
:
245 status_vms
[vm
['status']] = 1
247 status_vms
[vm
['status']] +=1
248 if vm
['status'] not in status_vnfs
[member_vnf_index
]:
249 status_vnfs
[member_vnf_index
][vm
['status']] = 1
251 status_vnfs
[member_vnf_index
][vm
['status']] += 1
253 for k
,v
in status_vms
.items():
254 message
+= "{}:{},".format(k
,v
)
255 message
+= "TOTAL:{}".format(n_vms
)
256 summary
+= "\n{}".format(message
)
258 for k
,v
in status_vnfs
.items():
260 message
= "\n {} VMs: ".format(k
)
261 for k2
,v2
in v
.items():
262 message
+= "{}:{},".format(k2
,v2
)
264 message
+= "TOTAL:{}".format(total
)
268 def summarize_config_status(ee_list
):
273 if ee
['elementType'] not in status_ee
:
274 status_ee
[ee
['elementType']] = {}
275 status_ee
[ee
['elementType']][ee
['status']] = 1
277 if ee
['status'] in status_ee
[ee
['elementType']]:
278 status_ee
[ee
['elementType']][ee
['status']] += 1
280 status_ee
[ee
['elementType']][ee
['status']] = 1
282 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
283 if elementType
in status_ee
:
286 for k
,v
in status_ee
[elementType
].items():
287 message
+= "{}:{},".format(k
,v
)
289 message
+= "TOTAL:{}\n".format(total
)
290 summary
+= "{}: {}".format(elementType
, message
)
291 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
295 check_client_version(ctx
.obj
, '--filter')
296 resp
= ctx
.obj
.ns
.list(filter)
298 resp
= ctx
.obj
.ns
.list()
310 'configuration status'])
311 project_list
= ctx
.obj
.project
.list()
312 vim_list
= ctx
.obj
.vim
.list()
322 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
323 if fullclassname
== 'osmclient.sol005.client.Client':
325 nsr_name
= nsr
['name']
327 date
= datetime
.fromtimestamp(nsr
['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
328 ns_state
= nsr
['nsState']
330 deployment_status
= summarize_deployment_status(nsr
['deploymentStatus'])
331 config_status
= summarize_config_status(nsr
['configurationStatus'])
332 project_id
= nsr
.get('_admin').get('projects_read')[0]
334 for p
in project_list
:
335 if p
['_id'] == project_id
:
336 project_name
= p
['name']
338 #project = '{} ({})'.format(project_name, project_id)
339 project
= project_name
340 vim_id
= nsr
.get('datacenter')
343 if v
['uuid'] == vim_id
:
346 #vim = '{} ({})'.format(vim_name, vim_id)
348 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
349 error_details
= "N/A"
350 if ns_state
== "BROKEN" or ns_state
== "DEGRADED":
351 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'],nsr
['errorDetail'])
353 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
354 nsr
= nsopdata
['nsr:nsr']
355 nsr_name
= nsr
['name-ref']
356 nsr_id
= nsr
['ns-instance-config-ref']
359 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
360 ns_state
= deployment_status
361 config_status
= nsr
['config-status'] if 'config-status' in nsr
else 'Not found'
362 current_operation
= "Unknown"
363 error_details
= nsr
['detailed-status'] if 'detailed-status' in nsr
else 'Not found'
364 if config_status
== "config_not_needed":
365 config_status
= "configured (no charms)"
374 wrap_text(text
=error_details
,width
=40),
386 wrap_text(text
=error_details
,width
=40)])
389 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
390 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
392 def nsd_list(ctx
, filter, long):
395 check_client_version(ctx
.obj
, '--filter')
396 resp
= ctx
.obj
.nsd
.list(filter)
398 resp
= ctx
.obj
.nsd
.list()
399 # print(yaml.safe_dump(resp))
400 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
401 if fullclassname
== 'osmclient.sol005.client.Client':
403 table
= PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state',
404 'usage state', 'date', 'last update'])
406 table
= PrettyTable(['nsd name', 'id'])
408 name
= nsd
.get('name','-')
410 onb_state
= nsd
['_admin'].get('onboardingState','-')
411 op_state
= nsd
['_admin'].get('operationalState','-')
412 usage_state
= nsd
['_admin'].get('usageState','-')
413 date
= datetime
.fromtimestamp(nsd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
414 last_update
= datetime
.fromtimestamp(nsd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
415 table
.add_row([name
, nsd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
417 table
.add_row([name
, nsd
['_id']])
419 table
= PrettyTable(['nsd name', 'id'])
421 table
.add_row([nsd
['name'], nsd
['id']])
426 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
427 @click.option('--filter', default
=None,
428 help='restricts the list to the NSD/NSpkg matching the filter')
429 @click.option('--long', is_flag
=True, help='get more details')
431 def nsd_list1(ctx
, filter, long):
432 """list all NSD/NS pkg in the system"""
434 nsd_list(ctx
, filter, long)
437 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
438 @click.option('--filter', default
=None,
439 help='restricts the list to the NSD/NSpkg matching the filter')
440 @click.option('--long', is_flag
=True, help='get more details')
442 def nsd_list2(ctx
, filter, long):
443 """list all NS packages"""
445 nsd_list(ctx
, filter, long)
448 def vnfd_list(ctx
, nf_type
, filter, long):
451 check_client_version(ctx
.obj
, '--nf_type')
453 check_client_version(ctx
.obj
, '--filter')
456 nf_filter
= "_admin.type=vnfd"
457 elif nf_type
== "pnf":
458 nf_filter
= "_admin.type=pnfd"
459 elif nf_type
== "hnf":
460 nf_filter
= "_admin.type=hnfd"
462 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
464 filter = '{}&{}'.format(nf_filter
, filter)
468 resp
= ctx
.obj
.vnfd
.list(filter)
470 resp
= ctx
.obj
.vnfd
.list()
471 # print(yaml.safe_dump(resp))
472 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
473 if fullclassname
== 'osmclient.sol005.client.Client':
475 table
= PrettyTable(['nfpkg name', 'id', 'onboarding state', 'operational state',
476 'usage state', 'date', 'last update'])
478 table
= PrettyTable(['nfpkg name', 'id'])
480 name
= vnfd
['name'] if 'name' in vnfd
else '-'
482 onb_state
= vnfd
['_admin'].get('onboardingState','-')
483 op_state
= vnfd
['_admin'].get('operationalState','-')
484 usage_state
= vnfd
['_admin'].get('usageState','-')
485 date
= datetime
.fromtimestamp(vnfd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
486 last_update
= datetime
.fromtimestamp(vnfd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
487 table
.add_row([name
, vnfd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
489 table
.add_row([name
, vnfd
['_id']])
491 table
= PrettyTable(['nfpkg name', 'id'])
493 table
.add_row([vnfd
['name'], vnfd
['id']])
498 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
499 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
500 @click.option('--filter', default
=None,
501 help='restricts the list to the NF pkg matching the filter')
502 @click.option('--long', is_flag
=True, help='get more details')
504 def vnfd_list1(ctx
, nf_type
, filter, long):
505 """list all xNF packages (VNF, HNF, PNF)"""
507 vnfd_list(ctx
, nf_type
, filter, long)
510 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
511 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
512 @click.option('--filter', default
=None,
513 help='restricts the list to the NFpkg matching the filter')
514 @click.option('--long', is_flag
=True, help='get more details')
516 def vnfd_list2(ctx
, nf_type
, filter, long):
517 """list all xNF packages (VNF, HNF, PNF)"""
519 vnfd_list(ctx
, nf_type
, filter, long)
522 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
523 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
524 @click.option('--filter', default
=None,
525 help='restricts the list to the NFpkg matching the filter')
526 @click.option('--long', is_flag
=True, help='get more details')
528 def nfpkg_list(ctx
, nf_type
, filter, long):
529 """list all xNF packages (VNF, HNF, PNF)"""
532 check_client_version(ctx
.obj
, ctx
.command
.name
)
533 vnfd_list(ctx
, nf_type
, filter, long)
534 # except ClientException as e:
539 def vnf_list(ctx
, ns
, filter, long):
543 check_client_version(ctx
.obj
, '--ns')
545 check_client_version(ctx
.obj
, '--filter')
546 resp
= ctx
.obj
.vnf
.list(ns
, filter)
548 resp
= ctx
.obj
.vnf
.list()
549 # except ClientException as e:
552 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
553 if fullclassname
== 'osmclient.sol005.client.Client':
554 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
555 'vnfd name', 'vim account id', 'ip address']
557 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
558 'vnfd name', 'vim account id', 'ip address',
559 'date', 'last update']
560 table
= PrettyTable(field_names
)
562 name
= vnfr
['name'] if 'name' in vnfr
else '-'
563 new_row
= [vnfr
['_id'], name
, vnfr
['nsr-id-ref'],
564 vnfr
['member-vnf-index-ref'], vnfr
['vnfd-ref'],
565 vnfr
['vim-account-id'], vnfr
['ip-address']]
567 date
= datetime
.fromtimestamp(vnfr
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
568 last_update
= datetime
.fromtimestamp(vnfr
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
569 new_row
.extend([date
, last_update
])
570 table
.add_row(new_row
)
575 'operational status',
578 if 'mgmt-interface' not in vnfr
:
579 vnfr
['mgmt-interface'] = {}
580 vnfr
['mgmt-interface']['ip-address'] = None
584 vnfr
['operational-status'],
585 vnfr
['config-status']])
590 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
591 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
592 @click.option('--filter', default
=None,
593 help='restricts the list to the NF instances matching the filter.')
594 @click.option('--long', is_flag
=True, help='get more details')
596 def vnf_list1(ctx
, ns
, filter, long):
597 """list all NF instances"""
599 vnf_list(ctx
, ns
, filter, long)
602 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
603 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
604 @click.option('--filter', default
=None,
605 help='restricts the list to the NF instances matching the filter.')
606 @click.option('--long', is_flag
=True, help='get more details')
608 def nf_list(ctx
, ns
, filter, long):
609 """list all NF instances
613 --ns TEXT NS instance id or name to restrict the VNF list
614 --filter filterExpr Restricts the list to the VNF instances matching the filter
617 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
618 concatenated using the "&" character:
621 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
622 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
623 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
625 value := scalar value
629 * zero or more occurrences
630 ? zero or one occurrence
631 [] grouping of expressions to be used with ? and *
632 "" quotation marks for marking string constants
636 "AttrName" is the name of one attribute in the data type that defines the representation
637 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
638 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
639 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
640 entries, it means that the operator "op" is applied to the attribute addressed by the last
641 <attrName> entry included in the concatenation. All simple filter expressions are combined
642 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
643 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
644 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
645 prefix". If an attribute referenced in an expression is an array, an object that contains a
646 corresponding array shall be considered to match the expression if any of the elements in the
647 array matches all expressions that have the same attribute prefix.
651 --filter vim-account-id=<VIM_ACCOUNT_ID>
652 --filter vnfd-ref=<VNFD_NAME>
653 --filter vdur.ip-address=<IP_ADDRESS>
654 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
657 vnf_list(ctx
, ns
, filter)
660 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
661 @click.argument('name')
662 @click.option('--long', is_flag
=True,
663 help='get more details of the NS operation (date, ).')
665 def ns_op_list(ctx
, name
, long):
666 """shows the history of operations over a NS instance
668 NAME: name or ID of the NS instance
670 def formatParams(params
):
671 if params
['lcmOperationType']=='instantiate':
672 params
.pop('nsDescription')
676 elif params
['lcmOperationType']=='action':
677 params
.pop('primitive')
678 params
.pop('lcmOperationType')
679 params
.pop('nsInstanceId')
684 check_client_version(ctx
.obj
, ctx
.command
.name
)
685 resp
= ctx
.obj
.ns
.list_op(name
)
686 # except ClientException as e:
691 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
693 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
695 #print(yaml.safe_dump(resp))
698 if op
['lcmOperationType']=='action':
699 action_name
= op
['operationParams']['primitive']
701 if op
['operationState']=='PROCESSING':
702 if op
['lcmOperationType']=='instantiate':
706 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
707 elif op
['operationState']=='FAILED' or op
['operationState']=='FAILED_TEMP':
708 detail
= op
['errorMessage']
709 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
710 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
712 table
.add_row([op
['id'],
713 op
['lcmOperationType'],
715 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
716 op
['operationState'],
719 wrap_text(text
=detail
,width
=50)])
721 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
722 op
['operationState'], date
, wrap_text(text
=detail
,width
=50)])
727 def nsi_list(ctx
, filter):
728 """list all Network Slice Instances"""
731 check_client_version(ctx
.obj
, ctx
.command
.name
)
732 resp
= ctx
.obj
.nsi
.list(filter)
733 # except ClientException as e:
737 ['netslice instance name',
739 'operational status',
743 nsi_name
= nsi
['name']
745 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
746 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
747 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
748 if configstatus
== "config_not_needed":
749 configstatus
= "configured (no charms)"
760 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
761 @click.option('--filter', default
=None,
762 help='restricts the list to the Network Slice Instances matching the filter')
764 def nsi_list1(ctx
, filter):
765 """list all Network Slice Instances (NSI)"""
767 nsi_list(ctx
, filter)
770 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
771 @click.option('--filter', default
=None,
772 help='restricts the list to the Network Slice Instances matching the filter')
774 def nsi_list2(ctx
, filter):
775 """list all Network Slice Instances (NSI)"""
777 nsi_list(ctx
, filter)
780 def nst_list(ctx
, filter):
783 check_client_version(ctx
.obj
, ctx
.command
.name
)
784 resp
= ctx
.obj
.nst
.list(filter)
785 # except ClientException as e:
788 # print(yaml.safe_dump(resp))
789 table
= PrettyTable(['nst name', 'id'])
791 name
= nst
['name'] if 'name' in nst
else '-'
792 table
.add_row([name
, nst
['_id']])
797 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
798 @click.option('--filter', default
=None,
799 help='restricts the list to the NST matching the filter')
801 def nst_list1(ctx
, filter):
802 """list all Network Slice Templates (NST) in the system"""
804 nst_list(ctx
, filter)
807 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
808 @click.option('--filter', default
=None,
809 help='restricts the list to the NST matching the filter')
811 def nst_list2(ctx
, filter):
812 """list all Network Slice Templates (NST) in the system"""
814 nst_list(ctx
, filter)
817 def nsi_op_list(ctx
, name
):
820 check_client_version(ctx
.obj
, ctx
.command
.name
)
821 resp
= ctx
.obj
.nsi
.list_op(name
)
822 # except ClientException as e:
825 table
= PrettyTable(['id', 'operation', 'status'])
827 table
.add_row([op
['id'], op
['lcmOperationType'],
828 op
['operationState']])
833 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
834 @click.argument('name')
836 def nsi_op_list1(ctx
, name
):
837 """shows the history of operations over a Network Slice Instance (NSI)
839 NAME: name or ID of the Network Slice Instance
842 nsi_op_list(ctx
, name
)
845 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
846 @click.argument('name')
848 def nsi_op_list2(ctx
, name
):
849 """shows the history of operations over a Network Slice Instance (NSI)
851 NAME: name or ID of the Network Slice Instance
854 nsi_op_list(ctx
, name
)
857 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
858 @click.option('--filter', default
=None,
859 help='restricts the list to the Physical Deployment Units matching the filter')
861 def pdu_list(ctx
, filter):
862 """list all Physical Deployment Units (PDU)"""
865 check_client_version(ctx
.obj
, ctx
.command
.name
)
866 resp
= ctx
.obj
.pdu
.list(filter)
867 # except ClientException as e:
876 pdu_name
= pdu
['name']
878 pdu_type
= pdu
['type']
879 pdu_ipaddress
= "None"
880 for iface
in pdu
['interfaces']:
882 pdu_ipaddress
= iface
['ip-address']
897 def nsd_show(ctx
, name
, literal
):
900 resp
= ctx
.obj
.nsd
.get(name
)
901 # resp = ctx.obj.nsd.get_individual(name)
902 # except ClientException as e:
907 print(yaml
.safe_dump(resp
))
910 table
= PrettyTable(['field', 'value'])
911 for k
, v
in list(resp
.items()):
912 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
917 @cli_osm.command(name
='nsd-show', short_help
='shows the content of a NSD')
918 @click.option('--literal', is_flag
=True,
919 help='print literally, no pretty table')
920 @click.argument('name')
922 def nsd_show1(ctx
, name
, literal
):
923 """shows the content of a NSD
925 NAME: name or ID of the NSD/NSpkg
928 nsd_show(ctx
, name
, literal
)
931 @cli_osm.command(name
='nspkg-show', short_help
='shows the content of a NSD')
932 @click.option('--literal', is_flag
=True,
933 help='print literally, no pretty table')
934 @click.argument('name')
936 def nsd_show2(ctx
, name
, literal
):
937 """shows the content of a NSD
939 NAME: name or ID of the NSD/NSpkg
942 nsd_show(ctx
, name
, literal
)
945 def vnfd_show(ctx
, name
, literal
):
948 resp
= ctx
.obj
.vnfd
.get(name
)
949 # resp = ctx.obj.vnfd.get_individual(name)
950 # except ClientException as e:
955 print(yaml
.safe_dump(resp
))
958 table
= PrettyTable(['field', 'value'])
959 for k
, v
in list(resp
.items()):
960 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
965 @cli_osm.command(name
='vnfd-show', short_help
='shows the content of a VNFD')
966 @click.option('--literal', is_flag
=True,
967 help='print literally, no pretty table')
968 @click.argument('name')
970 def vnfd_show1(ctx
, name
, literal
):
971 """shows the content of a VNFD
973 NAME: name or ID of the VNFD/VNFpkg
976 vnfd_show(ctx
, name
, literal
)
979 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the content of a VNFD')
980 @click.option('--literal', is_flag
=True,
981 help='print literally, no pretty table')
982 @click.argument('name')
984 def vnfd_show2(ctx
, name
, literal
):
985 """shows the content of a VNFD
987 NAME: name or ID of the VNFD/VNFpkg
990 vnfd_show(ctx
, name
, literal
)
993 @cli_osm.command(name
='nfpkg-show', short_help
='shows the content of a NF Descriptor')
994 @click.option('--literal', is_flag
=True,
995 help='print literally, no pretty table')
996 @click.argument('name')
998 def nfpkg_show(ctx
, name
, literal
):
999 """shows the content of a NF Descriptor
1001 NAME: name or ID of the NFpkg
1004 vnfd_show(ctx
, name
, literal
)
1007 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
1008 @click.argument('name')
1009 @click.option('--literal', is_flag
=True,
1010 help='print literally, no pretty table')
1011 @click.option('--filter', default
=None)
1013 def ns_show(ctx
, name
, literal
, filter):
1014 """shows the info of a NS instance
1016 NAME: name or ID of the NS instance
1020 ns
= ctx
.obj
.ns
.get(name
)
1021 # except ClientException as e:
1026 print(yaml
.safe_dump(ns
))
1029 table
= PrettyTable(['field', 'value'])
1031 for k
, v
in list(ns
.items()):
1032 if filter is None or filter in k
:
1033 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1035 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1036 if fullclassname
!= 'osmclient.sol005.client.Client':
1037 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1038 nsr_optdata
= nsopdata
['nsr:nsr']
1039 for k
, v
in list(nsr_optdata
.items()):
1040 if filter is None or filter in k
:
1041 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1046 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1047 @click.argument('name')
1048 @click.option('--literal', is_flag
=True,
1049 help='print literally, no pretty table')
1050 @click.option('--filter', default
=None, help='restricts the information to the fields in the filter')
1051 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1053 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1054 """shows the info of a VNF instance
1056 NAME: name or ID of the VNF instance
1058 def print_kdu_status(op_info_status
):
1059 """print KDU status properly formatted
1062 op_status
= yaml
.safe_load(op_info_status
)
1063 if "namespace" in op_status
and "info" in op_status
and \
1064 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1065 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1066 "notes" in op_status
["info"]["status"] and "seconds" in op_status
["info"]["last_deployed"]:
1067 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1068 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1069 print("NAMESPACE: {}".format(op_status
["namespace"]))
1070 status_code
= "UNKNOWN"
1071 if op_status
["info"]["status"]["code"]==1:
1072 status_code
= "DEPLOYED"
1073 print("STATUS: {}".format(status_code
))
1076 print(op_status
["info"]["status"]["resources"])
1078 print(op_status
["info"]["status"]["notes"])
1080 print(op_info_status
)
1082 print(op_info_status
)
1087 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1089 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1092 check_client_version(ctx
.obj
, ctx
.command
.name
)
1093 resp
= ctx
.obj
.vnf
.get(name
)
1096 ns_id
= resp
['nsr-id-ref']
1098 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1099 op_data
['kdu_name'] = kdu
1100 op_data
['primitive'] = 'status'
1101 op_data
['primitive_params'] = {}
1102 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1105 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1106 if op_info
['operationState'] == 'COMPLETED':
1107 print_kdu_status(op_info
['detailed-status'])
1111 print ("Could not determine KDU status")
1114 print(yaml
.safe_dump(resp
))
1117 table
= PrettyTable(['field', 'value'])
1119 for k
, v
in list(resp
.items()):
1120 if filter is None or filter in k
:
1121 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1124 # except ClientException as e:
1129 #@cli_osm.command(name='vnf-monitoring-show')
1130 #@click.argument('vnf_name')
1131 #@click.pass_context
1132 #def vnf_monitoring_show(ctx, vnf_name):
1134 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1135 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1136 # except ClientException as e:
1140 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1141 # if resp is not None:
1142 # for monitor in resp:
1146 # monitor['value-integer'],
1147 # monitor['units']])
1152 #@cli_osm.command(name='ns-monitoring-show')
1153 #@click.argument('ns_name')
1154 #@click.pass_context
1155 #def ns_monitoring_show(ctx, ns_name):
1157 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1158 # resp = ctx.obj.ns.get_monitoring(ns_name)
1159 # except ClientException as e:
1163 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1164 # for key, val in list(resp.items()):
1165 # for monitor in val:
1169 # monitor['value-integer'],
1170 # monitor['units']])
1175 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1176 @click.argument('id')
1177 @click.option('--filter', default
=None)
1178 @click.option('--literal', is_flag
=True,
1179 help='print literally, no pretty table')
1181 def ns_op_show(ctx
, id, filter, literal
):
1182 """shows the detailed info of a NS operation
1184 ID: operation identifier
1188 check_client_version(ctx
.obj
, ctx
.command
.name
)
1189 op_info
= ctx
.obj
.ns
.get_op(id)
1190 # except ClientException as e:
1195 print(yaml
.safe_dump(op_info
))
1198 table
= PrettyTable(['field', 'value'])
1199 for k
, v
in list(op_info
.items()):
1200 if filter is None or filter in k
:
1201 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1206 def nst_show(ctx
, name
, literal
):
1209 check_client_version(ctx
.obj
, ctx
.command
.name
)
1210 resp
= ctx
.obj
.nst
.get(name
)
1211 #resp = ctx.obj.nst.get_individual(name)
1212 # except ClientException as e:
1217 print(yaml
.safe_dump(resp
))
1220 table
= PrettyTable(['field', 'value'])
1221 for k
, v
in list(resp
.items()):
1222 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1227 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1228 @click.option('--literal', is_flag
=True,
1229 help='print literally, no pretty table')
1230 @click.argument('name')
1232 def nst_show1(ctx
, name
, literal
):
1233 """shows the content of a Network Slice Template (NST)
1235 NAME: name or ID of the NST
1238 nst_show(ctx
, name
, literal
)
1241 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1242 @click.option('--literal', is_flag
=True,
1243 help='print literally, no pretty table')
1244 @click.argument('name')
1246 def nst_show2(ctx
, name
, literal
):
1247 """shows the content of a Network Slice Template (NST)
1249 NAME: name or ID of the NST
1252 nst_show(ctx
, name
, literal
)
1255 def nsi_show(ctx
, name
, literal
, filter):
1258 check_client_version(ctx
.obj
, ctx
.command
.name
)
1259 nsi
= ctx
.obj
.nsi
.get(name
)
1260 # except ClientException as e:
1265 print(yaml
.safe_dump(nsi
))
1268 table
= PrettyTable(['field', 'value'])
1270 for k
, v
in list(nsi
.items()):
1271 if filter is None or filter in k
:
1272 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1278 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1279 @click.argument('name')
1280 @click.option('--literal', is_flag
=True,
1281 help='print literally, no pretty table')
1282 @click.option('--filter', default
=None)
1284 def nsi_show1(ctx
, name
, literal
, filter):
1285 """shows the content of a Network Slice Instance (NSI)
1287 NAME: name or ID of the Network Slice Instance
1290 nsi_show(ctx
, name
, literal
, filter)
1293 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1294 @click.argument('name')
1295 @click.option('--literal', is_flag
=True,
1296 help='print literally, no pretty table')
1297 @click.option('--filter', default
=None)
1299 def nsi_show2(ctx
, name
, literal
, filter):
1300 """shows the content of a Network Slice Instance (NSI)
1302 NAME: name or ID of the Network Slice Instance
1305 nsi_show(ctx
, name
, literal
, filter)
1308 def nsi_op_show(ctx
, id, filter):
1311 check_client_version(ctx
.obj
, ctx
.command
.name
)
1312 op_info
= ctx
.obj
.nsi
.get_op(id)
1313 # except ClientException as e:
1317 table
= PrettyTable(['field', 'value'])
1318 for k
, v
in list(op_info
.items()):
1319 if filter is None or filter in k
:
1320 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1325 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1326 @click.argument('id')
1327 @click.option('--filter', default
=None)
1329 def nsi_op_show1(ctx
, id, filter):
1330 """shows the info of an operation over a Network Slice Instance(NSI)
1332 ID: operation identifier
1335 nsi_op_show(ctx
, id, filter)
1338 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1339 @click.argument('id')
1340 @click.option('--filter', default
=None)
1342 def nsi_op_show2(ctx
, id, filter):
1343 """shows the info of an operation over a Network Slice Instance(NSI)
1345 ID: operation identifier
1348 nsi_op_show(ctx
, id, filter)
1351 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1352 @click.argument('name')
1353 @click.option('--literal', is_flag
=True,
1354 help='print literally, no pretty table')
1355 @click.option('--filter', default
=None)
1357 def pdu_show(ctx
, name
, literal
, filter):
1358 """shows the content of a Physical Deployment Unit (PDU)
1360 NAME: name or ID of the PDU
1364 check_client_version(ctx
.obj
, ctx
.command
.name
)
1365 pdu
= ctx
.obj
.pdu
.get(name
)
1366 # except ClientException as e:
1371 print(yaml
.safe_dump(pdu
))
1374 table
= PrettyTable(['field', 'value'])
1376 for k
, v
in list(pdu
.items()):
1377 if filter is None or filter in k
:
1378 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1384 ####################
1386 ####################
1388 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
):
1391 check_client_version(ctx
.obj
, ctx
.command
.name
)
1392 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1393 # except ClientException as e:
1398 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1399 @click.argument('filename')
1400 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1401 help='Deprecated. Use override')
1402 @click.option('--override', 'overwrite', default
=None,
1403 help='overrides fields in descriptor, format: '
1404 '"key1.key2...=value[;key3...=value;...]"')
1405 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1406 help='The charm will not be compiled, it is assumed to already exist')
1408 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
):
1409 """creates a new NSD/NSpkg
1411 FILENAME: NSD yaml file or NSpkg tar.gz file
1414 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1417 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1418 @click.argument('filename')
1419 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1420 help='Deprecated. Use override')
1421 @click.option('--override', 'overwrite', default
=None,
1422 help='overrides fields in descriptor, format: '
1423 '"key1.key2...=value[;key3...=value;...]"')
1424 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1425 help='The charm will not be compiled, it is assumed to already exist')
1427 def nsd_create2(ctx
, filename
, overwrite
, skip_charm_build
):
1428 """creates a new NSD/NSpkg
1430 FILENAME: NSD folder, NSD yaml file or NSpkg tar.gz file
1433 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1436 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
):
1439 check_client_version(ctx
.obj
, ctx
.command
.name
)
1440 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1441 # except ClientException as e:
1446 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1447 @click.argument('filename')
1448 @click.option('--overwrite', 'overwrite', default
=None,
1449 help='overwrite deprecated, use override')
1450 @click.option('--override', 'overwrite', default
=None,
1451 help='overrides fields in descriptor, format: '
1452 '"key1.key2...=value[;key3...=value;...]"')
1453 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1454 help='The charm will not be compiled, it is assumed to already exist')
1456 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
):
1457 """creates a new VNFD/VNFpkg
1459 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1462 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1465 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1466 @click.argument('filename')
1467 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1468 help='Deprecated. Use override')
1469 @click.option('--override', 'overwrite', default
=None,
1470 help='overrides fields in descriptor, format: '
1471 '"key1.key2...=value[;key3...=value;...]"')
1472 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1473 help='The charm will not be compiled, it is assumed to already exist')
1475 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
):
1476 """creates a new VNFD/VNFpkg
1478 FILENAME: NF Package Folder, NF Descriptor yaml file or NFpkg tar.gz file
1481 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1484 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1485 @click.argument('filename')
1486 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1487 help='Deprecated. Use override')
1488 @click.option('--override', 'overwrite', default
=None,
1489 help='overrides fields in descriptor, format: '
1490 '"key1.key2...=value[;key3...=value;...]"')
1491 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1492 help='The charm will not be compiled, it is assumed to already exist')
1494 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
):
1495 """creates a new NFpkg
1497 FILENAME: NF Package Folder, NF Descriptor yaml file or NFpkg tar.gz filems to build
1500 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1503 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1504 @click.option('--ns_name',
1505 prompt
=True, help='name of the NS instance')
1506 @click.option('--nsd_name',
1507 prompt
=True, help='name of the NS descriptor')
1508 @click.option('--vim_account',
1509 prompt
=True, help='default VIM account id or name for the deployment')
1510 @click.option('--admin_status',
1512 help='administration status')
1513 @click.option('--ssh_keys',
1515 help='comma separated list of public key files to inject to vnfs')
1516 @click.option('--config',
1518 help='ns specific yaml configuration')
1519 @click.option('--config_file',
1521 help='ns specific yaml configuration file')
1522 @click.option('--wait',
1526 help='do not return the control immediately, but keep it '
1527 'until the operation is completed, or timeout')
1538 """creates a new NS instance"""
1542 check_client_version(ctx
.obj
, '--config_file')
1544 raise ClientException('"--config" option is incompatible with "--config_file" option')
1545 with
open(config_file
, 'r') as cf
:
1552 account
=vim_account
,
1554 # except ClientException as e:
1559 def nst_create(ctx
, filename
, overwrite
):
1562 check_client_version(ctx
.obj
, ctx
.command
.name
)
1563 ctx
.obj
.nst
.create(filename
, overwrite
)
1564 # except ClientException as e:
1569 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1570 @click.argument('filename')
1571 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1572 help='Deprecated. Use override')
1573 @click.option('--override', 'overwrite', default
=None,
1574 help='overrides fields in descriptor, format: '
1575 '"key1.key2...=value[;key3...=value;...]"')
1577 def nst_create1(ctx
, charm_folder
, overwrite
):
1578 """creates a new Network Slice Template (NST)
1580 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1583 nst_create(ctx
, charm_folder
, overwrite
)
1586 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1587 @click.argument('filename')
1588 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1589 help='Deprecated. Use override')
1590 @click.option('--override', 'overwrite', default
=None,
1591 help='overrides fields in descriptor, format: '
1592 '"key1.key2...=value[;key3...=value;...]"')
1594 def nst_create2(ctx
, filename
, overwrite
):
1595 """creates a new Network Slice Template (NST)
1597 FILENAME: NST yaml file or NSTpkg tar.gz file
1600 nst_create(ctx
, filename
, overwrite
)
1603 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1604 """creates a new Network Slice Instance (NSI)"""
1607 check_client_version(ctx
.obj
, ctx
.command
.name
)
1610 raise ClientException('"--config" option is incompatible with "--config_file" option')
1611 with
open(config_file
, 'r') as cf
:
1613 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1614 account
=vim_account
, wait
=wait
)
1615 # except ClientException as e:
1620 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1621 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1622 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1623 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1624 @click.option('--ssh_keys', default
=None,
1625 help='comma separated list of keys to inject to vnfs')
1626 @click.option('--config', default
=None,
1627 help='Netslice specific yaml configuration:\n'
1628 'netslice_subnet: [\n'
1629 'id: TEXT, vim_account: TEXT,\n'
1630 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1631 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1632 'additionalParamsForNsi: {param: value, ...}\n'
1633 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1635 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1637 @click.option('--config_file',
1639 help='nsi specific yaml configuration file')
1640 @click.option('--wait',
1644 help='do not return the control immediately, but keep it '
1645 'until the operation is completed, or timeout')
1647 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1648 """creates a new Network Slice Instance (NSI)"""
1650 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1653 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1654 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1655 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1656 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1657 @click.option('--ssh_keys', default
=None,
1658 help='comma separated list of keys to inject to vnfs')
1659 @click.option('--config', default
=None,
1660 help='Netslice specific yaml configuration:\n'
1661 'netslice_subnet: [\n'
1662 'id: TEXT, vim_account: TEXT,\n'
1663 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1664 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1666 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1668 @click.option('--config_file',
1670 help='nsi specific yaml configuration file')
1671 @click.option('--wait',
1675 help='do not return the control immediately, but keep it '
1676 'until the operation is completed, or timeout')
1678 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1679 """creates a new Network Slice Instance (NSI)"""
1681 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1684 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1685 @click.option('--name', help='name of the Physical Deployment Unit')
1686 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1687 @click.option('--interface',
1688 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1689 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1691 @click.option('--description', help='human readable description')
1692 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
1693 @click.option('--descriptor_file', default
=None,
1694 help='PDU descriptor file (as an alternative to using the other arguments')
1696 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
1697 """creates a new Physical Deployment Unit (PDU)"""
1700 check_client_version(ctx
.obj
, ctx
.command
.name
)
1702 if not descriptor_file
:
1704 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1706 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1708 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1710 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1712 with
open(descriptor_file
, 'r') as df
:
1713 pdu
= yaml
.safe_load(df
.read())
1714 if name
: pdu
["name"] = name
1715 if pdu_type
: pdu
["type"] = pdu_type
1716 if description
: pdu
["description"] = description
1717 if vim_account
: pdu
["vim_accounts"] = vim_account
1720 for iface
in interface
:
1721 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
1722 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
1723 ifaces_list
.append(new_iface
)
1724 pdu
["interfaces"] = ifaces_list
1725 ctx
.obj
.pdu
.create(pdu
)
1726 # except ClientException as e:
1731 ####################
1733 ####################
1735 def nsd_update(ctx
, name
, content
):
1738 check_client_version(ctx
.obj
, ctx
.command
.name
)
1739 ctx
.obj
.nsd
.update(name
, content
)
1740 # except ClientException as e:
1745 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
1746 @click.argument('name')
1747 @click.option('--content', default
=None,
1748 help='filename with the NSD/NSpkg replacing the current one')
1750 def nsd_update1(ctx
, name
, content
):
1751 """updates a NSD/NSpkg
1753 NAME: name or ID of the NSD/NSpkg
1756 nsd_update(ctx
, name
, content
)
1759 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
1760 @click.argument('name')
1761 @click.option('--content', default
=None,
1762 help='filename with the NSD/NSpkg replacing the current one')
1764 def nsd_update2(ctx
, name
, content
):
1765 """updates a NSD/NSpkg
1767 NAME: name or ID of the NSD/NSpkg
1770 nsd_update(ctx
, name
, content
)
1773 def vnfd_update(ctx
, name
, content
):
1776 check_client_version(ctx
.obj
, ctx
.command
.name
)
1777 ctx
.obj
.vnfd
.update(name
, content
)
1778 # except ClientException as e:
1783 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
1784 @click.argument('name')
1785 @click.option('--content', default
=None,
1786 help='filename with the VNFD/VNFpkg replacing the current one')
1788 def vnfd_update1(ctx
, name
, content
):
1789 """updates a VNFD/VNFpkg
1791 NAME: name or ID of the VNFD/VNFpkg
1794 vnfd_update(ctx
, name
, content
)
1797 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
1798 @click.argument('name')
1799 @click.option('--content', default
=None,
1800 help='filename with the VNFD/VNFpkg replacing the current one')
1802 def vnfd_update2(ctx
, name
, content
):
1803 """updates a VNFD/VNFpkg
1805 NAME: VNFD yaml file or VNFpkg tar.gz file
1808 vnfd_update(ctx
, name
, content
)
1811 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
1812 @click.argument('name')
1813 @click.option('--content', default
=None,
1814 help='filename with the NFpkg replacing the current one')
1816 def nfpkg_update(ctx
, name
, content
):
1819 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1822 vnfd_update(ctx
, name
, content
)
1825 def nst_update(ctx
, name
, content
):
1828 check_client_version(ctx
.obj
, ctx
.command
.name
)
1829 ctx
.obj
.nst
.update(name
, content
)
1830 # except ClientException as e:
1835 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
1836 @click.argument('name')
1837 @click.option('--content', default
=None,
1838 help='filename with the NST/NSTpkg replacing the current one')
1840 def nst_update1(ctx
, name
, content
):
1841 """updates a Network Slice Template (NST)
1843 NAME: name or ID of the NSD/NSpkg
1846 nst_update(ctx
, name
, content
)
1849 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
1850 @click.argument('name')
1851 @click.option('--content', default
=None,
1852 help='filename with the NST/NSTpkg replacing the current one')
1854 def nst_update2(ctx
, name
, content
):
1855 """updates a Network Slice Template (NST)
1857 NAME: name or ID of the NSD/NSpkg
1860 nst_update(ctx
, name
, content
)
1863 ####################
1865 ####################
1867 def nsd_delete(ctx
, name
, force
):
1871 ctx
.obj
.nsd
.delete(name
)
1873 check_client_version(ctx
.obj
, '--force')
1874 ctx
.obj
.nsd
.delete(name
, force
)
1875 # except ClientException as e:
1880 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
1881 @click.argument('name')
1882 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1884 def nsd_delete1(ctx
, name
, force
):
1885 """deletes a NSD/NSpkg
1887 NAME: name or ID of the NSD/NSpkg to be deleted
1890 nsd_delete(ctx
, name
, force
)
1893 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
1894 @click.argument('name')
1895 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1897 def nsd_delete2(ctx
, name
, force
):
1898 """deletes a NSD/NSpkg
1900 NAME: name or ID of the NSD/NSpkg to be deleted
1903 nsd_delete(ctx
, name
, force
)
1906 def vnfd_delete(ctx
, name
, force
):
1910 ctx
.obj
.vnfd
.delete(name
)
1912 check_client_version(ctx
.obj
, '--force')
1913 ctx
.obj
.vnfd
.delete(name
, force
)
1914 # except ClientException as e:
1919 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
1920 @click.argument('name')
1921 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1923 def vnfd_delete1(ctx
, name
, force
):
1924 """deletes a VNFD/VNFpkg
1926 NAME: name or ID of the VNFD/VNFpkg to be deleted
1929 vnfd_delete(ctx
, name
, force
)
1932 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
1933 @click.argument('name')
1934 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1936 def vnfd_delete2(ctx
, name
, force
):
1937 """deletes a VNFD/VNFpkg
1939 NAME: name or ID of the VNFD/VNFpkg to be deleted
1942 vnfd_delete(ctx
, name
, force
)
1945 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
1946 @click.argument('name')
1947 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1949 def nfpkg_delete(ctx
, name
, force
):
1952 NAME: name or ID of the NFpkg to be deleted
1955 vnfd_delete(ctx
, name
, force
)
1958 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
1959 @click.argument('name')
1960 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1961 @click.option('--wait',
1965 help='do not return the control immediately, but keep it '
1966 'until the operation is completed, or timeout')
1968 def ns_delete(ctx
, name
, force
, wait
):
1969 """deletes a NS instance
1971 NAME: name or ID of the NS instance to be deleted
1976 ctx
.obj
.ns
.delete(name
, wait
=wait
)
1978 check_client_version(ctx
.obj
, '--force')
1979 ctx
.obj
.ns
.delete(name
, force
, wait
=wait
)
1980 # except ClientException as e:
1985 def nst_delete(ctx
, name
, force
):
1988 check_client_version(ctx
.obj
, ctx
.command
.name
)
1989 ctx
.obj
.nst
.delete(name
, force
)
1990 # except ClientException as e:
1995 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
1996 @click.argument('name')
1997 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1999 def nst_delete1(ctx
, name
, force
):
2000 """deletes a Network Slice Template (NST)
2002 NAME: name or ID of the NST/NSTpkg to be deleted
2005 nst_delete(ctx
, name
, force
)
2008 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
2009 @click.argument('name')
2010 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2012 def nst_delete2(ctx
, name
, force
):
2013 """deletes a Network Slice Template (NST)
2015 NAME: name or ID of the NST/NSTpkg to be deleted
2018 nst_delete(ctx
, name
, force
)
2021 def nsi_delete(ctx
, name
, force
, wait
):
2024 check_client_version(ctx
.obj
, ctx
.command
.name
)
2025 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2026 # except ClientException as e:
2031 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2032 @click.argument('name')
2033 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2034 @click.option('--wait',
2038 help='do not return the control immediately, but keep it '
2039 'until the operation is completed, or timeout')
2041 def nsi_delete1(ctx
, name
, force
, wait
):
2042 """deletes a Network Slice Instance (NSI)
2044 NAME: name or ID of the Network Slice instance to be deleted
2047 nsi_delete(ctx
, name
, force
, wait
=wait
)
2050 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2051 @click.argument('name')
2052 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2054 def nsi_delete2(ctx
, name
, force
, wait
):
2055 """deletes a Network Slice Instance (NSI)
2057 NAME: name or ID of the Network Slice instance to be deleted
2060 nsi_delete(ctx
, name
, force
, wait
=wait
)
2063 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2064 @click.argument('name')
2065 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2067 def pdu_delete(ctx
, name
, force
):
2068 """deletes a Physical Deployment Unit (PDU)
2070 NAME: name or ID of the PDU to be deleted
2074 check_client_version(ctx
.obj
, ctx
.command
.name
)
2075 ctx
.obj
.pdu
.delete(name
, force
)
2076 # except ClientException as e:
2085 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2086 @click.option('--name',
2088 help='Name to create datacenter')
2089 @click.option('--user',
2091 help='VIM username')
2092 @click.option('--password',
2095 confirmation_prompt
=True,
2096 help='VIM password')
2097 @click.option('--auth_url',
2100 @click.option('--tenant',
2102 help='VIM tenant name')
2103 @click.option('--config',
2105 help='VIM specific config parameters')
2106 @click.option('--account_type',
2107 default
='openstack',
2109 @click.option('--description',
2111 help='human readable description')
2112 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2113 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2114 @click.option('--wait',
2118 help='do not return the control immediately, but keep it '
2119 'until the operation is completed, or timeout')
2133 """creates a new VIM account"""
2137 check_client_version(ctx
.obj
, '--sdn_controller')
2138 if sdn_port_mapping
:
2139 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2141 vim
['vim-username'] = user
2142 vim
['vim-password'] = password
2143 vim
['vim-url'] = auth_url
2144 vim
['vim-tenant-name'] = tenant
2145 vim
['vim-type'] = account_type
2146 vim
['description'] = description
2147 vim
['config'] = config
2148 if sdn_controller
or sdn_port_mapping
:
2149 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2151 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2152 # except ClientException as e:
2157 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2158 @click.argument('name')
2159 @click.option('--newname', help='New name for the VIM account')
2160 @click.option('--user', help='VIM username')
2161 @click.option('--password', help='VIM password')
2162 @click.option('--auth_url', help='VIM url')
2163 @click.option('--tenant', help='VIM tenant name')
2164 @click.option('--config', help='VIM specific config parameters')
2165 @click.option('--account_type', help='VIM type')
2166 @click.option('--description', help='human readable description')
2167 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2168 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2169 @click.option('--wait',
2173 help='do not return the control immediately, but keep it '
2174 'until the operation is completed, or timeout')
2189 """updates a VIM account
2191 NAME: name or ID of the VIM account
2195 check_client_version(ctx
.obj
, ctx
.command
.name
)
2197 if newname
: vim
['name'] = newname
2198 if user
: vim
['vim_user'] = user
2199 if password
: vim
['vim_password'] = password
2200 if auth_url
: vim
['vim_url'] = auth_url
2201 if tenant
: vim
['vim-tenant-name'] = tenant
2202 if account_type
: vim
['vim_type'] = account_type
2203 if description
: vim
['description'] = description
2204 if config
: vim
['config'] = config
2205 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2206 # except ClientException as e:
2211 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2212 @click.argument('name')
2213 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2214 @click.option('--wait',
2218 help='do not return the control immediately, but keep it '
2219 'until the operation is completed, or timeout')
2221 def vim_delete(ctx
, name
, force
, wait
):
2222 """deletes a VIM account
2224 NAME: name or ID of the VIM account to be deleted
2229 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2231 check_client_version(ctx
.obj
, '--force')
2232 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2233 # except ClientException as e:
2238 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2239 #@click.option('--ro_update/--no_ro_update',
2241 # help='update list from RO')
2242 @click.option('--filter', default
=None,
2243 help='restricts the list to the VIM accounts matching the filter')
2245 def vim_list(ctx
, filter):
2246 """list all VIM accounts"""
2249 check_client_version(ctx
.obj
, '--filter')
2251 # check_client_version(ctx.obj, '--ro_update', 'v1')
2252 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2253 if fullclassname
== 'osmclient.sol005.client.Client':
2254 resp
= ctx
.obj
.vim
.list(filter)
2256 # resp = ctx.obj.vim.list(ro_update)
2257 table
= PrettyTable(['vim name', 'uuid'])
2259 table
.add_row([vim
['name'], vim
['uuid']])
2264 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2265 @click.argument('name')
2267 def vim_show(ctx
, name
):
2268 """shows the details of a VIM account
2270 NAME: name or ID of the VIM account
2274 resp
= ctx
.obj
.vim
.get(name
)
2275 if 'vim_password' in resp
:
2276 resp
['vim_password']='********'
2277 # except ClientException as e:
2281 table
= PrettyTable(['key', 'attribute'])
2282 for k
, v
in list(resp
.items()):
2283 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2288 ####################
2290 ####################
2292 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2293 @click.option('--name',
2295 help='Name for the WIM account')
2296 @click.option('--user',
2297 help='WIM username')
2298 @click.option('--password',
2299 help='WIM password')
2300 @click.option('--url',
2303 # @click.option('--tenant',
2304 # help='wIM tenant name')
2305 @click.option('--config',
2307 help='WIM specific config parameters')
2308 @click.option('--wim_type',
2310 @click.option('--description',
2312 help='human readable description')
2313 @click.option('--wim_port_mapping', default
=None,
2314 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2315 "(WAN service endpoint id and info)")
2316 @click.option('--wait',
2320 help='do not return the control immediately, but keep it '
2321 'until the operation is completed, or timeout')
2334 """creates a new WIM account"""
2337 check_client_version(ctx
.obj
, ctx
.command
.name
)
2338 # if sdn_controller:
2339 # check_client_version(ctx.obj, '--sdn_controller')
2340 # if sdn_port_mapping:
2341 # check_client_version(ctx.obj, '--sdn_port_mapping')
2343 if user
: wim
['user'] = user
2344 if password
: wim
['password'] = password
2345 if url
: wim
['wim_url'] = url
2346 # if tenant: wim['tenant'] = tenant
2347 wim
['wim_type'] = wim_type
2348 if description
: wim
['description'] = description
2349 if config
: wim
['config'] = config
2350 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2351 # except ClientException as e:
2356 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2357 @click.argument('name')
2358 @click.option('--newname', help='New name for the WIM account')
2359 @click.option('--user', help='WIM username')
2360 @click.option('--password', help='WIM password')
2361 @click.option('--url', help='WIM url')
2362 @click.option('--config', help='WIM specific config parameters')
2363 @click.option('--wim_type', help='WIM type')
2364 @click.option('--description', help='human readable description')
2365 @click.option('--wim_port_mapping', default
=None,
2366 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2367 "(WAN service endpoint id and info)")
2368 @click.option('--wait',
2372 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2385 """updates a WIM account
2387 NAME: name or ID of the WIM account
2391 check_client_version(ctx
.obj
, ctx
.command
.name
)
2393 if newname
: wim
['name'] = newname
2394 if user
: wim
['user'] = user
2395 if password
: wim
['password'] = password
2396 if url
: wim
['url'] = url
2397 # if tenant: wim['tenant'] = tenant
2398 if wim_type
: wim
['wim_type'] = wim_type
2399 if description
: wim
['description'] = description
2400 if config
: wim
['config'] = config
2401 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2402 # except ClientException as e:
2407 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2408 @click.argument('name')
2409 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2410 @click.option('--wait',
2414 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2416 def wim_delete(ctx
, name
, force
, wait
):
2417 """deletes a WIM account
2419 NAME: name or ID of the WIM account to be deleted
2423 check_client_version(ctx
.obj
, ctx
.command
.name
)
2424 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2425 # except ClientException as e:
2430 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2431 @click.option('--filter', default
=None,
2432 help='restricts the list to the WIM accounts matching the filter')
2434 def wim_list(ctx
, filter):
2435 """list all WIM accounts"""
2438 check_client_version(ctx
.obj
, ctx
.command
.name
)
2439 resp
= ctx
.obj
.wim
.list(filter)
2440 table
= PrettyTable(['wim name', 'uuid'])
2442 table
.add_row([wim
['name'], wim
['uuid']])
2445 # except ClientException as e:
2450 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2451 @click.argument('name')
2453 def wim_show(ctx
, name
):
2454 """shows the details of a WIM account
2456 NAME: name or ID of the WIM account
2460 check_client_version(ctx
.obj
, ctx
.command
.name
)
2461 resp
= ctx
.obj
.wim
.get(name
)
2462 if 'password' in resp
:
2463 resp
['wim_password']='********'
2464 # except ClientException as e:
2468 table
= PrettyTable(['key', 'attribute'])
2469 for k
, v
in list(resp
.items()):
2470 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2475 ####################
2476 # SDN controller operations
2477 ####################
2479 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2480 @click.option('--name',
2482 help='Name to create sdn controller')
2483 @click.option('--type',
2485 help='SDN controller type')
2486 @click.option('--sdn_controller_version', # hidden=True,
2487 help='Deprecated. Use --config {version: sdn_controller_version}')
2488 @click.option('--url',
2489 help='URL in format http[s]://HOST:IP/')
2490 @click.option('--ip_address', # hidden=True,
2491 help='Deprecated. Use --url')
2492 @click.option('--port', # hidden=True,
2493 help='Deprecated. Use --url')
2494 @click.option('--switch_dpid', # hidden=True,
2495 help='Deprecated. Use --config {dpid: DPID}')
2496 @click.option('--config',
2497 help='Extra information for SDN in yaml format, as {dpid: (Openflow Datapath ID), version: version}')
2498 @click.option('--user',
2499 help='SDN controller username')
2500 @click.option('--password',
2502 confirmation_prompt
=True,
2503 help='SDN controller password')
2504 @click.option('--description', default
=None, help='human readable description')
2505 @click.option('--wait',
2509 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2511 def sdnc_create(ctx
, **kwargs
):
2512 """creates a new SDN controller"""
2514 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2515 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2516 if kwargs
.get("port"):
2517 print("option '--port' is deprecated, use '-url' instead")
2518 sdncontroller
["port"] = int(kwargs
["port"])
2519 if kwargs
.get("ip_address"):
2520 print("option '--ip_address' is deprecated, use '-url' instead")
2521 sdncontroller
["ip"] = kwargs
["ip_address"]
2522 if kwargs
.get("switch_dpid"):
2523 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2524 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2525 if kwargs
.get("sdn_controller_version"):
2526 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2529 check_client_version(ctx
.obj
, ctx
.command
.name
)
2530 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2531 # except ClientException as e:
2535 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2536 @click.argument('name')
2537 @click.option('--newname', help='New name for the SDN controller')
2538 @click.option('--description', default
=None, help='human readable description')
2539 @click.option('--type', help='SDN controller type')
2540 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2541 @click.option('--config', help='Extra information for SDN in yaml format, as '
2542 '{dpid: (Openflow Datapath ID), version: version}')
2543 @click.option('--user', help='SDN controller username')
2544 @click.option('--password', help='SDN controller password')
2545 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2546 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2547 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2548 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2549 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2550 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2552 def sdnc_update(ctx
, **kwargs
):
2553 """updates an SDN controller
2555 NAME: name or ID of the SDN controller
2558 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2559 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2560 if kwargs
.get("newname"):
2561 sdncontroller
["name"] = kwargs
["newname"]
2562 if kwargs
.get("port"):
2563 print("option '--port' is deprecated, use '-url' instead")
2564 sdncontroller
["port"] = int(kwargs
["port"])
2565 if kwargs
.get("ip_address"):
2566 print("option '--ip_address' is deprecated, use '-url' instead")
2567 sdncontroller
["ip"] = kwargs
["ip_address"]
2568 if kwargs
.get("switch_dpid"):
2569 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2570 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2571 if kwargs
.get("sdn_controller_version"):
2572 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2576 check_client_version(ctx
.obj
, ctx
.command
.name
)
2577 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2578 # except ClientException as e:
2583 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2584 @click.argument('name')
2585 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2586 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2587 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2589 def sdnc_delete(ctx
, name
, force
, wait
):
2590 """deletes an SDN controller
2592 NAME: name or ID of the SDN controller to be deleted
2596 check_client_version(ctx
.obj
, ctx
.command
.name
)
2597 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2598 # except ClientException as e:
2603 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2604 @click.option('--filter', default
=None,
2605 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2607 def sdnc_list(ctx
, filter):
2608 """list all SDN controllers"""
2611 check_client_version(ctx
.obj
, ctx
.command
.name
)
2612 resp
= ctx
.obj
.sdnc
.list(filter)
2613 # except ClientException as e:
2616 table
= PrettyTable(['sdnc name', 'id'])
2618 table
.add_row([sdnc
['name'], sdnc
['_id']])
2623 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2624 @click.argument('name')
2626 def sdnc_show(ctx
, name
):
2627 """shows the details of an SDN controller
2629 NAME: name or ID of the SDN controller
2633 check_client_version(ctx
.obj
, ctx
.command
.name
)
2634 resp
= ctx
.obj
.sdnc
.get(name
)
2635 # except ClientException as e:
2639 table
= PrettyTable(['key', 'attribute'])
2640 for k
, v
in list(resp
.items()):
2641 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2646 ###########################
2647 # K8s cluster operations
2648 ###########################
2650 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2651 @click.argument('name')
2652 @click.option('--creds',
2654 help='credentials file, i.e. a valid `.kube/config` file')
2655 @click.option('--version',
2657 help='Kubernetes version')
2658 @click.option('--vim',
2660 help='VIM target, the VIM where the cluster resides')
2661 @click.option('--k8s-nets',
2663 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) ...]}"')
2664 @click.option('--description',
2666 help='human readable description')
2667 @click.option('--namespace',
2668 default
='kube-system',
2669 help='namespace to be used for its operation, defaults to `kube-system`')
2670 @click.option('--cni',
2672 help='list of CNI plugins, in JSON inline format, used in the cluster')
2673 #@click.option('--skip-init',
2675 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2676 #@click.option('--wait',
2678 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2680 def k8scluster_add(ctx
,
2689 """adds a K8s cluster to OSM
2691 NAME: name of the K8s cluster
2694 check_client_version(ctx
.obj
, ctx
.command
.name
)
2696 cluster
['name'] = name
2697 with
open(creds
, 'r') as cf
:
2698 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2699 cluster
['k8s_version'] = version
2700 cluster
['vim_account'] = vim
2701 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2702 cluster
['description'] = description
2703 if namespace
: cluster
['namespace'] = namespace
2704 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2705 ctx
.obj
.k8scluster
.create(name
, cluster
)
2706 # except ClientException as e:
2711 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
2712 @click.argument('name')
2713 @click.option('--newname', help='New name for the K8s cluster')
2714 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
2715 @click.option('--version', help='Kubernetes version')
2716 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
2717 @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) ...]}"')
2718 @click.option('--description', help='human readable description')
2719 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
2720 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
2722 def k8scluster_update(ctx
,
2732 """updates a K8s cluster
2734 NAME: name or ID of the K8s cluster
2737 check_client_version(ctx
.obj
, ctx
.command
.name
)
2739 if newname
: cluster
['name'] = newname
2741 with
open(creds
, 'r') as cf
:
2742 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2743 if version
: cluster
['k8s_version'] = version
2744 if vim
: cluster
['vim_account'] = vim
2745 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2746 if description
: cluster
['description'] = description
2747 if namespace
: cluster
['namespace'] = namespace
2748 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2749 ctx
.obj
.k8scluster
.update(name
, cluster
)
2750 # except ClientException as e:
2755 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
2756 @click.argument('name')
2757 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2758 #@click.option('--wait',
2760 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2762 def k8scluster_delete(ctx
, name
, force
):
2763 """deletes a K8s cluster
2765 NAME: name or ID of the K8s cluster to be deleted
2768 check_client_version(ctx
.obj
, ctx
.command
.name
)
2769 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
2770 # except ClientException as e:
2775 @cli_osm.command(name
='k8scluster-list')
2776 @click.option('--filter', default
=None,
2777 help='restricts the list to the K8s clusters matching the filter')
2778 @click.option('--literal', is_flag
=True,
2779 help='print literally, no pretty table')
2781 def k8scluster_list(ctx
, filter, literal
):
2782 """list all K8s clusters"""
2784 check_client_version(ctx
.obj
, ctx
.command
.name
)
2785 resp
= ctx
.obj
.k8scluster
.list(filter)
2787 print(yaml
.safe_dump(resp
))
2789 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
2790 for cluster
in resp
:
2791 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
2792 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
2793 trunc_text(cluster
.get('description',''),40)])
2796 # except ClientException as e:
2801 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
2802 @click.argument('name')
2803 @click.option('--literal', is_flag
=True,
2804 help='print literally, no pretty table')
2806 def k8scluster_show(ctx
, name
, literal
):
2807 """shows the details of a K8s cluster
2809 NAME: name or ID of the K8s cluster
2812 resp
= ctx
.obj
.k8scluster
.get(name
)
2814 print(yaml
.safe_dump(resp
))
2816 table
= PrettyTable(['key', 'attribute'])
2817 for k
, v
in list(resp
.items()):
2818 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2821 # except ClientException as e:
2827 ###########################
2829 ###########################
2831 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
2832 @click.argument('name')
2833 @click.argument('uri')
2834 @click.option('--type',
2835 type=click
.Choice(['helm-chart', 'juju-bundle']),
2837 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2838 @click.option('--description',
2840 help='human readable description')
2841 #@click.option('--wait',
2843 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2850 """adds a repo to OSM
2852 NAME: name of the repo
2853 URI: URI of the repo
2856 check_client_version(ctx
.obj
, ctx
.command
.name
)
2861 repo
['description'] = description
2862 ctx
.obj
.repo
.create(name
, repo
)
2863 # except ClientException as e:
2868 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
2869 @click.argument('name')
2870 @click.option('--newname', help='New name for the repo')
2871 @click.option('--uri', help='URI of the repo')
2872 @click.option('--type', type=click
.Choice(['helm-chart', 'juju-bundle']),
2873 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2874 @click.option('--description', help='human readable description')
2875 #@click.option('--wait',
2877 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2879 def repo_update(ctx
,
2885 """updates a repo in OSM
2887 NAME: name of the repo
2890 check_client_version(ctx
.obj
, ctx
.command
.name
)
2892 if newname
: repo
['name'] = newname
2893 if uri
: repo
['uri'] = uri
2894 if type: repo
['type'] = type
2895 if description
: repo
['description'] = description
2896 ctx
.obj
.repo
.update(name
, repo
)
2897 # except ClientException as e:
2902 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
2903 @click.argument('name')
2904 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2905 #@click.option('--wait',
2907 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2909 def repo_delete(ctx
, name
, force
):
2912 NAME: name or ID of the repo to be deleted
2915 check_client_version(ctx
.obj
, ctx
.command
.name
)
2916 ctx
.obj
.repo
.delete(name
, force
=force
)
2917 # except ClientException as e:
2922 @cli_osm.command(name
='repo-list')
2923 @click.option('--filter', default
=None,
2924 help='restricts the list to the repos matching the filter')
2925 @click.option('--literal', is_flag
=True,
2926 help='print literally, no pretty table')
2928 def repo_list(ctx
, filter, literal
):
2929 """list all repos"""
2931 check_client_version(ctx
.obj
, ctx
.command
.name
)
2932 resp
= ctx
.obj
.repo
.list(filter)
2934 print(yaml
.safe_dump(resp
))
2936 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
2938 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
2939 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description',''),40)])
2942 # except ClientException as e:
2947 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
2948 @click.argument('name')
2949 @click.option('--literal', is_flag
=True,
2950 help='print literally, no pretty table')
2952 def repo_show(ctx
, name
, literal
):
2953 """shows the details of a repo
2955 NAME: name or ID of the repo
2958 resp
= ctx
.obj
.repo
.get(name
)
2960 print(yaml
.safe_dump(resp
))
2962 table
= PrettyTable(['key', 'attribute'])
2963 for k
, v
in list(resp
.items()):
2964 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2967 # except ClientException as e:
2973 ####################
2974 # Project mgmt operations
2975 ####################
2977 @cli_osm.command(name
='project-create', short_help
='creates a new project')
2978 @click.argument('name')
2979 #@click.option('--description',
2980 # default='no description',
2981 # help='human readable description')
2983 def project_create(ctx
, name
):
2984 """Creates a new project
2986 NAME: name of the project
2990 project
['name'] = name
2992 check_client_version(ctx
.obj
, ctx
.command
.name
)
2993 ctx
.obj
.project
.create(name
, project
)
2994 # except ClientException as e:
2999 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3000 @click.argument('name')
3001 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3003 def project_delete(ctx
, name
):
3004 """deletes a project
3006 NAME: name or ID of the project to be deleted
3010 check_client_version(ctx
.obj
, ctx
.command
.name
)
3011 ctx
.obj
.project
.delete(name
)
3012 # except ClientException as e:
3017 @cli_osm.command(name
='project-list', short_help
='list all projects')
3018 @click.option('--filter', default
=None,
3019 help='restricts the list to the projects matching the filter')
3021 def project_list(ctx
, filter):
3022 """list all projects"""
3025 check_client_version(ctx
.obj
, ctx
.command
.name
)
3026 resp
= ctx
.obj
.project
.list(filter)
3027 # except ClientException as e:
3030 table
= PrettyTable(['name', 'id'])
3032 table
.add_row([proj
['name'], proj
['_id']])
3037 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3038 @click.argument('name')
3040 def project_show(ctx
, name
):
3041 """shows the details of a project
3043 NAME: name or ID of the project
3047 check_client_version(ctx
.obj
, ctx
.command
.name
)
3048 resp
= ctx
.obj
.project
.get(name
)
3049 # except ClientException as e:
3053 table
= PrettyTable(['key', 'attribute'])
3054 for k
, v
in resp
.items():
3055 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3060 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3061 @click.argument('project')
3062 @click.option('--name',
3064 help='new name for the project')
3067 def project_update(ctx
, project
, name
):
3069 Update a project name
3072 :param project: id or name of the project to modify
3073 :param name: new name for the project
3077 project_changes
= {}
3078 project_changes
['name'] = name
3081 check_client_version(ctx
.obj
, ctx
.command
.name
)
3082 ctx
.obj
.project
.update(project
, project_changes
)
3083 # except ClientException as e:
3087 ####################
3088 # User mgmt operations
3089 ####################
3091 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3092 @click.argument('username')
3093 @click.option('--password',
3096 confirmation_prompt
=True,
3097 help='user password')
3098 @click.option('--projects',
3099 # prompt="Comma separate list of projects",
3101 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3102 help='list of project ids that the user belongs to')
3103 @click.option('--project-role-mappings', 'project_role_mappings',
3104 default
=None, multiple
=True,
3105 help='creating user project/role(s) mapping')
3107 def user_create(ctx
, username
, password
, projects
, project_role_mappings
):
3108 """Creates a new user
3111 USERNAME: name of the user
3112 PASSWORD: password of the user
3113 PROJECTS: projects assigned to user (internal only)
3114 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3118 user
['username'] = username
3119 user
['password'] = password
3120 user
['projects'] = projects
3121 user
['project_role_mappings'] = project_role_mappings
3124 check_client_version(ctx
.obj
, ctx
.command
.name
)
3125 ctx
.obj
.user
.create(username
, user
)
3126 # except ClientException as e:
3131 @cli_osm.command(name
='user-update', short_help
='updates user information')
3132 @click.argument('username')
3133 @click.option('--password',
3136 # confirmation_prompt=True,
3137 help='user password')
3138 @click.option('--set-username', 'set_username',
3140 help='change username')
3141 @click.option('--set-project', 'set_project',
3142 default
=None, multiple
=True,
3143 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
3144 @click.option('--remove-project', 'remove_project',
3145 default
=None, multiple
=True,
3146 help='removes project from user: \'project\'')
3147 @click.option('--add-project-role', 'add_project_role',
3148 default
=None, multiple
=True,
3149 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
3150 @click.option('--remove-project-role', 'remove_project_role',
3151 default
=None, multiple
=True,
3152 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
3154 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3155 add_project_role
, remove_project_role
):
3156 """Update a user information
3159 USERNAME: name of the user
3160 PASSWORD: new password
3161 SET_USERNAME: new username
3162 SET_PROJECT: creating mappings for project/role(s)
3163 REMOVE_PROJECT: deleting mappings for project/role(s)
3164 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3165 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3169 user
['password'] = password
3170 user
['username'] = set_username
3171 user
['set-project'] = set_project
3172 user
['remove-project'] = remove_project
3173 user
['add-project-role'] = add_project_role
3174 user
['remove-project-role'] = remove_project_role
3177 check_client_version(ctx
.obj
, ctx
.command
.name
)
3178 ctx
.obj
.user
.update(username
, user
)
3179 # except ClientException as e:
3184 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3185 @click.argument('name')
3186 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3188 def user_delete(ctx
, name
):
3192 NAME: name or ID of the user to be deleted
3196 check_client_version(ctx
.obj
, ctx
.command
.name
)
3197 ctx
.obj
.user
.delete(name
)
3198 # except ClientException as e:
3203 @cli_osm.command(name
='user-list', short_help
='list all users')
3204 @click.option('--filter', default
=None,
3205 help='restricts the list to the users matching the filter')
3207 def user_list(ctx
, filter):
3208 """list all users"""
3210 check_client_version(ctx
.obj
, ctx
.command
.name
)
3211 resp
= ctx
.obj
.user
.list(filter)
3212 # except ClientException as e:
3215 table
= PrettyTable(['name', 'id'])
3217 table
.add_row([user
['username'], user
['_id']])
3222 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3223 @click.argument('name')
3225 def user_show(ctx
, name
):
3226 """shows the details of a user
3228 NAME: name or ID of the user
3232 check_client_version(ctx
.obj
, ctx
.command
.name
)
3233 resp
= ctx
.obj
.user
.get(name
)
3234 if 'password' in resp
:
3235 resp
['password']='********'
3236 # except ClientException as e:
3240 table
= PrettyTable(['key', 'attribute'])
3241 for k
, v
in resp
.items():
3242 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3247 ####################
3248 # Fault Management operations
3249 ####################
3251 @cli_osm.command(name
='ns-alarm-create')
3252 @click.argument('name')
3253 @click.option('--ns', prompt
=True, help='NS instance id or name')
3254 @click.option('--vnf', prompt
=True,
3255 help='VNF name (VNF member index as declared in the NSD)')
3256 @click.option('--vdu', prompt
=True,
3257 help='VDU name (VDU name as declared in the VNFD)')
3258 @click.option('--metric', prompt
=True,
3259 help='Name of the metric (e.g. cpu_utilization)')
3260 @click.option('--severity', default
='WARNING',
3261 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3262 @click.option('--threshold_value', prompt
=True,
3263 help='threshold value that, when crossed, an alarm is triggered')
3264 @click.option('--threshold_operator', prompt
=True,
3265 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3266 @click.option('--statistic', default
='AVERAGE',
3267 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3269 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3270 threshold_value
, threshold_operator
, statistic
):
3271 """creates a new alarm for a NS instance"""
3272 # TODO: Check how to validate threshold_value.
3273 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3276 ns_instance
= ctx
.obj
.ns
.get(ns
)
3278 alarm
['alarm_name'] = name
3279 alarm
['ns_id'] = ns_instance
['_id']
3280 alarm
['correlation_id'] = ns_instance
['_id']
3281 alarm
['vnf_member_index'] = vnf
3282 alarm
['vdu_name'] = vdu
3283 alarm
['metric_name'] = metric
3284 alarm
['severity'] = severity
3285 alarm
['threshold_value'] = int(threshold_value
)
3286 alarm
['operation'] = threshold_operator
3287 alarm
['statistic'] = statistic
3288 check_client_version(ctx
.obj
, ctx
.command
.name
)
3289 ctx
.obj
.ns
.create_alarm(alarm
)
3290 # except ClientException as e:
3295 #@cli_osm.command(name='ns-alarm-delete')
3296 #@click.argument('name')
3297 #@click.pass_context
3298 #def ns_alarm_delete(ctx, name):
3299 # """deletes an alarm
3301 # NAME: name of the alarm to be deleted
3304 # check_client_version(ctx.obj, ctx.command.name)
3305 # ctx.obj.ns.delete_alarm(name)
3306 # except ClientException as e:
3311 ####################
3312 # Performance Management operations
3313 ####################
3315 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3316 @click.option('--ns', prompt
=True, help='NS instance id or name')
3317 @click.option('--vnf', prompt
=True,
3318 help='VNF name (VNF member index as declared in the NSD)')
3319 @click.option('--vdu', prompt
=True,
3320 help='VDU name (VDU name as declared in the VNFD)')
3321 @click.option('--metric', prompt
=True,
3322 help='name of the metric (e.g. cpu_utilization)')
3323 #@click.option('--period', default='1w',
3324 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3325 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3327 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3328 """exports a metric to the internal OSM bus, which can be read by other apps"""
3329 # TODO: Check how to validate interval.
3330 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3333 ns_instance
= ctx
.obj
.ns
.get(ns
)
3335 metric_data
['ns_id'] = ns_instance
['_id']
3336 metric_data
['correlation_id'] = ns_instance
['_id']
3337 metric_data
['vnf_member_index'] = vnf
3338 metric_data
['vdu_name'] = vdu
3339 metric_data
['metric_name'] = metric
3340 metric_data
['collection_unit'] = 'WEEK'
3341 metric_data
['collection_period'] = 1
3342 check_client_version(ctx
.obj
, ctx
.command
.name
)
3344 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3348 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3349 time
.sleep(int(interval
))
3351 # except ClientException as e:
3356 ####################
3358 ####################
3360 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3362 def get_version(ctx
):
3363 """shows client and server versions"""
3365 check_client_version(ctx
.obj
, "version")
3366 print ("Server version: {}".format(ctx
.obj
.get_version()))
3367 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3368 # except ClientException as e:
3372 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3373 @click.argument('filename')
3374 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3375 help='the charm will not be compiled, it is assumed to already exist')
3377 def upload_package(ctx
, filename
, skip_charm_build
):
3378 """uploads a vnf package or ns package
3380 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3384 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3385 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3386 if fullclassname
!= 'osmclient.sol005.client.Client':
3387 ctx
.obj
.package
.wait_for_upload(filename
)
3388 # except ClientException as e:
3393 #@cli_osm.command(name='ns-scaling-show')
3394 #@click.argument('ns_name')
3395 #@click.pass_context
3396 #def show_ns_scaling(ctx, ns_name):
3397 # """shows the status of a NS scaling operation
3399 # NS_NAME: name of the NS instance being scaled
3402 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3403 # resp = ctx.obj.ns.list()
3404 # except ClientException as e:
3408 # table = PrettyTable(
3411 # 'operational status',
3416 # if ns_name == ns['name']:
3417 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3418 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3419 # for record in scaling_records:
3420 # if 'instance' in record:
3421 # instances = record['instance']
3422 # for inst in instances:
3424 # [record['scaling-group-name-ref'],
3425 # inst['instance-id'],
3426 # inst['op-status'],
3427 # time.strftime('%Y-%m-%d %H:%M:%S',
3429 # inst['create-time'])),
3435 #@cli_osm.command(name='ns-scale')
3436 #@click.argument('ns_name')
3437 #@click.option('--ns_scale_group', prompt=True)
3438 #@click.option('--index', prompt=True)
3439 #@click.option('--wait',
3443 # help='do not return the control immediately, but keep it \
3444 # until the operation is completed, or timeout')
3445 #@click.pass_context
3446 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3449 # NS_NAME: name of the NS instance to be scaled
3452 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3453 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3454 # except ClientException as e:
3459 #@cli_osm.command(name='config-agent-list')
3460 #@click.pass_context
3461 #def config_agent_list(ctx):
3462 # """list config agents"""
3464 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3465 # except ClientException as e:
3468 # table = PrettyTable(['name', 'account-type', 'details'])
3469 # for account in ctx.obj.vca.list():
3472 # account['account-type'],
3478 #@cli_osm.command(name='config-agent-delete')
3479 #@click.argument('name')
3480 #@click.pass_context
3481 #def config_agent_delete(ctx, name):
3482 # """deletes a config agent
3484 # NAME: name of the config agent to be deleted
3487 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3488 # ctx.obj.vca.delete(name)
3489 # except ClientException as e:
3494 #@cli_osm.command(name='config-agent-add')
3495 #@click.option('--name',
3497 #@click.option('--account_type',
3499 #@click.option('--server',
3501 #@click.option('--user',
3503 #@click.option('--secret',
3506 # confirmation_prompt=True)
3507 #@click.pass_context
3508 #def config_agent_add(ctx, name, account_type, server, user, secret):
3509 # """adds a config agent"""
3511 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3512 # ctx.obj.vca.create(name, account_type, server, user, secret)
3513 # except ClientException as e:
3518 #@cli_osm.command(name='ro-dump')
3519 #@click.pass_context
3521 # """shows RO agent information"""
3522 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3523 # resp = ctx.obj.vim.get_resource_orchestrator()
3524 # table = PrettyTable(['key', 'attribute'])
3525 # for k, v in list(resp.items()):
3526 # table.add_row([k, json.dumps(v, indent=2)])
3531 #@cli_osm.command(name='vcs-list')
3532 #@click.pass_context
3534 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3535 # resp = ctx.obj.utils.get_vcs_info()
3536 # table = PrettyTable(['component name', 'state'])
3537 # for component in resp:
3538 # table.add_row([component['component_name'], component['state']])
3543 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3544 @click.argument('ns_name')
3545 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3546 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3547 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3548 @click.option('--vdu_count', default
=None, help='number of vdu instance of this vdu_id')
3549 @click.option('--action_name', prompt
=True, help='action name')
3550 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3551 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3552 @click.option('--wait',
3556 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3568 """executes an action/primitive over a NS instance
3570 NS_NAME: name or ID of the NS instance
3574 check_client_version(ctx
.obj
, ctx
.command
.name
)
3577 op_data
['member_vnf_index'] = vnf_name
3579 op_data
['kdu_name'] = kdu_name
3581 op_data
['vdu_id'] = vdu_id
3583 op_data
['vdu_count_index'] = vdu_count
3584 op_data
['primitive'] = action_name
3586 with
open(params_file
, 'r') as pf
:
3589 op_data
['primitive_params'] = yaml
.safe_load(params
)
3591 op_data
['primitive_params'] = {}
3592 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
3594 # except ClientException as e:
3599 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
3600 @click.argument('ns_name')
3601 @click.argument('vnf_name')
3602 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
3603 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
3604 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
3613 Executes a VNF scale (adding/removing VDUs)
3616 NS_NAME: name or ID of the NS instance.
3617 VNF_NAME: member-vnf-index in the NS to be scaled.
3621 check_client_version(ctx
.obj
, ctx
.command
.name
)
3622 if not scale_in
and not scale_out
:
3624 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
)
3625 # except ClientException as e:
3630 ##############################
3631 # Role Management Operations #
3632 ##############################
3634 @cli_osm.command(name
='role-create', short_help
='creates a new role')
3635 @click.argument('name')
3636 @click.option('--permissions',
3638 help='role permissions using a dictionary')
3640 def role_create(ctx
, name
, permissions
):
3645 NAME: Name or ID of the role.
3646 DEFINITION: Definition of grant/denial of access to resources.
3650 check_client_version(ctx
.obj
, ctx
.command
.name
)
3651 ctx
.obj
.role
.create(name
, permissions
)
3652 # except ClientException as e:
3657 @cli_osm.command(name
='role-update', short_help
='updates a role')
3658 @click.argument('name')
3659 @click.option('--set-name',
3661 help='change name of rle')
3662 # @click.option('--permissions',
3664 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
3665 @click.option('--add',
3667 help='yaml format dictionary with permission: True/False to access grant/denial')
3668 @click.option('--remove',
3670 help='yaml format list to remove a permission')
3672 def role_update(ctx
, name
, set_name
, add
, remove
):
3677 NAME: Name or ID of the role.
3678 DEFINITION: Definition overwrites the old definition.
3679 ADD: Grant/denial of access to resource to add.
3680 REMOVE: Grant/denial of access to resource to remove.
3684 check_client_version(ctx
.obj
, ctx
.command
.name
)
3685 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
3686 # except ClientException as e:
3691 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
3692 @click.argument('name')
3693 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3695 def role_delete(ctx
, name
):
3700 NAME: Name or ID of the role.
3704 check_client_version(ctx
.obj
, ctx
.command
.name
)
3705 ctx
.obj
.role
.delete(name
)
3706 # except ClientException as e:
3711 @cli_osm.command(name
='role-list', short_help
='list all roles')
3712 @click.option('--filter', default
=None,
3713 help='restricts the list to the projects matching the filter')
3715 def role_list(ctx
, filter):
3721 check_client_version(ctx
.obj
, ctx
.command
.name
)
3722 resp
= ctx
.obj
.role
.list(filter)
3723 # except ClientException as e:
3726 table
= PrettyTable(['name', 'id'])
3728 table
.add_row([role
['name'], role
['_id']])
3733 @cli_osm.command(name
='role-show', short_help
='show specific role')
3734 @click.argument('name')
3736 def role_show(ctx
, name
):
3738 Shows the details of a role.
3741 NAME: Name or ID of the role.
3745 check_client_version(ctx
.obj
, ctx
.command
.name
)
3746 resp
= ctx
.obj
.role
.get(name
)
3747 # except ClientException as e:
3751 table
= PrettyTable(['key', 'attribute'])
3752 for k
, v
in resp
.items():
3753 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3758 @cli_osm.command(name
='package-create',
3759 short_help
='Create a package descriptor')
3760 @click.argument('package-type')
3761 @click.argument('package-name')
3762 @click.option('--base-directory',
3764 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
3765 @click.option('--image',
3766 default
="image-name",
3767 help='(VNF) Set the name of the vdu image. Default "image-name"')
3768 @click.option('--vdus',
3770 help='(VNF) Set the number of vdus in a VNF. Default 1')
3771 @click.option('--vcpu',
3773 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
3774 @click.option('--memory',
3776 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
3777 @click.option('--storage',
3779 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
3780 @click.option('--interfaces',
3782 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
3783 @click.option('--vendor',
3785 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
3786 @click.option('--override',
3789 help='(NS/VNF/NST) Flag for overriding the package if exists.')
3790 @click.option('--detailed',
3793 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
3794 @click.option('--netslice-subnets',
3796 help='(NST) Number of netslice subnets. Default 1')
3797 @click.option('--netslice-vlds',
3799 help='(NST) Number of netslice vlds. Default 1')
3801 def package_create(ctx
,
3817 Creates an OSM NS, VNF, NST package
3820 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
3821 PACKAGE_NAME: Name of the package to create the folder with the content.
3825 check_client_version(ctx
.obj
, ctx
.command
.name
)
3826 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
3827 resp
= ctx
.obj
.package_tool
.create(package_type
,
3836 interfaces
=interfaces
,
3839 netslice_subnets
=netslice_subnets
,
3840 netslice_vlds
=netslice_vlds
)
3842 # except ClientException as inst:
3843 # print("ERROR: {}".format(inst))
3846 @cli_osm.command(name
='package-validate',
3847 short_help
='Validate a package descriptor')
3848 @click.argument('base-directory',
3851 @click.option('--recursive/--no-recursive',
3853 help='The activated recursive option will validate the yaml files'
3854 ' within the indicated directory and in its subdirectories')
3856 def package_validate(ctx
,
3860 Validate descriptors given a base directory.
3863 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
3866 check_client_version(ctx
.obj
, ctx
.command
.name
)
3867 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
3868 table
= PrettyTable()
3869 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
3870 # Print the dictionary generated by the validation function
3871 for result
in results
:
3872 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
3873 table
.sortby
= "VALID"
3874 table
.align
["PATH"] = "l"
3875 table
.align
["TYPE"] = "l"
3876 table
.align
["ERROR"] = "l"
3878 # except ClientException as inst:
3879 # print("ERROR: {}".format(inst))
3882 @cli_osm.command(name
='package-build',
3883 short_help
='Build the tar.gz of the package')
3884 @click.argument('package-folder')
3885 @click.option('--skip-validation',
3888 help='skip package validation')
3889 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3890 help='the charm will not be compiled, it is assumed to already exist')
3892 def package_build(ctx
,
3897 Build the package NS, VNF given the package_folder.
3900 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
3903 check_client_version(ctx
.obj
, ctx
.command
.name
)
3904 results
= ctx
.obj
.package_tool
.build(package_folder
,
3905 skip_validation
=skip_validation
,
3906 skip_charm_build
=skip_charm_build
)
3908 # except ClientException as inst:
3909 # print("ERROR: {}".format(inst))
3917 except pycurl
.error
as exc
:
3919 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
3920 except ClientException
as exc
:
3921 print("ERROR: {}".format(exc
))
3922 except (FileNotFoundError
, PermissionError
) as exc
:
3923 print("Cannot open file: {}".format(exc
))
3924 except yaml
.YAMLError
as exc
:
3925 print("Invalid YAML format: {}".format(exc
))
3927 # TODO capture other controlled exceptions here
3928 # TODO remove the ClientException captures from all places, unless they do something different
3931 if __name__
== '__main__':