e3b5ac6f2252572220bb8f320230dd37af60579a
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('name', '-')
478 repository
= vnfd
.get('repository')
480 vendor
= vnfd
.get('vendor')
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
['name'] if 'name' in vnfd
else '-'
524 onb_state
= vnfd
['_admin'].get('onboardingState','-')
525 op_state
= vnfd
['_admin'].get('operationalState','-')
526 vendor
= vnfd
.get('vendor')
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
['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")
1311 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1314 table
= PrettyTable(['field', 'value'])
1316 for k
, v
in list(resp
.items()):
1317 if filter is None or filter in k
:
1318 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1321 # except ClientException as e:
1326 #@cli_osm.command(name='vnf-monitoring-show')
1327 #@click.argument('vnf_name')
1328 #@click.pass_context
1329 #def vnf_monitoring_show(ctx, vnf_name):
1331 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1332 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1333 # except ClientException as e:
1337 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1338 # if resp is not None:
1339 # for monitor in resp:
1343 # monitor['value-integer'],
1344 # monitor['units']])
1349 #@cli_osm.command(name='ns-monitoring-show')
1350 #@click.argument('ns_name')
1351 #@click.pass_context
1352 #def ns_monitoring_show(ctx, ns_name):
1354 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1355 # resp = ctx.obj.ns.get_monitoring(ns_name)
1356 # except ClientException as e:
1360 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1361 # for key, val in list(resp.items()):
1362 # for monitor in val:
1366 # monitor['value-integer'],
1367 # monitor['units']])
1372 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1373 @click.argument('id')
1374 @click.option('--filter', default
=None)
1375 @click.option('--literal', is_flag
=True,
1376 help='print literally, no pretty table')
1378 def ns_op_show(ctx
, id, filter, literal
):
1379 """shows the detailed info of a NS operation
1381 ID: operation identifier
1385 check_client_version(ctx
.obj
, ctx
.command
.name
)
1386 op_info
= ctx
.obj
.ns
.get_op(id)
1387 # except ClientException as e:
1392 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1395 table
= PrettyTable(['field', 'value'])
1396 for k
, v
in list(op_info
.items()):
1397 if filter is None or filter in k
:
1398 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1403 def nst_show(ctx
, name
, literal
):
1406 check_client_version(ctx
.obj
, ctx
.command
.name
)
1407 resp
= ctx
.obj
.nst
.get(name
)
1408 #resp = ctx.obj.nst.get_individual(name)
1409 # except ClientException as e:
1414 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1417 table
= PrettyTable(['field', 'value'])
1418 for k
, v
in list(resp
.items()):
1419 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1424 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1425 @click.option('--literal', is_flag
=True,
1426 help='print literally, no pretty table')
1427 @click.argument('name')
1429 def nst_show1(ctx
, name
, literal
):
1430 """shows the content of a Network Slice Template (NST)
1432 NAME: name or ID of the NST
1435 nst_show(ctx
, name
, literal
)
1438 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1439 @click.option('--literal', is_flag
=True,
1440 help='print literally, no pretty table')
1441 @click.argument('name')
1443 def nst_show2(ctx
, name
, literal
):
1444 """shows the content of a Network Slice Template (NST)
1446 NAME: name or ID of the NST
1449 nst_show(ctx
, name
, literal
)
1452 def nsi_show(ctx
, name
, literal
, filter):
1455 check_client_version(ctx
.obj
, ctx
.command
.name
)
1456 nsi
= ctx
.obj
.nsi
.get(name
)
1457 # except ClientException as e:
1462 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1465 table
= PrettyTable(['field', 'value'])
1467 for k
, v
in list(nsi
.items()):
1468 if filter is None or filter in k
:
1469 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1475 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1476 @click.argument('name')
1477 @click.option('--literal', is_flag
=True,
1478 help='print literally, no pretty table')
1479 @click.option('--filter', default
=None)
1481 def nsi_show1(ctx
, name
, literal
, filter):
1482 """shows the content of a Network Slice Instance (NSI)
1484 NAME: name or ID of the Network Slice Instance
1487 nsi_show(ctx
, name
, literal
, filter)
1490 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1491 @click.argument('name')
1492 @click.option('--literal', is_flag
=True,
1493 help='print literally, no pretty table')
1494 @click.option('--filter', default
=None)
1496 def nsi_show2(ctx
, name
, literal
, filter):
1497 """shows the content of a Network Slice Instance (NSI)
1499 NAME: name or ID of the Network Slice Instance
1502 nsi_show(ctx
, name
, literal
, filter)
1505 def nsi_op_show(ctx
, id, filter):
1508 check_client_version(ctx
.obj
, ctx
.command
.name
)
1509 op_info
= ctx
.obj
.nsi
.get_op(id)
1510 # except ClientException as e:
1514 table
= PrettyTable(['field', 'value'])
1515 for k
, v
in list(op_info
.items()):
1516 if filter is None or filter in k
:
1517 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1522 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1523 @click.argument('id')
1524 @click.option('--filter', default
=None)
1526 def nsi_op_show1(ctx
, id, filter):
1527 """shows the info of an operation over a Network Slice Instance(NSI)
1529 ID: operation identifier
1532 nsi_op_show(ctx
, id, filter)
1535 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1536 @click.argument('id')
1537 @click.option('--filter', default
=None)
1539 def nsi_op_show2(ctx
, id, filter):
1540 """shows the info of an operation over a Network Slice Instance(NSI)
1542 ID: operation identifier
1545 nsi_op_show(ctx
, id, filter)
1548 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1549 @click.argument('name')
1550 @click.option('--literal', is_flag
=True,
1551 help='print literally, no pretty table')
1552 @click.option('--filter', default
=None)
1554 def pdu_show(ctx
, name
, literal
, filter):
1555 """shows the content of a Physical Deployment Unit (PDU)
1557 NAME: name or ID of the PDU
1561 check_client_version(ctx
.obj
, ctx
.command
.name
)
1562 pdu
= ctx
.obj
.pdu
.get(name
)
1563 # except ClientException as e:
1568 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1571 table
= PrettyTable(['field', 'value'])
1573 for k
, v
in list(pdu
.items()):
1574 if filter is None or filter in k
:
1575 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1581 ####################
1583 ####################
1585 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1588 check_client_version(ctx
.obj
, ctx
.command
.name
)
1590 filename
= ctx
.obj
.osmrepo
.get_pkg('ns', filename
, repo
, vendor
, version
)
1591 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1592 # except ClientException as e:
1597 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1598 @click.argument('filename')
1599 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1600 help='Deprecated. Use override')
1601 @click.option('--override', 'overwrite', default
=None,
1602 help='overrides fields in descriptor, format: '
1603 '"key1.key2...=value[;key3...=value;...]"')
1604 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1605 help='The charm will not be compiled, it is assumed to already exist')
1606 @click.option('--repo', default
=None,
1607 help='[repository]: Repository name')
1608 @click.option('--vendor', default
=None,
1609 help='[repository]: filter by vendor]')
1610 @click.option('--version', default
='latest',
1611 help='[repository]: filter by version. Default: latest')
1613 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1614 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1617 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1618 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1619 If FILENAME is an NF Package folder, it is built and then onboarded.
1622 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1626 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1627 @click.argument('filename')
1628 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1629 help='Deprecated. Use override')
1630 @click.option('--override', 'overwrite', default
=None,
1631 help='overrides fields in descriptor, format: '
1632 '"key1.key2...=value[;key3...=value;...]"')
1633 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1634 help='The charm will not be compiled, it is assumed to already exist')
1635 @click.option('--repo', default
=None,
1636 help='[repository]: Repository name')
1637 @click.option('--vendor', default
=None,
1638 help='[repository]: filter by vendor]')
1639 @click.option('--version', default
='latest',
1640 help='[repository]: filter by version. Default: latest')
1642 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1643 """onboards a new NSpkg
1645 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1646 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1647 If FILENAME is an NF Package folder, it is built and then onboarded.
1650 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1654 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1655 repo
, vendor
, version
):
1658 check_client_version(ctx
.obj
, ctx
.command
.name
)
1660 filename
= ctx
.obj
.osmrepo
.get_pkg('vnf', filename
, repo
, vendor
, version
)
1661 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1662 override_epa
=override_epa
, override_nonepa
=override_nonepa
,
1663 override_paravirt
=override_paravirt
)
1664 # except ClientException as e:
1669 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1670 @click.argument('filename')
1671 @click.option('--overwrite', 'overwrite', default
=None,
1672 help='overwrite deprecated, use override')
1673 @click.option('--override', 'overwrite', default
=None,
1674 help='overrides fields in descriptor, format: '
1675 '"key1.key2...=value[;key3...=value;...]"')
1676 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1677 help='The charm will not be compiled, it is assumed to already exist')
1678 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1679 help='adds guest-epa parameters to all VDU')
1680 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1681 help='removes all guest-epa parameters from all VDU')
1682 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1683 help='overrides all VDU interfaces to PARAVIRT')
1684 @click.option('--repo', default
=None,
1685 help='[repository]: Repository name')
1686 @click.option('--vendor', default
=None,
1687 help='[repository]: filter by vendor]')
1688 @click.option('--version', default
='latest',
1689 help='[repository]: filter by version. Default: latest')
1691 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1692 repo
,vendor
, version
):
1693 """creates a new VNFD/VNFpkg
1695 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1696 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1697 If FILENAME is an NF Package folder, it is built and then onboarded.
1700 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1701 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1702 repo
=repo
, vendor
=vendor
, version
=version
)
1705 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1706 @click.argument('filename')
1707 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1708 help='Deprecated. Use override')
1709 @click.option('--override', 'overwrite', default
=None,
1710 help='overrides fields in descriptor, format: '
1711 '"key1.key2...=value[;key3...=value;...]"')
1712 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1713 help='The charm will not be compiled, it is assumed to already exist')
1714 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1715 help='adds guest-epa parameters to all VDU')
1716 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1717 help='removes all guest-epa parameters from all VDU')
1718 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1719 help='overrides all VDU interfaces to PARAVIRT')
1720 @click.option('--repo', default
=None,
1721 help='[repository]: Repository name')
1722 @click.option('--vendor', default
=None,
1723 help='[repository]: filter by vendor]')
1724 @click.option('--version', default
='latest',
1725 help='[repository]: filter by version. Default: latest')
1727 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1728 repo
, vendor
, version
):
1729 """creates a new VNFD/VNFpkg
1731 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1732 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1733 If FILENAME is an NF Package folder, it is built and then onboarded.
1736 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1737 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1738 repo
=repo
, vendor
=vendor
, version
=version
)
1740 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1741 @click.argument('filename')
1742 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1743 help='Deprecated. Use override')
1744 @click.option('--override', 'overwrite', default
=None,
1745 help='overrides fields in descriptor, format: '
1746 '"key1.key2...=value[;key3...=value;...]"')
1747 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1748 help='The charm will not be compiled, it is assumed to already exist')
1749 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1750 help='adds guest-epa parameters to all VDU')
1751 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1752 help='removes all guest-epa parameters from all VDU')
1753 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1754 help='overrides all VDU interfaces to PARAVIRT')
1755 @click.option('--repo', default
=None,
1756 help='[repository]: Repository name')
1757 @click.option('--vendor', default
=None,
1758 help='[repository]: filter by vendor]')
1759 @click.option('--version', default
='latest',
1760 help='[repository]: filter by version. Default: latest')
1762 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1763 repo
, vendor
, version
):
1764 """creates a new NFpkg
1767 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1768 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1769 If FILENAME is an NF Package folder, it is built and then onboarded.
1772 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1773 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1774 repo
=repo
, vendor
=vendor
, version
=version
)
1777 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1778 @click.option('--ns_name',
1779 prompt
=True, help='name of the NS instance')
1780 @click.option('--nsd_name',
1781 prompt
=True, help='name of the NS descriptor')
1782 @click.option('--vim_account',
1783 prompt
=True, help='default VIM account id or name for the deployment')
1784 @click.option('--admin_status',
1786 help='administration status')
1787 @click.option('--ssh_keys',
1789 help='comma separated list of public key files to inject to vnfs')
1790 @click.option('--config',
1792 help='ns specific yaml configuration')
1793 @click.option('--config_file',
1795 help='ns specific yaml configuration file')
1796 @click.option('--wait',
1800 help='do not return the control immediately, but keep it '
1801 'until the operation is completed, or timeout')
1812 """creates a new NS instance"""
1816 check_client_version(ctx
.obj
, '--config_file')
1818 raise ClientException('"--config" option is incompatible with "--config_file" option')
1819 with
open(config_file
, 'r') as cf
:
1826 account
=vim_account
,
1828 # except ClientException as e:
1833 def nst_create(ctx
, filename
, overwrite
):
1836 check_client_version(ctx
.obj
, ctx
.command
.name
)
1837 ctx
.obj
.nst
.create(filename
, overwrite
)
1838 # except ClientException as e:
1843 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1844 @click.argument('filename')
1845 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1846 help='Deprecated. Use override')
1847 @click.option('--override', 'overwrite', default
=None,
1848 help='overrides fields in descriptor, format: '
1849 '"key1.key2...=value[;key3...=value;...]"')
1851 def nst_create1(ctx
, filename
, overwrite
):
1852 """creates a new Network Slice Template (NST)
1854 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1857 nst_create(ctx
, filename
, overwrite
)
1860 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1861 @click.argument('filename')
1862 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1863 help='Deprecated. Use override')
1864 @click.option('--override', 'overwrite', default
=None,
1865 help='overrides fields in descriptor, format: '
1866 '"key1.key2...=value[;key3...=value;...]"')
1868 def nst_create2(ctx
, filename
, overwrite
):
1869 """creates a new Network Slice Template (NST)
1871 FILENAME: NST yaml file or NSTpkg tar.gz file
1874 nst_create(ctx
, filename
, overwrite
)
1877 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1878 """creates a new Network Slice Instance (NSI)"""
1881 check_client_version(ctx
.obj
, ctx
.command
.name
)
1884 raise ClientException('"--config" option is incompatible with "--config_file" option')
1885 with
open(config_file
, 'r') as cf
:
1887 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1888 account
=vim_account
, wait
=wait
)
1889 # except ClientException as e:
1894 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1895 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1896 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1897 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1898 @click.option('--ssh_keys', default
=None,
1899 help='comma separated list of keys to inject to vnfs')
1900 @click.option('--config', default
=None,
1901 help='Netslice specific yaml configuration:\n'
1902 'netslice_subnet: [\n'
1903 'id: TEXT, vim_account: TEXT,\n'
1904 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1905 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1906 'additionalParamsForNsi: {param: value, ...}\n'
1907 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1909 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1911 @click.option('--config_file',
1913 help='nsi specific yaml configuration file')
1914 @click.option('--wait',
1918 help='do not return the control immediately, but keep it '
1919 'until the operation is completed, or timeout')
1921 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1922 """creates a new Network Slice Instance (NSI)"""
1924 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1927 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1928 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1929 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1930 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1931 @click.option('--ssh_keys', default
=None,
1932 help='comma separated list of keys to inject to vnfs')
1933 @click.option('--config', default
=None,
1934 help='Netslice specific yaml configuration:\n'
1935 'netslice_subnet: [\n'
1936 'id: TEXT, vim_account: TEXT,\n'
1937 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1938 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1940 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1942 @click.option('--config_file',
1944 help='nsi specific yaml configuration file')
1945 @click.option('--wait',
1949 help='do not return the control immediately, but keep it '
1950 'until the operation is completed, or timeout')
1952 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1953 """creates a new Network Slice Instance (NSI)"""
1955 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1958 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1959 @click.option('--name', help='name of the Physical Deployment Unit')
1960 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1961 @click.option('--interface',
1962 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1963 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1965 @click.option('--description', help='human readable description')
1966 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
1967 @click.option('--descriptor_file', default
=None,
1968 help='PDU descriptor file (as an alternative to using the other arguments')
1970 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
1971 """creates a new Physical Deployment Unit (PDU)"""
1974 check_client_version(ctx
.obj
, ctx
.command
.name
)
1976 if not descriptor_file
:
1978 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1980 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1982 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1984 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1986 with
open(descriptor_file
, 'r') as df
:
1987 pdu
= yaml
.safe_load(df
.read())
1988 if name
: pdu
["name"] = name
1989 if pdu_type
: pdu
["type"] = pdu_type
1990 if description
: pdu
["description"] = description
1991 if vim_account
: pdu
["vim_accounts"] = vim_account
1994 for iface
in interface
:
1995 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
1996 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
1997 ifaces_list
.append(new_iface
)
1998 pdu
["interfaces"] = ifaces_list
1999 ctx
.obj
.pdu
.create(pdu
)
2000 # except ClientException as e:
2005 ####################
2007 ####################
2009 def nsd_update(ctx
, name
, content
):
2012 check_client_version(ctx
.obj
, ctx
.command
.name
)
2013 ctx
.obj
.nsd
.update(name
, content
)
2014 # except ClientException as e:
2019 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
2020 @click.argument('name')
2021 @click.option('--content', default
=None,
2022 help='filename with the NSD/NSpkg replacing the current one')
2024 def nsd_update1(ctx
, name
, content
):
2025 """updates a NSD/NSpkg
2027 NAME: name or ID of the NSD/NSpkg
2030 nsd_update(ctx
, name
, content
)
2033 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
2034 @click.argument('name')
2035 @click.option('--content', default
=None,
2036 help='filename with the NSD/NSpkg replacing the current one')
2038 def nsd_update2(ctx
, name
, content
):
2039 """updates a NSD/NSpkg
2041 NAME: name or ID of the NSD/NSpkg
2044 nsd_update(ctx
, name
, content
)
2047 def vnfd_update(ctx
, name
, content
):
2050 check_client_version(ctx
.obj
, ctx
.command
.name
)
2051 ctx
.obj
.vnfd
.update(name
, content
)
2052 # except ClientException as e:
2057 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
2058 @click.argument('name')
2059 @click.option('--content', default
=None,
2060 help='filename with the VNFD/VNFpkg replacing the current one')
2062 def vnfd_update1(ctx
, name
, content
):
2063 """updates a VNFD/VNFpkg
2065 NAME: name or ID of the VNFD/VNFpkg
2068 vnfd_update(ctx
, name
, content
)
2071 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
2072 @click.argument('name')
2073 @click.option('--content', default
=None,
2074 help='filename with the VNFD/VNFpkg replacing the current one')
2076 def vnfd_update2(ctx
, name
, content
):
2077 """updates a VNFD/VNFpkg
2079 NAME: VNFD yaml file or VNFpkg tar.gz file
2082 vnfd_update(ctx
, name
, content
)
2085 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
2086 @click.argument('name')
2087 @click.option('--content', default
=None,
2088 help='filename with the NFpkg replacing the current one')
2090 def nfpkg_update(ctx
, name
, content
):
2093 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2096 vnfd_update(ctx
, name
, content
)
2099 def nst_update(ctx
, name
, content
):
2102 check_client_version(ctx
.obj
, ctx
.command
.name
)
2103 ctx
.obj
.nst
.update(name
, content
)
2104 # except ClientException as e:
2109 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
2110 @click.argument('name')
2111 @click.option('--content', default
=None,
2112 help='filename with the NST/NSTpkg replacing the current one')
2114 def nst_update1(ctx
, name
, content
):
2115 """updates a Network Slice Template (NST)
2117 NAME: name or ID of the NSD/NSpkg
2120 nst_update(ctx
, name
, content
)
2123 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
2124 @click.argument('name')
2125 @click.option('--content', default
=None,
2126 help='filename with the NST/NSTpkg replacing the current one')
2128 def nst_update2(ctx
, name
, content
):
2129 """updates a Network Slice Template (NST)
2131 NAME: name or ID of the NSD/NSpkg
2134 nst_update(ctx
, name
, content
)
2137 ####################
2139 ####################
2141 def nsd_delete(ctx
, name
, force
):
2145 ctx
.obj
.nsd
.delete(name
)
2147 check_client_version(ctx
.obj
, '--force')
2148 ctx
.obj
.nsd
.delete(name
, force
)
2149 # except ClientException as e:
2154 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
2155 @click.argument('name')
2156 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2158 def nsd_delete1(ctx
, name
, force
):
2159 """deletes a NSD/NSpkg
2161 NAME: name or ID of the NSD/NSpkg to be deleted
2164 nsd_delete(ctx
, name
, force
)
2167 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
2168 @click.argument('name')
2169 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2171 def nsd_delete2(ctx
, name
, force
):
2172 """deletes a NSD/NSpkg
2174 NAME: name or ID of the NSD/NSpkg to be deleted
2177 nsd_delete(ctx
, name
, force
)
2180 def vnfd_delete(ctx
, name
, force
):
2184 ctx
.obj
.vnfd
.delete(name
)
2186 check_client_version(ctx
.obj
, '--force')
2187 ctx
.obj
.vnfd
.delete(name
, force
)
2188 # except ClientException as e:
2193 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
2194 @click.argument('name')
2195 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2197 def vnfd_delete1(ctx
, name
, force
):
2198 """deletes a VNFD/VNFpkg
2200 NAME: name or ID of the VNFD/VNFpkg to be deleted
2203 vnfd_delete(ctx
, name
, force
)
2206 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
2207 @click.argument('name')
2208 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2210 def vnfd_delete2(ctx
, name
, force
):
2211 """deletes a VNFD/VNFpkg
2213 NAME: name or ID of the VNFD/VNFpkg to be deleted
2216 vnfd_delete(ctx
, name
, force
)
2219 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
2220 @click.argument('name')
2221 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2223 def nfpkg_delete(ctx
, name
, force
):
2226 NAME: name or ID of the NFpkg to be deleted
2229 vnfd_delete(ctx
, name
, force
)
2232 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
2233 @click.argument('name')
2234 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2235 @click.option('--config', default
=None,
2236 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2237 "600, skip_terminate_primitives: True}'")
2238 @click.option('--wait',
2242 help='do not return the control immediately, but keep it '
2243 'until the operation is completed, or timeout')
2245 def ns_delete(ctx
, name
, force
, config
, wait
):
2246 """deletes a NS instance
2248 NAME: name or ID of the NS instance to be deleted
2253 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2255 check_client_version(ctx
.obj
, '--force')
2256 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2257 # except ClientException as e:
2262 def nst_delete(ctx
, name
, force
):
2265 check_client_version(ctx
.obj
, ctx
.command
.name
)
2266 ctx
.obj
.nst
.delete(name
, force
)
2267 # except ClientException as e:
2272 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
2273 @click.argument('name')
2274 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2276 def nst_delete1(ctx
, name
, force
):
2277 """deletes a Network Slice Template (NST)
2279 NAME: name or ID of the NST/NSTpkg to be deleted
2282 nst_delete(ctx
, name
, force
)
2285 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
2286 @click.argument('name')
2287 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2289 def nst_delete2(ctx
, name
, force
):
2290 """deletes a Network Slice Template (NST)
2292 NAME: name or ID of the NST/NSTpkg to be deleted
2295 nst_delete(ctx
, name
, force
)
2298 def nsi_delete(ctx
, name
, force
, wait
):
2301 check_client_version(ctx
.obj
, ctx
.command
.name
)
2302 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2303 # except ClientException as e:
2308 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2309 @click.argument('name')
2310 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2311 @click.option('--wait',
2315 help='do not return the control immediately, but keep it '
2316 'until the operation is completed, or timeout')
2318 def nsi_delete1(ctx
, name
, force
, wait
):
2319 """deletes a Network Slice Instance (NSI)
2321 NAME: name or ID of the Network Slice instance to be deleted
2324 nsi_delete(ctx
, name
, force
, wait
=wait
)
2327 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2328 @click.argument('name')
2329 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2331 def nsi_delete2(ctx
, name
, force
, wait
):
2332 """deletes a Network Slice Instance (NSI)
2334 NAME: name or ID of the Network Slice instance to be deleted
2337 nsi_delete(ctx
, name
, force
, wait
=wait
)
2340 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2341 @click.argument('name')
2342 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2344 def pdu_delete(ctx
, name
, force
):
2345 """deletes a Physical Deployment Unit (PDU)
2347 NAME: name or ID of the PDU to be deleted
2351 check_client_version(ctx
.obj
, ctx
.command
.name
)
2352 ctx
.obj
.pdu
.delete(name
, force
)
2353 # except ClientException as e:
2362 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2363 @click.option('--name',
2365 help='Name to create datacenter')
2366 @click.option('--user',
2368 help='VIM username')
2369 @click.option('--password',
2372 confirmation_prompt
=True,
2373 help='VIM password')
2374 @click.option('--auth_url',
2377 @click.option('--tenant',
2379 help='VIM tenant name')
2380 @click.option('--config',
2382 help='VIM specific config parameters')
2383 @click.option('--account_type',
2384 default
='openstack',
2386 @click.option('--description',
2388 help='human readable description')
2389 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2390 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2391 @click.option('--wait',
2395 help='do not return the control immediately, but keep it '
2396 'until the operation is completed, or timeout')
2410 """creates a new VIM account"""
2414 check_client_version(ctx
.obj
, '--sdn_controller')
2415 if sdn_port_mapping
:
2416 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2418 vim
['vim-username'] = user
2419 vim
['vim-password'] = password
2420 vim
['vim-url'] = auth_url
2421 vim
['vim-tenant-name'] = tenant
2422 vim
['vim-type'] = account_type
2423 vim
['description'] = description
2424 vim
['config'] = config
2425 if sdn_controller
or sdn_port_mapping
:
2426 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2428 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2429 # except ClientException as e:
2434 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2435 @click.argument('name')
2436 @click.option('--newname', help='New name for the VIM account')
2437 @click.option('--user', help='VIM username')
2438 @click.option('--password', help='VIM password')
2439 @click.option('--auth_url', help='VIM url')
2440 @click.option('--tenant', help='VIM tenant name')
2441 @click.option('--config', help='VIM specific config parameters')
2442 @click.option('--account_type', help='VIM type')
2443 @click.option('--description', help='human readable description')
2444 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller to be associated with this VIM'
2445 'account. Use empty string to disassociate')
2446 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2447 @click.option('--wait',
2451 help='do not return the control immediately, but keep it '
2452 'until the operation is completed, or timeout')
2467 """updates a VIM account
2469 NAME: name or ID of the VIM account
2473 check_client_version(ctx
.obj
, ctx
.command
.name
)
2475 if newname
: vim
['name'] = newname
2476 if user
: vim
['vim_user'] = user
2477 if password
: vim
['vim_password'] = password
2478 if auth_url
: vim
['vim_url'] = auth_url
2479 if tenant
: vim
['vim-tenant-name'] = tenant
2480 if account_type
: vim
['vim_type'] = account_type
2481 if description
: vim
['description'] = description
2482 if config
: vim
['config'] = config
2483 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2484 # except ClientException as e:
2489 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2490 @click.argument('name')
2491 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2492 @click.option('--wait',
2496 help='do not return the control immediately, but keep it '
2497 'until the operation is completed, or timeout')
2499 def vim_delete(ctx
, name
, force
, wait
):
2500 """deletes a VIM account
2502 NAME: name or ID of the VIM account to be deleted
2507 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2509 check_client_version(ctx
.obj
, '--force')
2510 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2511 # except ClientException as e:
2516 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2517 #@click.option('--ro_update/--no_ro_update',
2519 # help='update list from RO')
2520 @click.option('--filter', default
=None,
2521 help='restricts the list to the VIM accounts matching the filter')
2522 @click.option('--long', is_flag
=True,
2523 help='get more details of the NS (project, vim, deployment status, configuration status.')
2525 def vim_list(ctx
, filter, long):
2526 """list all VIM accounts"""
2529 check_client_version(ctx
.obj
, '--filter')
2531 # check_client_version(ctx.obj, '--ro_update', 'v1')
2532 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2533 if fullclassname
== 'osmclient.sol005.client.Client':
2534 resp
= ctx
.obj
.vim
.list(filter)
2536 # resp = ctx.obj.vim.list(ro_update)
2538 table
= PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details'])
2540 table
= PrettyTable(['vim name', 'uuid'])
2543 vim_details
= ctx
.obj
.vim
.get(vim
['uuid'])
2544 if 'vim_password' in vim_details
:
2545 vim_details
['vim_password']='********'
2546 logger
.debug('VIM details: {}'.format(yaml
.safe_dump(vim_details
)))
2547 vim_state
= vim_details
['_admin'].get('operationalState', '-')
2548 error_details
= 'N/A'
2549 if vim_state
== 'ERROR':
2550 error_details
= vim_details
['_admin'].get('detailed-status', 'Not found')
2551 project_list
= ctx
.obj
.project
.list()
2552 vim_project_list
= vim_details
.get('_admin').get('projects_read')
2554 project_name
= 'None'
2555 if vim_project_list
:
2556 project_id
= vim_project_list
[0]
2557 for p
in project_list
:
2558 if p
['_id'] == project_id
:
2559 project_name
= p
['name']
2561 table
.add_row([vim
['name'], vim
['uuid'], '{} ({})'.format(project_name
, project_id
),
2562 vim_state
, wrap_text(text
=error_details
, width
=80)])
2564 table
.add_row([vim
['name'], vim
['uuid']])
2569 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2570 @click.argument('name')
2572 def vim_show(ctx
, name
):
2573 """shows the details of a VIM account
2575 NAME: name or ID of the VIM account
2579 resp
= ctx
.obj
.vim
.get(name
)
2580 if 'vim_password' in resp
:
2581 resp
['vim_password']='********'
2582 # except ClientException as e:
2586 table
= PrettyTable(['key', 'attribute'])
2587 for k
, v
in list(resp
.items()):
2588 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2593 ####################
2595 ####################
2597 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2598 @click.option('--name',
2600 help='Name for the WIM account')
2601 @click.option('--user',
2602 help='WIM username')
2603 @click.option('--password',
2604 help='WIM password')
2605 @click.option('--url',
2608 # @click.option('--tenant',
2609 # help='wIM tenant name')
2610 @click.option('--config',
2612 help='WIM specific config parameters')
2613 @click.option('--wim_type',
2615 @click.option('--description',
2617 help='human readable description')
2618 @click.option('--wim_port_mapping', default
=None,
2619 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2620 "(WAN service endpoint id and info)")
2621 @click.option('--wait',
2625 help='do not return the control immediately, but keep it '
2626 'until the operation is completed, or timeout')
2639 """creates a new WIM account"""
2642 check_client_version(ctx
.obj
, ctx
.command
.name
)
2643 # if sdn_controller:
2644 # check_client_version(ctx.obj, '--sdn_controller')
2645 # if sdn_port_mapping:
2646 # check_client_version(ctx.obj, '--sdn_port_mapping')
2648 if user
: wim
['user'] = user
2649 if password
: wim
['password'] = password
2650 if url
: wim
['wim_url'] = url
2651 # if tenant: wim['tenant'] = tenant
2652 wim
['wim_type'] = wim_type
2653 if description
: wim
['description'] = description
2654 if config
: wim
['config'] = config
2655 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2656 # except ClientException as e:
2661 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2662 @click.argument('name')
2663 @click.option('--newname', help='New name for the WIM account')
2664 @click.option('--user', help='WIM username')
2665 @click.option('--password', help='WIM password')
2666 @click.option('--url', help='WIM url')
2667 @click.option('--config', help='WIM specific config parameters')
2668 @click.option('--wim_type', help='WIM type')
2669 @click.option('--description', help='human readable description')
2670 @click.option('--wim_port_mapping', default
=None,
2671 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2672 "(WAN service endpoint id and info)")
2673 @click.option('--wait',
2677 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2690 """updates a WIM account
2692 NAME: name or ID of the WIM account
2696 check_client_version(ctx
.obj
, ctx
.command
.name
)
2698 if newname
: wim
['name'] = newname
2699 if user
: wim
['user'] = user
2700 if password
: wim
['password'] = password
2701 if url
: wim
['url'] = url
2702 # if tenant: wim['tenant'] = tenant
2703 if wim_type
: wim
['wim_type'] = wim_type
2704 if description
: wim
['description'] = description
2705 if config
: wim
['config'] = config
2706 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2707 # except ClientException as e:
2712 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2713 @click.argument('name')
2714 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2715 @click.option('--wait',
2719 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2721 def wim_delete(ctx
, name
, force
, wait
):
2722 """deletes a WIM account
2724 NAME: name or ID of the WIM account to be deleted
2728 check_client_version(ctx
.obj
, ctx
.command
.name
)
2729 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2730 # except ClientException as e:
2735 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2736 @click.option('--filter', default
=None,
2737 help='restricts the list to the WIM accounts matching the filter')
2739 def wim_list(ctx
, filter):
2740 """list all WIM accounts"""
2743 check_client_version(ctx
.obj
, ctx
.command
.name
)
2744 resp
= ctx
.obj
.wim
.list(filter)
2745 table
= PrettyTable(['wim name', 'uuid'])
2747 table
.add_row([wim
['name'], wim
['uuid']])
2750 # except ClientException as e:
2755 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2756 @click.argument('name')
2758 def wim_show(ctx
, name
):
2759 """shows the details of a WIM account
2761 NAME: name or ID of the WIM account
2765 check_client_version(ctx
.obj
, ctx
.command
.name
)
2766 resp
= ctx
.obj
.wim
.get(name
)
2767 if 'password' in resp
:
2768 resp
['wim_password']='********'
2769 # except ClientException as e:
2773 table
= PrettyTable(['key', 'attribute'])
2774 for k
, v
in list(resp
.items()):
2775 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2780 ####################
2781 # SDN controller operations
2782 ####################
2784 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2785 @click.option('--name',
2787 help='Name to create sdn controller')
2788 @click.option('--type',
2790 help='SDN controller type')
2791 @click.option('--sdn_controller_version', # hidden=True,
2792 help='Deprecated. Use --config {version: sdn_controller_version}')
2793 @click.option('--url',
2794 help='URL in format http[s]://HOST:IP/')
2795 @click.option('--ip_address', # hidden=True,
2796 help='Deprecated. Use --url')
2797 @click.option('--port', # hidden=True,
2798 help='Deprecated. Use --url')
2799 @click.option('--switch_dpid', # hidden=True,
2800 help='Deprecated. Use --config {switch_id: DPID}')
2801 @click.option('--config',
2802 help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2803 'Openflow Datapath ID), version: version}')
2804 @click.option('--user',
2805 help='SDN controller username')
2806 @click.option('--password',
2808 confirmation_prompt
=True,
2809 help='SDN controller password')
2810 @click.option('--description', default
=None, help='human readable description')
2811 @click.option('--wait',
2815 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2817 def sdnc_create(ctx
, **kwargs
):
2818 """creates a new SDN controller"""
2820 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2821 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2822 if kwargs
.get("port"):
2823 print("option '--port' is deprecated, use '--url' instead")
2824 sdncontroller
["port"] = int(kwargs
["port"])
2825 if kwargs
.get("ip_address"):
2826 print("option '--ip_address' is deprecated, use '--url' instead")
2827 sdncontroller
["ip"] = kwargs
["ip_address"]
2828 if kwargs
.get("switch_dpid"):
2829 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2830 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2831 if kwargs
.get("sdn_controller_version"):
2832 print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2835 check_client_version(ctx
.obj
, ctx
.command
.name
)
2836 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2837 # except ClientException as e:
2841 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2842 @click.argument('name')
2843 @click.option('--newname', help='New name for the SDN controller')
2844 @click.option('--description', default
=None, help='human readable description')
2845 @click.option('--type', help='SDN controller type')
2846 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2847 @click.option('--config', help='Extra information for SDN in yaml format, as '
2848 '{switch_id: identity used for the plugin (e.g. DPID: '
2849 'Openflow Datapath ID), version: version}')
2850 @click.option('--user', help='SDN controller username')
2851 @click.option('--password', help='SDN controller password')
2852 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2853 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2854 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2855 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2856 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2857 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2859 def sdnc_update(ctx
, **kwargs
):
2860 """updates an SDN controller
2862 NAME: name or ID of the SDN controller
2865 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2866 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2867 if kwargs
.get("newname"):
2868 sdncontroller
["name"] = kwargs
["newname"]
2869 if kwargs
.get("port"):
2870 print("option '--port' is deprecated, use '--url' instead")
2871 sdncontroller
["port"] = int(kwargs
["port"])
2872 if kwargs
.get("ip_address"):
2873 print("option '--ip_address' is deprecated, use '--url' instead")
2874 sdncontroller
["ip"] = kwargs
["ip_address"]
2875 if kwargs
.get("switch_dpid"):
2876 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2877 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2878 if kwargs
.get("sdn_controller_version"):
2879 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2883 check_client_version(ctx
.obj
, ctx
.command
.name
)
2884 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2885 # except ClientException as e:
2890 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2891 @click.argument('name')
2892 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2893 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2894 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2896 def sdnc_delete(ctx
, name
, force
, wait
):
2897 """deletes an SDN controller
2899 NAME: name or ID of the SDN controller to be deleted
2903 check_client_version(ctx
.obj
, ctx
.command
.name
)
2904 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2905 # except ClientException as e:
2910 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2911 @click.option('--filter', default
=None,
2912 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2914 def sdnc_list(ctx
, filter):
2915 """list all SDN controllers"""
2918 check_client_version(ctx
.obj
, ctx
.command
.name
)
2919 resp
= ctx
.obj
.sdnc
.list(filter)
2920 # except ClientException as e:
2923 table
= PrettyTable(['sdnc name', 'id'])
2925 table
.add_row([sdnc
['name'], sdnc
['_id']])
2930 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2931 @click.argument('name')
2933 def sdnc_show(ctx
, name
):
2934 """shows the details of an SDN controller
2936 NAME: name or ID of the SDN controller
2940 check_client_version(ctx
.obj
, ctx
.command
.name
)
2941 resp
= ctx
.obj
.sdnc
.get(name
)
2942 # except ClientException as e:
2946 table
= PrettyTable(['key', 'attribute'])
2947 for k
, v
in list(resp
.items()):
2948 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2953 ###########################
2954 # K8s cluster operations
2955 ###########################
2957 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2958 @click.argument('name')
2959 @click.option('--creds',
2961 help='credentials file, i.e. a valid `.kube/config` file')
2962 @click.option('--version',
2964 help='Kubernetes version')
2965 @click.option('--vim',
2967 help='VIM target, the VIM where the cluster resides')
2968 @click.option('--k8s-nets',
2970 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) ...]}"')
2971 @click.option('--description',
2973 help='human readable description')
2974 @click.option('--namespace',
2975 default
='kube-system',
2976 help='namespace to be used for its operation, defaults to `kube-system`')
2977 @click.option('--cni',
2979 help='list of CNI plugins, in JSON inline format, used in the cluster')
2980 #@click.option('--skip-init',
2982 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2983 #@click.option('--wait',
2985 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2987 def k8scluster_add(ctx
,
2996 """adds a K8s cluster to OSM
2998 NAME: name of the K8s cluster
3001 check_client_version(ctx
.obj
, ctx
.command
.name
)
3003 cluster
['name'] = name
3004 with
open(creds
, 'r') as cf
:
3005 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3006 cluster
['k8s_version'] = version
3007 cluster
['vim_account'] = vim
3008 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3010 cluster
['description'] = description
3011 if namespace
: cluster
['namespace'] = namespace
3012 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3013 ctx
.obj
.k8scluster
.create(name
, cluster
)
3014 # except ClientException as e:
3019 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
3020 @click.argument('name')
3021 @click.option('--newname', help='New name for the K8s cluster')
3022 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3023 @click.option('--version', help='Kubernetes version')
3024 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3025 @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) ...]}"')
3026 @click.option('--description', help='human readable description')
3027 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3028 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3030 def k8scluster_update(ctx
,
3040 """updates a K8s cluster
3042 NAME: name or ID of the K8s cluster
3045 check_client_version(ctx
.obj
, ctx
.command
.name
)
3047 if newname
: cluster
['name'] = newname
3049 with
open(creds
, 'r') as cf
:
3050 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3051 if version
: cluster
['k8s_version'] = version
3052 if vim
: cluster
['vim_account'] = vim
3053 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3054 if description
: cluster
['description'] = description
3055 if namespace
: cluster
['namespace'] = namespace
3056 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3057 ctx
.obj
.k8scluster
.update(name
, cluster
)
3058 # except ClientException as e:
3063 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
3064 @click.argument('name')
3065 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3066 #@click.option('--wait',
3068 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3070 def k8scluster_delete(ctx
, name
, force
):
3071 """deletes a K8s cluster
3073 NAME: name or ID of the K8s cluster to be deleted
3076 check_client_version(ctx
.obj
, ctx
.command
.name
)
3077 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3078 # except ClientException as e:
3083 @cli_osm.command(name
='k8scluster-list')
3084 @click.option('--filter', default
=None,
3085 help='restricts the list to the K8s clusters matching the filter')
3086 @click.option('--literal', is_flag
=True,
3087 help='print literally, no pretty table')
3089 def k8scluster_list(ctx
, filter, literal
):
3090 """list all K8s clusters"""
3092 check_client_version(ctx
.obj
, ctx
.command
.name
)
3093 resp
= ctx
.obj
.k8scluster
.list(filter)
3095 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3097 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
3098 for cluster
in resp
:
3099 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
3100 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
3101 trunc_text(cluster
.get('description') or '', 40)])
3104 # except ClientException as e:
3109 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
3110 @click.argument('name')
3111 @click.option('--literal', is_flag
=True,
3112 help='print literally, no pretty table')
3114 def k8scluster_show(ctx
, name
, literal
):
3115 """shows the details of a K8s cluster
3117 NAME: name or ID of the K8s cluster
3120 resp
= ctx
.obj
.k8scluster
.get(name
)
3122 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3124 table
= PrettyTable(['key', 'attribute'])
3125 for k
, v
in list(resp
.items()):
3126 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
3129 # except ClientException as e:
3135 ###########################
3137 ###########################
3139 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
3140 @click.argument('name')
3141 @click.argument('uri')
3142 @click.option('--type',
3143 type=click
.Choice(['helm-chart', 'juju-bundle', 'osm']),
3145 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3146 @click.option('--description',
3148 help='human readable description')
3149 @click.option('--user',
3151 help='OSM repository: The username of the OSM repository')
3152 @click.option('--password',
3154 help='OSM repository: The password of the OSM repository')
3155 #@click.option('--wait',
3157 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3159 def repo_add(ctx
, **kwargs
):
3160 """adds a repo to OSM
3162 NAME: name of the repo
3163 URI: URI of the repo
3166 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
3168 repo
["url"] = repo
.pop("uri")
3169 if repo
["type"] in ['helm-chart', 'juju-bundle']:
3170 ctx
.obj
.repo
.create(repo
['name'], repo
)
3172 ctx
.obj
.osmrepo
.create(repo
['name'], repo
)
3173 # except ClientException as e:
3178 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
3179 @click.argument('name')
3180 @click.option('--newname', help='New name for the repo')
3181 @click.option('--uri', help='URI of the repo')
3182 @click.option('--description', help='human readable description')
3183 #@click.option('--wait',
3185 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3187 def repo_update(ctx
,
3192 """updates a repo in OSM
3194 NAME: name of the repo
3197 check_client_version(ctx
.obj
, ctx
.command
.name
)
3200 repo
['name'] = newname
3203 if description
: repo
['description'] = description
3205 ctx
.obj
.repo
.update(name
, repo
)
3207 ctx
.obj
.osmrepo
.update(name
, repo
)
3209 # except ClientException as e:
3214 @cli_osm.command(name
='repo-index', short_help
='Index a repository from a folder with artifacts')
3215 @click.option('--origin', default
='.', help='origin path where the artifacts are located')
3216 @click.option('--destination', default
='.', help='destination path where the index is deployed')
3218 def repo_index(ctx
, origin
, destination
):
3219 """Index a repository
3221 NAME: name or ID of the repo to be deleted
3223 check_client_version(ctx
.obj
, ctx
.command
.name
)
3224 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
3227 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
3228 @click.argument('name')
3229 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3230 #@click.option('--wait',
3232 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3234 def repo_delete(ctx
, name
, force
):
3237 NAME: name or ID of the repo to be deleted
3241 ctx
.obj
.repo
.delete(name
, force
=force
)
3243 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
3244 # except ClientException as e:
3249 @cli_osm.command(name
='repo-list')
3250 @click.option('--filter', default
=None,
3251 help='restricts the list to the repos matching the filter')
3252 @click.option('--literal', is_flag
=True,
3253 help='print literally, no pretty table')
3255 def repo_list(ctx
, filter, literal
):
3256 """list all repos"""
3259 check_client_version(ctx
.obj
, ctx
.command
.name
)
3260 resp
= ctx
.obj
.repo
.list(filter)
3261 resp
+= ctx
.obj
.osmrepo
.list(filter)
3263 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3265 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3267 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3268 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description') or '',40)])
3272 # except ClientException as e:
3277 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
3278 @click.argument('name')
3279 @click.option('--literal', is_flag
=True,
3280 help='print literally, no pretty table')
3282 def repo_show(ctx
, name
, literal
):
3283 """shows the details of a repo
3285 NAME: name or ID of the repo
3288 resp
= ctx
.obj
.repo
.get(name
)
3290 resp
= ctx
.obj
.osmrepo
.get(name
)
3294 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3296 table
= PrettyTable(['key', 'attribute'])
3298 for k
, v
in list(resp
.items()):
3299 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3303 # except ClientException as e:
3309 ####################
3310 # Project mgmt operations
3311 ####################
3313 @cli_osm.command(name
='project-create', short_help
='creates a new project')
3314 @click.argument('name')
3315 #@click.option('--description',
3316 # default='no description',
3317 # help='human readable description')
3318 @click.option('--domain-name', 'domain_name',
3320 help='assign to a domain')
3321 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3322 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3323 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3325 def project_create(ctx
, name
, domain_name
, quotas
):
3326 """Creates a new project
3328 NAME: name of the project
3329 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3330 QUOTAS: set quotas for the project
3333 project
= {'name': name
}
3335 project
['domain_name'] = domain_name
3336 quotas_dict
= _process_project_quotas(quotas
)
3338 project
['quotas'] = quotas_dict
3341 check_client_version(ctx
.obj
, ctx
.command
.name
)
3342 ctx
.obj
.project
.create(name
, project
)
3343 # except ClientException as e:
3348 def _process_project_quotas(quota_list
):
3353 for quota
in quota_list
:
3354 for single_quota
in quota
.split(","):
3355 k
, v
= single_quota
.split("=")
3356 quotas_dict
[k
] = None if v
in ('None', 'null', '') else int(v
)
3357 except (ValueError, TypeError):
3358 raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3362 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3363 @click.argument('name')
3364 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3366 def project_delete(ctx
, name
):
3367 """deletes a project
3369 NAME: name or ID of the project to be deleted
3373 check_client_version(ctx
.obj
, ctx
.command
.name
)
3374 ctx
.obj
.project
.delete(name
)
3375 # except ClientException as e:
3380 @cli_osm.command(name
='project-list', short_help
='list all projects')
3381 @click.option('--filter', default
=None,
3382 help='restricts the list to the projects matching the filter')
3384 def project_list(ctx
, filter):
3385 """list all projects"""
3388 check_client_version(ctx
.obj
, ctx
.command
.name
)
3389 resp
= ctx
.obj
.project
.list(filter)
3390 # except ClientException as e:
3393 table
= PrettyTable(['name', 'id'])
3395 table
.add_row([proj
['name'], proj
['_id']])
3400 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3401 @click.argument('name')
3403 def project_show(ctx
, name
):
3404 """shows the details of a project
3406 NAME: name or ID of the project
3410 check_client_version(ctx
.obj
, ctx
.command
.name
)
3411 resp
= ctx
.obj
.project
.get(name
)
3412 # except ClientException as e:
3416 table
= PrettyTable(['key', 'attribute'])
3417 for k
, v
in resp
.items():
3418 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3423 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3424 @click.argument('project')
3425 @click.option('--name', default
=None,
3426 help='new name for the project')
3427 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3428 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3429 "(use empty to reset quota to default")
3431 def project_update(ctx
, project
, name
, quotas
):
3433 Update a project name
3436 :param project: id or name of the project to modify
3437 :param name: new name for the project
3438 :param quotas: change quotas of the project
3442 project_changes
= {}
3444 project_changes
['name'] = name
3445 quotas_dict
= _process_project_quotas(quotas
)
3447 project_changes
['quotas'] = quotas_dict
3450 check_client_version(ctx
.obj
, ctx
.command
.name
)
3451 ctx
.obj
.project
.update(project
, project_changes
)
3452 # except ClientException as e:
3456 ####################
3457 # User mgmt operations
3458 ####################
3460 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3461 @click.argument('username')
3462 @click.option('--password',
3465 confirmation_prompt
=True,
3466 help='user password')
3467 @click.option('--projects',
3468 # prompt="Comma separate list of projects",
3470 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3471 help='list of project ids that the user belongs to')
3472 @click.option('--project-role-mappings', 'project_role_mappings',
3473 default
=None, multiple
=True,
3474 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3475 @click.option('--domain-name', 'domain_name',
3477 help='assign to a domain')
3479 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
3480 """Creates a new user
3483 USERNAME: name of the user
3484 PASSWORD: password of the user
3485 PROJECTS: projects assigned to user (internal only)
3486 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3487 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3491 user
['username'] = username
3492 user
['password'] = password
3493 user
['projects'] = projects
3494 user
['project_role_mappings'] = project_role_mappings
3496 user
['domain_name'] = domain_name
3499 check_client_version(ctx
.obj
, ctx
.command
.name
)
3500 ctx
.obj
.user
.create(username
, user
)
3501 # except ClientException as e:
3506 @cli_osm.command(name
='user-update', short_help
='updates user information')
3507 @click.argument('username')
3508 @click.option('--password',
3511 # confirmation_prompt=True,
3512 help='user password')
3513 @click.option('--set-username', 'set_username',
3515 help='change username')
3516 @click.option('--set-project', 'set_project',
3517 default
=None, multiple
=True,
3518 help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3519 @click.option('--remove-project', 'remove_project',
3520 default
=None, multiple
=True,
3521 help="removes project from user: 'project'")
3522 @click.option('--add-project-role', 'add_project_role',
3523 default
=None, multiple
=True,
3524 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3525 @click.option('--remove-project-role', 'remove_project_role',
3526 default
=None, multiple
=True,
3527 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3529 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3530 add_project_role
, remove_project_role
):
3531 """Update a user information
3534 USERNAME: name of the user
3535 PASSWORD: new password
3536 SET_USERNAME: new username
3537 SET_PROJECT: creating mappings for project/role(s)
3538 REMOVE_PROJECT: deleting mappings for project/role(s)
3539 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3540 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3544 user
['password'] = password
3545 user
['username'] = set_username
3546 user
['set-project'] = set_project
3547 user
['remove-project'] = remove_project
3548 user
['add-project-role'] = add_project_role
3549 user
['remove-project-role'] = remove_project_role
3552 check_client_version(ctx
.obj
, ctx
.command
.name
)
3553 ctx
.obj
.user
.update(username
, user
)
3554 # except ClientException as e:
3559 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3560 @click.argument('name')
3561 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3563 def user_delete(ctx
, name
):
3567 NAME: name or ID of the user to be deleted
3571 check_client_version(ctx
.obj
, ctx
.command
.name
)
3572 ctx
.obj
.user
.delete(name
)
3573 # except ClientException as e:
3578 @cli_osm.command(name
='user-list', short_help
='list all users')
3579 @click.option('--filter', default
=None,
3580 help='restricts the list to the users matching the filter')
3582 def user_list(ctx
, filter):
3583 """list all users"""
3585 check_client_version(ctx
.obj
, ctx
.command
.name
)
3586 resp
= ctx
.obj
.user
.list(filter)
3587 # except ClientException as e:
3590 table
= PrettyTable(['name', 'id'])
3592 table
.add_row([user
['username'], user
['_id']])
3597 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3598 @click.argument('name')
3600 def user_show(ctx
, name
):
3601 """shows the details of a user
3603 NAME: name or ID of the user
3607 check_client_version(ctx
.obj
, ctx
.command
.name
)
3608 resp
= ctx
.obj
.user
.get(name
)
3609 if 'password' in resp
:
3610 resp
['password']='********'
3611 # except ClientException as e:
3615 table
= PrettyTable(['key', 'attribute'])
3616 for k
, v
in resp
.items():
3617 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3622 ####################
3623 # Fault Management operations
3624 ####################
3626 @cli_osm.command(name
='ns-alarm-create')
3627 @click.argument('name')
3628 @click.option('--ns', prompt
=True, help='NS instance id or name')
3629 @click.option('--vnf', prompt
=True,
3630 help='VNF name (VNF member index as declared in the NSD)')
3631 @click.option('--vdu', prompt
=True,
3632 help='VDU name (VDU name as declared in the VNFD)')
3633 @click.option('--metric', prompt
=True,
3634 help='Name of the metric (e.g. cpu_utilization)')
3635 @click.option('--severity', default
='WARNING',
3636 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3637 @click.option('--threshold_value', prompt
=True,
3638 help='threshold value that, when crossed, an alarm is triggered')
3639 @click.option('--threshold_operator', prompt
=True,
3640 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3641 @click.option('--statistic', default
='AVERAGE',
3642 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3644 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3645 threshold_value
, threshold_operator
, statistic
):
3646 """creates a new alarm for a NS instance"""
3647 # TODO: Check how to validate threshold_value.
3648 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3651 ns_instance
= ctx
.obj
.ns
.get(ns
)
3653 alarm
['alarm_name'] = name
3654 alarm
['ns_id'] = ns_instance
['_id']
3655 alarm
['correlation_id'] = ns_instance
['_id']
3656 alarm
['vnf_member_index'] = vnf
3657 alarm
['vdu_name'] = vdu
3658 alarm
['metric_name'] = metric
3659 alarm
['severity'] = severity
3660 alarm
['threshold_value'] = int(threshold_value
)
3661 alarm
['operation'] = threshold_operator
3662 alarm
['statistic'] = statistic
3663 check_client_version(ctx
.obj
, ctx
.command
.name
)
3664 ctx
.obj
.ns
.create_alarm(alarm
)
3665 # except ClientException as e:
3670 #@cli_osm.command(name='ns-alarm-delete')
3671 #@click.argument('name')
3672 #@click.pass_context
3673 #def ns_alarm_delete(ctx, name):
3674 # """deletes an alarm
3676 # NAME: name of the alarm to be deleted
3679 # check_client_version(ctx.obj, ctx.command.name)
3680 # ctx.obj.ns.delete_alarm(name)
3681 # except ClientException as e:
3686 ####################
3687 # Performance Management operations
3688 ####################
3690 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3691 @click.option('--ns', prompt
=True, help='NS instance id or name')
3692 @click.option('--vnf', prompt
=True,
3693 help='VNF name (VNF member index as declared in the NSD)')
3694 @click.option('--vdu', prompt
=True,
3695 help='VDU name (VDU name as declared in the VNFD)')
3696 @click.option('--metric', prompt
=True,
3697 help='name of the metric (e.g. cpu_utilization)')
3698 #@click.option('--period', default='1w',
3699 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3700 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3702 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3703 """exports a metric to the internal OSM bus, which can be read by other apps"""
3704 # TODO: Check how to validate interval.
3705 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3708 ns_instance
= ctx
.obj
.ns
.get(ns
)
3710 metric_data
['ns_id'] = ns_instance
['_id']
3711 metric_data
['correlation_id'] = ns_instance
['_id']
3712 metric_data
['vnf_member_index'] = vnf
3713 metric_data
['vdu_name'] = vdu
3714 metric_data
['metric_name'] = metric
3715 metric_data
['collection_unit'] = 'WEEK'
3716 metric_data
['collection_period'] = 1
3717 check_client_version(ctx
.obj
, ctx
.command
.name
)
3719 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3723 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3724 time
.sleep(int(interval
))
3726 # except ClientException as e:
3731 ####################
3733 ####################
3735 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3737 def get_version(ctx
):
3738 """shows client and server versions"""
3740 check_client_version(ctx
.obj
, "version")
3741 print ("Server version: {}".format(ctx
.obj
.get_version()))
3742 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3743 # except ClientException as e:
3747 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3748 @click.argument('filename')
3749 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3750 help='the charm will not be compiled, it is assumed to already exist')
3752 def upload_package(ctx
, filename
, skip_charm_build
):
3753 """uploads a vnf package or ns package
3755 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3759 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3760 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3761 if fullclassname
!= 'osmclient.sol005.client.Client':
3762 ctx
.obj
.package
.wait_for_upload(filename
)
3763 # except ClientException as e:
3768 #@cli_osm.command(name='ns-scaling-show')
3769 #@click.argument('ns_name')
3770 #@click.pass_context
3771 #def show_ns_scaling(ctx, ns_name):
3772 # """shows the status of a NS scaling operation
3774 # NS_NAME: name of the NS instance being scaled
3777 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3778 # resp = ctx.obj.ns.list()
3779 # except ClientException as e:
3783 # table = PrettyTable(
3786 # 'operational status',
3791 # if ns_name == ns['name']:
3792 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3793 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3794 # for record in scaling_records:
3795 # if 'instance' in record:
3796 # instances = record['instance']
3797 # for inst in instances:
3799 # [record['scaling-group-name-ref'],
3800 # inst['instance-id'],
3801 # inst['op-status'],
3802 # time.strftime('%Y-%m-%d %H:%M:%S',
3804 # inst['create-time'])),
3810 #@cli_osm.command(name='ns-scale')
3811 #@click.argument('ns_name')
3812 #@click.option('--ns_scale_group', prompt=True)
3813 #@click.option('--index', prompt=True)
3814 #@click.option('--wait',
3818 # help='do not return the control immediately, but keep it \
3819 # until the operation is completed, or timeout')
3820 #@click.pass_context
3821 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3824 # NS_NAME: name of the NS instance to be scaled
3827 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3828 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3829 # except ClientException as e:
3834 #@cli_osm.command(name='config-agent-list')
3835 #@click.pass_context
3836 #def config_agent_list(ctx):
3837 # """list config agents"""
3839 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3840 # except ClientException as e:
3843 # table = PrettyTable(['name', 'account-type', 'details'])
3844 # for account in ctx.obj.vca.list():
3847 # account['account-type'],
3853 #@cli_osm.command(name='config-agent-delete')
3854 #@click.argument('name')
3855 #@click.pass_context
3856 #def config_agent_delete(ctx, name):
3857 # """deletes a config agent
3859 # NAME: name of the config agent to be deleted
3862 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3863 # ctx.obj.vca.delete(name)
3864 # except ClientException as e:
3869 #@cli_osm.command(name='config-agent-add')
3870 #@click.option('--name',
3872 #@click.option('--account_type',
3874 #@click.option('--server',
3876 #@click.option('--user',
3878 #@click.option('--secret',
3881 # confirmation_prompt=True)
3882 #@click.pass_context
3883 #def config_agent_add(ctx, name, account_type, server, user, secret):
3884 # """adds a config agent"""
3886 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3887 # ctx.obj.vca.create(name, account_type, server, user, secret)
3888 # except ClientException as e:
3893 #@cli_osm.command(name='ro-dump')
3894 #@click.pass_context
3896 # """shows RO agent information"""
3897 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3898 # resp = ctx.obj.vim.get_resource_orchestrator()
3899 # table = PrettyTable(['key', 'attribute'])
3900 # for k, v in list(resp.items()):
3901 # table.add_row([k, json.dumps(v, indent=2)])
3906 #@cli_osm.command(name='vcs-list')
3907 #@click.pass_context
3909 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3910 # resp = ctx.obj.utils.get_vcs_info()
3911 # table = PrettyTable(['component name', 'state'])
3912 # for component in resp:
3913 # table.add_row([component['component_name'], component['state']])
3918 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3919 @click.argument('ns_name')
3920 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3921 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3922 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3923 @click.option('--vdu_count', default
=None, help='number of vdu instance of this vdu_id')
3924 @click.option('--action_name', prompt
=True, help='action name')
3925 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3926 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3927 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
3928 @click.option('--wait',
3932 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3945 """executes an action/primitive over a NS instance
3947 NS_NAME: name or ID of the NS instance
3951 check_client_version(ctx
.obj
, ctx
.command
.name
)
3954 op_data
['member_vnf_index'] = vnf_name
3956 op_data
['kdu_name'] = kdu_name
3958 op_data
['vdu_id'] = vdu_id
3960 op_data
['vdu_count_index'] = vdu_count
3962 op_data
['timeout_ns_action'] = timeout
3963 op_data
['primitive'] = action_name
3965 with
open(params_file
, 'r') as pf
:
3968 op_data
['primitive_params'] = yaml
.safe_load(params
)
3970 op_data
['primitive_params'] = {}
3971 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
3973 # except ClientException as e:
3978 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
3979 @click.argument('ns_name')
3980 @click.argument('vnf_name')
3981 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
3982 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
3983 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
3984 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
3985 @click.option('--wait', required
=False, default
=False, is_flag
=True,
3986 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3997 Executes a VNF scale (adding/removing VDUs)
4000 NS_NAME: name or ID of the NS instance.
4001 VNF_NAME: member-vnf-index in the NS to be scaled.
4005 check_client_version(ctx
.obj
, ctx
.command
.name
)
4006 if not scale_in
and not scale_out
:
4008 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
)
4009 # except ClientException as e:
4014 ##############################
4015 # Role Management Operations #
4016 ##############################
4018 @cli_osm.command(name
='role-create', short_help
='creates a new role')
4019 @click.argument('name')
4020 @click.option('--permissions',
4022 help='role permissions using a dictionary')
4024 def role_create(ctx
, name
, permissions
):
4029 NAME: Name or ID of the role.
4030 DEFINITION: Definition of grant/denial of access to resources.
4034 check_client_version(ctx
.obj
, ctx
.command
.name
)
4035 ctx
.obj
.role
.create(name
, permissions
)
4036 # except ClientException as e:
4041 @cli_osm.command(name
='role-update', short_help
='updates a role')
4042 @click.argument('name')
4043 @click.option('--set-name',
4045 help='change name of rle')
4046 # @click.option('--permissions',
4048 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4049 @click.option('--add',
4051 help='yaml format dictionary with permission: True/False to access grant/denial')
4052 @click.option('--remove',
4054 help='yaml format list to remove a permission')
4056 def role_update(ctx
, name
, set_name
, add
, remove
):
4061 NAME: Name or ID of the role.
4062 DEFINITION: Definition overwrites the old definition.
4063 ADD: Grant/denial of access to resource to add.
4064 REMOVE: Grant/denial of access to resource to remove.
4068 check_client_version(ctx
.obj
, ctx
.command
.name
)
4069 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
4070 # except ClientException as e:
4075 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
4076 @click.argument('name')
4077 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4079 def role_delete(ctx
, name
):
4084 NAME: Name or ID of the role.
4088 check_client_version(ctx
.obj
, ctx
.command
.name
)
4089 ctx
.obj
.role
.delete(name
)
4090 # except ClientException as e:
4095 @cli_osm.command(name
='role-list', short_help
='list all roles')
4096 @click.option('--filter', default
=None,
4097 help='restricts the list to the projects matching the filter')
4099 def role_list(ctx
, filter):
4105 check_client_version(ctx
.obj
, ctx
.command
.name
)
4106 resp
= ctx
.obj
.role
.list(filter)
4107 # except ClientException as e:
4110 table
= PrettyTable(['name', 'id'])
4112 table
.add_row([role
['name'], role
['_id']])
4117 @cli_osm.command(name
='role-show', short_help
='show specific role')
4118 @click.argument('name')
4120 def role_show(ctx
, name
):
4122 Shows the details of a role.
4125 NAME: Name or ID of the role.
4129 check_client_version(ctx
.obj
, ctx
.command
.name
)
4130 resp
= ctx
.obj
.role
.get(name
)
4131 # except ClientException as e:
4135 table
= PrettyTable(['key', 'attribute'])
4136 for k
, v
in resp
.items():
4137 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4142 @cli_osm.command(name
='package-create',
4143 short_help
='Create a package descriptor')
4144 @click.argument('package-type')
4145 @click.argument('package-name')
4146 @click.option('--base-directory',
4148 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4149 @click.option('--image',
4150 default
="image-name",
4151 help='(VNF) Set the name of the vdu image. Default "image-name"')
4152 @click.option('--vdus',
4154 help='(VNF) Set the number of vdus in a VNF. Default 1')
4155 @click.option('--vcpu',
4157 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4158 @click.option('--memory',
4160 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4161 @click.option('--storage',
4163 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4164 @click.option('--interfaces',
4166 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4167 @click.option('--vendor',
4169 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4170 @click.option('--override',
4173 help='(NS/VNF/NST) Flag for overriding the package if exists.')
4174 @click.option('--detailed',
4177 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4178 @click.option('--netslice-subnets',
4180 help='(NST) Number of netslice subnets. Default 1')
4181 @click.option('--netslice-vlds',
4183 help='(NST) Number of netslice vlds. Default 1')
4185 def package_create(ctx
,
4201 Creates an OSM NS, VNF, NST package
4204 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4205 PACKAGE_NAME: Name of the package to create the folder with the content.
4209 check_client_version(ctx
.obj
, ctx
.command
.name
)
4210 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
4211 resp
= ctx
.obj
.package_tool
.create(package_type
,
4220 interfaces
=interfaces
,
4223 netslice_subnets
=netslice_subnets
,
4224 netslice_vlds
=netslice_vlds
)
4226 # except ClientException as inst:
4227 # print("ERROR: {}".format(inst))
4230 @cli_osm.command(name
='package-validate',
4231 short_help
='Validate a package descriptor')
4232 @click.argument('base-directory',
4235 @click.option('--recursive/--no-recursive',
4237 help='The activated recursive option will validate the yaml files'
4238 ' within the indicated directory and in its subdirectories')
4240 def package_validate(ctx
,
4244 Validate descriptors given a base directory.
4247 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4250 check_client_version(ctx
.obj
, ctx
.command
.name
)
4251 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
4252 table
= PrettyTable()
4253 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
4254 # Print the dictionary generated by the validation function
4255 for result
in results
:
4256 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
4257 table
.sortby
= "VALID"
4258 table
.align
["PATH"] = "l"
4259 table
.align
["TYPE"] = "l"
4260 table
.align
["ERROR"] = "l"
4262 # except ClientException as inst:
4263 # print("ERROR: {}".format(inst))
4266 @cli_osm.command(name
='package-build',
4267 short_help
='Build the tar.gz of the package')
4268 @click.argument('package-folder')
4269 @click.option('--skip-validation',
4272 help='skip package validation')
4273 @click.option('--skip-charm-build', default
=False, is_flag
=True,
4274 help='the charm will not be compiled, it is assumed to already exist')
4276 def package_build(ctx
,
4281 Build the package NS, VNF given the package_folder.
4284 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4287 check_client_version(ctx
.obj
, ctx
.command
.name
)
4288 results
= ctx
.obj
.package_tool
.build(package_folder
,
4289 skip_validation
=skip_validation
,
4290 skip_charm_build
=skip_charm_build
)
4292 # except ClientException as inst:
4293 # print("ERROR: {}".format(inst))
4301 except pycurl
.error
as exc
:
4303 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4304 except ClientException
as exc
:
4305 print("ERROR: {}".format(exc
))
4306 except (FileNotFoundError
, PermissionError
) as exc
:
4307 print("Cannot open file: {}".format(exc
))
4308 except yaml
.YAMLError
as exc
:
4309 print("Invalid YAML format: {}".format(exc
))
4311 # TODO capture other controlled exceptions here
4312 # TODO remove the ClientException captures from all places, unless they do something different
4315 if __name__
== '__main__':