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
, NotFound
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('--project-domain-name', 'project_domain_name',
108 envvar
='OSM_PROJECT_DOMAIN_NAME',
109 help='project domain name for keystone authentication (default to None). ' +
110 'Also can set OSM_PROJECT_DOMAIN_NAME in environment')
111 @click.option('--user-domain-name', 'user_domain_name',
113 envvar
='OSM_USER_DOMAIN_NAME',
114 help='user domain name for keystone authentication (default to None). ' +
115 'Also can set OSM_USER_DOMAIN_NAME in environment')
116 #@click.option('--so-port',
118 # envvar='OSM_SO_PORT',
119 # help='hostname of server. ' +
120 # 'Also can set OSM_SO_PORT in environment')
121 #@click.option('--so-project',
123 # envvar='OSM_SO_PROJECT',
124 # help='Project Name in SO. ' +
125 # 'Also can set OSM_SO_PROJECT in environment')
126 #@click.option('--ro-hostname',
128 # envvar='OSM_RO_HOSTNAME',
129 # help='hostname of RO server. ' +
130 # 'Also can set OSM_RO_HOSTNAME in environment')
131 #@click.option('--ro-port',
133 # envvar='OSM_RO_PORT',
134 # help='hostname of RO server. ' +
135 # 'Also can set OSM_RO_PORT in environment')
137 def cli_osm(ctx
, **kwargs
):
139 hostname
= kwargs
.pop("hostname", None)
142 "either hostname option or OSM_HOSTNAME " +
143 "environment variable needs to be specified"))
146 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
147 # if so_port is not None:
148 # kwargs['so_port']=so_port
149 # if so_project is not None:
150 # kwargs['so_project']=so_project
151 # if ro_hostname is not None:
152 # kwargs['ro_host']=ro_hostname
153 # if ro_port is not None:
154 # kwargs['ro_port']=ro_port
155 sol005
= os
.getenv('OSM_SOL005', True)
156 # if user is not None:
157 # kwargs['user']=user
158 # if password is not None:
159 # kwargs['password']=password
160 # if project is not None:
161 # kwargs['project']=project
163 # kwargs['all_projects']=all_projects
164 # if public is not None:
165 # kwargs['public']=public
166 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
167 logger
= logging
.getLogger('osmclient')
174 @cli_osm.command(name
='ns-list', short_help
='list all NS instances')
175 @click.option('--filter', default
=None,
176 help='restricts the list to the NS instances matching the filter.')
177 @click.option('--long', is_flag
=True,
178 help='get more details of the NS (project, vim, deployment status, configuration status.')
180 def ns_list(ctx
, filter, long):
181 """list all NS instances
185 --filter filterExpr Restricts the list to the NS instances matching the filter
188 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
189 concatenated using the "&" character:
192 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
193 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
194 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
196 value := scalar value
200 * zero or more occurrences
201 ? zero or one occurrence
202 [] grouping of expressions to be used with ? and *
203 "" quotation marks for marking string constants
207 "AttrName" is the name of one attribute in the data type that defines the representation
208 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
209 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
210 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
211 entries, it means that the operator "op" is applied to the attribute addressed by the last
212 <attrName> entry included in the concatenation. All simple filter expressions are combined
213 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
214 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
215 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
216 prefix". If an attribute referenced in an expression is an array, an object that contains a
217 corresponding array shall be considered to match the expression if any of the elements in the
218 array matches all expressions that have the same attribute prefix.
222 --filter admin-status=ENABLED
223 --filter nsd-ref=<NSD_NAME>
224 --filter nsd.vendor=<VENDOR>
225 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
226 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
228 def summarize_deployment_status(status_dict
):
235 net_list
= status_dict
.get('nets',[])
238 if net
['status'] not in status_nets
:
239 status_nets
[net
['status']] = 1
241 status_nets
[net
['status']] +=1
243 for k
,v
in status_nets
.items():
244 message
+= "{}:{},".format(k
,v
)
245 message
+= "TOTAL:{}".format(n_nets
)
246 summary
+= "{}".format(message
)
251 vnf_list
= status_dict
['vnfs']
253 member_vnf_index
= vnf
['member_vnf_index']
254 if member_vnf_index
not in status_vnfs
:
255 status_vnfs
[member_vnf_index
] = {}
256 for vm
in vnf
['vms']:
258 if vm
['status'] not in status_vms
:
259 status_vms
[vm
['status']] = 1
261 status_vms
[vm
['status']] +=1
262 if vm
['status'] not in status_vnfs
[member_vnf_index
]:
263 status_vnfs
[member_vnf_index
][vm
['status']] = 1
265 status_vnfs
[member_vnf_index
][vm
['status']] += 1
267 for k
,v
in status_vms
.items():
268 message
+= "{}:{},".format(k
,v
)
269 message
+= "TOTAL:{}".format(n_vms
)
270 summary
+= "\n{}".format(message
)
272 for k
,v
in status_vnfs
.items():
274 message
= "\n {} VMs: ".format(k
)
275 for k2
,v2
in v
.items():
276 message
+= "{}:{},".format(k2
,v2
)
278 message
+= "TOTAL:{}".format(total
)
282 def summarize_config_status(ee_list
):
290 if ee
['elementType'] not in status_ee
:
291 status_ee
[ee
['elementType']] = {}
292 status_ee
[ee
['elementType']][ee
['status']] = 1
294 if ee
['status'] in status_ee
[ee
['elementType']]:
295 status_ee
[ee
['elementType']][ee
['status']] += 1
297 status_ee
[ee
['elementType']][ee
['status']] = 1
298 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
299 if elementType
in status_ee
:
302 for k
,v
in status_ee
[elementType
].items():
303 message
+= "{}:{},".format(k
,v
)
305 message
+= "TOTAL:{}\n".format(total
)
306 summary
+= "{}: {}".format(elementType
, message
)
307 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
312 check_client_version(ctx
.obj
, '--filter')
313 resp
= ctx
.obj
.ns
.list(filter)
315 resp
= ctx
.obj
.ns
.list()
327 'configuration status'])
328 project_list
= ctx
.obj
.project
.list()
329 vim_list
= ctx
.obj
.vim
.list()
339 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
340 if fullclassname
== 'osmclient.sol005.client.Client':
342 logger
.debug('NS info: {}'.format(nsr
))
343 nsr_name
= nsr
['name']
345 date
= datetime
.fromtimestamp(nsr
['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
346 ns_state
= nsr
.get('nsState', nsr
['_admin']['nsState'])
348 deployment_status
= summarize_deployment_status(nsr
.get('deploymentStatus'))
349 config_status
= summarize_config_status(nsr
.get('configurationStatus'))
350 project_id
= nsr
.get('_admin').get('projects_read')[0]
352 for p
in project_list
:
353 if p
['_id'] == project_id
:
354 project_name
= p
['name']
356 #project = '{} ({})'.format(project_name, project_id)
357 project
= project_name
358 vim_id
= nsr
.get('datacenter')
361 if v
['uuid'] == vim_id
:
364 #vim = '{} ({})'.format(vim_name, vim_id)
366 if 'currentOperation' in nsr
:
367 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
369 current_operation
= "{} ({})".format(nsr
['_admin'].get('current-operation','-'), nsr
['_admin']['nslcmop'])
370 error_details
= "N/A"
371 if ns_state
== "BROKEN" or ns_state
== "DEGRADED" or \
372 ('currentOperation' not in nsr
and nsr
.get('errorDescription')):
373 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'], nsr
['errorDetail'])
375 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
376 nsr
= nsopdata
['nsr:nsr']
377 nsr_name
= nsr
['name-ref']
378 nsr_id
= nsr
['ns-instance-config-ref']
381 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
382 ns_state
= deployment_status
383 config_status
= nsr
.get('config-status', 'Not found')
384 current_operation
= "Unknown"
385 error_details
= nsr
.get('detailed-status', 'Not found')
386 if config_status
== "config_not_needed":
387 config_status
= "configured (no charms)"
396 wrap_text(text
=error_details
,width
=40),
408 wrap_text(text
=error_details
,width
=40)])
411 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
412 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
414 def nsd_list(ctx
, filter, long):
417 check_client_version(ctx
.obj
, '--filter')
418 resp
= ctx
.obj
.nsd
.list(filter)
420 resp
= ctx
.obj
.nsd
.list()
421 # print(yaml.safe_dump(resp))
422 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
423 if fullclassname
== 'osmclient.sol005.client.Client':
425 table
= PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state',
426 'usage state', 'date', 'last update'])
428 table
= PrettyTable(['nsd name', 'id'])
430 name
= nsd
.get('name','-')
432 onb_state
= nsd
['_admin'].get('onboardingState','-')
433 op_state
= nsd
['_admin'].get('operationalState','-')
434 usage_state
= nsd
['_admin'].get('usageState','-')
435 date
= datetime
.fromtimestamp(nsd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
436 last_update
= datetime
.fromtimestamp(nsd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
437 table
.add_row([name
, nsd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
439 table
.add_row([name
, nsd
['_id']])
441 table
= PrettyTable(['nsd name', 'id'])
443 table
.add_row([nsd
['name'], nsd
['id']])
448 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
449 @click.option('--filter', default
=None,
450 help='restricts the list to the NSD/NSpkg matching the filter')
451 @click.option('--long', is_flag
=True, help='get more details')
453 def nsd_list1(ctx
, filter, long):
454 """list all NSD/NS pkg in the system"""
456 nsd_list(ctx
, filter, long)
459 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
460 @click.option('--filter', default
=None,
461 help='restricts the list to the NSD/NSpkg matching the filter')
462 @click.option('--long', is_flag
=True, help='get more details')
464 def nsd_list2(ctx
, filter, long):
465 """list all NS packages"""
467 nsd_list(ctx
, filter, long)
470 def pkg_repo_list(ctx
, pkgtype
, filter, repo
, long):
471 resp
= ctx
.obj
.osmrepo
.pkg_list(pkgtype
, filter, repo
)
473 table
= PrettyTable(['nfpkg name', 'vendor', 'version', 'latest', 'description', 'repository'])
475 table
= PrettyTable(['nfpkg name', 'repository'])
477 name
= vnfd
.get('product-name', '-')
478 repository
= vnfd
.get('repository')
480 vendor
= vnfd
.get('provider')
481 version
= vnfd
.get('version')
482 description
= vnfd
.get('description')
483 latest
= vnfd
.get('latest')
484 table
.add_row([name
, vendor
, version
, latest
, description
, repository
])
486 table
.add_row([name
, repository
])
490 def vnfd_list(ctx
, nf_type
, filter, long):
493 check_client_version(ctx
.obj
, '--nf_type')
495 check_client_version(ctx
.obj
, '--filter')
498 nf_filter
= "_admin.type=vnfd"
499 elif nf_type
== "pnf":
500 nf_filter
= "_admin.type=pnfd"
501 elif nf_type
== "hnf":
502 nf_filter
= "_admin.type=hnfd"
504 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
506 filter = '{}&{}'.format(nf_filter
, filter)
510 resp
= ctx
.obj
.vnfd
.list(filter)
512 resp
= ctx
.obj
.vnfd
.list()
513 # print(yaml.safe_dump(resp))
514 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
515 if fullclassname
== 'osmclient.sol005.client.Client':
517 table
= PrettyTable(['nfpkg name', 'id', 'vendor', 'version', 'onboarding state', 'operational state',
518 'usage state', 'date', 'last update'])
520 table
= PrettyTable(['nfpkg name', 'id'])
522 name
= vnfd
['product-name'] if 'product-name' in vnfd
else '-'
524 onb_state
= vnfd
['_admin'].get('onboardingState','-')
525 op_state
= vnfd
['_admin'].get('operationalState','-')
526 vendor
= vnfd
.get('provider')
527 version
= vnfd
.get('version')
528 usage_state
= vnfd
['_admin'].get('usageState','-')
529 date
= datetime
.fromtimestamp(vnfd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
530 last_update
= datetime
.fromtimestamp(vnfd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
531 table
.add_row([name
, vnfd
['_id'], vendor
, version
, onb_state
, op_state
, usage_state
, date
, last_update
])
533 table
.add_row([name
, vnfd
['_id']])
535 table
= PrettyTable(['nfpkg name', 'id'])
537 table
.add_row([vnfd
['product-name'], vnfd
['id']])
542 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
543 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
544 @click.option('--filter', default
=None,
545 help='restricts the list to the NF pkg matching the filter')
546 @click.option('--long', is_flag
=True, help='get more details')
548 def vnfd_list1(ctx
, nf_type
, filter, long):
549 """list all xNF packages (VNF, HNF, PNF)"""
551 vnfd_list(ctx
, nf_type
, filter, long)
554 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
555 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
556 @click.option('--filter', default
=None,
557 help='restricts the list to the NFpkg matching the filter')
558 @click.option('--long', is_flag
=True, help='get more details')
560 def vnfd_list2(ctx
, nf_type
, filter, long):
561 """list all xNF packages (VNF, HNF, PNF)"""
563 vnfd_list(ctx
, nf_type
, filter, long)
565 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
566 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
567 @click.option('--filter', default
=None,
568 help='restricts the list to the NFpkg matching the filter')
569 @click.option('--long', is_flag
=True, help='get more details')
571 def nfpkg_list(ctx
, nf_type
, filter, long):
572 """list all xNF packages (VNF, HNF, PNF)"""
575 check_client_version(ctx
.obj
, ctx
.command
.name
)
576 vnfd_list(ctx
, nf_type
, filter, long)
577 # except ClientException as e:
581 @cli_osm.command(name
='vnfpkg-repo-list', short_help
='list all xNF from OSM repositories')
582 @click.option('--filter', default
=None,
583 help='restricts the list to the NFpkg matching the filter')
584 @click.option('--repo', default
=None,
585 help='restricts the list to a particular OSM repository')
586 @click.option('--long', is_flag
=True, help='get more details')
588 def nfpkg_repo_list1(ctx
, filter, repo
, long):
589 """list xNF packages from OSM repositories"""
591 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
593 @cli_osm.command(name
='nfpkg-repo-list', short_help
='list all xNF from OSM repositories')
594 @click.option('--filter', default
=None,
595 help='restricts the list to the NFpkg matching the filter')
596 @click.option('--repo', default
=None,
597 help='restricts the list to a particular OSM repository')
598 @click.option('--long', is_flag
=True, help='get more details')
600 def nfpkg_repo_list2(ctx
, filter, repo
, long):
601 """list xNF packages from OSM repositories"""
603 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
605 def vnf_list(ctx
, ns
, filter, long):
609 check_client_version(ctx
.obj
, '--ns')
611 check_client_version(ctx
.obj
, '--filter')
612 resp
= ctx
.obj
.vnf
.list(ns
, filter)
614 resp
= ctx
.obj
.vnf
.list()
615 # except ClientException as e:
618 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
619 if fullclassname
== 'osmclient.sol005.client.Client':
620 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
621 'vnfd name', 'vim account id', 'ip address']
623 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
624 'vnfd name', 'vim account id', 'ip address',
625 'date', 'last update']
626 table
= PrettyTable(field_names
)
628 name
= vnfr
['name'] if 'name' in vnfr
else '-'
629 new_row
= [vnfr
['_id'], name
, vnfr
['nsr-id-ref'],
630 vnfr
['member-vnf-index-ref'], vnfr
['vnfd-ref'],
631 vnfr
['vim-account-id'], vnfr
['ip-address']]
633 date
= datetime
.fromtimestamp(vnfr
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
634 last_update
= datetime
.fromtimestamp(vnfr
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
635 new_row
.extend([date
, last_update
])
636 table
.add_row(new_row
)
641 'operational status',
644 if 'mgmt-interface' not in vnfr
:
645 vnfr
['mgmt-interface'] = {}
646 vnfr
['mgmt-interface']['ip-address'] = None
650 vnfr
['operational-status'],
651 vnfr
['config-status']])
656 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
657 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
658 @click.option('--filter', default
=None,
659 help='restricts the list to the NF instances matching the filter.')
660 @click.option('--long', is_flag
=True, help='get more details')
662 def vnf_list1(ctx
, ns
, filter, long):
663 """list all NF instances"""
665 vnf_list(ctx
, ns
, filter, long)
667 @cli_osm.command(name
='nsd-repo-list', short_help
='list all NS from OSM repositories')
668 @click.option('--filter', default
=None,
669 help='restricts the list to the NS matching the filter')
670 @click.option('--repo', default
=None,
671 help='restricts the list to a particular OSM repository')
672 @click.option('--long', is_flag
=True, help='get more details')
674 def nspkg_repo_list(ctx
, filter, repo
, long):
675 """list xNF packages from OSM repositories"""
677 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
679 @cli_osm.command(name
='nspkg-repo-list', short_help
='list all NS from OSM repositories')
680 @click.option('--filter', default
=None,
681 help='restricts the list to the NS matching the filter')
682 @click.option('--repo', default
=None,
683 help='restricts the list to a particular OSM repository')
684 @click.option('--long', is_flag
=True, help='get more details')
686 def nspkg_repo_list2(ctx
, filter, repo
, long):
687 """list xNF packages from OSM repositories"""
689 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
691 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
692 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
693 @click.option('--filter', default
=None,
694 help='restricts the list to the NF instances matching the filter.')
695 @click.option('--long', is_flag
=True, help='get more details')
697 def nf_list(ctx
, ns
, filter, long):
698 """list all NF instances
702 --ns TEXT NS instance id or name to restrict the VNF list
703 --filter filterExpr Restricts the list to the VNF instances matching the filter
706 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
707 concatenated using the "&" character:
710 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
711 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
712 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
714 value := scalar value
718 * zero or more occurrences
719 ? zero or one occurrence
720 [] grouping of expressions to be used with ? and *
721 "" quotation marks for marking string constants
725 "AttrName" is the name of one attribute in the data type that defines the representation
726 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
727 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
728 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
729 entries, it means that the operator "op" is applied to the attribute addressed by the last
730 <attrName> entry included in the concatenation. All simple filter expressions are combined
731 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
732 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
733 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
734 prefix". If an attribute referenced in an expression is an array, an object that contains a
735 corresponding array shall be considered to match the expression if any of the elements in the
736 array matches all expressions that have the same attribute prefix.
740 --filter vim-account-id=<VIM_ACCOUNT_ID>
741 --filter vnfd-ref=<VNFD_NAME>
742 --filter vdur.ip-address=<IP_ADDRESS>
743 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
746 vnf_list(ctx
, ns
, filter, long)
749 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
750 @click.argument('name')
751 @click.option('--long', is_flag
=True,
752 help='get more details of the NS operation (date, ).')
754 def ns_op_list(ctx
, name
, long):
755 """shows the history of operations over a NS instance
757 NAME: name or ID of the NS instance
759 def formatParams(params
):
760 if params
['lcmOperationType']=='instantiate':
761 params
.pop('nsDescription')
765 elif params
['lcmOperationType']=='action':
766 params
.pop('primitive')
767 params
.pop('lcmOperationType')
768 params
.pop('nsInstanceId')
773 check_client_version(ctx
.obj
, ctx
.command
.name
)
774 resp
= ctx
.obj
.ns
.list_op(name
)
775 # except ClientException as e:
780 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
782 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
784 #print(yaml.safe_dump(resp))
787 if op
['lcmOperationType']=='action':
788 action_name
= op
['operationParams']['primitive']
790 if op
['operationState'] == 'PROCESSING':
791 if op
['queuePosition'] is not None and op
['queuePosition'] > 0:
792 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
793 elif op
['lcmOperationType'] in ('instantiate', 'terminate'):
796 elif op
['operationState'] in ('FAILED', 'FAILED_TEMP'):
797 detail
= op
.get('errorMessage','-')
798 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
799 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
801 table
.add_row([op
['id'],
802 op
['lcmOperationType'],
804 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
805 op
['operationState'],
808 wrap_text(text
=detail
,width
=50)])
810 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
811 op
['operationState'], date
, wrap_text(text
=detail
or "",width
=50)])
816 def nsi_list(ctx
, filter):
817 """list all Network Slice Instances"""
820 check_client_version(ctx
.obj
, ctx
.command
.name
)
821 resp
= ctx
.obj
.nsi
.list(filter)
822 # except ClientException as e:
826 ['netslice instance name',
828 'operational status',
832 nsi_name
= nsi
['name']
834 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
835 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
836 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
837 if configstatus
== "config_not_needed":
838 configstatus
= "configured (no charms)"
849 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
850 @click.option('--filter', default
=None,
851 help='restricts the list to the Network Slice Instances matching the filter')
853 def nsi_list1(ctx
, filter):
854 """list all Network Slice Instances (NSI)"""
856 nsi_list(ctx
, filter)
859 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
860 @click.option('--filter', default
=None,
861 help='restricts the list to the Network Slice Instances matching the filter')
863 def nsi_list2(ctx
, filter):
864 """list all Network Slice Instances (NSI)"""
866 nsi_list(ctx
, filter)
869 def nst_list(ctx
, filter):
872 check_client_version(ctx
.obj
, ctx
.command
.name
)
873 resp
= ctx
.obj
.nst
.list(filter)
874 # except ClientException as e:
877 # print(yaml.safe_dump(resp))
878 table
= PrettyTable(['nst name', 'id'])
880 name
= nst
['name'] if 'name' in nst
else '-'
881 table
.add_row([name
, nst
['_id']])
886 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
887 @click.option('--filter', default
=None,
888 help='restricts the list to the NST matching the filter')
890 def nst_list1(ctx
, filter):
891 """list all Network Slice Templates (NST) in the system"""
893 nst_list(ctx
, filter)
896 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
897 @click.option('--filter', default
=None,
898 help='restricts the list to the NST matching the filter')
900 def nst_list2(ctx
, filter):
901 """list all Network Slice Templates (NST) in the system"""
903 nst_list(ctx
, filter)
906 def nsi_op_list(ctx
, name
):
909 check_client_version(ctx
.obj
, ctx
.command
.name
)
910 resp
= ctx
.obj
.nsi
.list_op(name
)
911 # except ClientException as e:
914 table
= PrettyTable(['id', 'operation', 'status'])
916 table
.add_row([op
['id'], op
['lcmOperationType'],
917 op
['operationState']])
922 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
923 @click.argument('name')
925 def nsi_op_list1(ctx
, name
):
926 """shows the history of operations over a Network Slice Instance (NSI)
928 NAME: name or ID of the Network Slice Instance
931 nsi_op_list(ctx
, name
)
934 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
935 @click.argument('name')
937 def nsi_op_list2(ctx
, name
):
938 """shows the history of operations over a Network Slice Instance (NSI)
940 NAME: name or ID of the Network Slice Instance
943 nsi_op_list(ctx
, name
)
946 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
947 @click.option('--filter', default
=None,
948 help='restricts the list to the Physical Deployment Units matching the filter')
950 def pdu_list(ctx
, filter):
951 """list all Physical Deployment Units (PDU)"""
954 check_client_version(ctx
.obj
, ctx
.command
.name
)
955 resp
= ctx
.obj
.pdu
.list(filter)
956 # except ClientException as e:
965 pdu_name
= pdu
['name']
967 pdu_type
= pdu
['type']
968 pdu_ipaddress
= "None"
969 for iface
in pdu
['interfaces']:
971 pdu_ipaddress
= iface
['ip-address']
986 def nsd_show(ctx
, name
, literal
):
989 resp
= ctx
.obj
.nsd
.get(name
)
990 # resp = ctx.obj.nsd.get_individual(name)
991 # except ClientException as e:
996 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
999 table
= PrettyTable(['field', 'value'])
1000 for k
, v
in list(resp
.items()):
1001 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1006 @cli_osm.command(name
='nsd-show', short_help
='shows the details of a NS package')
1007 @click.option('--literal', is_flag
=True,
1008 help='print literally, no pretty table')
1009 @click.argument('name')
1011 def nsd_show1(ctx
, name
, literal
):
1012 """shows the content of a NSD
1014 NAME: name or ID of the NSD/NSpkg
1017 nsd_show(ctx
, name
, literal
)
1020 @cli_osm.command(name
='nspkg-show', short_help
='shows the details of a NS package')
1021 @click.option('--literal', is_flag
=True,
1022 help='print literally, no pretty table')
1023 @click.argument('name')
1025 def nsd_show2(ctx
, name
, literal
):
1026 """shows the content of a NSD
1028 NAME: name or ID of the NSD/NSpkg
1031 nsd_show(ctx
, name
, literal
)
1034 def vnfd_show(ctx
, name
, literal
):
1037 resp
= ctx
.obj
.vnfd
.get(name
)
1038 # resp = ctx.obj.vnfd.get_individual(name)
1039 # except ClientException as e:
1044 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1047 table
= PrettyTable(['field', 'value'])
1048 for k
, v
in list(resp
.items()):
1049 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1054 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1057 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1060 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1063 catalog
= pkgtype
+ '-catalog'
1064 full_catalog
= pkgtype
+ ':' + catalog
1065 if resp
.get(catalog
):
1066 resp
= resp
.pop(catalog
)[pkgtype
][0]
1067 elif resp
.get(full_catalog
):
1068 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1070 table
= PrettyTable(['field', 'value'])
1071 for k
, v
in list(resp
.items()):
1072 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1076 @cli_osm.command(name
='vnfd-show', short_help
='shows the details of a NF package')
1077 @click.option('--literal', is_flag
=True,
1078 help='print literally, no pretty table')
1079 @click.argument('name')
1081 def vnfd_show1(ctx
, name
, literal
):
1082 """shows the content of a VNFD
1084 NAME: name or ID of the VNFD/VNFpkg
1087 vnfd_show(ctx
, name
, literal
)
1090 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the details of a NF package')
1091 @click.option('--literal', is_flag
=True,
1092 help='print literally, no pretty table')
1093 @click.argument('name')
1095 def vnfd_show2(ctx
, name
, literal
):
1096 """shows the content of a VNFD
1098 NAME: name or ID of the VNFD/VNFpkg
1101 vnfd_show(ctx
, name
, literal
)
1103 @cli_osm.command(name
='vnfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1104 @click.option('--literal', is_flag
=True,
1105 help='print literally, no pretty table')
1106 @click.option('--repo',
1108 help='Repository name')
1109 @click.argument('name')
1110 @click.option('--filter',
1111 help='filter by fields')
1112 @click.option('--version',
1114 help='package version')
1116 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1117 """shows the content of a VNFD in a repository
1119 NAME: name or ID of the VNFD/VNFpkg
1122 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1125 @cli_osm.command(name
='nsd-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1126 @click.option('--literal', is_flag
=True,
1127 help='print literally, no pretty table')
1128 @click.option('--repo',
1130 help='Repository name')
1131 @click.argument('name')
1132 @click.option('--filter',
1133 help='filter by fields')
1134 @click.option('--version',
1136 help='package version')
1138 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1139 """shows the content of a VNFD in a repository
1141 NAME: name or ID of the VNFD/VNFpkg
1144 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1146 @cli_osm.command(name
='nspkg-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1147 @click.option('--literal', is_flag
=True,
1148 help='print literally, no pretty table')
1149 @click.option('--repo',
1151 help='Repository name')
1152 @click.argument('name')
1153 @click.option('--filter',
1154 help='filter by fields')
1155 @click.option('--version',
1157 help='package version')
1159 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1160 """shows the content of a VNFD in a repository
1162 NAME: name or ID of the VNFD/VNFpkg
1165 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1167 @cli_osm.command(name
='nfpkg-show', short_help
='shows the details of a NF package')
1168 @click.option('--literal', is_flag
=True,
1169 help='print literally, no pretty table')
1170 @click.argument('name')
1172 def nfpkg_show(ctx
, name
, literal
):
1173 """shows the content of a NF Descriptor
1175 NAME: name or ID of the NFpkg
1178 vnfd_show(ctx
, name
, literal
)
1181 @cli_osm.command(name
='nfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1182 @click.option('--literal', is_flag
=True,
1183 help='print literally, no pretty table')
1184 @click.option('--repo',
1186 help='Repository name')
1187 @click.argument('name')
1188 @click.option('--filter',
1189 help='filter by fields')
1190 @click.option('--version',
1192 help='package version')
1194 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1195 """shows the content of a VNFD in a repository
1197 NAME: name or ID of the VNFD/VNFpkg
1200 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1203 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
1204 @click.argument('name')
1205 @click.option('--literal', is_flag
=True,
1206 help='print literally, no pretty table')
1207 @click.option('--filter', default
=None)
1209 def ns_show(ctx
, name
, literal
, filter):
1210 """shows the info of a NS instance
1212 NAME: name or ID of the NS instance
1216 ns
= ctx
.obj
.ns
.get(name
)
1217 # except ClientException as e:
1222 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1225 table
= PrettyTable(['field', 'value'])
1227 for k
, v
in list(ns
.items()):
1228 if filter is None or filter in k
:
1229 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1231 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1232 if fullclassname
!= 'osmclient.sol005.client.Client':
1233 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1234 nsr_optdata
= nsopdata
['nsr:nsr']
1235 for k
, v
in list(nsr_optdata
.items()):
1236 if filter is None or filter in k
:
1237 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1242 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1243 @click.argument('name')
1244 @click.option('--literal', is_flag
=True,
1245 help='print literally, no pretty table')
1246 @click.option('--filter', default
=None, help='restricts the information to the fields in the filter')
1247 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1249 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1250 """shows the info of a VNF instance
1252 NAME: name or ID of the VNF instance
1254 def print_kdu_status(op_info_status
):
1255 """print KDU status properly formatted
1258 op_status
= yaml
.safe_load(op_info_status
)
1259 if "namespace" in op_status
and "info" in op_status
and \
1260 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1261 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1262 "seconds" in op_status
["info"]["last_deployed"]:
1263 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1264 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1265 print("NAMESPACE: {}".format(op_status
["namespace"]))
1266 status_code
= "UNKNOWN"
1267 if op_status
["info"]["status"]["code"]==1:
1268 status_code
= "DEPLOYED"
1269 print("STATUS: {}".format(status_code
))
1272 print(op_status
["info"]["status"]["resources"])
1273 if "notes" in op_status
["info"]["status"]:
1275 print(op_status
["info"]["status"]["notes"])
1277 print(op_info_status
)
1279 print(op_info_status
)
1284 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1286 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1289 check_client_version(ctx
.obj
, ctx
.command
.name
)
1290 resp
= ctx
.obj
.vnf
.get(name
)
1293 ns_id
= resp
['nsr-id-ref']
1295 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1296 op_data
['kdu_name'] = kdu
1297 op_data
['primitive'] = 'status'
1298 op_data
['primitive_params'] = {}
1299 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1302 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1303 if op_info
['operationState'] == 'COMPLETED':
1304 print_kdu_status(op_info
['detailed-status'])
1308 print ("Could not determine KDU status")
1312 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1315 table
= PrettyTable(['field', 'value'])
1317 for k
, v
in list(resp
.items()):
1318 if filter is None or filter in k
:
1319 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1322 # except ClientException as e:
1327 #@cli_osm.command(name='vnf-monitoring-show')
1328 #@click.argument('vnf_name')
1329 #@click.pass_context
1330 #def vnf_monitoring_show(ctx, vnf_name):
1332 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1333 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1334 # except ClientException as e:
1338 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1339 # if resp is not None:
1340 # for monitor in resp:
1344 # monitor['value-integer'],
1345 # monitor['units']])
1350 #@cli_osm.command(name='ns-monitoring-show')
1351 #@click.argument('ns_name')
1352 #@click.pass_context
1353 #def ns_monitoring_show(ctx, ns_name):
1355 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1356 # resp = ctx.obj.ns.get_monitoring(ns_name)
1357 # except ClientException as e:
1361 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1362 # for key, val in list(resp.items()):
1363 # for monitor in val:
1367 # monitor['value-integer'],
1368 # monitor['units']])
1373 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1374 @click.argument('id')
1375 @click.option('--filter', default
=None)
1376 @click.option('--literal', is_flag
=True,
1377 help='print literally, no pretty table')
1379 def ns_op_show(ctx
, id, filter, literal
):
1380 """shows the detailed info of a NS operation
1382 ID: operation identifier
1386 check_client_version(ctx
.obj
, ctx
.command
.name
)
1387 op_info
= ctx
.obj
.ns
.get_op(id)
1388 # except ClientException as e:
1393 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1396 table
= PrettyTable(['field', 'value'])
1397 for k
, v
in list(op_info
.items()):
1398 if filter is None or filter in k
:
1399 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1404 def nst_show(ctx
, name
, literal
):
1407 check_client_version(ctx
.obj
, ctx
.command
.name
)
1408 resp
= ctx
.obj
.nst
.get(name
)
1409 #resp = ctx.obj.nst.get_individual(name)
1410 # except ClientException as e:
1415 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1418 table
= PrettyTable(['field', 'value'])
1419 for k
, v
in list(resp
.items()):
1420 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1425 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1426 @click.option('--literal', is_flag
=True,
1427 help='print literally, no pretty table')
1428 @click.argument('name')
1430 def nst_show1(ctx
, name
, literal
):
1431 """shows the content of a Network Slice Template (NST)
1433 NAME: name or ID of the NST
1436 nst_show(ctx
, name
, literal
)
1439 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1440 @click.option('--literal', is_flag
=True,
1441 help='print literally, no pretty table')
1442 @click.argument('name')
1444 def nst_show2(ctx
, name
, literal
):
1445 """shows the content of a Network Slice Template (NST)
1447 NAME: name or ID of the NST
1450 nst_show(ctx
, name
, literal
)
1453 def nsi_show(ctx
, name
, literal
, filter):
1456 check_client_version(ctx
.obj
, ctx
.command
.name
)
1457 nsi
= ctx
.obj
.nsi
.get(name
)
1458 # except ClientException as e:
1463 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1466 table
= PrettyTable(['field', 'value'])
1468 for k
, v
in list(nsi
.items()):
1469 if filter is None or filter in k
:
1470 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1476 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1477 @click.argument('name')
1478 @click.option('--literal', is_flag
=True,
1479 help='print literally, no pretty table')
1480 @click.option('--filter', default
=None)
1482 def nsi_show1(ctx
, name
, literal
, filter):
1483 """shows the content of a Network Slice Instance (NSI)
1485 NAME: name or ID of the Network Slice Instance
1488 nsi_show(ctx
, name
, literal
, filter)
1491 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1492 @click.argument('name')
1493 @click.option('--literal', is_flag
=True,
1494 help='print literally, no pretty table')
1495 @click.option('--filter', default
=None)
1497 def nsi_show2(ctx
, name
, literal
, filter):
1498 """shows the content of a Network Slice Instance (NSI)
1500 NAME: name or ID of the Network Slice Instance
1503 nsi_show(ctx
, name
, literal
, filter)
1506 def nsi_op_show(ctx
, id, filter):
1509 check_client_version(ctx
.obj
, ctx
.command
.name
)
1510 op_info
= ctx
.obj
.nsi
.get_op(id)
1511 # except ClientException as e:
1515 table
= PrettyTable(['field', 'value'])
1516 for k
, v
in list(op_info
.items()):
1517 if filter is None or filter in k
:
1518 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1523 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1524 @click.argument('id')
1525 @click.option('--filter', default
=None)
1527 def nsi_op_show1(ctx
, id, filter):
1528 """shows the info of an operation over a Network Slice Instance(NSI)
1530 ID: operation identifier
1533 nsi_op_show(ctx
, id, filter)
1536 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1537 @click.argument('id')
1538 @click.option('--filter', default
=None)
1540 def nsi_op_show2(ctx
, id, filter):
1541 """shows the info of an operation over a Network Slice Instance(NSI)
1543 ID: operation identifier
1546 nsi_op_show(ctx
, id, filter)
1549 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1550 @click.argument('name')
1551 @click.option('--literal', is_flag
=True,
1552 help='print literally, no pretty table')
1553 @click.option('--filter', default
=None)
1555 def pdu_show(ctx
, name
, literal
, filter):
1556 """shows the content of a Physical Deployment Unit (PDU)
1558 NAME: name or ID of the PDU
1562 check_client_version(ctx
.obj
, ctx
.command
.name
)
1563 pdu
= ctx
.obj
.pdu
.get(name
)
1564 # except ClientException as e:
1569 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1572 table
= PrettyTable(['field', 'value'])
1574 for k
, v
in list(pdu
.items()):
1575 if filter is None or filter in k
:
1576 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1582 ####################
1584 ####################
1586 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1589 check_client_version(ctx
.obj
, ctx
.command
.name
)
1591 filename
= ctx
.obj
.osmrepo
.get_pkg('ns', filename
, repo
, vendor
, version
)
1592 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1593 # except ClientException as e:
1598 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1599 @click.argument('filename')
1600 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1601 help='Deprecated. Use override')
1602 @click.option('--override', 'overwrite', default
=None,
1603 help='overrides fields in descriptor, format: '
1604 '"key1.key2...=value[;key3...=value;...]"')
1605 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1606 help='The charm will not be compiled, it is assumed to already exist')
1607 @click.option('--repo', default
=None,
1608 help='[repository]: Repository name')
1609 @click.option('--vendor', default
=None,
1610 help='[repository]: filter by vendor]')
1611 @click.option('--version', default
='latest',
1612 help='[repository]: filter by version. Default: latest')
1614 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1615 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1618 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1619 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1620 If FILENAME is an NF Package folder, it is built and then onboarded.
1623 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1627 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1628 @click.argument('filename')
1629 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1630 help='Deprecated. Use override')
1631 @click.option('--override', 'overwrite', default
=None,
1632 help='overrides fields in descriptor, format: '
1633 '"key1.key2...=value[;key3...=value;...]"')
1634 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1635 help='The charm will not be compiled, it is assumed to already exist')
1636 @click.option('--repo', default
=None,
1637 help='[repository]: Repository name')
1638 @click.option('--vendor', default
=None,
1639 help='[repository]: filter by vendor]')
1640 @click.option('--version', default
='latest',
1641 help='[repository]: filter by version. Default: latest')
1643 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1644 """onboards a new NSpkg
1646 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1647 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1648 If FILENAME is an NF Package folder, it is built and then onboarded.
1651 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1655 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1656 repo
, vendor
, version
):
1659 check_client_version(ctx
.obj
, ctx
.command
.name
)
1661 filename
= ctx
.obj
.osmrepo
.get_pkg('vnf', filename
, repo
, vendor
, version
)
1662 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1663 override_epa
=override_epa
, override_nonepa
=override_nonepa
,
1664 override_paravirt
=override_paravirt
)
1665 # except ClientException as e:
1670 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1671 @click.argument('filename')
1672 @click.option('--overwrite', 'overwrite', default
=None,
1673 help='overwrite deprecated, use override')
1674 @click.option('--override', 'overwrite', default
=None,
1675 help='overrides fields in descriptor, format: '
1676 '"key1.key2...=value[;key3...=value;...]"')
1677 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1678 help='The charm will not be compiled, it is assumed to already exist')
1679 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1680 help='adds guest-epa parameters to all VDU')
1681 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1682 help='removes all guest-epa parameters from all VDU')
1683 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1684 help='overrides all VDU interfaces to PARAVIRT')
1685 @click.option('--repo', default
=None,
1686 help='[repository]: Repository name')
1687 @click.option('--vendor', default
=None,
1688 help='[repository]: filter by vendor]')
1689 @click.option('--version', default
='latest',
1690 help='[repository]: filter by version. Default: latest')
1692 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1693 repo
,vendor
, version
):
1694 """creates a new VNFD/VNFpkg
1696 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1697 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1698 If FILENAME is an NF Package folder, it is built and then onboarded.
1701 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1702 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1703 repo
=repo
, vendor
=vendor
, version
=version
)
1706 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1707 @click.argument('filename')
1708 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1709 help='Deprecated. Use override')
1710 @click.option('--override', 'overwrite', default
=None,
1711 help='overrides fields in descriptor, format: '
1712 '"key1.key2...=value[;key3...=value;...]"')
1713 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1714 help='The charm will not be compiled, it is assumed to already exist')
1715 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1716 help='adds guest-epa parameters to all VDU')
1717 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1718 help='removes all guest-epa parameters from all VDU')
1719 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1720 help='overrides all VDU interfaces to PARAVIRT')
1721 @click.option('--repo', default
=None,
1722 help='[repository]: Repository name')
1723 @click.option('--vendor', default
=None,
1724 help='[repository]: filter by vendor]')
1725 @click.option('--version', default
='latest',
1726 help='[repository]: filter by version. Default: latest')
1728 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1729 repo
, vendor
, version
):
1730 """creates a new VNFD/VNFpkg
1732 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1733 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1734 If FILENAME is an NF Package folder, it is built and then onboarded.
1737 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1738 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1739 repo
=repo
, vendor
=vendor
, version
=version
)
1741 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1742 @click.argument('filename')
1743 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1744 help='Deprecated. Use override')
1745 @click.option('--override', 'overwrite', default
=None,
1746 help='overrides fields in descriptor, format: '
1747 '"key1.key2...=value[;key3...=value;...]"')
1748 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1749 help='The charm will not be compiled, it is assumed to already exist')
1750 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1751 help='adds guest-epa parameters to all VDU')
1752 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1753 help='removes all guest-epa parameters from all VDU')
1754 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1755 help='overrides all VDU interfaces to PARAVIRT')
1756 @click.option('--repo', default
=None,
1757 help='[repository]: Repository name')
1758 @click.option('--vendor', default
=None,
1759 help='[repository]: filter by vendor]')
1760 @click.option('--version', default
='latest',
1761 help='[repository]: filter by version. Default: latest')
1763 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1764 repo
, vendor
, version
):
1765 """creates a new NFpkg
1768 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1769 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1770 If FILENAME is an NF Package folder, it is built and then onboarded.
1773 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1774 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1775 repo
=repo
, vendor
=vendor
, version
=version
)
1778 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1779 @click.option('--ns_name',
1780 prompt
=True, help='name of the NS instance')
1781 @click.option('--nsd_name',
1782 prompt
=True, help='name of the NS descriptor')
1783 @click.option('--vim_account',
1784 prompt
=True, help='default VIM account id or name for the deployment')
1785 @click.option('--admin_status',
1787 help='administration status')
1788 @click.option('--ssh_keys',
1790 help='comma separated list of public key files to inject to vnfs')
1791 @click.option('--config',
1793 help='ns specific yaml configuration')
1794 @click.option('--config_file',
1796 help='ns specific yaml configuration file')
1797 @click.option('--wait',
1801 help='do not return the control immediately, but keep it '
1802 'until the operation is completed, or timeout')
1813 """creates a new NS instance"""
1817 check_client_version(ctx
.obj
, '--config_file')
1819 raise ClientException('"--config" option is incompatible with "--config_file" option')
1820 with
open(config_file
, 'r') as cf
:
1827 account
=vim_account
,
1829 # except ClientException as e:
1834 def nst_create(ctx
, filename
, overwrite
):
1837 check_client_version(ctx
.obj
, ctx
.command
.name
)
1838 ctx
.obj
.nst
.create(filename
, overwrite
)
1839 # except ClientException as e:
1844 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1845 @click.argument('filename')
1846 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1847 help='Deprecated. Use override')
1848 @click.option('--override', 'overwrite', default
=None,
1849 help='overrides fields in descriptor, format: '
1850 '"key1.key2...=value[;key3...=value;...]"')
1852 def nst_create1(ctx
, filename
, overwrite
):
1853 """creates a new Network Slice Template (NST)
1855 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1858 nst_create(ctx
, filename
, overwrite
)
1861 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1862 @click.argument('filename')
1863 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1864 help='Deprecated. Use override')
1865 @click.option('--override', 'overwrite', default
=None,
1866 help='overrides fields in descriptor, format: '
1867 '"key1.key2...=value[;key3...=value;...]"')
1869 def nst_create2(ctx
, filename
, overwrite
):
1870 """creates a new Network Slice Template (NST)
1872 FILENAME: NST yaml file or NSTpkg tar.gz file
1875 nst_create(ctx
, filename
, overwrite
)
1878 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1879 """creates a new Network Slice Instance (NSI)"""
1882 check_client_version(ctx
.obj
, ctx
.command
.name
)
1885 raise ClientException('"--config" option is incompatible with "--config_file" option')
1886 with
open(config_file
, 'r') as cf
:
1888 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1889 account
=vim_account
, wait
=wait
)
1890 # except ClientException as e:
1895 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1896 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1897 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1898 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1899 @click.option('--ssh_keys', default
=None,
1900 help='comma separated list of keys to inject to vnfs')
1901 @click.option('--config', default
=None,
1902 help='Netslice specific yaml configuration:\n'
1903 'netslice_subnet: [\n'
1904 'id: TEXT, vim_account: TEXT,\n'
1905 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1906 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1907 'additionalParamsForNsi: {param: value, ...}\n'
1908 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1910 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1912 @click.option('--config_file',
1914 help='nsi specific yaml configuration file')
1915 @click.option('--wait',
1919 help='do not return the control immediately, but keep it '
1920 'until the operation is completed, or timeout')
1922 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1923 """creates a new Network Slice Instance (NSI)"""
1925 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1928 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1929 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1930 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1931 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1932 @click.option('--ssh_keys', default
=None,
1933 help='comma separated list of keys to inject to vnfs')
1934 @click.option('--config', default
=None,
1935 help='Netslice specific yaml configuration:\n'
1936 'netslice_subnet: [\n'
1937 'id: TEXT, vim_account: TEXT,\n'
1938 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1939 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1941 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1943 @click.option('--config_file',
1945 help='nsi specific yaml configuration file')
1946 @click.option('--wait',
1950 help='do not return the control immediately, but keep it '
1951 'until the operation is completed, or timeout')
1953 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1954 """creates a new Network Slice Instance (NSI)"""
1956 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1959 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1960 @click.option('--name', help='name of the Physical Deployment Unit')
1961 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1962 @click.option('--interface',
1963 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1964 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1966 @click.option('--description', help='human readable description')
1967 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
1968 @click.option('--descriptor_file', default
=None,
1969 help='PDU descriptor file (as an alternative to using the other arguments')
1971 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
1972 """creates a new Physical Deployment Unit (PDU)"""
1975 check_client_version(ctx
.obj
, ctx
.command
.name
)
1977 if not descriptor_file
:
1979 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1981 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1983 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1985 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1987 with
open(descriptor_file
, 'r') as df
:
1988 pdu
= yaml
.safe_load(df
.read())
1989 if name
: pdu
["name"] = name
1990 if pdu_type
: pdu
["type"] = pdu_type
1991 if description
: pdu
["description"] = description
1992 if vim_account
: pdu
["vim_accounts"] = vim_account
1995 for iface
in interface
:
1996 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
1997 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
1998 ifaces_list
.append(new_iface
)
1999 pdu
["interfaces"] = ifaces_list
2000 ctx
.obj
.pdu
.create(pdu
)
2001 # except ClientException as e:
2006 ####################
2008 ####################
2010 def nsd_update(ctx
, name
, content
):
2013 check_client_version(ctx
.obj
, ctx
.command
.name
)
2014 ctx
.obj
.nsd
.update(name
, content
)
2015 # except ClientException as e:
2020 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
2021 @click.argument('name')
2022 @click.option('--content', default
=None,
2023 help='filename with the NSD/NSpkg replacing the current one')
2025 def nsd_update1(ctx
, name
, content
):
2026 """updates a NSD/NSpkg
2028 NAME: name or ID of the NSD/NSpkg
2031 nsd_update(ctx
, name
, content
)
2034 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
2035 @click.argument('name')
2036 @click.option('--content', default
=None,
2037 help='filename with the NSD/NSpkg replacing the current one')
2039 def nsd_update2(ctx
, name
, content
):
2040 """updates a NSD/NSpkg
2042 NAME: name or ID of the NSD/NSpkg
2045 nsd_update(ctx
, name
, content
)
2048 def vnfd_update(ctx
, name
, content
):
2051 check_client_version(ctx
.obj
, ctx
.command
.name
)
2052 ctx
.obj
.vnfd
.update(name
, content
)
2053 # except ClientException as e:
2058 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
2059 @click.argument('name')
2060 @click.option('--content', default
=None,
2061 help='filename with the VNFD/VNFpkg replacing the current one')
2063 def vnfd_update1(ctx
, name
, content
):
2064 """updates a VNFD/VNFpkg
2066 NAME: name or ID of the VNFD/VNFpkg
2069 vnfd_update(ctx
, name
, content
)
2072 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
2073 @click.argument('name')
2074 @click.option('--content', default
=None,
2075 help='filename with the VNFD/VNFpkg replacing the current one')
2077 def vnfd_update2(ctx
, name
, content
):
2078 """updates a VNFD/VNFpkg
2080 NAME: VNFD yaml file or VNFpkg tar.gz file
2083 vnfd_update(ctx
, name
, content
)
2086 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
2087 @click.argument('name')
2088 @click.option('--content', default
=None,
2089 help='filename with the NFpkg replacing the current one')
2091 def nfpkg_update(ctx
, name
, content
):
2094 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2097 vnfd_update(ctx
, name
, content
)
2100 def nst_update(ctx
, name
, content
):
2103 check_client_version(ctx
.obj
, ctx
.command
.name
)
2104 ctx
.obj
.nst
.update(name
, content
)
2105 # except ClientException as e:
2110 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
2111 @click.argument('name')
2112 @click.option('--content', default
=None,
2113 help='filename with the NST/NSTpkg replacing the current one')
2115 def nst_update1(ctx
, name
, content
):
2116 """updates a Network Slice Template (NST)
2118 NAME: name or ID of the NSD/NSpkg
2121 nst_update(ctx
, name
, content
)
2124 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
2125 @click.argument('name')
2126 @click.option('--content', default
=None,
2127 help='filename with the NST/NSTpkg replacing the current one')
2129 def nst_update2(ctx
, name
, content
):
2130 """updates a Network Slice Template (NST)
2132 NAME: name or ID of the NSD/NSpkg
2135 nst_update(ctx
, name
, content
)
2138 ####################
2140 ####################
2142 def nsd_delete(ctx
, name
, force
):
2146 ctx
.obj
.nsd
.delete(name
)
2148 check_client_version(ctx
.obj
, '--force')
2149 ctx
.obj
.nsd
.delete(name
, force
)
2150 # except ClientException as e:
2155 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
2156 @click.argument('name')
2157 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2159 def nsd_delete1(ctx
, name
, force
):
2160 """deletes a NSD/NSpkg
2162 NAME: name or ID of the NSD/NSpkg to be deleted
2165 nsd_delete(ctx
, name
, force
)
2168 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
2169 @click.argument('name')
2170 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2172 def nsd_delete2(ctx
, name
, force
):
2173 """deletes a NSD/NSpkg
2175 NAME: name or ID of the NSD/NSpkg to be deleted
2178 nsd_delete(ctx
, name
, force
)
2181 def vnfd_delete(ctx
, name
, force
):
2185 ctx
.obj
.vnfd
.delete(name
)
2187 check_client_version(ctx
.obj
, '--force')
2188 ctx
.obj
.vnfd
.delete(name
, force
)
2189 # except ClientException as e:
2194 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
2195 @click.argument('name')
2196 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2198 def vnfd_delete1(ctx
, name
, force
):
2199 """deletes a VNFD/VNFpkg
2201 NAME: name or ID of the VNFD/VNFpkg to be deleted
2204 vnfd_delete(ctx
, name
, force
)
2207 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
2208 @click.argument('name')
2209 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2211 def vnfd_delete2(ctx
, name
, force
):
2212 """deletes a VNFD/VNFpkg
2214 NAME: name or ID of the VNFD/VNFpkg to be deleted
2217 vnfd_delete(ctx
, name
, force
)
2220 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
2221 @click.argument('name')
2222 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2224 def nfpkg_delete(ctx
, name
, force
):
2227 NAME: name or ID of the NFpkg to be deleted
2230 vnfd_delete(ctx
, name
, force
)
2233 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
2234 @click.argument('name')
2235 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2236 @click.option('--config', default
=None,
2237 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2238 "600, skip_terminate_primitives: True}'")
2239 @click.option('--wait',
2243 help='do not return the control immediately, but keep it '
2244 'until the operation is completed, or timeout')
2246 def ns_delete(ctx
, name
, force
, config
, wait
):
2247 """deletes a NS instance
2249 NAME: name or ID of the NS instance to be deleted
2254 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2256 check_client_version(ctx
.obj
, '--force')
2257 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2258 # except ClientException as e:
2263 def nst_delete(ctx
, name
, force
):
2266 check_client_version(ctx
.obj
, ctx
.command
.name
)
2267 ctx
.obj
.nst
.delete(name
, force
)
2268 # except ClientException as e:
2273 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
2274 @click.argument('name')
2275 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2277 def nst_delete1(ctx
, name
, force
):
2278 """deletes a Network Slice Template (NST)
2280 NAME: name or ID of the NST/NSTpkg to be deleted
2283 nst_delete(ctx
, name
, force
)
2286 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
2287 @click.argument('name')
2288 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2290 def nst_delete2(ctx
, name
, force
):
2291 """deletes a Network Slice Template (NST)
2293 NAME: name or ID of the NST/NSTpkg to be deleted
2296 nst_delete(ctx
, name
, force
)
2299 def nsi_delete(ctx
, name
, force
, wait
):
2302 check_client_version(ctx
.obj
, ctx
.command
.name
)
2303 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2304 # except ClientException as e:
2309 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2310 @click.argument('name')
2311 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2312 @click.option('--wait',
2316 help='do not return the control immediately, but keep it '
2317 'until the operation is completed, or timeout')
2319 def nsi_delete1(ctx
, name
, force
, wait
):
2320 """deletes a Network Slice Instance (NSI)
2322 NAME: name or ID of the Network Slice instance to be deleted
2325 nsi_delete(ctx
, name
, force
, wait
=wait
)
2328 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2329 @click.argument('name')
2330 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2332 def nsi_delete2(ctx
, name
, force
, wait
):
2333 """deletes a Network Slice Instance (NSI)
2335 NAME: name or ID of the Network Slice instance to be deleted
2338 nsi_delete(ctx
, name
, force
, wait
=wait
)
2341 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2342 @click.argument('name')
2343 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2345 def pdu_delete(ctx
, name
, force
):
2346 """deletes a Physical Deployment Unit (PDU)
2348 NAME: name or ID of the PDU to be deleted
2352 check_client_version(ctx
.obj
, ctx
.command
.name
)
2353 ctx
.obj
.pdu
.delete(name
, force
)
2354 # except ClientException as e:
2363 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2364 @click.option('--name',
2366 help='Name to create datacenter')
2367 @click.option('--user',
2369 help='VIM username')
2370 @click.option('--password',
2373 confirmation_prompt
=True,
2374 help='VIM password')
2375 @click.option('--auth_url',
2378 @click.option('--tenant',
2380 help='VIM tenant name')
2381 @click.option('--config',
2383 help='VIM specific config parameters')
2384 @click.option('--account_type',
2385 default
='openstack',
2387 @click.option('--description',
2389 help='human readable description')
2390 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2391 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2392 @click.option('--wait',
2396 help='do not return the control immediately, but keep it '
2397 'until the operation is completed, or timeout')
2411 """creates a new VIM account"""
2415 check_client_version(ctx
.obj
, '--sdn_controller')
2416 if sdn_port_mapping
:
2417 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2419 vim
['vim-username'] = user
2420 vim
['vim-password'] = password
2421 vim
['vim-url'] = auth_url
2422 vim
['vim-tenant-name'] = tenant
2423 vim
['vim-type'] = account_type
2424 vim
['description'] = description
2425 vim
['config'] = config
2426 if sdn_controller
or sdn_port_mapping
:
2427 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2429 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2430 # except ClientException as e:
2435 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2436 @click.argument('name')
2437 @click.option('--newname', help='New name for the VIM account')
2438 @click.option('--user', help='VIM username')
2439 @click.option('--password', help='VIM password')
2440 @click.option('--auth_url', help='VIM url')
2441 @click.option('--tenant', help='VIM tenant name')
2442 @click.option('--config', help='VIM specific config parameters')
2443 @click.option('--account_type', help='VIM type')
2444 @click.option('--description', help='human readable description')
2445 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller to be associated with this VIM'
2446 'account. Use empty string to disassociate')
2447 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2448 @click.option('--wait',
2452 help='do not return the control immediately, but keep it '
2453 'until the operation is completed, or timeout')
2468 """updates a VIM account
2470 NAME: name or ID of the VIM account
2474 check_client_version(ctx
.obj
, ctx
.command
.name
)
2476 if newname
: vim
['name'] = newname
2477 if user
: vim
['vim_user'] = user
2478 if password
: vim
['vim_password'] = password
2479 if auth_url
: vim
['vim_url'] = auth_url
2480 if tenant
: vim
['vim-tenant-name'] = tenant
2481 if account_type
: vim
['vim_type'] = account_type
2482 if description
: vim
['description'] = description
2483 if config
: vim
['config'] = config
2484 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2485 # except ClientException as e:
2490 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2491 @click.argument('name')
2492 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2493 @click.option('--wait',
2497 help='do not return the control immediately, but keep it '
2498 'until the operation is completed, or timeout')
2500 def vim_delete(ctx
, name
, force
, wait
):
2501 """deletes a VIM account
2503 NAME: name or ID of the VIM account to be deleted
2508 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2510 check_client_version(ctx
.obj
, '--force')
2511 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2512 # except ClientException as e:
2517 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2518 #@click.option('--ro_update/--no_ro_update',
2520 # help='update list from RO')
2521 @click.option('--filter', default
=None,
2522 help='restricts the list to the VIM accounts matching the filter')
2523 @click.option('--long', is_flag
=True,
2524 help='get more details of the NS (project, vim, deployment status, configuration status.')
2526 def vim_list(ctx
, filter, long):
2527 """list all VIM accounts"""
2530 check_client_version(ctx
.obj
, '--filter')
2532 # check_client_version(ctx.obj, '--ro_update', 'v1')
2533 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2534 if fullclassname
== 'osmclient.sol005.client.Client':
2535 resp
= ctx
.obj
.vim
.list(filter)
2537 # resp = ctx.obj.vim.list(ro_update)
2539 table
= PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details'])
2541 table
= PrettyTable(['vim name', 'uuid', 'operational state'])
2544 vim_details
= ctx
.obj
.vim
.get(vim
['uuid'])
2545 if 'vim_password' in vim_details
:
2546 vim_details
['vim_password']='********'
2547 logger
.debug('VIM details: {}'.format(yaml
.safe_dump(vim_details
)))
2548 vim_state
= vim_details
['_admin'].get('operationalState', '-')
2549 error_details
= 'N/A'
2550 if vim_state
== 'ERROR':
2551 error_details
= vim_details
['_admin'].get('detailed-status', 'Not found')
2552 project_list
= ctx
.obj
.project
.list()
2553 vim_project_list
= vim_details
.get('_admin').get('projects_read')
2555 project_name
= 'None'
2556 if vim_project_list
:
2557 project_id
= vim_project_list
[0]
2558 for p
in project_list
:
2559 if p
['_id'] == project_id
:
2560 project_name
= p
['name']
2562 table
.add_row([vim
['name'], vim
['uuid'], '{} ({})'.format(project_name
, project_id
),
2563 vim_state
, wrap_text(text
=error_details
, width
=80)])
2565 table
.add_row([vim
['name'], vim
['uuid'], vim
['_admin'].get('operationalState', '-')])
2570 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2571 @click.argument('name')
2573 def vim_show(ctx
, name
):
2574 """shows the details of a VIM account
2576 NAME: name or ID of the VIM account
2580 resp
= ctx
.obj
.vim
.get(name
)
2581 if 'vim_password' in resp
:
2582 resp
['vim_password']='********'
2583 # except ClientException as e:
2587 table
= PrettyTable(['key', 'attribute'])
2588 for k
, v
in list(resp
.items()):
2589 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2594 ####################
2596 ####################
2598 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2599 @click.option('--name',
2601 help='Name for the WIM account')
2602 @click.option('--user',
2603 help='WIM username')
2604 @click.option('--password',
2605 help='WIM password')
2606 @click.option('--url',
2609 # @click.option('--tenant',
2610 # help='wIM tenant name')
2611 @click.option('--config',
2613 help='WIM specific config parameters')
2614 @click.option('--wim_type',
2616 @click.option('--description',
2618 help='human readable description')
2619 @click.option('--wim_port_mapping', default
=None,
2620 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2621 "(WAN service endpoint id and info)")
2622 @click.option('--wait',
2626 help='do not return the control immediately, but keep it '
2627 'until the operation is completed, or timeout')
2640 """creates a new WIM account"""
2643 check_client_version(ctx
.obj
, ctx
.command
.name
)
2644 # if sdn_controller:
2645 # check_client_version(ctx.obj, '--sdn_controller')
2646 # if sdn_port_mapping:
2647 # check_client_version(ctx.obj, '--sdn_port_mapping')
2649 if user
: wim
['user'] = user
2650 if password
: wim
['password'] = password
2651 if url
: wim
['wim_url'] = url
2652 # if tenant: wim['tenant'] = tenant
2653 wim
['wim_type'] = wim_type
2654 if description
: wim
['description'] = description
2655 if config
: wim
['config'] = config
2656 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2657 # except ClientException as e:
2662 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2663 @click.argument('name')
2664 @click.option('--newname', help='New name for the WIM account')
2665 @click.option('--user', help='WIM username')
2666 @click.option('--password', help='WIM password')
2667 @click.option('--url', help='WIM url')
2668 @click.option('--config', help='WIM specific config parameters')
2669 @click.option('--wim_type', help='WIM type')
2670 @click.option('--description', help='human readable description')
2671 @click.option('--wim_port_mapping', default
=None,
2672 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2673 "(WAN service endpoint id and info)")
2674 @click.option('--wait',
2678 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2691 """updates a WIM account
2693 NAME: name or ID of the WIM account
2697 check_client_version(ctx
.obj
, ctx
.command
.name
)
2699 if newname
: wim
['name'] = newname
2700 if user
: wim
['user'] = user
2701 if password
: wim
['password'] = password
2702 if url
: wim
['url'] = url
2703 # if tenant: wim['tenant'] = tenant
2704 if wim_type
: wim
['wim_type'] = wim_type
2705 if description
: wim
['description'] = description
2706 if config
: wim
['config'] = config
2707 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2708 # except ClientException as e:
2713 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2714 @click.argument('name')
2715 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2716 @click.option('--wait',
2720 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2722 def wim_delete(ctx
, name
, force
, wait
):
2723 """deletes a WIM account
2725 NAME: name or ID of the WIM account to be deleted
2729 check_client_version(ctx
.obj
, ctx
.command
.name
)
2730 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2731 # except ClientException as e:
2736 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2737 @click.option('--filter', default
=None,
2738 help='restricts the list to the WIM accounts matching the filter')
2740 def wim_list(ctx
, filter):
2741 """list all WIM accounts"""
2744 check_client_version(ctx
.obj
, ctx
.command
.name
)
2745 resp
= ctx
.obj
.wim
.list(filter)
2746 table
= PrettyTable(['wim name', 'uuid'])
2748 table
.add_row([wim
['name'], wim
['uuid']])
2751 # except ClientException as e:
2756 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2757 @click.argument('name')
2759 def wim_show(ctx
, name
):
2760 """shows the details of a WIM account
2762 NAME: name or ID of the WIM account
2766 check_client_version(ctx
.obj
, ctx
.command
.name
)
2767 resp
= ctx
.obj
.wim
.get(name
)
2768 if 'password' in resp
:
2769 resp
['wim_password']='********'
2770 # except ClientException as e:
2774 table
= PrettyTable(['key', 'attribute'])
2775 for k
, v
in list(resp
.items()):
2776 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2781 ####################
2782 # SDN controller operations
2783 ####################
2785 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2786 @click.option('--name',
2788 help='Name to create sdn controller')
2789 @click.option('--type',
2791 help='SDN controller type')
2792 @click.option('--sdn_controller_version', # hidden=True,
2793 help='Deprecated. Use --config {version: sdn_controller_version}')
2794 @click.option('--url',
2795 help='URL in format http[s]://HOST:IP/')
2796 @click.option('--ip_address', # hidden=True,
2797 help='Deprecated. Use --url')
2798 @click.option('--port', # hidden=True,
2799 help='Deprecated. Use --url')
2800 @click.option('--switch_dpid', # hidden=True,
2801 help='Deprecated. Use --config {switch_id: DPID}')
2802 @click.option('--config',
2803 help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2804 'Openflow Datapath ID), version: version}')
2805 @click.option('--user',
2806 help='SDN controller username')
2807 @click.option('--password',
2809 confirmation_prompt
=True,
2810 help='SDN controller password')
2811 @click.option('--description', default
=None, help='human readable description')
2812 @click.option('--wait',
2816 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2818 def sdnc_create(ctx
, **kwargs
):
2819 """creates a new SDN controller"""
2821 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2822 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2823 if kwargs
.get("port"):
2824 print("option '--port' is deprecated, use '--url' instead")
2825 sdncontroller
["port"] = int(kwargs
["port"])
2826 if kwargs
.get("ip_address"):
2827 print("option '--ip_address' is deprecated, use '--url' instead")
2828 sdncontroller
["ip"] = kwargs
["ip_address"]
2829 if kwargs
.get("switch_dpid"):
2830 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2831 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2832 if kwargs
.get("sdn_controller_version"):
2833 print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2836 check_client_version(ctx
.obj
, ctx
.command
.name
)
2837 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2838 # except ClientException as e:
2842 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2843 @click.argument('name')
2844 @click.option('--newname', help='New name for the SDN controller')
2845 @click.option('--description', default
=None, help='human readable description')
2846 @click.option('--type', help='SDN controller type')
2847 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2848 @click.option('--config', help='Extra information for SDN in yaml format, as '
2849 '{switch_id: identity used for the plugin (e.g. DPID: '
2850 'Openflow Datapath ID), version: version}')
2851 @click.option('--user', help='SDN controller username')
2852 @click.option('--password', help='SDN controller password')
2853 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2854 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2855 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2856 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2857 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2858 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2860 def sdnc_update(ctx
, **kwargs
):
2861 """updates an SDN controller
2863 NAME: name or ID of the SDN controller
2866 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2867 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2868 if kwargs
.get("newname"):
2869 sdncontroller
["name"] = kwargs
["newname"]
2870 if kwargs
.get("port"):
2871 print("option '--port' is deprecated, use '--url' instead")
2872 sdncontroller
["port"] = int(kwargs
["port"])
2873 if kwargs
.get("ip_address"):
2874 print("option '--ip_address' is deprecated, use '--url' instead")
2875 sdncontroller
["ip"] = kwargs
["ip_address"]
2876 if kwargs
.get("switch_dpid"):
2877 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2878 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2879 if kwargs
.get("sdn_controller_version"):
2880 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2884 check_client_version(ctx
.obj
, ctx
.command
.name
)
2885 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2886 # except ClientException as e:
2891 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2892 @click.argument('name')
2893 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2894 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2895 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2897 def sdnc_delete(ctx
, name
, force
, wait
):
2898 """deletes an SDN controller
2900 NAME: name or ID of the SDN controller to be deleted
2904 check_client_version(ctx
.obj
, ctx
.command
.name
)
2905 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2906 # except ClientException as e:
2911 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2912 @click.option('--filter', default
=None,
2913 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2915 def sdnc_list(ctx
, filter):
2916 """list all SDN controllers"""
2919 check_client_version(ctx
.obj
, ctx
.command
.name
)
2920 resp
= ctx
.obj
.sdnc
.list(filter)
2921 # except ClientException as e:
2924 table
= PrettyTable(['sdnc name', 'id'])
2926 table
.add_row([sdnc
['name'], sdnc
['_id']])
2931 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2932 @click.argument('name')
2934 def sdnc_show(ctx
, name
):
2935 """shows the details of an SDN controller
2937 NAME: name or ID of the SDN controller
2941 check_client_version(ctx
.obj
, ctx
.command
.name
)
2942 resp
= ctx
.obj
.sdnc
.get(name
)
2943 # except ClientException as e:
2947 table
= PrettyTable(['key', 'attribute'])
2948 for k
, v
in list(resp
.items()):
2949 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2954 ###########################
2955 # K8s cluster operations
2956 ###########################
2958 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2959 @click.argument('name')
2960 @click.option('--creds',
2962 help='credentials file, i.e. a valid `.kube/config` file')
2963 @click.option('--version',
2965 help='Kubernetes version')
2966 @click.option('--vim',
2968 help='VIM target, the VIM where the cluster resides')
2969 @click.option('--k8s-nets',
2971 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) ...]}"')
2972 @click.option('--description',
2974 help='human readable description')
2975 @click.option('--namespace',
2976 default
='kube-system',
2977 help='namespace to be used for its operation, defaults to `kube-system`')
2978 @click.option('--cni',
2980 help='list of CNI plugins, in JSON inline format, used in the cluster')
2981 #@click.option('--skip-init',
2983 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2984 #@click.option('--wait',
2986 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2988 def k8scluster_add(ctx
,
2997 """adds a K8s cluster to OSM
2999 NAME: name of the K8s cluster
3002 check_client_version(ctx
.obj
, ctx
.command
.name
)
3004 cluster
['name'] = name
3005 with
open(creds
, 'r') as cf
:
3006 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3007 cluster
['k8s_version'] = version
3008 cluster
['vim_account'] = vim
3009 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3011 cluster
['description'] = description
3012 if namespace
: cluster
['namespace'] = namespace
3013 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3014 ctx
.obj
.k8scluster
.create(name
, cluster
)
3015 # except ClientException as e:
3020 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
3021 @click.argument('name')
3022 @click.option('--newname', help='New name for the K8s cluster')
3023 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3024 @click.option('--version', help='Kubernetes version')
3025 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3026 @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) ...]}"')
3027 @click.option('--description', help='human readable description')
3028 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3029 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3031 def k8scluster_update(ctx
,
3041 """updates a K8s cluster
3043 NAME: name or ID of the K8s cluster
3046 check_client_version(ctx
.obj
, ctx
.command
.name
)
3048 if newname
: cluster
['name'] = newname
3050 with
open(creds
, 'r') as cf
:
3051 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3052 if version
: cluster
['k8s_version'] = version
3053 if vim
: cluster
['vim_account'] = vim
3054 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3055 if description
: cluster
['description'] = description
3056 if namespace
: cluster
['namespace'] = namespace
3057 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3058 ctx
.obj
.k8scluster
.update(name
, cluster
)
3059 # except ClientException as e:
3064 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
3065 @click.argument('name')
3066 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3067 #@click.option('--wait',
3069 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3071 def k8scluster_delete(ctx
, name
, force
):
3072 """deletes a K8s cluster
3074 NAME: name or ID of the K8s cluster to be deleted
3077 check_client_version(ctx
.obj
, ctx
.command
.name
)
3078 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3079 # except ClientException as e:
3084 @cli_osm.command(name
='k8scluster-list')
3085 @click.option('--filter', default
=None,
3086 help='restricts the list to the K8s clusters matching the filter')
3087 @click.option('--literal', is_flag
=True,
3088 help='print literally, no pretty table')
3090 def k8scluster_list(ctx
, filter, literal
):
3091 """list all K8s clusters"""
3093 check_client_version(ctx
.obj
, ctx
.command
.name
)
3094 resp
= ctx
.obj
.k8scluster
.list(filter)
3096 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3098 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
3099 for cluster
in resp
:
3100 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
3101 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
3102 trunc_text(cluster
.get('description') or '', 40)])
3105 # except ClientException as e:
3110 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
3111 @click.argument('name')
3112 @click.option('--literal', is_flag
=True,
3113 help='print literally, no pretty table')
3115 def k8scluster_show(ctx
, name
, literal
):
3116 """shows the details of a K8s cluster
3118 NAME: name or ID of the K8s cluster
3121 resp
= ctx
.obj
.k8scluster
.get(name
)
3123 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3125 table
= PrettyTable(['key', 'attribute'])
3126 for k
, v
in list(resp
.items()):
3127 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
3130 # except ClientException as e:
3136 ###########################
3138 ###########################
3140 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
3141 @click.argument('name')
3142 @click.argument('uri')
3143 @click.option('--type',
3144 type=click
.Choice(['helm-chart', 'juju-bundle', 'osm']),
3146 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3147 @click.option('--description',
3149 help='human readable description')
3150 @click.option('--user',
3152 help='OSM repository: The username of the OSM repository')
3153 @click.option('--password',
3155 help='OSM repository: The password of the OSM repository')
3156 #@click.option('--wait',
3158 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3160 def repo_add(ctx
, **kwargs
):
3161 """adds a repo to OSM
3163 NAME: name of the repo
3164 URI: URI of the repo
3167 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
3169 repo
["url"] = repo
.pop("uri")
3170 if repo
["type"] in ['helm-chart', 'juju-bundle']:
3171 ctx
.obj
.repo
.create(repo
['name'], repo
)
3173 ctx
.obj
.osmrepo
.create(repo
['name'], repo
)
3174 # except ClientException as e:
3179 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
3180 @click.argument('name')
3181 @click.option('--newname', help='New name for the repo')
3182 @click.option('--uri', help='URI of the repo')
3183 @click.option('--description', help='human readable description')
3184 #@click.option('--wait',
3186 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3188 def repo_update(ctx
,
3193 """updates a repo in OSM
3195 NAME: name of the repo
3198 check_client_version(ctx
.obj
, ctx
.command
.name
)
3201 repo
['name'] = newname
3204 if description
: repo
['description'] = description
3206 ctx
.obj
.repo
.update(name
, repo
)
3208 ctx
.obj
.osmrepo
.update(name
, repo
)
3210 # except ClientException as e:
3215 @cli_osm.command(name
='repo-index', short_help
='Index a repository from a folder with artifacts')
3216 @click.option('--origin', default
='.', help='origin path where the artifacts are located')
3217 @click.option('--destination', default
='.', help='destination path where the index is deployed')
3219 def repo_index(ctx
, origin
, destination
):
3220 """Index a repository
3222 NAME: name or ID of the repo to be deleted
3224 check_client_version(ctx
.obj
, ctx
.command
.name
)
3225 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
3228 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
3229 @click.argument('name')
3230 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3231 #@click.option('--wait',
3233 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3235 def repo_delete(ctx
, name
, force
):
3238 NAME: name or ID of the repo to be deleted
3242 ctx
.obj
.repo
.delete(name
, force
=force
)
3244 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
3245 # except ClientException as e:
3250 @cli_osm.command(name
='repo-list')
3251 @click.option('--filter', default
=None,
3252 help='restricts the list to the repos matching the filter')
3253 @click.option('--literal', is_flag
=True,
3254 help='print literally, no pretty table')
3256 def repo_list(ctx
, filter, literal
):
3257 """list all repos"""
3260 check_client_version(ctx
.obj
, ctx
.command
.name
)
3261 resp
= ctx
.obj
.repo
.list(filter)
3262 resp
+= ctx
.obj
.osmrepo
.list(filter)
3264 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3266 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3268 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3269 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description') or '',40)])
3273 # except ClientException as e:
3278 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
3279 @click.argument('name')
3280 @click.option('--literal', is_flag
=True,
3281 help='print literally, no pretty table')
3283 def repo_show(ctx
, name
, literal
):
3284 """shows the details of a repo
3286 NAME: name or ID of the repo
3289 resp
= ctx
.obj
.repo
.get(name
)
3291 resp
= ctx
.obj
.osmrepo
.get(name
)
3295 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3297 table
= PrettyTable(['key', 'attribute'])
3299 for k
, v
in list(resp
.items()):
3300 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3304 # except ClientException as e:
3310 ####################
3311 # Project mgmt operations
3312 ####################
3314 @cli_osm.command(name
='project-create', short_help
='creates a new project')
3315 @click.argument('name')
3316 #@click.option('--description',
3317 # default='no description',
3318 # help='human readable description')
3319 @click.option('--domain-name', 'domain_name',
3321 help='assign to a domain')
3322 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3323 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3324 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3326 def project_create(ctx
, name
, domain_name
, quotas
):
3327 """Creates a new project
3329 NAME: name of the project
3330 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3331 QUOTAS: set quotas for the project
3334 project
= {'name': name
}
3336 project
['domain_name'] = domain_name
3337 quotas_dict
= _process_project_quotas(quotas
)
3339 project
['quotas'] = quotas_dict
3342 check_client_version(ctx
.obj
, ctx
.command
.name
)
3343 ctx
.obj
.project
.create(name
, project
)
3344 # except ClientException as e:
3349 def _process_project_quotas(quota_list
):
3354 for quota
in quota_list
:
3355 for single_quota
in quota
.split(","):
3356 k
, v
= single_quota
.split("=")
3357 quotas_dict
[k
] = None if v
in ('None', 'null', '') else int(v
)
3358 except (ValueError, TypeError):
3359 raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3363 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3364 @click.argument('name')
3365 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3367 def project_delete(ctx
, name
):
3368 """deletes a project
3370 NAME: name or ID of the project to be deleted
3374 check_client_version(ctx
.obj
, ctx
.command
.name
)
3375 ctx
.obj
.project
.delete(name
)
3376 # except ClientException as e:
3381 @cli_osm.command(name
='project-list', short_help
='list all projects')
3382 @click.option('--filter', default
=None,
3383 help='restricts the list to the projects matching the filter')
3385 def project_list(ctx
, filter):
3386 """list all projects"""
3389 check_client_version(ctx
.obj
, ctx
.command
.name
)
3390 resp
= ctx
.obj
.project
.list(filter)
3391 # except ClientException as e:
3394 table
= PrettyTable(['name', 'id'])
3396 table
.add_row([proj
['name'], proj
['_id']])
3401 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3402 @click.argument('name')
3404 def project_show(ctx
, name
):
3405 """shows the details of a project
3407 NAME: name or ID of the project
3411 check_client_version(ctx
.obj
, ctx
.command
.name
)
3412 resp
= ctx
.obj
.project
.get(name
)
3413 # except ClientException as e:
3417 table
= PrettyTable(['key', 'attribute'])
3418 for k
, v
in resp
.items():
3419 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3424 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3425 @click.argument('project')
3426 @click.option('--name', default
=None,
3427 help='new name for the project')
3428 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3429 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3430 "(use empty to reset quota to default")
3432 def project_update(ctx
, project
, name
, quotas
):
3434 Update a project name
3437 :param project: id or name of the project to modify
3438 :param name: new name for the project
3439 :param quotas: change quotas of the project
3443 project_changes
= {}
3445 project_changes
['name'] = name
3446 quotas_dict
= _process_project_quotas(quotas
)
3448 project_changes
['quotas'] = quotas_dict
3451 check_client_version(ctx
.obj
, ctx
.command
.name
)
3452 ctx
.obj
.project
.update(project
, project_changes
)
3453 # except ClientException as e:
3457 ####################
3458 # User mgmt operations
3459 ####################
3461 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3462 @click.argument('username')
3463 @click.option('--password',
3466 confirmation_prompt
=True,
3467 help='user password')
3468 @click.option('--projects',
3469 # prompt="Comma separate list of projects",
3471 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3472 help='list of project ids that the user belongs to')
3473 @click.option('--project-role-mappings', 'project_role_mappings',
3474 default
=None, multiple
=True,
3475 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3476 @click.option('--domain-name', 'domain_name',
3478 help='assign to a domain')
3480 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
3481 """Creates a new user
3484 USERNAME: name of the user
3485 PASSWORD: password of the user
3486 PROJECTS: projects assigned to user (internal only)
3487 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3488 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3492 user
['username'] = username
3493 user
['password'] = password
3494 user
['projects'] = projects
3495 user
['project_role_mappings'] = project_role_mappings
3497 user
['domain_name'] = domain_name
3500 check_client_version(ctx
.obj
, ctx
.command
.name
)
3501 ctx
.obj
.user
.create(username
, user
)
3502 # except ClientException as e:
3507 @cli_osm.command(name
='user-update', short_help
='updates user information')
3508 @click.argument('username')
3509 @click.option('--password',
3512 # confirmation_prompt=True,
3513 help='user password')
3514 @click.option('--set-username', 'set_username',
3516 help='change username')
3517 @click.option('--set-project', 'set_project',
3518 default
=None, multiple
=True,
3519 help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3520 @click.option('--remove-project', 'remove_project',
3521 default
=None, multiple
=True,
3522 help="removes project from user: 'project'")
3523 @click.option('--add-project-role', 'add_project_role',
3524 default
=None, multiple
=True,
3525 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3526 @click.option('--remove-project-role', 'remove_project_role',
3527 default
=None, multiple
=True,
3528 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3530 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3531 add_project_role
, remove_project_role
):
3532 """Update a user information
3535 USERNAME: name of the user
3536 PASSWORD: new password
3537 SET_USERNAME: new username
3538 SET_PROJECT: creating mappings for project/role(s)
3539 REMOVE_PROJECT: deleting mappings for project/role(s)
3540 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3541 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3545 user
['password'] = password
3546 user
['username'] = set_username
3547 user
['set-project'] = set_project
3548 user
['remove-project'] = remove_project
3549 user
['add-project-role'] = add_project_role
3550 user
['remove-project-role'] = remove_project_role
3553 check_client_version(ctx
.obj
, ctx
.command
.name
)
3554 ctx
.obj
.user
.update(username
, user
)
3555 # except ClientException as e:
3560 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3561 @click.argument('name')
3562 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3564 def user_delete(ctx
, name
):
3568 NAME: name or ID of the user to be deleted
3572 check_client_version(ctx
.obj
, ctx
.command
.name
)
3573 ctx
.obj
.user
.delete(name
)
3574 # except ClientException as e:
3579 @cli_osm.command(name
='user-list', short_help
='list all users')
3580 @click.option('--filter', default
=None,
3581 help='restricts the list to the users matching the filter')
3583 def user_list(ctx
, filter):
3584 """list all users"""
3586 check_client_version(ctx
.obj
, ctx
.command
.name
)
3587 resp
= ctx
.obj
.user
.list(filter)
3588 # except ClientException as e:
3591 table
= PrettyTable(['name', 'id'])
3593 table
.add_row([user
['username'], user
['_id']])
3598 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3599 @click.argument('name')
3601 def user_show(ctx
, name
):
3602 """shows the details of a user
3604 NAME: name or ID of the user
3608 check_client_version(ctx
.obj
, ctx
.command
.name
)
3609 resp
= ctx
.obj
.user
.get(name
)
3610 if 'password' in resp
:
3611 resp
['password']='********'
3612 # except ClientException as e:
3616 table
= PrettyTable(['key', 'attribute'])
3617 for k
, v
in resp
.items():
3618 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3623 ####################
3624 # Fault Management operations
3625 ####################
3627 @cli_osm.command(name
='ns-alarm-create')
3628 @click.argument('name')
3629 @click.option('--ns', prompt
=True, help='NS instance id or name')
3630 @click.option('--vnf', prompt
=True,
3631 help='VNF name (VNF member index as declared in the NSD)')
3632 @click.option('--vdu', prompt
=True,
3633 help='VDU name (VDU name as declared in the VNFD)')
3634 @click.option('--metric', prompt
=True,
3635 help='Name of the metric (e.g. cpu_utilization)')
3636 @click.option('--severity', default
='WARNING',
3637 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3638 @click.option('--threshold_value', prompt
=True,
3639 help='threshold value that, when crossed, an alarm is triggered')
3640 @click.option('--threshold_operator', prompt
=True,
3641 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3642 @click.option('--statistic', default
='AVERAGE',
3643 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3645 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3646 threshold_value
, threshold_operator
, statistic
):
3647 """creates a new alarm for a NS instance"""
3648 # TODO: Check how to validate threshold_value.
3649 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3652 ns_instance
= ctx
.obj
.ns
.get(ns
)
3654 alarm
['alarm_name'] = name
3655 alarm
['ns_id'] = ns_instance
['_id']
3656 alarm
['correlation_id'] = ns_instance
['_id']
3657 alarm
['vnf_member_index'] = vnf
3658 alarm
['vdu_name'] = vdu
3659 alarm
['metric_name'] = metric
3660 alarm
['severity'] = severity
3661 alarm
['threshold_value'] = int(threshold_value
)
3662 alarm
['operation'] = threshold_operator
3663 alarm
['statistic'] = statistic
3664 check_client_version(ctx
.obj
, ctx
.command
.name
)
3665 ctx
.obj
.ns
.create_alarm(alarm
)
3666 # except ClientException as e:
3671 #@cli_osm.command(name='ns-alarm-delete')
3672 #@click.argument('name')
3673 #@click.pass_context
3674 #def ns_alarm_delete(ctx, name):
3675 # """deletes an alarm
3677 # NAME: name of the alarm to be deleted
3680 # check_client_version(ctx.obj, ctx.command.name)
3681 # ctx.obj.ns.delete_alarm(name)
3682 # except ClientException as e:
3687 ####################
3688 # Performance Management operations
3689 ####################
3691 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3692 @click.option('--ns', prompt
=True, help='NS instance id or name')
3693 @click.option('--vnf', prompt
=True,
3694 help='VNF name (VNF member index as declared in the NSD)')
3695 @click.option('--vdu', prompt
=True,
3696 help='VDU name (VDU name as declared in the VNFD)')
3697 @click.option('--metric', prompt
=True,
3698 help='name of the metric (e.g. cpu_utilization)')
3699 #@click.option('--period', default='1w',
3700 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3701 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3703 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3704 """exports a metric to the internal OSM bus, which can be read by other apps"""
3705 # TODO: Check how to validate interval.
3706 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3709 ns_instance
= ctx
.obj
.ns
.get(ns
)
3711 metric_data
['ns_id'] = ns_instance
['_id']
3712 metric_data
['correlation_id'] = ns_instance
['_id']
3713 metric_data
['vnf_member_index'] = vnf
3714 metric_data
['vdu_name'] = vdu
3715 metric_data
['metric_name'] = metric
3716 metric_data
['collection_unit'] = 'WEEK'
3717 metric_data
['collection_period'] = 1
3718 check_client_version(ctx
.obj
, ctx
.command
.name
)
3720 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3724 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3725 time
.sleep(int(interval
))
3727 # except ClientException as e:
3732 ####################
3734 ####################
3736 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3738 def get_version(ctx
):
3739 """shows client and server versions"""
3741 check_client_version(ctx
.obj
, "version")
3742 print ("Server version: {}".format(ctx
.obj
.get_version()))
3743 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3744 # except ClientException as e:
3748 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3749 @click.argument('filename')
3750 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3751 help='the charm will not be compiled, it is assumed to already exist')
3753 def upload_package(ctx
, filename
, skip_charm_build
):
3754 """uploads a vnf package or ns package
3756 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3760 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3761 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3762 if fullclassname
!= 'osmclient.sol005.client.Client':
3763 ctx
.obj
.package
.wait_for_upload(filename
)
3764 # except ClientException as e:
3769 #@cli_osm.command(name='ns-scaling-show')
3770 #@click.argument('ns_name')
3771 #@click.pass_context
3772 #def show_ns_scaling(ctx, ns_name):
3773 # """shows the status of a NS scaling operation
3775 # NS_NAME: name of the NS instance being scaled
3778 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3779 # resp = ctx.obj.ns.list()
3780 # except ClientException as e:
3784 # table = PrettyTable(
3787 # 'operational status',
3792 # if ns_name == ns['name']:
3793 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3794 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3795 # for record in scaling_records:
3796 # if 'instance' in record:
3797 # instances = record['instance']
3798 # for inst in instances:
3800 # [record['scaling-group-name-ref'],
3801 # inst['instance-id'],
3802 # inst['op-status'],
3803 # time.strftime('%Y-%m-%d %H:%M:%S',
3805 # inst['create-time'])),
3811 #@cli_osm.command(name='ns-scale')
3812 #@click.argument('ns_name')
3813 #@click.option('--ns_scale_group', prompt=True)
3814 #@click.option('--index', prompt=True)
3815 #@click.option('--wait',
3819 # help='do not return the control immediately, but keep it \
3820 # until the operation is completed, or timeout')
3821 #@click.pass_context
3822 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3825 # NS_NAME: name of the NS instance to be scaled
3828 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3829 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3830 # except ClientException as e:
3835 #@cli_osm.command(name='config-agent-list')
3836 #@click.pass_context
3837 #def config_agent_list(ctx):
3838 # """list config agents"""
3840 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3841 # except ClientException as e:
3844 # table = PrettyTable(['name', 'account-type', 'details'])
3845 # for account in ctx.obj.vca.list():
3848 # account['account-type'],
3854 #@cli_osm.command(name='config-agent-delete')
3855 #@click.argument('name')
3856 #@click.pass_context
3857 #def config_agent_delete(ctx, name):
3858 # """deletes a config agent
3860 # NAME: name of the config agent to be deleted
3863 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3864 # ctx.obj.vca.delete(name)
3865 # except ClientException as e:
3870 #@cli_osm.command(name='config-agent-add')
3871 #@click.option('--name',
3873 #@click.option('--account_type',
3875 #@click.option('--server',
3877 #@click.option('--user',
3879 #@click.option('--secret',
3882 # confirmation_prompt=True)
3883 #@click.pass_context
3884 #def config_agent_add(ctx, name, account_type, server, user, secret):
3885 # """adds a config agent"""
3887 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3888 # ctx.obj.vca.create(name, account_type, server, user, secret)
3889 # except ClientException as e:
3894 #@cli_osm.command(name='ro-dump')
3895 #@click.pass_context
3897 # """shows RO agent information"""
3898 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3899 # resp = ctx.obj.vim.get_resource_orchestrator()
3900 # table = PrettyTable(['key', 'attribute'])
3901 # for k, v in list(resp.items()):
3902 # table.add_row([k, json.dumps(v, indent=2)])
3907 #@cli_osm.command(name='vcs-list')
3908 #@click.pass_context
3910 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3911 # resp = ctx.obj.utils.get_vcs_info()
3912 # table = PrettyTable(['component name', 'state'])
3913 # for component in resp:
3914 # table.add_row([component['component_name'], component['state']])
3919 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3920 @click.argument('ns_name')
3921 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3922 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3923 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3924 @click.option('--vdu_count', default
=None, type=int, help='number of vdu instance of this vdu_id')
3925 @click.option('--action_name', prompt
=True, help='action name')
3926 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3927 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3928 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
3929 @click.option('--wait',
3933 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3946 """executes an action/primitive over a NS instance
3948 NS_NAME: name or ID of the NS instance
3952 check_client_version(ctx
.obj
, ctx
.command
.name
)
3955 op_data
['member_vnf_index'] = vnf_name
3957 op_data
['kdu_name'] = kdu_name
3959 op_data
['vdu_id'] = vdu_id
3960 if vdu_count
is not None:
3961 op_data
['vdu_count_index'] = vdu_count
3963 op_data
['timeout_ns_action'] = timeout
3964 op_data
['primitive'] = action_name
3966 with
open(params_file
, 'r') as pf
:
3969 op_data
['primitive_params'] = yaml
.safe_load(params
)
3971 op_data
['primitive_params'] = {}
3972 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
3974 # except ClientException as e:
3979 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
3980 @click.argument('ns_name')
3981 @click.argument('vnf_name')
3982 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
3983 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
3984 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
3985 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
3986 @click.option('--wait', required
=False, default
=False, is_flag
=True,
3987 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3998 Executes a VNF scale (adding/removing VDUs)
4001 NS_NAME: name or ID of the NS instance.
4002 VNF_NAME: member-vnf-index in the NS to be scaled.
4006 check_client_version(ctx
.obj
, ctx
.command
.name
)
4007 if not scale_in
and not scale_out
:
4009 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
)
4010 # except ClientException as e:
4015 ##############################
4016 # Role Management Operations #
4017 ##############################
4019 @cli_osm.command(name
='role-create', short_help
='creates a new role')
4020 @click.argument('name')
4021 @click.option('--permissions',
4023 help='role permissions using a dictionary')
4025 def role_create(ctx
, name
, permissions
):
4030 NAME: Name or ID of the role.
4031 DEFINITION: Definition of grant/denial of access to resources.
4035 check_client_version(ctx
.obj
, ctx
.command
.name
)
4036 ctx
.obj
.role
.create(name
, permissions
)
4037 # except ClientException as e:
4042 @cli_osm.command(name
='role-update', short_help
='updates a role')
4043 @click.argument('name')
4044 @click.option('--set-name',
4046 help='change name of rle')
4047 # @click.option('--permissions',
4049 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4050 @click.option('--add',
4052 help='yaml format dictionary with permission: True/False to access grant/denial')
4053 @click.option('--remove',
4055 help='yaml format list to remove a permission')
4057 def role_update(ctx
, name
, set_name
, add
, remove
):
4062 NAME: Name or ID of the role.
4063 DEFINITION: Definition overwrites the old definition.
4064 ADD: Grant/denial of access to resource to add.
4065 REMOVE: Grant/denial of access to resource to remove.
4069 check_client_version(ctx
.obj
, ctx
.command
.name
)
4070 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
4071 # except ClientException as e:
4076 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
4077 @click.argument('name')
4078 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4080 def role_delete(ctx
, name
):
4085 NAME: Name or ID of the role.
4089 check_client_version(ctx
.obj
, ctx
.command
.name
)
4090 ctx
.obj
.role
.delete(name
)
4091 # except ClientException as e:
4096 @cli_osm.command(name
='role-list', short_help
='list all roles')
4097 @click.option('--filter', default
=None,
4098 help='restricts the list to the projects matching the filter')
4100 def role_list(ctx
, filter):
4106 check_client_version(ctx
.obj
, ctx
.command
.name
)
4107 resp
= ctx
.obj
.role
.list(filter)
4108 # except ClientException as e:
4111 table
= PrettyTable(['name', 'id'])
4113 table
.add_row([role
['name'], role
['_id']])
4118 @cli_osm.command(name
='role-show', short_help
='show specific role')
4119 @click.argument('name')
4121 def role_show(ctx
, name
):
4123 Shows the details of a role.
4126 NAME: Name or ID of the role.
4130 check_client_version(ctx
.obj
, ctx
.command
.name
)
4131 resp
= ctx
.obj
.role
.get(name
)
4132 # except ClientException as e:
4136 table
= PrettyTable(['key', 'attribute'])
4137 for k
, v
in resp
.items():
4138 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4143 @cli_osm.command(name
='package-create',
4144 short_help
='Create a package descriptor')
4145 @click.argument('package-type')
4146 @click.argument('package-name')
4147 @click.option('--base-directory',
4149 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4150 @click.option('--image',
4151 default
="image-name",
4152 help='(VNF) Set the name of the vdu image. Default "image-name"')
4153 @click.option('--vdus',
4155 help='(VNF) Set the number of vdus in a VNF. Default 1')
4156 @click.option('--vcpu',
4158 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4159 @click.option('--memory',
4161 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4162 @click.option('--storage',
4164 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4165 @click.option('--interfaces',
4167 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4168 @click.option('--vendor',
4170 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4171 @click.option('--override',
4174 help='(NS/VNF/NST) Flag for overriding the package if exists.')
4175 @click.option('--detailed',
4178 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4179 @click.option('--netslice-subnets',
4181 help='(NST) Number of netslice subnets. Default 1')
4182 @click.option('--netslice-vlds',
4184 help='(NST) Number of netslice vlds. Default 1')
4186 def package_create(ctx
,
4202 Creates an OSM NS, VNF, NST package
4205 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4206 PACKAGE_NAME: Name of the package to create the folder with the content.
4210 check_client_version(ctx
.obj
, ctx
.command
.name
)
4211 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
4212 resp
= ctx
.obj
.package_tool
.create(package_type
,
4221 interfaces
=interfaces
,
4224 netslice_subnets
=netslice_subnets
,
4225 netslice_vlds
=netslice_vlds
)
4227 # except ClientException as inst:
4228 # print("ERROR: {}".format(inst))
4231 @cli_osm.command(name
='package-validate',
4232 short_help
='Validate a package descriptor')
4233 @click.argument('base-directory',
4236 @click.option('--recursive/--no-recursive',
4238 help='The activated recursive option will validate the yaml files'
4239 ' within the indicated directory and in its subdirectories')
4241 def package_validate(ctx
,
4245 Validate descriptors given a base directory.
4248 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4251 check_client_version(ctx
.obj
, ctx
.command
.name
)
4252 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
4253 table
= PrettyTable()
4254 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
4255 # Print the dictionary generated by the validation function
4256 for result
in results
:
4257 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
4258 table
.sortby
= "VALID"
4259 table
.align
["PATH"] = "l"
4260 table
.align
["TYPE"] = "l"
4261 table
.align
["ERROR"] = "l"
4263 # except ClientException as inst:
4264 # print("ERROR: {}".format(inst))
4267 @cli_osm.command(name
='package-build',
4268 short_help
='Build the tar.gz of the package')
4269 @click.argument('package-folder')
4270 @click.option('--skip-validation',
4273 help='skip package validation')
4274 @click.option('--skip-charm-build', default
=False, is_flag
=True,
4275 help='the charm will not be compiled, it is assumed to already exist')
4277 def package_build(ctx
,
4282 Build the package NS, VNF given the package_folder.
4285 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4288 check_client_version(ctx
.obj
, ctx
.command
.name
)
4289 results
= ctx
.obj
.package_tool
.build(package_folder
,
4290 skip_validation
=skip_validation
,
4291 skip_charm_build
=skip_charm_build
)
4293 # except ClientException as inst:
4294 # print("ERROR: {}".format(inst))
4302 except pycurl
.error
as exc
:
4304 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4305 except ClientException
as exc
:
4306 print("ERROR: {}".format(exc
))
4307 except (FileNotFoundError
, PermissionError
) as exc
:
4308 print("Cannot open file: {}".format(exc
))
4309 except yaml
.YAMLError
as exc
:
4310 print("Invalid YAML format: {}".format(exc
))
4312 # TODO capture other controlled exceptions here
4313 # TODO remove the ClientException captures from all places, unless they do something different
4316 if __name__
== '__main__':