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('id','-')
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('id', vnfd
.get('name','-'))
478 repository
= vnfd
.get('repository')
480 vendor
= vnfd
.get('provider', 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', 'desc type', 'vendor', 'version', 'onboarding state', 'operational state',
518 'usage state', 'date', 'last update'])
520 table
= PrettyTable(['nfpkg name', 'id', 'desc type'])
522 name
= vnfd
.get('id', vnfd
.get('name','-'))
523 descriptor_type
= 'sol005' if 'product-name' in vnfd
else 'rel8'
525 onb_state
= vnfd
['_admin'].get('onboardingState','-')
526 op_state
= vnfd
['_admin'].get('operationalState','-')
527 vendor
= vnfd
.get('provider', vnfd
.get('vendor'))
528 version
= vnfd
.get('version')
529 usage_state
= vnfd
['_admin'].get('usageState','-')
530 date
= datetime
.fromtimestamp(vnfd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
531 last_update
= datetime
.fromtimestamp(vnfd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
532 table
.add_row([name
, vnfd
['_id'], descriptor_type
, vendor
, version
, onb_state
, op_state
, usage_state
, date
, last_update
])
534 table
.add_row([name
, vnfd
['_id'], descriptor_type
])
536 table
= PrettyTable(['nfpkg name', 'id'])
538 table
.add_row([vnfd
['name'], vnfd
['id']])
543 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
544 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
545 @click.option('--filter', default
=None,
546 help='restricts the list to the NF pkg matching the filter')
547 @click.option('--long', is_flag
=True, help='get more details')
549 def vnfd_list1(ctx
, nf_type
, filter, long):
550 """list all xNF packages (VNF, HNF, PNF)"""
552 vnfd_list(ctx
, nf_type
, filter, long)
555 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
556 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
557 @click.option('--filter', default
=None,
558 help='restricts the list to the NFpkg matching the filter')
559 @click.option('--long', is_flag
=True, help='get more details')
561 def vnfd_list2(ctx
, nf_type
, filter, long):
562 """list all xNF packages (VNF, HNF, PNF)"""
564 vnfd_list(ctx
, nf_type
, filter, long)
566 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
567 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
568 @click.option('--filter', default
=None,
569 help='restricts the list to the NFpkg matching the filter')
570 @click.option('--long', is_flag
=True, help='get more details')
572 def nfpkg_list(ctx
, nf_type
, filter, long):
573 """list all xNF packages (VNF, HNF, PNF)"""
576 check_client_version(ctx
.obj
, ctx
.command
.name
)
577 vnfd_list(ctx
, nf_type
, filter, long)
578 # except ClientException as e:
582 @cli_osm.command(name
='vnfpkg-repo-list', short_help
='list all xNF from OSM repositories')
583 @click.option('--filter', default
=None,
584 help='restricts the list to the NFpkg matching the filter')
585 @click.option('--repo', default
=None,
586 help='restricts the list to a particular OSM repository')
587 @click.option('--long', is_flag
=True, help='get more details')
589 def nfpkg_repo_list1(ctx
, filter, repo
, long):
590 """list xNF packages from OSM repositories"""
592 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
594 @cli_osm.command(name
='nfpkg-repo-list', short_help
='list all xNF from OSM repositories')
595 @click.option('--filter', default
=None,
596 help='restricts the list to the NFpkg matching the filter')
597 @click.option('--repo', default
=None,
598 help='restricts the list to a particular OSM repository')
599 @click.option('--long', is_flag
=True, help='get more details')
601 def nfpkg_repo_list2(ctx
, filter, repo
, long):
602 """list xNF packages from OSM repositories"""
604 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
606 def vnf_list(ctx
, ns
, filter, long):
610 check_client_version(ctx
.obj
, '--ns')
612 check_client_version(ctx
.obj
, '--filter')
613 resp
= ctx
.obj
.vnf
.list(ns
, filter)
615 resp
= ctx
.obj
.vnf
.list()
616 # except ClientException as e:
619 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
620 if fullclassname
== 'osmclient.sol005.client.Client':
621 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
622 'vnfd name', 'vim account id', 'ip address']
624 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
625 'vnfd name', 'vim account id', 'ip address',
626 'date', 'last update']
627 table
= PrettyTable(field_names
)
629 name
= vnfr
['name'] if 'name' in vnfr
else '-'
630 new_row
= [vnfr
['_id'], name
, vnfr
['nsr-id-ref'],
631 vnfr
['member-vnf-index-ref'], vnfr
['vnfd-ref'],
632 vnfr
['vim-account-id'], vnfr
['ip-address']]
634 date
= datetime
.fromtimestamp(vnfr
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
635 last_update
= datetime
.fromtimestamp(vnfr
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
636 new_row
.extend([date
, last_update
])
637 table
.add_row(new_row
)
642 'operational status',
645 if 'mgmt-interface' not in vnfr
:
646 vnfr
['mgmt-interface'] = {}
647 vnfr
['mgmt-interface']['ip-address'] = None
651 vnfr
['operational-status'],
652 vnfr
['config-status']])
657 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
658 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
659 @click.option('--filter', default
=None,
660 help='restricts the list to the NF instances matching the filter.')
661 @click.option('--long', is_flag
=True, help='get more details')
663 def vnf_list1(ctx
, ns
, filter, long):
664 """list all NF instances"""
666 vnf_list(ctx
, ns
, filter, long)
668 @cli_osm.command(name
='nsd-repo-list', short_help
='list all NS from OSM repositories')
669 @click.option('--filter', default
=None,
670 help='restricts the list to the NS matching the filter')
671 @click.option('--repo', default
=None,
672 help='restricts the list to a particular OSM repository')
673 @click.option('--long', is_flag
=True, help='get more details')
675 def nspkg_repo_list(ctx
, filter, repo
, long):
676 """list xNF packages from OSM repositories"""
678 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
680 @cli_osm.command(name
='nspkg-repo-list', short_help
='list all NS from OSM repositories')
681 @click.option('--filter', default
=None,
682 help='restricts the list to the NS matching the filter')
683 @click.option('--repo', default
=None,
684 help='restricts the list to a particular OSM repository')
685 @click.option('--long', is_flag
=True, help='get more details')
687 def nspkg_repo_list2(ctx
, filter, repo
, long):
688 """list xNF packages from OSM repositories"""
690 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
692 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
693 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
694 @click.option('--filter', default
=None,
695 help='restricts the list to the NF instances matching the filter.')
696 @click.option('--long', is_flag
=True, help='get more details')
698 def nf_list(ctx
, ns
, filter, long):
699 """list all NF instances
703 --ns TEXT NS instance id or name to restrict the VNF list
704 --filter filterExpr Restricts the list to the VNF instances matching the filter
707 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
708 concatenated using the "&" character:
711 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
712 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
713 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
715 value := scalar value
719 * zero or more occurrences
720 ? zero or one occurrence
721 [] grouping of expressions to be used with ? and *
722 "" quotation marks for marking string constants
726 "AttrName" is the name of one attribute in the data type that defines the representation
727 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
728 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
729 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
730 entries, it means that the operator "op" is applied to the attribute addressed by the last
731 <attrName> entry included in the concatenation. All simple filter expressions are combined
732 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
733 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
734 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
735 prefix". If an attribute referenced in an expression is an array, an object that contains a
736 corresponding array shall be considered to match the expression if any of the elements in the
737 array matches all expressions that have the same attribute prefix.
741 --filter vim-account-id=<VIM_ACCOUNT_ID>
742 --filter vnfd-ref=<VNFD_NAME>
743 --filter vdur.ip-address=<IP_ADDRESS>
744 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
747 vnf_list(ctx
, ns
, filter, long)
750 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
751 @click.argument('name')
752 @click.option('--long', is_flag
=True,
753 help='get more details of the NS operation (date, ).')
755 def ns_op_list(ctx
, name
, long):
756 """shows the history of operations over a NS instance
758 NAME: name or ID of the NS instance
760 def formatParams(params
):
761 if params
['lcmOperationType']=='instantiate':
762 params
.pop('nsDescription')
766 elif params
['lcmOperationType']=='action':
767 params
.pop('primitive')
768 params
.pop('lcmOperationType')
769 params
.pop('nsInstanceId')
774 check_client_version(ctx
.obj
, ctx
.command
.name
)
775 resp
= ctx
.obj
.ns
.list_op(name
)
776 # except ClientException as e:
781 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
783 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
785 #print(yaml.safe_dump(resp))
788 if op
['lcmOperationType']=='action':
789 action_name
= op
['operationParams']['primitive']
791 if op
['operationState'] == 'PROCESSING':
792 if op
['queuePosition'] is not None and op
['queuePosition'] > 0:
793 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
794 elif op
['lcmOperationType'] in ('instantiate', 'terminate'):
797 elif op
['operationState'] in ('FAILED', 'FAILED_TEMP'):
798 detail
= op
.get('errorMessage','-')
799 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
800 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
802 table
.add_row([op
['id'],
803 op
['lcmOperationType'],
805 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
806 op
['operationState'],
809 wrap_text(text
=detail
,width
=50)])
811 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
812 op
['operationState'], date
, wrap_text(text
=detail
or "",width
=50)])
817 def nsi_list(ctx
, filter):
818 """list all Network Slice Instances"""
821 check_client_version(ctx
.obj
, ctx
.command
.name
)
822 resp
= ctx
.obj
.nsi
.list(filter)
823 # except ClientException as e:
827 ['netslice instance name',
829 'operational status',
833 nsi_name
= nsi
['name']
835 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
836 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
837 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
838 if configstatus
== "config_not_needed":
839 configstatus
= "configured (no charms)"
850 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
851 @click.option('--filter', default
=None,
852 help='restricts the list to the Network Slice Instances matching the filter')
854 def nsi_list1(ctx
, filter):
855 """list all Network Slice Instances (NSI)"""
857 nsi_list(ctx
, filter)
860 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
861 @click.option('--filter', default
=None,
862 help='restricts the list to the Network Slice Instances matching the filter')
864 def nsi_list2(ctx
, filter):
865 """list all Network Slice Instances (NSI)"""
867 nsi_list(ctx
, filter)
870 def nst_list(ctx
, filter):
873 check_client_version(ctx
.obj
, ctx
.command
.name
)
874 resp
= ctx
.obj
.nst
.list(filter)
875 # except ClientException as e:
878 # print(yaml.safe_dump(resp))
879 table
= PrettyTable(['nst name', 'id'])
881 name
= nst
['name'] if 'name' in nst
else '-'
882 table
.add_row([name
, nst
['_id']])
887 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
888 @click.option('--filter', default
=None,
889 help='restricts the list to the NST matching the filter')
891 def nst_list1(ctx
, filter):
892 """list all Network Slice Templates (NST) in the system"""
894 nst_list(ctx
, filter)
897 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
898 @click.option('--filter', default
=None,
899 help='restricts the list to the NST matching the filter')
901 def nst_list2(ctx
, filter):
902 """list all Network Slice Templates (NST) in the system"""
904 nst_list(ctx
, filter)
907 def nsi_op_list(ctx
, name
):
910 check_client_version(ctx
.obj
, ctx
.command
.name
)
911 resp
= ctx
.obj
.nsi
.list_op(name
)
912 # except ClientException as e:
915 table
= PrettyTable(['id', 'operation', 'status'])
917 table
.add_row([op
['id'], op
['lcmOperationType'],
918 op
['operationState']])
923 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
924 @click.argument('name')
926 def nsi_op_list1(ctx
, name
):
927 """shows the history of operations over a Network Slice Instance (NSI)
929 NAME: name or ID of the Network Slice Instance
932 nsi_op_list(ctx
, name
)
935 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
936 @click.argument('name')
938 def nsi_op_list2(ctx
, name
):
939 """shows the history of operations over a Network Slice Instance (NSI)
941 NAME: name or ID of the Network Slice Instance
944 nsi_op_list(ctx
, name
)
947 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
948 @click.option('--filter', default
=None,
949 help='restricts the list to the Physical Deployment Units matching the filter')
951 def pdu_list(ctx
, filter):
952 """list all Physical Deployment Units (PDU)"""
955 check_client_version(ctx
.obj
, ctx
.command
.name
)
956 resp
= ctx
.obj
.pdu
.list(filter)
957 # except ClientException as e:
966 pdu_name
= pdu
['name']
968 pdu_type
= pdu
['type']
969 pdu_ipaddress
= "None"
970 for iface
in pdu
['interfaces']:
972 pdu_ipaddress
= iface
['ip-address']
987 def nsd_show(ctx
, name
, literal
):
990 resp
= ctx
.obj
.nsd
.get(name
)
991 # resp = ctx.obj.nsd.get_individual(name)
992 # except ClientException as e:
997 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1000 table
= PrettyTable(['field', 'value'])
1001 for k
, v
in list(resp
.items()):
1002 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1007 @cli_osm.command(name
='nsd-show', short_help
='shows the details of a NS package')
1008 @click.option('--literal', is_flag
=True,
1009 help='print literally, no pretty table')
1010 @click.argument('name')
1012 def nsd_show1(ctx
, name
, literal
):
1013 """shows the content of a NSD
1015 NAME: name or ID of the NSD/NSpkg
1018 nsd_show(ctx
, name
, literal
)
1021 @cli_osm.command(name
='nspkg-show', short_help
='shows the details of a NS package')
1022 @click.option('--literal', is_flag
=True,
1023 help='print literally, no pretty table')
1024 @click.argument('name')
1026 def nsd_show2(ctx
, name
, literal
):
1027 """shows the content of a NSD
1029 NAME: name or ID of the NSD/NSpkg
1032 nsd_show(ctx
, name
, literal
)
1035 def vnfd_show(ctx
, name
, literal
):
1038 resp
= ctx
.obj
.vnfd
.get(name
)
1039 # resp = ctx.obj.vnfd.get_individual(name)
1040 # except ClientException as e:
1045 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1048 table
= PrettyTable(['field', 'value'])
1049 for k
, v
in list(resp
.items()):
1050 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1055 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1058 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1061 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1064 catalog
= pkgtype
+ '-catalog'
1065 full_catalog
= pkgtype
+ ':' + catalog
1066 if resp
.get(catalog
):
1067 resp
= resp
.pop(catalog
)[pkgtype
][0]
1068 elif resp
.get(full_catalog
):
1069 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1071 table
= PrettyTable(['field', 'value'])
1072 for k
, v
in list(resp
.items()):
1073 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1077 @cli_osm.command(name
='vnfd-show', short_help
='shows the details of a NF package')
1078 @click.option('--literal', is_flag
=True,
1079 help='print literally, no pretty table')
1080 @click.argument('name')
1082 def vnfd_show1(ctx
, name
, literal
):
1083 """shows the content of a VNFD
1085 NAME: name or ID of the VNFD/VNFpkg
1088 vnfd_show(ctx
, name
, literal
)
1091 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the details of a NF package')
1092 @click.option('--literal', is_flag
=True,
1093 help='print literally, no pretty table')
1094 @click.argument('name')
1096 def vnfd_show2(ctx
, name
, literal
):
1097 """shows the content of a VNFD
1099 NAME: name or ID of the VNFD/VNFpkg
1102 vnfd_show(ctx
, name
, literal
)
1104 @cli_osm.command(name
='vnfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1105 @click.option('--literal', is_flag
=True,
1106 help='print literally, no pretty table')
1107 @click.option('--repo',
1109 help='Repository name')
1110 @click.argument('name')
1111 @click.option('--filter',
1112 help='filter by fields')
1113 @click.option('--version',
1115 help='package version')
1117 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1118 """shows the content of a VNFD in a repository
1120 NAME: name or ID of the VNFD/VNFpkg
1123 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1126 @cli_osm.command(name
='nsd-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1127 @click.option('--literal', is_flag
=True,
1128 help='print literally, no pretty table')
1129 @click.option('--repo',
1131 help='Repository name')
1132 @click.argument('name')
1133 @click.option('--filter',
1134 help='filter by fields')
1135 @click.option('--version',
1137 help='package version')
1139 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1140 """shows the content of a VNFD in a repository
1142 NAME: name or ID of the VNFD/VNFpkg
1145 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1147 @cli_osm.command(name
='nspkg-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1148 @click.option('--literal', is_flag
=True,
1149 help='print literally, no pretty table')
1150 @click.option('--repo',
1152 help='Repository name')
1153 @click.argument('name')
1154 @click.option('--filter',
1155 help='filter by fields')
1156 @click.option('--version',
1158 help='package version')
1160 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1161 """shows the content of a VNFD in a repository
1163 NAME: name or ID of the VNFD/VNFpkg
1166 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1168 @cli_osm.command(name
='nfpkg-show', short_help
='shows the details of a NF package')
1169 @click.option('--literal', is_flag
=True,
1170 help='print literally, no pretty table')
1171 @click.argument('name')
1173 def nfpkg_show(ctx
, name
, literal
):
1174 """shows the content of a NF Descriptor
1176 NAME: name or ID of the NFpkg
1179 vnfd_show(ctx
, name
, literal
)
1182 @cli_osm.command(name
='nfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1183 @click.option('--literal', is_flag
=True,
1184 help='print literally, no pretty table')
1185 @click.option('--repo',
1187 help='Repository name')
1188 @click.argument('name')
1189 @click.option('--filter',
1190 help='filter by fields')
1191 @click.option('--version',
1193 help='package version')
1195 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1196 """shows the content of a VNFD in a repository
1198 NAME: name or ID of the VNFD/VNFpkg
1201 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1204 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
1205 @click.argument('name')
1206 @click.option('--literal', is_flag
=True,
1207 help='print literally, no pretty table')
1208 @click.option('--filter', default
=None)
1210 def ns_show(ctx
, name
, literal
, filter):
1211 """shows the info of a NS instance
1213 NAME: name or ID of the NS instance
1217 ns
= ctx
.obj
.ns
.get(name
)
1218 # except ClientException as e:
1223 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1226 table
= PrettyTable(['field', 'value'])
1228 for k
, v
in list(ns
.items()):
1229 if filter is None or filter in k
:
1230 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1232 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1233 if fullclassname
!= 'osmclient.sol005.client.Client':
1234 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1235 nsr_optdata
= nsopdata
['nsr:nsr']
1236 for k
, v
in list(nsr_optdata
.items()):
1237 if filter is None or filter in k
:
1238 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1243 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1244 @click.argument('name')
1245 @click.option('--literal', is_flag
=True,
1246 help='print literally, no pretty table')
1247 @click.option('--filter', default
=None, help='restricts the information to the fields in the filter')
1248 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1250 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1251 """shows the info of a VNF instance
1253 NAME: name or ID of the VNF instance
1255 def print_kdu_status(op_info_status
):
1256 """print KDU status properly formatted
1259 op_status
= yaml
.safe_load(op_info_status
)
1260 if "namespace" in op_status
and "info" in op_status
and \
1261 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1262 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1263 "seconds" in op_status
["info"]["last_deployed"]:
1264 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1265 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1266 print("NAMESPACE: {}".format(op_status
["namespace"]))
1267 status_code
= "UNKNOWN"
1268 if op_status
["info"]["status"]["code"]==1:
1269 status_code
= "DEPLOYED"
1270 print("STATUS: {}".format(status_code
))
1273 print(op_status
["info"]["status"]["resources"])
1274 if "notes" in op_status
["info"]["status"]:
1276 print(op_status
["info"]["status"]["notes"])
1278 print(op_info_status
)
1280 print(op_info_status
)
1285 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1287 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1290 check_client_version(ctx
.obj
, ctx
.command
.name
)
1291 resp
= ctx
.obj
.vnf
.get(name
)
1294 ns_id
= resp
['nsr-id-ref']
1296 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1297 op_data
['kdu_name'] = kdu
1298 op_data
['primitive'] = 'status'
1299 op_data
['primitive_params'] = {}
1300 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1303 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1304 if op_info
['operationState'] == 'COMPLETED':
1305 print_kdu_status(op_info
['detailed-status'])
1309 print ("Could not determine KDU status")
1313 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1316 table
= PrettyTable(['field', 'value'])
1318 for k
, v
in list(resp
.items()):
1319 if filter is None or filter in k
:
1320 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1323 # except ClientException as e:
1328 #@cli_osm.command(name='vnf-monitoring-show')
1329 #@click.argument('vnf_name')
1330 #@click.pass_context
1331 #def vnf_monitoring_show(ctx, vnf_name):
1333 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1334 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1335 # except ClientException as e:
1339 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1340 # if resp is not None:
1341 # for monitor in resp:
1345 # monitor['value-integer'],
1346 # monitor['units']])
1351 #@cli_osm.command(name='ns-monitoring-show')
1352 #@click.argument('ns_name')
1353 #@click.pass_context
1354 #def ns_monitoring_show(ctx, ns_name):
1356 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1357 # resp = ctx.obj.ns.get_monitoring(ns_name)
1358 # except ClientException as e:
1362 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1363 # for key, val in list(resp.items()):
1364 # for monitor in val:
1368 # monitor['value-integer'],
1369 # monitor['units']])
1374 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1375 @click.argument('id')
1376 @click.option('--filter', default
=None)
1377 @click.option('--literal', is_flag
=True,
1378 help='print literally, no pretty table')
1380 def ns_op_show(ctx
, id, filter, literal
):
1381 """shows the detailed info of a NS operation
1383 ID: operation identifier
1387 check_client_version(ctx
.obj
, ctx
.command
.name
)
1388 op_info
= ctx
.obj
.ns
.get_op(id)
1389 # except ClientException as e:
1394 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1397 table
= PrettyTable(['field', 'value'])
1398 for k
, v
in list(op_info
.items()):
1399 if filter is None or filter in k
:
1400 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1405 def nst_show(ctx
, name
, literal
):
1408 check_client_version(ctx
.obj
, ctx
.command
.name
)
1409 resp
= ctx
.obj
.nst
.get(name
)
1410 #resp = ctx.obj.nst.get_individual(name)
1411 # except ClientException as e:
1416 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1419 table
= PrettyTable(['field', 'value'])
1420 for k
, v
in list(resp
.items()):
1421 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1426 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1427 @click.option('--literal', is_flag
=True,
1428 help='print literally, no pretty table')
1429 @click.argument('name')
1431 def nst_show1(ctx
, name
, literal
):
1432 """shows the content of a Network Slice Template (NST)
1434 NAME: name or ID of the NST
1437 nst_show(ctx
, name
, literal
)
1440 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1441 @click.option('--literal', is_flag
=True,
1442 help='print literally, no pretty table')
1443 @click.argument('name')
1445 def nst_show2(ctx
, name
, literal
):
1446 """shows the content of a Network Slice Template (NST)
1448 NAME: name or ID of the NST
1451 nst_show(ctx
, name
, literal
)
1454 def nsi_show(ctx
, name
, literal
, filter):
1457 check_client_version(ctx
.obj
, ctx
.command
.name
)
1458 nsi
= ctx
.obj
.nsi
.get(name
)
1459 # except ClientException as e:
1464 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1467 table
= PrettyTable(['field', 'value'])
1469 for k
, v
in list(nsi
.items()):
1470 if filter is None or filter in k
:
1471 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1477 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1478 @click.argument('name')
1479 @click.option('--literal', is_flag
=True,
1480 help='print literally, no pretty table')
1481 @click.option('--filter', default
=None)
1483 def nsi_show1(ctx
, name
, literal
, filter):
1484 """shows the content of a Network Slice Instance (NSI)
1486 NAME: name or ID of the Network Slice Instance
1489 nsi_show(ctx
, name
, literal
, filter)
1492 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1493 @click.argument('name')
1494 @click.option('--literal', is_flag
=True,
1495 help='print literally, no pretty table')
1496 @click.option('--filter', default
=None)
1498 def nsi_show2(ctx
, name
, literal
, filter):
1499 """shows the content of a Network Slice Instance (NSI)
1501 NAME: name or ID of the Network Slice Instance
1504 nsi_show(ctx
, name
, literal
, filter)
1507 def nsi_op_show(ctx
, id, filter):
1510 check_client_version(ctx
.obj
, ctx
.command
.name
)
1511 op_info
= ctx
.obj
.nsi
.get_op(id)
1512 # except ClientException as e:
1516 table
= PrettyTable(['field', 'value'])
1517 for k
, v
in list(op_info
.items()):
1518 if filter is None or filter in k
:
1519 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1524 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1525 @click.argument('id')
1526 @click.option('--filter', default
=None)
1528 def nsi_op_show1(ctx
, id, filter):
1529 """shows the info of an operation over a Network Slice Instance(NSI)
1531 ID: operation identifier
1534 nsi_op_show(ctx
, id, filter)
1537 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1538 @click.argument('id')
1539 @click.option('--filter', default
=None)
1541 def nsi_op_show2(ctx
, id, filter):
1542 """shows the info of an operation over a Network Slice Instance(NSI)
1544 ID: operation identifier
1547 nsi_op_show(ctx
, id, filter)
1550 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1551 @click.argument('name')
1552 @click.option('--literal', is_flag
=True,
1553 help='print literally, no pretty table')
1554 @click.option('--filter', default
=None)
1556 def pdu_show(ctx
, name
, literal
, filter):
1557 """shows the content of a Physical Deployment Unit (PDU)
1559 NAME: name or ID of the PDU
1563 check_client_version(ctx
.obj
, ctx
.command
.name
)
1564 pdu
= ctx
.obj
.pdu
.get(name
)
1565 # except ClientException as e:
1570 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1573 table
= PrettyTable(['field', 'value'])
1575 for k
, v
in list(pdu
.items()):
1576 if filter is None or filter in k
:
1577 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1583 ####################
1585 ####################
1587 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1590 check_client_version(ctx
.obj
, ctx
.command
.name
)
1592 filename
= ctx
.obj
.osmrepo
.get_pkg('ns', filename
, repo
, vendor
, version
)
1593 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1594 # except ClientException as e:
1599 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1600 @click.argument('filename')
1601 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1602 help='Deprecated. Use override')
1603 @click.option('--override', 'overwrite', default
=None,
1604 help='overrides fields in descriptor, format: '
1605 '"key1.key2...=value[;key3...=value;...]"')
1606 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1607 help='The charm will not be compiled, it is assumed to already exist')
1608 @click.option('--repo', default
=None,
1609 help='[repository]: Repository name')
1610 @click.option('--vendor', default
=None,
1611 help='[repository]: filter by vendor]')
1612 @click.option('--version', default
='latest',
1613 help='[repository]: filter by version. Default: latest')
1615 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1616 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1619 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1620 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1621 If FILENAME is an NF Package folder, it is built and then onboarded.
1624 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1628 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1629 @click.argument('filename')
1630 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1631 help='Deprecated. Use override')
1632 @click.option('--override', 'overwrite', default
=None,
1633 help='overrides fields in descriptor, format: '
1634 '"key1.key2...=value[;key3...=value;...]"')
1635 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1636 help='The charm will not be compiled, it is assumed to already exist')
1637 @click.option('--repo', default
=None,
1638 help='[repository]: Repository name')
1639 @click.option('--vendor', default
=None,
1640 help='[repository]: filter by vendor]')
1641 @click.option('--version', default
='latest',
1642 help='[repository]: filter by version. Default: latest')
1644 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1645 """onboards a new NSpkg
1647 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1648 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1649 If FILENAME is an NF Package folder, it is built and then onboarded.
1652 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1656 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1657 repo
, vendor
, version
):
1660 check_client_version(ctx
.obj
, ctx
.command
.name
)
1662 filename
= ctx
.obj
.osmrepo
.get_pkg('vnf', filename
, repo
, vendor
, version
)
1663 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1664 override_epa
=override_epa
, override_nonepa
=override_nonepa
,
1665 override_paravirt
=override_paravirt
)
1666 # except ClientException as e:
1671 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1672 @click.argument('filename')
1673 @click.option('--overwrite', 'overwrite', default
=None,
1674 help='overwrite deprecated, use override')
1675 @click.option('--override', 'overwrite', default
=None,
1676 help='overrides fields in descriptor, format: '
1677 '"key1.key2...=value[;key3...=value;...]"')
1678 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1679 help='The charm will not be compiled, it is assumed to already exist')
1680 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1681 help='adds guest-epa parameters to all VDU')
1682 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1683 help='removes all guest-epa parameters from all VDU')
1684 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1685 help='overrides all VDU interfaces to PARAVIRT')
1686 @click.option('--repo', default
=None,
1687 help='[repository]: Repository name')
1688 @click.option('--vendor', default
=None,
1689 help='[repository]: filter by vendor]')
1690 @click.option('--version', default
='latest',
1691 help='[repository]: filter by version. Default: latest')
1693 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1694 repo
,vendor
, version
):
1695 """creates a new VNFD/VNFpkg
1697 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1698 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1699 If FILENAME is an NF Package folder, it is built and then onboarded.
1702 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1703 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1704 repo
=repo
, vendor
=vendor
, version
=version
)
1707 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1708 @click.argument('filename')
1709 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1710 help='Deprecated. Use override')
1711 @click.option('--override', 'overwrite', default
=None,
1712 help='overrides fields in descriptor, format: '
1713 '"key1.key2...=value[;key3...=value;...]"')
1714 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1715 help='The charm will not be compiled, it is assumed to already exist')
1716 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1717 help='adds guest-epa parameters to all VDU')
1718 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1719 help='removes all guest-epa parameters from all VDU')
1720 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1721 help='overrides all VDU interfaces to PARAVIRT')
1722 @click.option('--repo', default
=None,
1723 help='[repository]: Repository name')
1724 @click.option('--vendor', default
=None,
1725 help='[repository]: filter by vendor]')
1726 @click.option('--version', default
='latest',
1727 help='[repository]: filter by version. Default: latest')
1729 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1730 repo
, vendor
, version
):
1731 """creates a new VNFD/VNFpkg
1733 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1734 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1735 If FILENAME is an NF Package folder, it is built and then onboarded.
1738 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1739 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1740 repo
=repo
, vendor
=vendor
, version
=version
)
1742 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1743 @click.argument('filename')
1744 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1745 help='Deprecated. Use override')
1746 @click.option('--override', 'overwrite', default
=None,
1747 help='overrides fields in descriptor, format: '
1748 '"key1.key2...=value[;key3...=value;...]"')
1749 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1750 help='The charm will not be compiled, it is assumed to already exist')
1751 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1752 help='adds guest-epa parameters to all VDU')
1753 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1754 help='removes all guest-epa parameters from all VDU')
1755 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1756 help='overrides all VDU interfaces to PARAVIRT')
1757 @click.option('--repo', default
=None,
1758 help='[repository]: Repository name')
1759 @click.option('--vendor', default
=None,
1760 help='[repository]: filter by vendor]')
1761 @click.option('--version', default
='latest',
1762 help='[repository]: filter by version. Default: latest')
1764 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1765 repo
, vendor
, version
):
1766 """creates a new NFpkg
1769 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1770 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1771 If FILENAME is an NF Package folder, it is built and then onboarded.
1774 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1775 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1776 repo
=repo
, vendor
=vendor
, version
=version
)
1779 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1780 @click.option('--ns_name',
1781 prompt
=True, help='name of the NS instance')
1782 @click.option('--nsd_name',
1783 prompt
=True, help='name of the NS descriptor')
1784 @click.option('--vim_account',
1785 prompt
=True, help='default VIM account id or name for the deployment')
1786 @click.option('--admin_status',
1788 help='administration status')
1789 @click.option('--ssh_keys',
1791 help='comma separated list of public key files to inject to vnfs')
1792 @click.option('--config',
1794 help='ns specific yaml configuration')
1795 @click.option('--config_file',
1797 help='ns specific yaml configuration file')
1798 @click.option('--wait',
1802 help='do not return the control immediately, but keep it '
1803 'until the operation is completed, or timeout')
1814 """creates a new NS instance"""
1818 check_client_version(ctx
.obj
, '--config_file')
1820 raise ClientException('"--config" option is incompatible with "--config_file" option')
1821 with
open(config_file
, 'r') as cf
:
1828 account
=vim_account
,
1830 # except ClientException as e:
1835 def nst_create(ctx
, filename
, overwrite
):
1838 check_client_version(ctx
.obj
, ctx
.command
.name
)
1839 ctx
.obj
.nst
.create(filename
, overwrite
)
1840 # except ClientException as e:
1845 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1846 @click.argument('filename')
1847 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1848 help='Deprecated. Use override')
1849 @click.option('--override', 'overwrite', default
=None,
1850 help='overrides fields in descriptor, format: '
1851 '"key1.key2...=value[;key3...=value;...]"')
1853 def nst_create1(ctx
, filename
, overwrite
):
1854 """creates a new Network Slice Template (NST)
1856 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1859 nst_create(ctx
, filename
, overwrite
)
1862 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1863 @click.argument('filename')
1864 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1865 help='Deprecated. Use override')
1866 @click.option('--override', 'overwrite', default
=None,
1867 help='overrides fields in descriptor, format: '
1868 '"key1.key2...=value[;key3...=value;...]"')
1870 def nst_create2(ctx
, filename
, overwrite
):
1871 """creates a new Network Slice Template (NST)
1873 FILENAME: NST yaml file or NSTpkg tar.gz file
1876 nst_create(ctx
, filename
, overwrite
)
1879 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1880 """creates a new Network Slice Instance (NSI)"""
1883 check_client_version(ctx
.obj
, ctx
.command
.name
)
1886 raise ClientException('"--config" option is incompatible with "--config_file" option')
1887 with
open(config_file
, 'r') as cf
:
1889 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1890 account
=vim_account
, wait
=wait
)
1891 # except ClientException as e:
1896 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1897 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1898 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1899 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1900 @click.option('--ssh_keys', default
=None,
1901 help='comma separated list of keys to inject to vnfs')
1902 @click.option('--config', default
=None,
1903 help='Netslice specific yaml configuration:\n'
1904 'netslice_subnet: [\n'
1905 'id: TEXT, vim_account: TEXT,\n'
1906 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1907 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1908 'additionalParamsForNsi: {param: value, ...}\n'
1909 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1911 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1913 @click.option('--config_file',
1915 help='nsi specific yaml configuration file')
1916 @click.option('--wait',
1920 help='do not return the control immediately, but keep it '
1921 'until the operation is completed, or timeout')
1923 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1924 """creates a new Network Slice Instance (NSI)"""
1926 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1929 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1930 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1931 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1932 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1933 @click.option('--ssh_keys', default
=None,
1934 help='comma separated list of keys to inject to vnfs')
1935 @click.option('--config', default
=None,
1936 help='Netslice specific yaml configuration:\n'
1937 'netslice_subnet: [\n'
1938 'id: TEXT, vim_account: TEXT,\n'
1939 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1940 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1942 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1944 @click.option('--config_file',
1946 help='nsi specific yaml configuration file')
1947 @click.option('--wait',
1951 help='do not return the control immediately, but keep it '
1952 'until the operation is completed, or timeout')
1954 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1955 """creates a new Network Slice Instance (NSI)"""
1957 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1960 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1961 @click.option('--name', help='name of the Physical Deployment Unit')
1962 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1963 @click.option('--interface',
1964 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1965 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1967 @click.option('--description', help='human readable description')
1968 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
1969 @click.option('--descriptor_file', default
=None,
1970 help='PDU descriptor file (as an alternative to using the other arguments')
1972 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
1973 """creates a new Physical Deployment Unit (PDU)"""
1976 check_client_version(ctx
.obj
, ctx
.command
.name
)
1978 if not descriptor_file
:
1980 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1982 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1984 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1986 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1988 with
open(descriptor_file
, 'r') as df
:
1989 pdu
= yaml
.safe_load(df
.read())
1990 if name
: pdu
["name"] = name
1991 if pdu_type
: pdu
["type"] = pdu_type
1992 if description
: pdu
["description"] = description
1993 if vim_account
: pdu
["vim_accounts"] = vim_account
1996 for iface
in interface
:
1997 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
1998 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
1999 ifaces_list
.append(new_iface
)
2000 pdu
["interfaces"] = ifaces_list
2001 ctx
.obj
.pdu
.create(pdu
)
2002 # except ClientException as e:
2007 ####################
2009 ####################
2011 def nsd_update(ctx
, name
, content
):
2014 check_client_version(ctx
.obj
, ctx
.command
.name
)
2015 ctx
.obj
.nsd
.update(name
, content
)
2016 # except ClientException as e:
2021 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
2022 @click.argument('name')
2023 @click.option('--content', default
=None,
2024 help='filename with the NSD/NSpkg replacing the current one')
2026 def nsd_update1(ctx
, name
, content
):
2027 """updates a NSD/NSpkg
2029 NAME: name or ID of the NSD/NSpkg
2032 nsd_update(ctx
, name
, content
)
2035 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
2036 @click.argument('name')
2037 @click.option('--content', default
=None,
2038 help='filename with the NSD/NSpkg replacing the current one')
2040 def nsd_update2(ctx
, name
, content
):
2041 """updates a NSD/NSpkg
2043 NAME: name or ID of the NSD/NSpkg
2046 nsd_update(ctx
, name
, content
)
2049 def vnfd_update(ctx
, name
, content
):
2052 check_client_version(ctx
.obj
, ctx
.command
.name
)
2053 ctx
.obj
.vnfd
.update(name
, content
)
2054 # except ClientException as e:
2059 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
2060 @click.argument('name')
2061 @click.option('--content', default
=None,
2062 help='filename with the VNFD/VNFpkg replacing the current one')
2064 def vnfd_update1(ctx
, name
, content
):
2065 """updates a VNFD/VNFpkg
2067 NAME: name or ID of the VNFD/VNFpkg
2070 vnfd_update(ctx
, name
, content
)
2073 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
2074 @click.argument('name')
2075 @click.option('--content', default
=None,
2076 help='filename with the VNFD/VNFpkg replacing the current one')
2078 def vnfd_update2(ctx
, name
, content
):
2079 """updates a VNFD/VNFpkg
2081 NAME: VNFD yaml file or VNFpkg tar.gz file
2084 vnfd_update(ctx
, name
, content
)
2087 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
2088 @click.argument('name')
2089 @click.option('--content', default
=None,
2090 help='filename with the NFpkg replacing the current one')
2092 def nfpkg_update(ctx
, name
, content
):
2095 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2098 vnfd_update(ctx
, name
, content
)
2101 def nst_update(ctx
, name
, content
):
2104 check_client_version(ctx
.obj
, ctx
.command
.name
)
2105 ctx
.obj
.nst
.update(name
, content
)
2106 # except ClientException as e:
2111 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
2112 @click.argument('name')
2113 @click.option('--content', default
=None,
2114 help='filename with the NST/NSTpkg replacing the current one')
2116 def nst_update1(ctx
, name
, content
):
2117 """updates a Network Slice Template (NST)
2119 NAME: name or ID of the NSD/NSpkg
2122 nst_update(ctx
, name
, content
)
2125 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
2126 @click.argument('name')
2127 @click.option('--content', default
=None,
2128 help='filename with the NST/NSTpkg replacing the current one')
2130 def nst_update2(ctx
, name
, content
):
2131 """updates a Network Slice Template (NST)
2133 NAME: name or ID of the NSD/NSpkg
2136 nst_update(ctx
, name
, content
)
2139 ####################
2141 ####################
2143 def nsd_delete(ctx
, name
, force
):
2147 ctx
.obj
.nsd
.delete(name
)
2149 check_client_version(ctx
.obj
, '--force')
2150 ctx
.obj
.nsd
.delete(name
, force
)
2151 # except ClientException as e:
2156 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
2157 @click.argument('name')
2158 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2160 def nsd_delete1(ctx
, name
, force
):
2161 """deletes a NSD/NSpkg
2163 NAME: name or ID of the NSD/NSpkg to be deleted
2166 nsd_delete(ctx
, name
, force
)
2169 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
2170 @click.argument('name')
2171 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2173 def nsd_delete2(ctx
, name
, force
):
2174 """deletes a NSD/NSpkg
2176 NAME: name or ID of the NSD/NSpkg to be deleted
2179 nsd_delete(ctx
, name
, force
)
2182 def vnfd_delete(ctx
, name
, force
):
2186 ctx
.obj
.vnfd
.delete(name
)
2188 check_client_version(ctx
.obj
, '--force')
2189 ctx
.obj
.vnfd
.delete(name
, force
)
2190 # except ClientException as e:
2195 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
2196 @click.argument('name')
2197 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2199 def vnfd_delete1(ctx
, name
, force
):
2200 """deletes a VNFD/VNFpkg
2202 NAME: name or ID of the VNFD/VNFpkg to be deleted
2205 vnfd_delete(ctx
, name
, force
)
2208 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
2209 @click.argument('name')
2210 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2212 def vnfd_delete2(ctx
, name
, force
):
2213 """deletes a VNFD/VNFpkg
2215 NAME: name or ID of the VNFD/VNFpkg to be deleted
2218 vnfd_delete(ctx
, name
, force
)
2221 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
2222 @click.argument('name')
2223 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2225 def nfpkg_delete(ctx
, name
, force
):
2228 NAME: name or ID of the NFpkg to be deleted
2231 vnfd_delete(ctx
, name
, force
)
2234 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
2235 @click.argument('name')
2236 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2237 @click.option('--config', default
=None,
2238 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2239 "600, skip_terminate_primitives: True}'")
2240 @click.option('--wait',
2244 help='do not return the control immediately, but keep it '
2245 'until the operation is completed, or timeout')
2247 def ns_delete(ctx
, name
, force
, config
, wait
):
2248 """deletes a NS instance
2250 NAME: name or ID of the NS instance to be deleted
2255 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2257 check_client_version(ctx
.obj
, '--force')
2258 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2259 # except ClientException as e:
2264 def nst_delete(ctx
, name
, force
):
2267 check_client_version(ctx
.obj
, ctx
.command
.name
)
2268 ctx
.obj
.nst
.delete(name
, force
)
2269 # except ClientException as e:
2274 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
2275 @click.argument('name')
2276 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2278 def nst_delete1(ctx
, name
, force
):
2279 """deletes a Network Slice Template (NST)
2281 NAME: name or ID of the NST/NSTpkg to be deleted
2284 nst_delete(ctx
, name
, force
)
2287 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
2288 @click.argument('name')
2289 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2291 def nst_delete2(ctx
, name
, force
):
2292 """deletes a Network Slice Template (NST)
2294 NAME: name or ID of the NST/NSTpkg to be deleted
2297 nst_delete(ctx
, name
, force
)
2300 def nsi_delete(ctx
, name
, force
, wait
):
2303 check_client_version(ctx
.obj
, ctx
.command
.name
)
2304 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2305 # except ClientException as e:
2310 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2311 @click.argument('name')
2312 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2313 @click.option('--wait',
2317 help='do not return the control immediately, but keep it '
2318 'until the operation is completed, or timeout')
2320 def nsi_delete1(ctx
, name
, force
, wait
):
2321 """deletes a Network Slice Instance (NSI)
2323 NAME: name or ID of the Network Slice instance to be deleted
2326 nsi_delete(ctx
, name
, force
, wait
=wait
)
2329 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2330 @click.argument('name')
2331 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2333 def nsi_delete2(ctx
, name
, force
, wait
):
2334 """deletes a Network Slice Instance (NSI)
2336 NAME: name or ID of the Network Slice instance to be deleted
2339 nsi_delete(ctx
, name
, force
, wait
=wait
)
2342 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2343 @click.argument('name')
2344 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2346 def pdu_delete(ctx
, name
, force
):
2347 """deletes a Physical Deployment Unit (PDU)
2349 NAME: name or ID of the PDU to be deleted
2353 check_client_version(ctx
.obj
, ctx
.command
.name
)
2354 ctx
.obj
.pdu
.delete(name
, force
)
2355 # except ClientException as e:
2364 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2365 @click.option('--name',
2367 help='Name to create datacenter')
2368 @click.option('--user',
2370 help='VIM username')
2371 @click.option('--password',
2374 confirmation_prompt
=True,
2375 help='VIM password')
2376 @click.option('--auth_url',
2379 @click.option('--tenant',
2381 help='VIM tenant name')
2382 @click.option('--config',
2384 help='VIM specific config parameters')
2385 @click.option('--account_type',
2386 default
='openstack',
2388 @click.option('--description',
2390 help='human readable description')
2391 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2392 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2393 @click.option('--wait',
2397 help='do not return the control immediately, but keep it '
2398 'until the operation is completed, or timeout')
2412 """creates a new VIM account"""
2416 check_client_version(ctx
.obj
, '--sdn_controller')
2417 if sdn_port_mapping
:
2418 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2420 vim
['vim-username'] = user
2421 vim
['vim-password'] = password
2422 vim
['vim-url'] = auth_url
2423 vim
['vim-tenant-name'] = tenant
2424 vim
['vim-type'] = account_type
2425 vim
['description'] = description
2426 vim
['config'] = config
2427 if sdn_controller
or sdn_port_mapping
:
2428 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2430 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2431 # except ClientException as e:
2436 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2437 @click.argument('name')
2438 @click.option('--newname', help='New name for the VIM account')
2439 @click.option('--user', help='VIM username')
2440 @click.option('--password', help='VIM password')
2441 @click.option('--auth_url', help='VIM url')
2442 @click.option('--tenant', help='VIM tenant name')
2443 @click.option('--config', help='VIM specific config parameters')
2444 @click.option('--account_type', help='VIM type')
2445 @click.option('--description', help='human readable description')
2446 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller to be associated with this VIM'
2447 'account. Use empty string to disassociate')
2448 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2449 @click.option('--wait',
2453 help='do not return the control immediately, but keep it '
2454 'until the operation is completed, or timeout')
2469 """updates a VIM account
2471 NAME: name or ID of the VIM account
2475 check_client_version(ctx
.obj
, ctx
.command
.name
)
2477 if newname
: vim
['name'] = newname
2478 if user
: vim
['vim_user'] = user
2479 if password
: vim
['vim_password'] = password
2480 if auth_url
: vim
['vim_url'] = auth_url
2481 if tenant
: vim
['vim-tenant-name'] = tenant
2482 if account_type
: vim
['vim_type'] = account_type
2483 if description
: vim
['description'] = description
2484 if config
: vim
['config'] = config
2485 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2486 # except ClientException as e:
2491 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2492 @click.argument('name')
2493 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2494 @click.option('--wait',
2498 help='do not return the control immediately, but keep it '
2499 'until the operation is completed, or timeout')
2501 def vim_delete(ctx
, name
, force
, wait
):
2502 """deletes a VIM account
2504 NAME: name or ID of the VIM account to be deleted
2509 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2511 check_client_version(ctx
.obj
, '--force')
2512 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2513 # except ClientException as e:
2518 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2519 #@click.option('--ro_update/--no_ro_update',
2521 # help='update list from RO')
2522 @click.option('--filter', default
=None,
2523 help='restricts the list to the VIM accounts matching the filter')
2524 @click.option('--long', is_flag
=True,
2525 help='get more details of the NS (project, vim, deployment status, configuration status.')
2527 def vim_list(ctx
, filter, long):
2528 """list all VIM accounts"""
2531 check_client_version(ctx
.obj
, '--filter')
2533 # check_client_version(ctx.obj, '--ro_update', 'v1')
2534 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2535 if fullclassname
== 'osmclient.sol005.client.Client':
2536 resp
= ctx
.obj
.vim
.list(filter)
2538 # resp = ctx.obj.vim.list(ro_update)
2540 table
= PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details'])
2542 table
= PrettyTable(['vim name', 'uuid', 'operational state'])
2545 vim_details
= ctx
.obj
.vim
.get(vim
['uuid'])
2546 if 'vim_password' in vim_details
:
2547 vim_details
['vim_password']='********'
2548 logger
.debug('VIM details: {}'.format(yaml
.safe_dump(vim_details
)))
2549 vim_state
= vim_details
['_admin'].get('operationalState', '-')
2550 error_details
= 'N/A'
2551 if vim_state
== 'ERROR':
2552 error_details
= vim_details
['_admin'].get('detailed-status', 'Not found')
2553 project_list
= ctx
.obj
.project
.list()
2554 vim_project_list
= vim_details
.get('_admin').get('projects_read')
2556 project_name
= 'None'
2557 if vim_project_list
:
2558 project_id
= vim_project_list
[0]
2559 for p
in project_list
:
2560 if p
['_id'] == project_id
:
2561 project_name
= p
['name']
2563 table
.add_row([vim
['name'], vim
['uuid'], '{} ({})'.format(project_name
, project_id
),
2564 vim_state
, wrap_text(text
=error_details
, width
=80)])
2566 table
.add_row([vim
['name'], vim
['uuid'], vim
['_admin'].get('operationalState', '-')])
2571 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2572 @click.argument('name')
2574 def vim_show(ctx
, name
):
2575 """shows the details of a VIM account
2577 NAME: name or ID of the VIM account
2581 resp
= ctx
.obj
.vim
.get(name
)
2582 if 'vim_password' in resp
:
2583 resp
['vim_password']='********'
2584 # except ClientException as e:
2588 table
= PrettyTable(['key', 'attribute'])
2589 for k
, v
in list(resp
.items()):
2590 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2595 ####################
2597 ####################
2599 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2600 @click.option('--name',
2602 help='Name for the WIM account')
2603 @click.option('--user',
2604 help='WIM username')
2605 @click.option('--password',
2606 help='WIM password')
2607 @click.option('--url',
2610 # @click.option('--tenant',
2611 # help='wIM tenant name')
2612 @click.option('--config',
2614 help='WIM specific config parameters')
2615 @click.option('--wim_type',
2617 @click.option('--description',
2619 help='human readable description')
2620 @click.option('--wim_port_mapping', default
=None,
2621 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2622 "(WAN service endpoint id and info)")
2623 @click.option('--wait',
2627 help='do not return the control immediately, but keep it '
2628 'until the operation is completed, or timeout')
2641 """creates a new WIM account"""
2644 check_client_version(ctx
.obj
, ctx
.command
.name
)
2645 # if sdn_controller:
2646 # check_client_version(ctx.obj, '--sdn_controller')
2647 # if sdn_port_mapping:
2648 # check_client_version(ctx.obj, '--sdn_port_mapping')
2650 if user
: wim
['user'] = user
2651 if password
: wim
['password'] = password
2652 if url
: wim
['wim_url'] = url
2653 # if tenant: wim['tenant'] = tenant
2654 wim
['wim_type'] = wim_type
2655 if description
: wim
['description'] = description
2656 if config
: wim
['config'] = config
2657 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2658 # except ClientException as e:
2663 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2664 @click.argument('name')
2665 @click.option('--newname', help='New name for the WIM account')
2666 @click.option('--user', help='WIM username')
2667 @click.option('--password', help='WIM password')
2668 @click.option('--url', help='WIM url')
2669 @click.option('--config', help='WIM specific config parameters')
2670 @click.option('--wim_type', help='WIM type')
2671 @click.option('--description', help='human readable description')
2672 @click.option('--wim_port_mapping', default
=None,
2673 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2674 "(WAN service endpoint id and info)")
2675 @click.option('--wait',
2679 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2692 """updates a WIM account
2694 NAME: name or ID of the WIM account
2698 check_client_version(ctx
.obj
, ctx
.command
.name
)
2700 if newname
: wim
['name'] = newname
2701 if user
: wim
['user'] = user
2702 if password
: wim
['password'] = password
2703 if url
: wim
['url'] = url
2704 # if tenant: wim['tenant'] = tenant
2705 if wim_type
: wim
['wim_type'] = wim_type
2706 if description
: wim
['description'] = description
2707 if config
: wim
['config'] = config
2708 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2709 # except ClientException as e:
2714 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2715 @click.argument('name')
2716 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2717 @click.option('--wait',
2721 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2723 def wim_delete(ctx
, name
, force
, wait
):
2724 """deletes a WIM account
2726 NAME: name or ID of the WIM account to be deleted
2730 check_client_version(ctx
.obj
, ctx
.command
.name
)
2731 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2732 # except ClientException as e:
2737 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2738 @click.option('--filter', default
=None,
2739 help='restricts the list to the WIM accounts matching the filter')
2741 def wim_list(ctx
, filter):
2742 """list all WIM accounts"""
2745 check_client_version(ctx
.obj
, ctx
.command
.name
)
2746 resp
= ctx
.obj
.wim
.list(filter)
2747 table
= PrettyTable(['wim name', 'uuid'])
2749 table
.add_row([wim
['name'], wim
['uuid']])
2752 # except ClientException as e:
2757 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2758 @click.argument('name')
2760 def wim_show(ctx
, name
):
2761 """shows the details of a WIM account
2763 NAME: name or ID of the WIM account
2767 check_client_version(ctx
.obj
, ctx
.command
.name
)
2768 resp
= ctx
.obj
.wim
.get(name
)
2769 if 'password' in resp
:
2770 resp
['wim_password']='********'
2771 # except ClientException as e:
2775 table
= PrettyTable(['key', 'attribute'])
2776 for k
, v
in list(resp
.items()):
2777 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2782 ####################
2783 # SDN controller operations
2784 ####################
2786 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2787 @click.option('--name',
2789 help='Name to create sdn controller')
2790 @click.option('--type',
2792 help='SDN controller type')
2793 @click.option('--sdn_controller_version', # hidden=True,
2794 help='Deprecated. Use --config {version: sdn_controller_version}')
2795 @click.option('--url',
2796 help='URL in format http[s]://HOST:IP/')
2797 @click.option('--ip_address', # hidden=True,
2798 help='Deprecated. Use --url')
2799 @click.option('--port', # hidden=True,
2800 help='Deprecated. Use --url')
2801 @click.option('--switch_dpid', # hidden=True,
2802 help='Deprecated. Use --config {switch_id: DPID}')
2803 @click.option('--config',
2804 help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2805 'Openflow Datapath ID), version: version}')
2806 @click.option('--user',
2807 help='SDN controller username')
2808 @click.option('--password',
2810 confirmation_prompt
=True,
2811 help='SDN controller password')
2812 @click.option('--description', default
=None, help='human readable description')
2813 @click.option('--wait',
2817 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2819 def sdnc_create(ctx
, **kwargs
):
2820 """creates a new SDN controller"""
2822 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2823 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2824 if kwargs
.get("port"):
2825 print("option '--port' is deprecated, use '--url' instead")
2826 sdncontroller
["port"] = int(kwargs
["port"])
2827 if kwargs
.get("ip_address"):
2828 print("option '--ip_address' is deprecated, use '--url' instead")
2829 sdncontroller
["ip"] = kwargs
["ip_address"]
2830 if kwargs
.get("switch_dpid"):
2831 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2832 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2833 if kwargs
.get("sdn_controller_version"):
2834 print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2837 check_client_version(ctx
.obj
, ctx
.command
.name
)
2838 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2839 # except ClientException as e:
2843 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2844 @click.argument('name')
2845 @click.option('--newname', help='New name for the SDN controller')
2846 @click.option('--description', default
=None, help='human readable description')
2847 @click.option('--type', help='SDN controller type')
2848 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2849 @click.option('--config', help='Extra information for SDN in yaml format, as '
2850 '{switch_id: identity used for the plugin (e.g. DPID: '
2851 'Openflow Datapath ID), version: version}')
2852 @click.option('--user', help='SDN controller username')
2853 @click.option('--password', help='SDN controller password')
2854 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2855 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2856 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2857 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2858 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2859 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2861 def sdnc_update(ctx
, **kwargs
):
2862 """updates an SDN controller
2864 NAME: name or ID of the SDN controller
2867 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2868 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2869 if kwargs
.get("newname"):
2870 sdncontroller
["name"] = kwargs
["newname"]
2871 if kwargs
.get("port"):
2872 print("option '--port' is deprecated, use '--url' instead")
2873 sdncontroller
["port"] = int(kwargs
["port"])
2874 if kwargs
.get("ip_address"):
2875 print("option '--ip_address' is deprecated, use '--url' instead")
2876 sdncontroller
["ip"] = kwargs
["ip_address"]
2877 if kwargs
.get("switch_dpid"):
2878 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2879 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2880 if kwargs
.get("sdn_controller_version"):
2881 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2885 check_client_version(ctx
.obj
, ctx
.command
.name
)
2886 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2887 # except ClientException as e:
2892 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2893 @click.argument('name')
2894 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2895 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2896 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2898 def sdnc_delete(ctx
, name
, force
, wait
):
2899 """deletes an SDN controller
2901 NAME: name or ID of the SDN controller to be deleted
2905 check_client_version(ctx
.obj
, ctx
.command
.name
)
2906 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2907 # except ClientException as e:
2912 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2913 @click.option('--filter', default
=None,
2914 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2916 def sdnc_list(ctx
, filter):
2917 """list all SDN controllers"""
2920 check_client_version(ctx
.obj
, ctx
.command
.name
)
2921 resp
= ctx
.obj
.sdnc
.list(filter)
2922 # except ClientException as e:
2925 table
= PrettyTable(['sdnc name', 'id'])
2927 table
.add_row([sdnc
['name'], sdnc
['_id']])
2932 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2933 @click.argument('name')
2935 def sdnc_show(ctx
, name
):
2936 """shows the details of an SDN controller
2938 NAME: name or ID of the SDN controller
2942 check_client_version(ctx
.obj
, ctx
.command
.name
)
2943 resp
= ctx
.obj
.sdnc
.get(name
)
2944 # except ClientException as e:
2948 table
= PrettyTable(['key', 'attribute'])
2949 for k
, v
in list(resp
.items()):
2950 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2955 ###########################
2956 # K8s cluster operations
2957 ###########################
2959 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2960 @click.argument('name')
2961 @click.option('--creds',
2963 help='credentials file, i.e. a valid `.kube/config` file')
2964 @click.option('--version',
2966 help='Kubernetes version')
2967 @click.option('--vim',
2969 help='VIM target, the VIM where the cluster resides')
2970 @click.option('--k8s-nets',
2972 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) ...]}"')
2973 @click.option('--description',
2975 help='human readable description')
2976 @click.option('--namespace',
2977 default
='kube-system',
2978 help='namespace to be used for its operation, defaults to `kube-system`')
2979 @click.option('--cni',
2981 help='list of CNI plugins, in JSON inline format, used in the cluster')
2982 #@click.option('--skip-init',
2984 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2985 #@click.option('--wait',
2987 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2989 def k8scluster_add(ctx
,
2998 """adds a K8s cluster to OSM
3000 NAME: name of the K8s cluster
3003 check_client_version(ctx
.obj
, ctx
.command
.name
)
3005 cluster
['name'] = name
3006 with
open(creds
, 'r') as cf
:
3007 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3008 cluster
['k8s_version'] = version
3009 cluster
['vim_account'] = vim
3010 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3012 cluster
['description'] = description
3013 if namespace
: cluster
['namespace'] = namespace
3014 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3015 ctx
.obj
.k8scluster
.create(name
, cluster
)
3016 # except ClientException as e:
3021 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
3022 @click.argument('name')
3023 @click.option('--newname', help='New name for the K8s cluster')
3024 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3025 @click.option('--version', help='Kubernetes version')
3026 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3027 @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) ...]}"')
3028 @click.option('--description', help='human readable description')
3029 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3030 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3032 def k8scluster_update(ctx
,
3042 """updates a K8s cluster
3044 NAME: name or ID of the K8s cluster
3047 check_client_version(ctx
.obj
, ctx
.command
.name
)
3049 if newname
: cluster
['name'] = newname
3051 with
open(creds
, 'r') as cf
:
3052 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3053 if version
: cluster
['k8s_version'] = version
3054 if vim
: cluster
['vim_account'] = vim
3055 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3056 if description
: cluster
['description'] = description
3057 if namespace
: cluster
['namespace'] = namespace
3058 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3059 ctx
.obj
.k8scluster
.update(name
, cluster
)
3060 # except ClientException as e:
3065 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
3066 @click.argument('name')
3067 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3068 #@click.option('--wait',
3070 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3072 def k8scluster_delete(ctx
, name
, force
):
3073 """deletes a K8s cluster
3075 NAME: name or ID of the K8s cluster to be deleted
3078 check_client_version(ctx
.obj
, ctx
.command
.name
)
3079 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3080 # except ClientException as e:
3085 @cli_osm.command(name
='k8scluster-list')
3086 @click.option('--filter', default
=None,
3087 help='restricts the list to the K8s clusters matching the filter')
3088 @click.option('--literal', is_flag
=True,
3089 help='print literally, no pretty table')
3091 def k8scluster_list(ctx
, filter, literal
):
3092 """list all K8s clusters"""
3094 check_client_version(ctx
.obj
, ctx
.command
.name
)
3095 resp
= ctx
.obj
.k8scluster
.list(filter)
3097 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3099 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
3100 for cluster
in resp
:
3101 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
3102 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
3103 trunc_text(cluster
.get('description') or '', 40)])
3106 # except ClientException as e:
3111 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
3112 @click.argument('name')
3113 @click.option('--literal', is_flag
=True,
3114 help='print literally, no pretty table')
3116 def k8scluster_show(ctx
, name
, literal
):
3117 """shows the details of a K8s cluster
3119 NAME: name or ID of the K8s cluster
3122 resp
= ctx
.obj
.k8scluster
.get(name
)
3124 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3126 table
= PrettyTable(['key', 'attribute'])
3127 for k
, v
in list(resp
.items()):
3128 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
3131 # except ClientException as e:
3137 ###########################
3139 ###########################
3141 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
3142 @click.argument('name')
3143 @click.argument('uri')
3144 @click.option('--type',
3145 type=click
.Choice(['helm-chart', 'juju-bundle', 'osm']),
3147 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3148 @click.option('--description',
3150 help='human readable description')
3151 @click.option('--user',
3153 help='OSM repository: The username of the OSM repository')
3154 @click.option('--password',
3156 help='OSM repository: The password of the OSM repository')
3157 #@click.option('--wait',
3159 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3161 def repo_add(ctx
, **kwargs
):
3162 """adds a repo to OSM
3164 NAME: name of the repo
3165 URI: URI of the repo
3168 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
3170 repo
["url"] = repo
.pop("uri")
3171 if repo
["type"] in ['helm-chart', 'juju-bundle']:
3172 ctx
.obj
.repo
.create(repo
['name'], repo
)
3174 ctx
.obj
.osmrepo
.create(repo
['name'], repo
)
3175 # except ClientException as e:
3180 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
3181 @click.argument('name')
3182 @click.option('--newname', help='New name for the repo')
3183 @click.option('--uri', help='URI of the repo')
3184 @click.option('--description', help='human readable description')
3185 #@click.option('--wait',
3187 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3189 def repo_update(ctx
,
3194 """updates a repo in OSM
3196 NAME: name of the repo
3199 check_client_version(ctx
.obj
, ctx
.command
.name
)
3202 repo
['name'] = newname
3205 if description
: repo
['description'] = description
3207 ctx
.obj
.repo
.update(name
, repo
)
3209 ctx
.obj
.osmrepo
.update(name
, repo
)
3211 # except ClientException as e:
3216 @cli_osm.command(name
='repo-index', short_help
='Index a repository from a folder with artifacts')
3217 @click.option('--origin', default
='.', help='origin path where the artifacts are located')
3218 @click.option('--destination', default
='.', help='destination path where the index is deployed')
3220 def repo_index(ctx
, origin
, destination
):
3221 """Index a repository
3223 NAME: name or ID of the repo to be deleted
3225 check_client_version(ctx
.obj
, ctx
.command
.name
)
3226 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
3229 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
3230 @click.argument('name')
3231 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3232 #@click.option('--wait',
3234 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3236 def repo_delete(ctx
, name
, force
):
3239 NAME: name or ID of the repo to be deleted
3243 ctx
.obj
.repo
.delete(name
, force
=force
)
3245 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
3246 # except ClientException as e:
3251 @cli_osm.command(name
='repo-list')
3252 @click.option('--filter', default
=None,
3253 help='restricts the list to the repos matching the filter')
3254 @click.option('--literal', is_flag
=True,
3255 help='print literally, no pretty table')
3257 def repo_list(ctx
, filter, literal
):
3258 """list all repos"""
3261 check_client_version(ctx
.obj
, ctx
.command
.name
)
3262 resp
= ctx
.obj
.repo
.list(filter)
3263 resp
+= ctx
.obj
.osmrepo
.list(filter)
3265 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3267 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3269 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3270 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description') or '',40)])
3274 # except ClientException as e:
3279 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
3280 @click.argument('name')
3281 @click.option('--literal', is_flag
=True,
3282 help='print literally, no pretty table')
3284 def repo_show(ctx
, name
, literal
):
3285 """shows the details of a repo
3287 NAME: name or ID of the repo
3290 resp
= ctx
.obj
.repo
.get(name
)
3292 resp
= ctx
.obj
.osmrepo
.get(name
)
3296 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3298 table
= PrettyTable(['key', 'attribute'])
3300 for k
, v
in list(resp
.items()):
3301 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3305 # except ClientException as e:
3311 ####################
3312 # Project mgmt operations
3313 ####################
3315 @cli_osm.command(name
='project-create', short_help
='creates a new project')
3316 @click.argument('name')
3317 #@click.option('--description',
3318 # default='no description',
3319 # help='human readable description')
3320 @click.option('--domain-name', 'domain_name',
3322 help='assign to a domain')
3323 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3324 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3325 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3327 def project_create(ctx
, name
, domain_name
, quotas
):
3328 """Creates a new project
3330 NAME: name of the project
3331 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3332 QUOTAS: set quotas for the project
3335 project
= {'name': name
}
3337 project
['domain_name'] = domain_name
3338 quotas_dict
= _process_project_quotas(quotas
)
3340 project
['quotas'] = quotas_dict
3343 check_client_version(ctx
.obj
, ctx
.command
.name
)
3344 ctx
.obj
.project
.create(name
, project
)
3345 # except ClientException as e:
3350 def _process_project_quotas(quota_list
):
3355 for quota
in quota_list
:
3356 for single_quota
in quota
.split(","):
3357 k
, v
= single_quota
.split("=")
3358 quotas_dict
[k
] = None if v
in ('None', 'null', '') else int(v
)
3359 except (ValueError, TypeError):
3360 raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3364 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3365 @click.argument('name')
3366 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3368 def project_delete(ctx
, name
):
3369 """deletes a project
3371 NAME: name or ID of the project to be deleted
3375 check_client_version(ctx
.obj
, ctx
.command
.name
)
3376 ctx
.obj
.project
.delete(name
)
3377 # except ClientException as e:
3382 @cli_osm.command(name
='project-list', short_help
='list all projects')
3383 @click.option('--filter', default
=None,
3384 help='restricts the list to the projects matching the filter')
3386 def project_list(ctx
, filter):
3387 """list all projects"""
3390 check_client_version(ctx
.obj
, ctx
.command
.name
)
3391 resp
= ctx
.obj
.project
.list(filter)
3392 # except ClientException as e:
3395 table
= PrettyTable(['name', 'id'])
3397 table
.add_row([proj
['name'], proj
['_id']])
3402 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3403 @click.argument('name')
3405 def project_show(ctx
, name
):
3406 """shows the details of a project
3408 NAME: name or ID of the project
3412 check_client_version(ctx
.obj
, ctx
.command
.name
)
3413 resp
= ctx
.obj
.project
.get(name
)
3414 # except ClientException as e:
3418 table
= PrettyTable(['key', 'attribute'])
3419 for k
, v
in resp
.items():
3420 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3425 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3426 @click.argument('project')
3427 @click.option('--name', default
=None,
3428 help='new name for the project')
3429 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3430 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3431 "(use empty to reset quota to default")
3433 def project_update(ctx
, project
, name
, quotas
):
3435 Update a project name
3438 :param project: id or name of the project to modify
3439 :param name: new name for the project
3440 :param quotas: change quotas of the project
3444 project_changes
= {}
3446 project_changes
['name'] = name
3447 quotas_dict
= _process_project_quotas(quotas
)
3449 project_changes
['quotas'] = quotas_dict
3452 check_client_version(ctx
.obj
, ctx
.command
.name
)
3453 ctx
.obj
.project
.update(project
, project_changes
)
3454 # except ClientException as e:
3458 ####################
3459 # User mgmt operations
3460 ####################
3462 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3463 @click.argument('username')
3464 @click.option('--password',
3467 confirmation_prompt
=True,
3468 help='user password')
3469 @click.option('--projects',
3470 # prompt="Comma separate list of projects",
3472 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3473 help='list of project ids that the user belongs to')
3474 @click.option('--project-role-mappings', 'project_role_mappings',
3475 default
=None, multiple
=True,
3476 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3477 @click.option('--domain-name', 'domain_name',
3479 help='assign to a domain')
3481 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
3482 """Creates a new user
3485 USERNAME: name of the user
3486 PASSWORD: password of the user
3487 PROJECTS: projects assigned to user (internal only)
3488 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3489 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3493 user
['username'] = username
3494 user
['password'] = password
3495 user
['projects'] = projects
3496 user
['project_role_mappings'] = project_role_mappings
3498 user
['domain_name'] = domain_name
3501 check_client_version(ctx
.obj
, ctx
.command
.name
)
3502 ctx
.obj
.user
.create(username
, user
)
3503 # except ClientException as e:
3508 @cli_osm.command(name
='user-update', short_help
='updates user information')
3509 @click.argument('username')
3510 @click.option('--password',
3513 # confirmation_prompt=True,
3514 help='user password')
3515 @click.option('--set-username', 'set_username',
3517 help='change username')
3518 @click.option('--set-project', 'set_project',
3519 default
=None, multiple
=True,
3520 help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3521 @click.option('--remove-project', 'remove_project',
3522 default
=None, multiple
=True,
3523 help="removes project from user: 'project'")
3524 @click.option('--add-project-role', 'add_project_role',
3525 default
=None, multiple
=True,
3526 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3527 @click.option('--remove-project-role', 'remove_project_role',
3528 default
=None, multiple
=True,
3529 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3531 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3532 add_project_role
, remove_project_role
):
3533 """Update a user information
3536 USERNAME: name of the user
3537 PASSWORD: new password
3538 SET_USERNAME: new username
3539 SET_PROJECT: creating mappings for project/role(s)
3540 REMOVE_PROJECT: deleting mappings for project/role(s)
3541 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3542 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3546 user
['password'] = password
3547 user
['username'] = set_username
3548 user
['set-project'] = set_project
3549 user
['remove-project'] = remove_project
3550 user
['add-project-role'] = add_project_role
3551 user
['remove-project-role'] = remove_project_role
3554 check_client_version(ctx
.obj
, ctx
.command
.name
)
3555 ctx
.obj
.user
.update(username
, user
)
3556 # except ClientException as e:
3561 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3562 @click.argument('name')
3563 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3565 def user_delete(ctx
, name
):
3569 NAME: name or ID of the user to be deleted
3573 check_client_version(ctx
.obj
, ctx
.command
.name
)
3574 ctx
.obj
.user
.delete(name
)
3575 # except ClientException as e:
3580 @cli_osm.command(name
='user-list', short_help
='list all users')
3581 @click.option('--filter', default
=None,
3582 help='restricts the list to the users matching the filter')
3584 def user_list(ctx
, filter):
3585 """list all users"""
3587 check_client_version(ctx
.obj
, ctx
.command
.name
)
3588 resp
= ctx
.obj
.user
.list(filter)
3589 # except ClientException as e:
3592 table
= PrettyTable(['name', 'id'])
3594 table
.add_row([user
['username'], user
['_id']])
3599 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3600 @click.argument('name')
3602 def user_show(ctx
, name
):
3603 """shows the details of a user
3605 NAME: name or ID of the user
3609 check_client_version(ctx
.obj
, ctx
.command
.name
)
3610 resp
= ctx
.obj
.user
.get(name
)
3611 if 'password' in resp
:
3612 resp
['password']='********'
3613 # except ClientException as e:
3617 table
= PrettyTable(['key', 'attribute'])
3618 for k
, v
in resp
.items():
3619 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3624 ####################
3625 # Fault Management operations
3626 ####################
3628 @cli_osm.command(name
='ns-alarm-create')
3629 @click.argument('name')
3630 @click.option('--ns', prompt
=True, help='NS instance id or name')
3631 @click.option('--vnf', prompt
=True,
3632 help='VNF name (VNF member index as declared in the NSD)')
3633 @click.option('--vdu', prompt
=True,
3634 help='VDU name (VDU name as declared in the VNFD)')
3635 @click.option('--metric', prompt
=True,
3636 help='Name of the metric (e.g. cpu_utilization)')
3637 @click.option('--severity', default
='WARNING',
3638 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3639 @click.option('--threshold_value', prompt
=True,
3640 help='threshold value that, when crossed, an alarm is triggered')
3641 @click.option('--threshold_operator', prompt
=True,
3642 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3643 @click.option('--statistic', default
='AVERAGE',
3644 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3646 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3647 threshold_value
, threshold_operator
, statistic
):
3648 """creates a new alarm for a NS instance"""
3649 # TODO: Check how to validate threshold_value.
3650 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3653 ns_instance
= ctx
.obj
.ns
.get(ns
)
3655 alarm
['alarm_name'] = name
3656 alarm
['ns_id'] = ns_instance
['_id']
3657 alarm
['correlation_id'] = ns_instance
['_id']
3658 alarm
['vnf_member_index'] = vnf
3659 alarm
['vdu_name'] = vdu
3660 alarm
['metric_name'] = metric
3661 alarm
['severity'] = severity
3662 alarm
['threshold_value'] = int(threshold_value
)
3663 alarm
['operation'] = threshold_operator
3664 alarm
['statistic'] = statistic
3665 check_client_version(ctx
.obj
, ctx
.command
.name
)
3666 ctx
.obj
.ns
.create_alarm(alarm
)
3667 # except ClientException as e:
3672 #@cli_osm.command(name='ns-alarm-delete')
3673 #@click.argument('name')
3674 #@click.pass_context
3675 #def ns_alarm_delete(ctx, name):
3676 # """deletes an alarm
3678 # NAME: name of the alarm to be deleted
3681 # check_client_version(ctx.obj, ctx.command.name)
3682 # ctx.obj.ns.delete_alarm(name)
3683 # except ClientException as e:
3688 ####################
3689 # Performance Management operations
3690 ####################
3692 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3693 @click.option('--ns', prompt
=True, help='NS instance id or name')
3694 @click.option('--vnf', prompt
=True,
3695 help='VNF name (VNF member index as declared in the NSD)')
3696 @click.option('--vdu', prompt
=True,
3697 help='VDU name (VDU name as declared in the VNFD)')
3698 @click.option('--metric', prompt
=True,
3699 help='name of the metric (e.g. cpu_utilization)')
3700 #@click.option('--period', default='1w',
3701 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3702 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3704 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3705 """exports a metric to the internal OSM bus, which can be read by other apps"""
3706 # TODO: Check how to validate interval.
3707 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3710 ns_instance
= ctx
.obj
.ns
.get(ns
)
3712 metric_data
['ns_id'] = ns_instance
['_id']
3713 metric_data
['correlation_id'] = ns_instance
['_id']
3714 metric_data
['vnf_member_index'] = vnf
3715 metric_data
['vdu_name'] = vdu
3716 metric_data
['metric_name'] = metric
3717 metric_data
['collection_unit'] = 'WEEK'
3718 metric_data
['collection_period'] = 1
3719 check_client_version(ctx
.obj
, ctx
.command
.name
)
3721 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3725 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3726 time
.sleep(int(interval
))
3728 # except ClientException as e:
3733 ####################
3735 ####################
3737 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3739 def get_version(ctx
):
3740 """shows client and server versions"""
3742 check_client_version(ctx
.obj
, "version")
3743 print ("Server version: {}".format(ctx
.obj
.get_version()))
3744 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3745 # except ClientException as e:
3749 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3750 @click.argument('filename')
3751 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3752 help='the charm will not be compiled, it is assumed to already exist')
3754 def upload_package(ctx
, filename
, skip_charm_build
):
3755 """uploads a vnf package or ns package
3757 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3761 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3762 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3763 if fullclassname
!= 'osmclient.sol005.client.Client':
3764 ctx
.obj
.package
.wait_for_upload(filename
)
3765 # except ClientException as e:
3770 #@cli_osm.command(name='ns-scaling-show')
3771 #@click.argument('ns_name')
3772 #@click.pass_context
3773 #def show_ns_scaling(ctx, ns_name):
3774 # """shows the status of a NS scaling operation
3776 # NS_NAME: name of the NS instance being scaled
3779 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3780 # resp = ctx.obj.ns.list()
3781 # except ClientException as e:
3785 # table = PrettyTable(
3788 # 'operational status',
3793 # if ns_name == ns['name']:
3794 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3795 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3796 # for record in scaling_records:
3797 # if 'instance' in record:
3798 # instances = record['instance']
3799 # for inst in instances:
3801 # [record['scaling-group-name-ref'],
3802 # inst['instance-id'],
3803 # inst['op-status'],
3804 # time.strftime('%Y-%m-%d %H:%M:%S',
3806 # inst['create-time'])),
3812 #@cli_osm.command(name='ns-scale')
3813 #@click.argument('ns_name')
3814 #@click.option('--ns_scale_group', prompt=True)
3815 #@click.option('--index', prompt=True)
3816 #@click.option('--wait',
3820 # help='do not return the control immediately, but keep it \
3821 # until the operation is completed, or timeout')
3822 #@click.pass_context
3823 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3826 # NS_NAME: name of the NS instance to be scaled
3829 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3830 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3831 # except ClientException as e:
3836 #@cli_osm.command(name='config-agent-list')
3837 #@click.pass_context
3838 #def config_agent_list(ctx):
3839 # """list config agents"""
3841 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3842 # except ClientException as e:
3845 # table = PrettyTable(['name', 'account-type', 'details'])
3846 # for account in ctx.obj.vca.list():
3849 # account['account-type'],
3855 #@cli_osm.command(name='config-agent-delete')
3856 #@click.argument('name')
3857 #@click.pass_context
3858 #def config_agent_delete(ctx, name):
3859 # """deletes a config agent
3861 # NAME: name of the config agent to be deleted
3864 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3865 # ctx.obj.vca.delete(name)
3866 # except ClientException as e:
3871 #@cli_osm.command(name='config-agent-add')
3872 #@click.option('--name',
3874 #@click.option('--account_type',
3876 #@click.option('--server',
3878 #@click.option('--user',
3880 #@click.option('--secret',
3883 # confirmation_prompt=True)
3884 #@click.pass_context
3885 #def config_agent_add(ctx, name, account_type, server, user, secret):
3886 # """adds a config agent"""
3888 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3889 # ctx.obj.vca.create(name, account_type, server, user, secret)
3890 # except ClientException as e:
3895 #@cli_osm.command(name='ro-dump')
3896 #@click.pass_context
3898 # """shows RO agent information"""
3899 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3900 # resp = ctx.obj.vim.get_resource_orchestrator()
3901 # table = PrettyTable(['key', 'attribute'])
3902 # for k, v in list(resp.items()):
3903 # table.add_row([k, json.dumps(v, indent=2)])
3908 #@cli_osm.command(name='vcs-list')
3909 #@click.pass_context
3911 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3912 # resp = ctx.obj.utils.get_vcs_info()
3913 # table = PrettyTable(['component name', 'state'])
3914 # for component in resp:
3915 # table.add_row([component['component_name'], component['state']])
3920 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3921 @click.argument('ns_name')
3922 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3923 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3924 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3925 @click.option('--vdu_count', default
=None, type=int, help='number of vdu instance of this vdu_id')
3926 @click.option('--action_name', prompt
=True, help='action name')
3927 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3928 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3929 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
3930 @click.option('--wait',
3934 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3947 """executes an action/primitive over a NS instance
3949 NS_NAME: name or ID of the NS instance
3953 check_client_version(ctx
.obj
, ctx
.command
.name
)
3956 op_data
['member_vnf_index'] = vnf_name
3958 op_data
['kdu_name'] = kdu_name
3960 op_data
['vdu_id'] = vdu_id
3961 if vdu_count
is not None:
3962 op_data
['vdu_count_index'] = vdu_count
3964 op_data
['timeout_ns_action'] = timeout
3965 op_data
['primitive'] = action_name
3967 with
open(params_file
, 'r') as pf
:
3970 op_data
['primitive_params'] = yaml
.safe_load(params
)
3972 op_data
['primitive_params'] = {}
3973 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
3975 # except ClientException as e:
3980 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
3981 @click.argument('ns_name')
3982 @click.argument('vnf_name')
3983 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
3984 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
3985 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
3986 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
3987 @click.option('--wait', required
=False, default
=False, is_flag
=True,
3988 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3999 Executes a VNF scale (adding/removing VDUs)
4002 NS_NAME: name or ID of the NS instance.
4003 VNF_NAME: member-vnf-index in the NS to be scaled.
4007 check_client_version(ctx
.obj
, ctx
.command
.name
)
4008 if not scale_in
and not scale_out
:
4010 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
)
4011 # except ClientException as e:
4016 ##############################
4017 # Role Management Operations #
4018 ##############################
4020 @cli_osm.command(name
='role-create', short_help
='creates a new role')
4021 @click.argument('name')
4022 @click.option('--permissions',
4024 help='role permissions using a dictionary')
4026 def role_create(ctx
, name
, permissions
):
4031 NAME: Name or ID of the role.
4032 DEFINITION: Definition of grant/denial of access to resources.
4036 check_client_version(ctx
.obj
, ctx
.command
.name
)
4037 ctx
.obj
.role
.create(name
, permissions
)
4038 # except ClientException as e:
4043 @cli_osm.command(name
='role-update', short_help
='updates a role')
4044 @click.argument('name')
4045 @click.option('--set-name',
4047 help='change name of rle')
4048 # @click.option('--permissions',
4050 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4051 @click.option('--add',
4053 help='yaml format dictionary with permission: True/False to access grant/denial')
4054 @click.option('--remove',
4056 help='yaml format list to remove a permission')
4058 def role_update(ctx
, name
, set_name
, add
, remove
):
4063 NAME: Name or ID of the role.
4064 DEFINITION: Definition overwrites the old definition.
4065 ADD: Grant/denial of access to resource to add.
4066 REMOVE: Grant/denial of access to resource to remove.
4070 check_client_version(ctx
.obj
, ctx
.command
.name
)
4071 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
4072 # except ClientException as e:
4077 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
4078 @click.argument('name')
4079 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4081 def role_delete(ctx
, name
):
4086 NAME: Name or ID of the role.
4090 check_client_version(ctx
.obj
, ctx
.command
.name
)
4091 ctx
.obj
.role
.delete(name
)
4092 # except ClientException as e:
4097 @cli_osm.command(name
='role-list', short_help
='list all roles')
4098 @click.option('--filter', default
=None,
4099 help='restricts the list to the projects matching the filter')
4101 def role_list(ctx
, filter):
4107 check_client_version(ctx
.obj
, ctx
.command
.name
)
4108 resp
= ctx
.obj
.role
.list(filter)
4109 # except ClientException as e:
4112 table
= PrettyTable(['name', 'id'])
4114 table
.add_row([role
['name'], role
['_id']])
4119 @cli_osm.command(name
='role-show', short_help
='show specific role')
4120 @click.argument('name')
4122 def role_show(ctx
, name
):
4124 Shows the details of a role.
4127 NAME: Name or ID of the role.
4131 check_client_version(ctx
.obj
, ctx
.command
.name
)
4132 resp
= ctx
.obj
.role
.get(name
)
4133 # except ClientException as e:
4137 table
= PrettyTable(['key', 'attribute'])
4138 for k
, v
in resp
.items():
4139 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4144 @cli_osm.command(name
='package-create',
4145 short_help
='Create a package descriptor')
4146 @click.argument('package-type')
4147 @click.argument('package-name')
4148 @click.option('--base-directory',
4150 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4151 @click.option('--image',
4152 default
="image-name",
4153 help='(VNF) Set the name of the vdu image. Default "image-name"')
4154 @click.option('--vdus',
4156 help='(VNF) Set the number of vdus in a VNF. Default 1')
4157 @click.option('--vcpu',
4159 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4160 @click.option('--memory',
4162 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4163 @click.option('--storage',
4165 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4166 @click.option('--interfaces',
4168 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4169 @click.option('--vendor',
4171 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4172 @click.option('--override',
4175 help='(NS/VNF/NST) Flag for overriding the package if exists.')
4176 @click.option('--detailed',
4179 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4180 @click.option('--netslice-subnets',
4182 help='(NST) Number of netslice subnets. Default 1')
4183 @click.option('--netslice-vlds',
4185 help='(NST) Number of netslice vlds. Default 1')
4187 def package_create(ctx
,
4203 Creates an OSM NS, VNF, NST package
4206 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4207 PACKAGE_NAME: Name of the package to create the folder with the content.
4211 check_client_version(ctx
.obj
, ctx
.command
.name
)
4212 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
4213 resp
= ctx
.obj
.package_tool
.create(package_type
,
4222 interfaces
=interfaces
,
4225 netslice_subnets
=netslice_subnets
,
4226 netslice_vlds
=netslice_vlds
)
4228 # except ClientException as inst:
4229 # print("ERROR: {}".format(inst))
4232 @cli_osm.command(name
='package-validate',
4233 short_help
='Validate a package descriptor')
4234 @click.argument('base-directory',
4237 @click.option('--recursive/--no-recursive',
4239 help='The activated recursive option will validate the yaml files'
4240 ' within the indicated directory and in its subdirectories')
4242 def package_validate(ctx
,
4246 Validate descriptors given a base directory.
4249 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4252 check_client_version(ctx
.obj
, ctx
.command
.name
)
4253 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
4254 table
= PrettyTable()
4255 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
4256 # Print the dictionary generated by the validation function
4257 for result
in results
:
4258 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
4259 table
.sortby
= "VALID"
4260 table
.align
["PATH"] = "l"
4261 table
.align
["TYPE"] = "l"
4262 table
.align
["ERROR"] = "l"
4264 # except ClientException as inst:
4265 # print("ERROR: {}".format(inst))
4268 @cli_osm.command(name
='package-build',
4269 short_help
='Build the tar.gz of the package')
4270 @click.argument('package-folder')
4271 @click.option('--skip-validation',
4274 help='skip package validation')
4275 @click.option('--skip-charm-build', default
=False, is_flag
=True,
4276 help='the charm will not be compiled, it is assumed to already exist')
4278 def package_build(ctx
,
4283 Build the package NS, VNF given the package_folder.
4286 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4289 check_client_version(ctx
.obj
, ctx
.command
.name
)
4290 results
= ctx
.obj
.package_tool
.build(package_folder
,
4291 skip_validation
=skip_validation
,
4292 skip_charm_build
=skip_charm_build
)
4294 # except ClientException as inst:
4295 # print("ERROR: {}".format(inst))
4303 except pycurl
.error
as exc
:
4305 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4306 except ClientException
as exc
:
4307 print("ERROR: {}".format(exc
))
4308 except (FileNotFoundError
, PermissionError
) as exc
:
4309 print("Cannot open file: {}".format(exc
))
4310 except yaml
.YAMLError
as exc
:
4311 print("Invalid YAML format: {}".format(exc
))
4313 # TODO capture other controlled exceptions here
4314 # TODO remove the ClientException captures from all places, unless they do something different
4317 if __name__
== '__main__':