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, multiple
=True,
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 filter='&'.join(filter)
314 resp
= ctx
.obj
.ns
.list(filter)
316 resp
= ctx
.obj
.ns
.list()
328 'configuration status'])
329 project_list
= ctx
.obj
.project
.list()
330 vim_list
= ctx
.obj
.vim
.list()
340 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
341 if fullclassname
== 'osmclient.sol005.client.Client':
343 logger
.debug('NS info: {}'.format(nsr
))
344 nsr_name
= nsr
['name']
346 date
= datetime
.fromtimestamp(nsr
['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
347 ns_state
= nsr
.get('nsState', nsr
['_admin']['nsState'])
349 deployment_status
= summarize_deployment_status(nsr
.get('deploymentStatus'))
350 config_status
= summarize_config_status(nsr
.get('configurationStatus'))
351 project_id
= nsr
.get('_admin').get('projects_read')[0]
353 for p
in project_list
:
354 if p
['_id'] == project_id
:
355 project_name
= p
['name']
357 #project = '{} ({})'.format(project_name, project_id)
358 project
= project_name
359 vim_id
= nsr
.get('datacenter')
362 if v
['uuid'] == vim_id
:
365 #vim = '{} ({})'.format(vim_name, vim_id)
367 if 'currentOperation' in nsr
:
368 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
370 current_operation
= "{} ({})".format(nsr
['_admin'].get('current-operation','-'), nsr
['_admin']['nslcmop'])
371 error_details
= "N/A"
372 if ns_state
== "BROKEN" or ns_state
== "DEGRADED" or \
373 ('currentOperation' not in nsr
and nsr
.get('errorDescription')):
374 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'], nsr
['errorDetail'])
376 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
377 nsr
= nsopdata
['nsr:nsr']
378 nsr_name
= nsr
['name-ref']
379 nsr_id
= nsr
['ns-instance-config-ref']
382 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
383 ns_state
= deployment_status
384 config_status
= nsr
.get('config-status', 'Not found')
385 current_operation
= "Unknown"
386 error_details
= nsr
.get('detailed-status', 'Not found')
387 if config_status
== "config_not_needed":
388 config_status
= "configured (no charms)"
397 wrap_text(text
=error_details
,width
=40),
409 wrap_text(text
=error_details
,width
=40)])
412 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
413 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
415 def nsd_list(ctx
, filter, long):
418 check_client_version(ctx
.obj
, '--filter')
419 filter='&'.join(filter)
420 resp
= ctx
.obj
.nsd
.list(filter)
422 resp
= ctx
.obj
.nsd
.list()
423 # print(yaml.safe_dump(resp))
424 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
425 if fullclassname
== 'osmclient.sol005.client.Client':
427 table
= PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state',
428 'usage state', 'date', 'last update'])
430 table
= PrettyTable(['nsd name', 'id'])
432 name
= nsd
.get('name','-')
434 onb_state
= nsd
['_admin'].get('onboardingState','-')
435 op_state
= nsd
['_admin'].get('operationalState','-')
436 usage_state
= nsd
['_admin'].get('usageState','-')
437 date
= datetime
.fromtimestamp(nsd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
438 last_update
= datetime
.fromtimestamp(nsd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
439 table
.add_row([name
, nsd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
441 table
.add_row([name
, nsd
['_id']])
443 table
= PrettyTable(['nsd name', 'id'])
445 table
.add_row([nsd
['name'], nsd
['id']])
450 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
451 @click.option('--filter', default
=None, multiple
=True,
452 help='restricts the list to the NSD/NSpkg matching the filter')
453 @click.option('--long', is_flag
=True, help='get more details')
455 def nsd_list1(ctx
, filter, long):
456 """list all NSD/NS pkg in the system"""
458 nsd_list(ctx
, filter, long)
461 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
462 @click.option('--filter', default
=None, multiple
=True,
463 help='restricts the list to the NSD/NSpkg matching the filter')
464 @click.option('--long', is_flag
=True, help='get more details')
466 def nsd_list2(ctx
, filter, long):
467 """list all NS packages"""
469 nsd_list(ctx
, filter, long)
472 def vnfd_list(ctx
, nf_type
, filter, long):
475 check_client_version(ctx
.obj
, '--nf_type')
477 check_client_version(ctx
.obj
, '--filter')
479 filter='&'.join(filter)
482 nf_filter
= "_admin.type=vnfd"
483 elif nf_type
== "pnf":
484 nf_filter
= "_admin.type=pnfd"
485 elif nf_type
== "hnf":
486 nf_filter
= "_admin.type=hnfd"
488 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
490 filter = '{}&{}'.format(nf_filter
, filter)
494 resp
= ctx
.obj
.vnfd
.list(filter)
496 resp
= ctx
.obj
.vnfd
.list()
497 # print(yaml.safe_dump(resp))
498 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
499 if fullclassname
== 'osmclient.sol005.client.Client':
501 table
= PrettyTable(['nfpkg name', 'id', 'vendor', 'version', 'onboarding state', 'operational state',
502 'usage state', 'date', 'last update'])
504 table
= PrettyTable(['nfpkg name', 'id'])
506 name
= vnfd
['name'] if 'name' in vnfd
else '-'
508 onb_state
= vnfd
['_admin'].get('onboardingState','-')
509 op_state
= vnfd
['_admin'].get('operationalState','-')
510 vendor
= vnfd
.get('vendor')
511 version
= vnfd
.get('version')
512 usage_state
= vnfd
['_admin'].get('usageState','-')
513 date
= datetime
.fromtimestamp(vnfd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
514 last_update
= datetime
.fromtimestamp(vnfd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
515 table
.add_row([name
, vnfd
['_id'], vendor
, version
, onb_state
, op_state
, usage_state
, date
, last_update
])
517 table
.add_row([name
, vnfd
['_id']])
519 table
= PrettyTable(['nfpkg name', 'id'])
521 table
.add_row([vnfd
['name'], vnfd
['id']])
526 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
527 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
528 @click.option('--filter', default
=None, multiple
=True,
529 help='restricts the list to the NF pkg matching the filter')
530 @click.option('--long', is_flag
=True, help='get more details')
532 def vnfd_list1(ctx
, nf_type
, filter, long):
533 """list all xNF packages (VNF, HNF, PNF)"""
535 vnfd_list(ctx
, nf_type
, filter, long)
538 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
539 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
540 @click.option('--filter', default
=None, multiple
=True,
541 help='restricts the list to the NFpkg matching the filter')
542 @click.option('--long', is_flag
=True, help='get more details')
544 def vnfd_list2(ctx
, nf_type
, filter, long):
545 """list all xNF packages (VNF, HNF, PNF)"""
547 vnfd_list(ctx
, nf_type
, filter, long)
550 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
551 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
552 @click.option('--filter', default
=None, multiple
=True,
553 help='restricts the list to the NFpkg matching the filter')
554 @click.option('--long', is_flag
=True, help='get more details')
556 def nfpkg_list(ctx
, nf_type
, filter, long):
557 """list all xNF packages (VNF, HNF, PNF)"""
560 check_client_version(ctx
.obj
, ctx
.command
.name
)
561 vnfd_list(ctx
, nf_type
, filter, long)
562 # except ClientException as e:
567 def pkg_repo_list(ctx
, pkgtype
, filter, repo
, long):
569 filter='&'.join(filter)
570 resp
= ctx
.obj
.osmrepo
.pkg_list(pkgtype
, filter, repo
)
572 table
= PrettyTable(['nfpkg name', 'vendor', 'version', 'latest', 'description', 'repository'])
574 table
= PrettyTable(['nfpkg name', 'repository'])
576 name
= vnfd
.get('name', '-')
577 repository
= vnfd
.get('repository')
579 vendor
= vnfd
.get('vendor')
580 version
= vnfd
.get('version')
581 description
= vnfd
.get('description')
582 latest
= vnfd
.get('latest')
583 table
.add_row([name
, vendor
, version
, latest
, description
, repository
])
585 table
.add_row([name
, repository
])
590 @cli_osm.command(name
='vnfpkg-repo-list', short_help
='list all xNF from OSM repositories')
591 @click.option('--filter', default
=None, multiple
=True,
592 help='restricts the list to the NFpkg matching the filter')
593 @click.option('--repo', default
=None,
594 help='restricts the list to a particular OSM repository')
595 @click.option('--long', is_flag
=True, help='get more details')
597 def nfpkg_repo_list1(ctx
, filter, repo
, long):
598 """list xNF packages from OSM repositories"""
600 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
603 @cli_osm.command(name
='nfpkg-repo-list', short_help
='list all xNF from OSM repositories')
604 @click.option('--filter', default
=None, multiple
=True,
605 help='restricts the list to the NFpkg matching the filter')
606 @click.option('--repo', default
=None,
607 help='restricts the list to a particular OSM repository')
608 @click.option('--long', is_flag
=True, help='get more details')
610 def nfpkg_repo_list2(ctx
, filter, repo
, long):
611 """list xNF packages from OSM repositories"""
613 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
616 @cli_osm.command(name
='nsd-repo-list', short_help
='list all NS from OSM repositories')
617 @click.option('--filter', default
=None, multiple
=True,
618 help='restricts the list to the NS matching the filter')
619 @click.option('--repo', default
=None,
620 help='restricts the list to a particular OSM repository')
621 @click.option('--long', is_flag
=True, help='get more details')
623 def nspkg_repo_list(ctx
, filter, repo
, long):
624 """list xNF packages from OSM repositories"""
626 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
629 @cli_osm.command(name
='nspkg-repo-list', short_help
='list all NS from OSM repositories')
630 @click.option('--filter', default
=None, multiple
=True,
631 help='restricts the list to the NS matching the filter')
632 @click.option('--repo', default
=None,
633 help='restricts the list to a particular OSM repository')
634 @click.option('--long', is_flag
=True, help='get more details')
636 def nspkg_repo_list2(ctx
, filter, repo
, long):
637 """list xNF packages from OSM repositories"""
639 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
642 def vnf_list(ctx
, ns
, filter, long):
646 check_client_version(ctx
.obj
, '--ns')
648 filter='&'.join(filter)
649 check_client_version(ctx
.obj
, '--filter')
650 resp
= ctx
.obj
.vnf
.list(ns
, filter)
652 resp
= ctx
.obj
.vnf
.list()
653 # except ClientException as e:
656 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
657 if fullclassname
== 'osmclient.sol005.client.Client':
658 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
659 'vnfd name', 'vim account id', 'ip address']
661 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
662 'vnfd name', 'vim account id', 'ip address',
663 'date', 'last update']
664 table
= PrettyTable(field_names
)
666 name
= vnfr
['name'] if 'name' in vnfr
else '-'
667 new_row
= [vnfr
['_id'], name
, vnfr
['nsr-id-ref'],
668 vnfr
['member-vnf-index-ref'], vnfr
['vnfd-ref'],
669 vnfr
['vim-account-id'], vnfr
['ip-address']]
671 date
= datetime
.fromtimestamp(vnfr
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
672 last_update
= datetime
.fromtimestamp(vnfr
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
673 new_row
.extend([date
, last_update
])
674 table
.add_row(new_row
)
679 'operational status',
682 if 'mgmt-interface' not in vnfr
:
683 vnfr
['mgmt-interface'] = {}
684 vnfr
['mgmt-interface']['ip-address'] = None
688 vnfr
['operational-status'],
689 vnfr
['config-status']])
694 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
695 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
696 @click.option('--filter', default
=None, multiple
=True,
697 help='restricts the list to the NF instances matching the filter.')
698 @click.option('--long', is_flag
=True, help='get more details')
700 def vnf_list1(ctx
, ns
, filter, long):
701 """list all NF instances"""
703 vnf_list(ctx
, ns
, filter, long)
706 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
707 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
708 @click.option('--filter', default
=None, multiple
=True,
709 help='restricts the list to the NF instances matching the filter.')
710 @click.option('--long', is_flag
=True, help='get more details')
712 def nf_list(ctx
, ns
, filter, long):
713 """list all NF instances
717 --ns TEXT NS instance id or name to restrict the VNF list
718 --filter filterExpr Restricts the list to the VNF instances matching the filter
721 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
722 concatenated using the "&" character:
725 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
726 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
727 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
729 value := scalar value
733 * zero or more occurrences
734 ? zero or one occurrence
735 [] grouping of expressions to be used with ? and *
736 "" quotation marks for marking string constants
740 "AttrName" is the name of one attribute in the data type that defines the representation
741 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
742 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
743 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
744 entries, it means that the operator "op" is applied to the attribute addressed by the last
745 <attrName> entry included in the concatenation. All simple filter expressions are combined
746 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
747 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
748 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
749 prefix". If an attribute referenced in an expression is an array, an object that contains a
750 corresponding array shall be considered to match the expression if any of the elements in the
751 array matches all expressions that have the same attribute prefix.
755 --filter vim-account-id=<VIM_ACCOUNT_ID>
756 --filter vnfd-ref=<VNFD_NAME>
757 --filter vdur.ip-address=<IP_ADDRESS>
758 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
761 vnf_list(ctx
, ns
, filter, long)
764 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
765 @click.argument('name')
766 @click.option('--long', is_flag
=True,
767 help='get more details of the NS operation (date, ).')
769 def ns_op_list(ctx
, name
, long):
770 """shows the history of operations over a NS instance
772 NAME: name or ID of the NS instance
774 def formatParams(params
):
775 if params
['lcmOperationType']=='instantiate':
776 params
.pop('nsDescription')
780 elif params
['lcmOperationType']=='action':
781 params
.pop('primitive')
782 params
.pop('lcmOperationType')
783 params
.pop('nsInstanceId')
788 check_client_version(ctx
.obj
, ctx
.command
.name
)
789 resp
= ctx
.obj
.ns
.list_op(name
)
790 # except ClientException as e:
795 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
797 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
799 #print(yaml.safe_dump(resp))
802 if op
['lcmOperationType']=='action':
803 action_name
= op
['operationParams']['primitive']
805 if op
['operationState'] == 'PROCESSING':
806 if op
['queuePosition'] is not None and op
['queuePosition'] > 0:
807 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
808 elif op
['lcmOperationType'] in ('instantiate', 'terminate'):
811 elif op
['operationState'] in ('FAILED', 'FAILED_TEMP'):
812 detail
= op
.get('errorMessage','-')
813 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
814 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
816 table
.add_row([op
['id'],
817 op
['lcmOperationType'],
819 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
820 op
['operationState'],
823 wrap_text(text
=detail
,width
=50)])
825 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
826 op
['operationState'], date
, wrap_text(text
=detail
or "",width
=50)])
831 def nsi_list(ctx
, filter):
832 """list all Network Slice Instances"""
835 check_client_version(ctx
.obj
, ctx
.command
.name
)
837 filter='&'.join(filter)
838 resp
= ctx
.obj
.nsi
.list(filter)
839 # except ClientException as e:
843 ['netslice instance name',
845 'operational status',
849 nsi_name
= nsi
['name']
851 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
852 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
853 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
854 if configstatus
== "config_not_needed":
855 configstatus
= "configured (no charms)"
866 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
867 @click.option('--filter', default
=None, multiple
=True,
868 help='restricts the list to the Network Slice Instances matching the filter')
870 def nsi_list1(ctx
, filter):
871 """list all Network Slice Instances (NSI)"""
873 nsi_list(ctx
, filter)
876 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
877 @click.option('--filter', default
=None, multiple
=True,
878 help='restricts the list to the Network Slice Instances matching the filter')
880 def nsi_list2(ctx
, filter):
881 """list all Network Slice Instances (NSI)"""
883 nsi_list(ctx
, filter)
886 def nst_list(ctx
, filter):
889 check_client_version(ctx
.obj
, ctx
.command
.name
)
891 filter='&'.join(filter)
892 resp
= ctx
.obj
.nst
.list(filter)
893 # except ClientException as e:
896 # print(yaml.safe_dump(resp))
897 table
= PrettyTable(['nst name', 'id'])
899 name
= nst
['name'] if 'name' in nst
else '-'
900 table
.add_row([name
, nst
['_id']])
905 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
906 @click.option('--filter', default
=None, multiple
=True,
907 help='restricts the list to the NST matching the filter')
909 def nst_list1(ctx
, filter):
910 """list all Network Slice Templates (NST) in the system"""
912 nst_list(ctx
, filter)
915 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
916 @click.option('--filter', default
=None, multiple
=True,
917 help='restricts the list to the NST matching the filter')
919 def nst_list2(ctx
, filter):
920 """list all Network Slice Templates (NST) in the system"""
922 nst_list(ctx
, filter)
925 def nsi_op_list(ctx
, name
):
928 check_client_version(ctx
.obj
, ctx
.command
.name
)
929 resp
= ctx
.obj
.nsi
.list_op(name
)
930 # except ClientException as e:
933 table
= PrettyTable(['id', 'operation', 'status'])
935 table
.add_row([op
['id'], op
['lcmOperationType'],
936 op
['operationState']])
941 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
942 @click.argument('name')
944 def nsi_op_list1(ctx
, name
):
945 """shows the history of operations over a Network Slice Instance (NSI)
947 NAME: name or ID of the Network Slice Instance
950 nsi_op_list(ctx
, name
)
953 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
954 @click.argument('name')
956 def nsi_op_list2(ctx
, name
):
957 """shows the history of operations over a Network Slice Instance (NSI)
959 NAME: name or ID of the Network Slice Instance
962 nsi_op_list(ctx
, name
)
965 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
966 @click.option('--filter', default
=None, multiple
=True,
967 help='restricts the list to the Physical Deployment Units matching the filter')
969 def pdu_list(ctx
, filter):
970 """list all Physical Deployment Units (PDU)"""
973 check_client_version(ctx
.obj
, ctx
.command
.name
)
975 filter='&'.join(filter)
976 resp
= ctx
.obj
.pdu
.list(filter)
977 # except ClientException as e:
986 pdu_name
= pdu
['name']
988 pdu_type
= pdu
['type']
989 pdu_ipaddress
= "None"
990 for iface
in pdu
['interfaces']:
992 pdu_ipaddress
= iface
['ip-address']
1003 ####################
1005 ####################
1007 def nsd_show(ctx
, name
, literal
):
1010 resp
= ctx
.obj
.nsd
.get(name
)
1011 # resp = ctx.obj.nsd.get_individual(name)
1012 # except ClientException as e:
1017 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1020 table
= PrettyTable(['field', 'value'])
1021 for k
, v
in list(resp
.items()):
1022 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1027 @cli_osm.command(name
='nsd-show', short_help
='shows the details of a NS package')
1028 @click.option('--literal', is_flag
=True,
1029 help='print literally, no pretty table')
1030 @click.argument('name')
1032 def nsd_show1(ctx
, name
, literal
):
1033 """shows the content of a NSD
1035 NAME: name or ID of the NSD/NSpkg
1038 nsd_show(ctx
, name
, literal
)
1041 @cli_osm.command(name
='nspkg-show', short_help
='shows the details of a NS package')
1042 @click.option('--literal', is_flag
=True,
1043 help='print literally, no pretty table')
1044 @click.argument('name')
1046 def nsd_show2(ctx
, name
, literal
):
1047 """shows the content of a NSD
1049 NAME: name or ID of the NSD/NSpkg
1052 nsd_show(ctx
, name
, literal
)
1055 def vnfd_show(ctx
, name
, literal
):
1058 resp
= ctx
.obj
.vnfd
.get(name
)
1059 # resp = ctx.obj.vnfd.get_individual(name)
1060 # except ClientException as e:
1065 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1068 table
= PrettyTable(['field', 'value'])
1069 for k
, v
in list(resp
.items()):
1070 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1075 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1078 filter='&'.join(filter)
1080 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1083 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1086 catalog
= pkgtype
+ '-catalog'
1087 full_catalog
= pkgtype
+ ':' + catalog
1088 if resp
.get(catalog
):
1089 resp
= resp
.pop(catalog
)[pkgtype
][0]
1090 elif resp
.get(full_catalog
):
1091 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1093 table
= PrettyTable(['field', 'value'])
1094 for k
, v
in list(resp
.items()):
1095 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1100 @cli_osm.command(name
='vnfd-show', short_help
='shows the details of a NF package')
1101 @click.option('--literal', is_flag
=True,
1102 help='print literally, no pretty table')
1103 @click.argument('name')
1105 def vnfd_show1(ctx
, name
, literal
):
1106 """shows the content of a VNFD
1108 NAME: name or ID of the VNFD/VNFpkg
1111 vnfd_show(ctx
, name
, literal
)
1114 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the details of a NF package')
1115 @click.option('--literal', is_flag
=True,
1116 help='print literally, no pretty table')
1117 @click.argument('name')
1119 def vnfd_show2(ctx
, name
, literal
):
1120 """shows the content of a VNFD
1122 NAME: name or ID of the VNFD/VNFpkg
1125 vnfd_show(ctx
, name
, literal
)
1128 @cli_osm.command(name
='vnfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1129 @click.option('--literal', is_flag
=True,
1130 help='print literally, no pretty table')
1131 @click.option('--repo',
1133 help='Repository name')
1134 @click.argument('name')
1135 @click.option('--filter', default
=None, multiple
=True,
1136 help='filter by fields')
1137 @click.option('--version',
1139 help='package version')
1141 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1142 """shows the content of a VNFD in a repository
1144 NAME: name or ID of the VNFD/VNFpkg
1147 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1150 @cli_osm.command(name
='nsd-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1151 @click.option('--literal', is_flag
=True,
1152 help='print literally, no pretty table')
1153 @click.option('--repo',
1155 help='Repository name')
1156 @click.argument('name')
1157 @click.option('--filter', default
=None, multiple
=True,
1158 help='filter by fields')
1159 @click.option('--version',
1161 help='package version')
1163 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1164 """shows the content of a VNFD in a repository
1166 NAME: name or ID of the VNFD/VNFpkg
1169 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1172 @cli_osm.command(name
='nspkg-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1173 @click.option('--literal', is_flag
=True,
1174 help='print literally, no pretty table')
1175 @click.option('--repo',
1177 help='Repository name')
1178 @click.argument('name')
1179 @click.option('--filter', default
=None, multiple
=True,
1180 help='filter by fields')
1181 @click.option('--version',
1183 help='package version')
1185 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1186 """shows the content of a VNFD in a repository
1188 NAME: name or ID of the VNFD/VNFpkg
1191 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1194 @cli_osm.command(name
='nfpkg-show', short_help
='shows the details of a NF package')
1195 @click.option('--literal', is_flag
=True,
1196 help='print literally, no pretty table')
1197 @click.argument('name')
1199 def nfpkg_show(ctx
, name
, literal
):
1200 """shows the content of a NF Descriptor
1202 NAME: name or ID of the NFpkg
1205 vnfd_show(ctx
, name
, literal
)
1208 @cli_osm.command(name
='nfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1209 @click.option('--literal', is_flag
=True,
1210 help='print literally, no pretty table')
1211 @click.option('--repo',
1213 help='Repository name')
1214 @click.argument('name')
1215 @click.option('--filter', default
=None, multiple
=True,
1216 help='filter by fields')
1217 @click.option('--version',
1219 help='package version')
1221 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1222 """shows the content of a VNFD in a repository
1224 NAME: name or ID of the VNFD/VNFpkg
1227 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1230 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
1231 @click.argument('name')
1232 @click.option('--literal', is_flag
=True,
1233 help='print literally, no pretty table')
1234 @click.option('--filter', multiple
=True,
1235 help='restricts the information to the fields in the filter')
1237 def ns_show(ctx
, name
, literal
, filter):
1238 """shows the info of a NS instance
1240 NAME: name or ID of the NS instance
1244 ns
= ctx
.obj
.ns
.get(name
)
1245 # except ClientException as e:
1250 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1253 table
= PrettyTable(['field', 'value'])
1255 for k
, v
in list(ns
.items()):
1256 if not filter or k
in filter:
1257 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1259 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1260 if fullclassname
!= 'osmclient.sol005.client.Client':
1261 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1262 nsr_optdata
= nsopdata
['nsr:nsr']
1263 for k
, v
in list(nsr_optdata
.items()):
1264 if not filter or k
in filter:
1265 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1270 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1271 @click.argument('name')
1272 @click.option('--literal', is_flag
=True,
1273 help='print literally, no pretty table')
1274 @click.option('--filter', multiple
=True,
1275 help='restricts the information to the fields in the filter')
1276 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1278 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1279 """shows the info of a VNF instance
1281 NAME: name or ID of the VNF instance
1283 def print_kdu_status(op_info_status
):
1284 """print KDU status properly formatted
1287 op_status
= yaml
.safe_load(op_info_status
)
1288 if "namespace" in op_status
and "info" in op_status
and \
1289 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1290 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1291 "seconds" in op_status
["info"]["last_deployed"]:
1292 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1293 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1294 print("NAMESPACE: {}".format(op_status
["namespace"]))
1295 status_code
= "UNKNOWN"
1296 if op_status
["info"]["status"]["code"]==1:
1297 status_code
= "DEPLOYED"
1298 print("STATUS: {}".format(status_code
))
1301 print(op_status
["info"]["status"]["resources"])
1302 if "notes" in op_status
["info"]["status"]:
1304 print(op_status
["info"]["status"]["notes"])
1306 print(op_info_status
)
1308 print(op_info_status
)
1313 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1315 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1318 check_client_version(ctx
.obj
, ctx
.command
.name
)
1319 resp
= ctx
.obj
.vnf
.get(name
)
1322 ns_id
= resp
['nsr-id-ref']
1324 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1325 op_data
['kdu_name'] = kdu
1326 op_data
['primitive'] = 'status'
1327 op_data
['primitive_params'] = {}
1328 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1331 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1332 if op_info
['operationState'] == 'COMPLETED':
1333 print_kdu_status(op_info
['detailed-status'])
1337 print ("Could not determine KDU status")
1341 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1344 table
= PrettyTable(['field', 'value'])
1346 for k
, v
in list(resp
.items()):
1347 if not filter or k
in filter:
1348 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1351 # except ClientException as e:
1356 #@cli_osm.command(name='vnf-monitoring-show')
1357 #@click.argument('vnf_name')
1358 #@click.pass_context
1359 #def vnf_monitoring_show(ctx, vnf_name):
1361 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1362 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1363 # except ClientException as e:
1367 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1368 # if resp is not None:
1369 # for monitor in resp:
1373 # monitor['value-integer'],
1374 # monitor['units']])
1379 #@cli_osm.command(name='ns-monitoring-show')
1380 #@click.argument('ns_name')
1381 #@click.pass_context
1382 #def ns_monitoring_show(ctx, ns_name):
1384 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1385 # resp = ctx.obj.ns.get_monitoring(ns_name)
1386 # except ClientException as e:
1390 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1391 # for key, val in list(resp.items()):
1392 # for monitor in val:
1396 # monitor['value-integer'],
1397 # monitor['units']])
1402 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1403 @click.argument('id')
1404 @click.option('--filter', multiple
=True,
1405 help='restricts the information to the fields in the filter')
1406 @click.option('--literal', is_flag
=True,
1407 help='print literally, no pretty table')
1409 def ns_op_show(ctx
, id, filter, literal
):
1410 """shows the detailed info of a NS operation
1412 ID: operation identifier
1416 check_client_version(ctx
.obj
, ctx
.command
.name
)
1417 op_info
= ctx
.obj
.ns
.get_op(id)
1418 # except ClientException as e:
1423 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1426 table
= PrettyTable(['field', 'value'])
1427 for k
, v
in list(op_info
.items()):
1428 if not filter or k
in filter:
1429 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1434 def nst_show(ctx
, name
, literal
):
1437 check_client_version(ctx
.obj
, ctx
.command
.name
)
1438 resp
= ctx
.obj
.nst
.get(name
)
1439 #resp = ctx.obj.nst.get_individual(name)
1440 # except ClientException as e:
1445 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1448 table
= PrettyTable(['field', 'value'])
1449 for k
, v
in list(resp
.items()):
1450 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1455 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1456 @click.option('--literal', is_flag
=True,
1457 help='print literally, no pretty table')
1458 @click.argument('name')
1460 def nst_show1(ctx
, name
, literal
):
1461 """shows the content of a Network Slice Template (NST)
1463 NAME: name or ID of the NST
1466 nst_show(ctx
, name
, literal
)
1469 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1470 @click.option('--literal', is_flag
=True,
1471 help='print literally, no pretty table')
1472 @click.argument('name')
1474 def nst_show2(ctx
, name
, literal
):
1475 """shows the content of a Network Slice Template (NST)
1477 NAME: name or ID of the NST
1480 nst_show(ctx
, name
, literal
)
1483 def nsi_show(ctx
, name
, literal
, filter):
1486 check_client_version(ctx
.obj
, ctx
.command
.name
)
1487 nsi
= ctx
.obj
.nsi
.get(name
)
1488 # except ClientException as e:
1493 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1496 table
= PrettyTable(['field', 'value'])
1498 for k
, v
in list(nsi
.items()):
1499 if not filter or k
in filter:
1500 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1506 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1507 @click.argument('name')
1508 @click.option('--literal', is_flag
=True,
1509 help='print literally, no pretty table')
1510 @click.option('--filter', multiple
=True,
1511 help='restricts the information to the fields in the filter')
1513 def nsi_show1(ctx
, name
, literal
, filter):
1514 """shows the content of a Network Slice Instance (NSI)
1516 NAME: name or ID of the Network Slice Instance
1519 nsi_show(ctx
, name
, literal
, filter)
1522 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1523 @click.argument('name')
1524 @click.option('--literal', is_flag
=True,
1525 help='print literally, no pretty table')
1526 @click.option('--filter', multiple
=True,
1527 help='restricts the information to the fields in the filter')
1529 def nsi_show2(ctx
, name
, literal
, filter):
1530 """shows the content of a Network Slice Instance (NSI)
1532 NAME: name or ID of the Network Slice Instance
1535 nsi_show(ctx
, name
, literal
, filter)
1538 def nsi_op_show(ctx
, id, filter):
1541 check_client_version(ctx
.obj
, ctx
.command
.name
)
1542 op_info
= ctx
.obj
.nsi
.get_op(id)
1543 # except ClientException as e:
1547 table
= PrettyTable(['field', 'value'])
1548 for k
, v
in list(op_info
.items()):
1549 if not filter or k
in filter:
1550 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1555 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1556 @click.argument('id')
1557 @click.option('--filter', multiple
=True,
1558 help='restricts the information to the fields in the filter')
1560 def nsi_op_show1(ctx
, id, filter):
1561 """shows the info of an operation over a Network Slice Instance(NSI)
1563 ID: operation identifier
1566 nsi_op_show(ctx
, id, filter)
1569 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1570 @click.argument('id')
1571 @click.option('--filter', multiple
=True,
1572 help='restricts the information to the fields in the filter')
1574 def nsi_op_show2(ctx
, id, filter):
1575 """shows the info of an operation over a Network Slice Instance(NSI)
1577 ID: operation identifier
1580 nsi_op_show(ctx
, id, filter)
1583 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1584 @click.argument('name')
1585 @click.option('--literal', is_flag
=True,
1586 help='print literally, no pretty table')
1587 @click.option('--filter', multiple
=True,
1588 help='restricts the information to the fields in the filter')
1590 def pdu_show(ctx
, name
, literal
, filter):
1591 """shows the content of a Physical Deployment Unit (PDU)
1593 NAME: name or ID of the PDU
1597 check_client_version(ctx
.obj
, ctx
.command
.name
)
1598 pdu
= ctx
.obj
.pdu
.get(name
)
1599 # except ClientException as e:
1604 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1607 table
= PrettyTable(['field', 'value'])
1609 for k
, v
in list(pdu
.items()):
1610 if not filter or k
in filter:
1611 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1617 ####################
1619 ####################
1621 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1624 check_client_version(ctx
.obj
, ctx
.command
.name
)
1626 filename
= ctx
.obj
.osmrepo
.get_pkg('ns', filename
, repo
, vendor
, version
)
1627 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1628 # except ClientException as e:
1633 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1634 @click.argument('filename')
1635 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1636 help='Deprecated. Use override')
1637 @click.option('--override', 'overwrite', default
=None,
1638 help='overrides fields in descriptor, format: '
1639 '"key1.key2...=value[;key3...=value;...]"')
1640 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1641 help='The charm will not be compiled, it is assumed to already exist')
1642 @click.option('--repo', default
=None,
1643 help='[repository]: Repository name')
1644 @click.option('--vendor', default
=None,
1645 help='[repository]: filter by vendor]')
1646 @click.option('--version', default
='latest',
1647 help='[repository]: filter by version. Default: latest')
1649 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1650 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1653 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1654 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1655 If FILENAME is an NF Package folder, it is built and then onboarded.
1658 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1662 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1663 @click.argument('filename')
1664 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1665 help='Deprecated. Use override')
1666 @click.option('--override', 'overwrite', default
=None,
1667 help='overrides fields in descriptor, format: '
1668 '"key1.key2...=value[;key3...=value;...]"')
1669 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1670 help='The charm will not be compiled, it is assumed to already exist')
1671 @click.option('--repo', default
=None,
1672 help='[repository]: Repository name')
1673 @click.option('--vendor', default
=None,
1674 help='[repository]: filter by vendor]')
1675 @click.option('--version', default
='latest',
1676 help='[repository]: filter by version. Default: latest')
1678 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1679 """onboards a new NSpkg
1681 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1682 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1683 If FILENAME is an NF Package folder, it is built and then onboarded.
1686 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1690 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1691 repo
, vendor
, version
):
1694 check_client_version(ctx
.obj
, ctx
.command
.name
)
1696 filename
= ctx
.obj
.osmrepo
.get_pkg('vnf', filename
, repo
, vendor
, version
)
1697 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1698 override_epa
=override_epa
, override_nonepa
=override_nonepa
,
1699 override_paravirt
=override_paravirt
)
1700 # except ClientException as e:
1705 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1706 @click.argument('filename')
1707 @click.option('--overwrite', 'overwrite', default
=None,
1708 help='overwrite deprecated, use override')
1709 @click.option('--override', 'overwrite', default
=None,
1710 help='overrides fields in descriptor, format: '
1711 '"key1.key2...=value[;key3...=value;...]"')
1712 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1713 help='The charm will not be compiled, it is assumed to already exist')
1714 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1715 help='adds guest-epa parameters to all VDU')
1716 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1717 help='removes all guest-epa parameters from all VDU')
1718 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1719 help='overrides all VDU interfaces to PARAVIRT')
1720 @click.option('--repo', default
=None,
1721 help='[repository]: Repository name')
1722 @click.option('--vendor', default
=None,
1723 help='[repository]: filter by vendor]')
1724 @click.option('--version', default
='latest',
1725 help='[repository]: filter by version. Default: latest')
1727 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1728 repo
,vendor
, version
):
1729 """creates a new VNFD/VNFpkg
1731 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1732 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1733 If FILENAME is an NF Package folder, it is built and then onboarded.
1736 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1737 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1738 repo
=repo
, vendor
=vendor
, version
=version
)
1741 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1742 @click.argument('filename')
1743 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1744 help='Deprecated. Use override')
1745 @click.option('--override', 'overwrite', default
=None,
1746 help='overrides fields in descriptor, format: '
1747 '"key1.key2...=value[;key3...=value;...]"')
1748 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1749 help='The charm will not be compiled, it is assumed to already exist')
1750 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1751 help='adds guest-epa parameters to all VDU')
1752 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1753 help='removes all guest-epa parameters from all VDU')
1754 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1755 help='overrides all VDU interfaces to PARAVIRT')
1756 @click.option('--repo', default
=None,
1757 help='[repository]: Repository name')
1758 @click.option('--vendor', default
=None,
1759 help='[repository]: filter by vendor]')
1760 @click.option('--version', default
='latest',
1761 help='[repository]: filter by version. Default: latest')
1763 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1764 repo
, vendor
, version
):
1765 """creates a new VNFD/VNFpkg
1767 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1768 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1769 If FILENAME is an NF Package folder, it is built and then onboarded.
1772 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1773 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1774 repo
=repo
, vendor
=vendor
, version
=version
)
1776 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1777 @click.argument('filename')
1778 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1779 help='Deprecated. Use override')
1780 @click.option('--override', 'overwrite', default
=None,
1781 help='overrides fields in descriptor, format: '
1782 '"key1.key2...=value[;key3...=value;...]"')
1783 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1784 help='The charm will not be compiled, it is assumed to already exist')
1785 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1786 help='adds guest-epa parameters to all VDU')
1787 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1788 help='removes all guest-epa parameters from all VDU')
1789 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1790 help='overrides all VDU interfaces to PARAVIRT')
1791 @click.option('--repo', default
=None,
1792 help='[repository]: Repository name')
1793 @click.option('--vendor', default
=None,
1794 help='[repository]: filter by vendor]')
1795 @click.option('--version', default
='latest',
1796 help='[repository]: filter by version. Default: latest')
1798 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1799 repo
, vendor
, version
):
1800 """creates a new NFpkg
1803 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1804 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1805 If FILENAME is an NF Package folder, it is built and then onboarded.
1808 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1809 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1810 repo
=repo
, vendor
=vendor
, version
=version
)
1813 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1814 @click.option('--ns_name',
1815 prompt
=True, help='name of the NS instance')
1816 @click.option('--nsd_name',
1817 prompt
=True, help='name of the NS descriptor')
1818 @click.option('--vim_account',
1819 prompt
=True, help='default VIM account id or name for the deployment')
1820 @click.option('--admin_status',
1822 help='administration status')
1823 @click.option('--ssh_keys',
1825 help='comma separated list of public key files to inject to vnfs')
1826 @click.option('--config',
1828 help='ns specific yaml configuration')
1829 @click.option('--config_file',
1831 help='ns specific yaml configuration file')
1832 @click.option('--wait',
1836 help='do not return the control immediately, but keep it '
1837 'until the operation is completed, or timeout')
1848 """creates a new NS instance"""
1852 check_client_version(ctx
.obj
, '--config_file')
1854 raise ClientException('"--config" option is incompatible with "--config_file" option')
1855 with
open(config_file
, 'r') as cf
:
1862 account
=vim_account
,
1864 # except ClientException as e:
1869 def nst_create(ctx
, filename
, overwrite
):
1872 check_client_version(ctx
.obj
, ctx
.command
.name
)
1873 ctx
.obj
.nst
.create(filename
, overwrite
)
1874 # except ClientException as e:
1879 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1880 @click.argument('filename')
1881 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1882 help='Deprecated. Use override')
1883 @click.option('--override', 'overwrite', default
=None,
1884 help='overrides fields in descriptor, format: '
1885 '"key1.key2...=value[;key3...=value;...]"')
1887 def nst_create1(ctx
, filename
, overwrite
):
1888 """creates a new Network Slice Template (NST)
1890 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1893 nst_create(ctx
, filename
, overwrite
)
1896 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1897 @click.argument('filename')
1898 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1899 help='Deprecated. Use override')
1900 @click.option('--override', 'overwrite', default
=None,
1901 help='overrides fields in descriptor, format: '
1902 '"key1.key2...=value[;key3...=value;...]"')
1904 def nst_create2(ctx
, filename
, overwrite
):
1905 """creates a new Network Slice Template (NST)
1907 FILENAME: NST yaml file or NSTpkg tar.gz file
1910 nst_create(ctx
, filename
, overwrite
)
1913 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1914 """creates a new Network Slice Instance (NSI)"""
1917 check_client_version(ctx
.obj
, ctx
.command
.name
)
1920 raise ClientException('"--config" option is incompatible with "--config_file" option')
1921 with
open(config_file
, 'r') as cf
:
1923 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1924 account
=vim_account
, wait
=wait
)
1925 # except ClientException as e:
1930 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1931 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1932 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1933 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1934 @click.option('--ssh_keys', default
=None,
1935 help='comma separated list of keys to inject to vnfs')
1936 @click.option('--config', default
=None,
1937 help='Netslice specific yaml configuration:\n'
1938 'netslice_subnet: [\n'
1939 'id: TEXT, vim_account: TEXT,\n'
1940 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1941 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1942 'additionalParamsForNsi: {param: value, ...}\n'
1943 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1945 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1947 @click.option('--config_file',
1949 help='nsi specific yaml configuration file')
1950 @click.option('--wait',
1954 help='do not return the control immediately, but keep it '
1955 'until the operation is completed, or timeout')
1957 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1958 """creates a new Network Slice Instance (NSI)"""
1960 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1963 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1964 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1965 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1966 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1967 @click.option('--ssh_keys', default
=None,
1968 help='comma separated list of keys to inject to vnfs')
1969 @click.option('--config', default
=None,
1970 help='Netslice specific yaml configuration:\n'
1971 'netslice_subnet: [\n'
1972 'id: TEXT, vim_account: TEXT,\n'
1973 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1974 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1976 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1978 @click.option('--config_file',
1980 help='nsi specific yaml configuration file')
1981 @click.option('--wait',
1985 help='do not return the control immediately, but keep it '
1986 'until the operation is completed, or timeout')
1988 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1989 """creates a new Network Slice Instance (NSI)"""
1991 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1994 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1995 @click.option('--name', help='name of the Physical Deployment Unit')
1996 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1997 @click.option('--interface',
1998 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1999 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
2001 @click.option('--description', help='human readable description')
2002 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
2003 @click.option('--descriptor_file', default
=None,
2004 help='PDU descriptor file (as an alternative to using the other arguments')
2006 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
2007 """creates a new Physical Deployment Unit (PDU)"""
2010 check_client_version(ctx
.obj
, ctx
.command
.name
)
2012 if not descriptor_file
:
2014 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
2016 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
2018 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
2020 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
2022 with
open(descriptor_file
, 'r') as df
:
2023 pdu
= yaml
.safe_load(df
.read())
2024 if name
: pdu
["name"] = name
2025 if pdu_type
: pdu
["type"] = pdu_type
2026 if description
: pdu
["description"] = description
2027 if vim_account
: pdu
["vim_accounts"] = vim_account
2030 for iface
in interface
:
2031 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
2032 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
2033 ifaces_list
.append(new_iface
)
2034 pdu
["interfaces"] = ifaces_list
2035 ctx
.obj
.pdu
.create(pdu
)
2036 # except ClientException as e:
2041 ####################
2043 ####################
2045 def nsd_update(ctx
, name
, content
):
2048 check_client_version(ctx
.obj
, ctx
.command
.name
)
2049 ctx
.obj
.nsd
.update(name
, content
)
2050 # except ClientException as e:
2055 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
2056 @click.argument('name')
2057 @click.option('--content', default
=None,
2058 help='filename with the NSD/NSpkg replacing the current one')
2060 def nsd_update1(ctx
, name
, content
):
2061 """updates a NSD/NSpkg
2063 NAME: name or ID of the NSD/NSpkg
2066 nsd_update(ctx
, name
, content
)
2069 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
2070 @click.argument('name')
2071 @click.option('--content', default
=None,
2072 help='filename with the NSD/NSpkg replacing the current one')
2074 def nsd_update2(ctx
, name
, content
):
2075 """updates a NSD/NSpkg
2077 NAME: name or ID of the NSD/NSpkg
2080 nsd_update(ctx
, name
, content
)
2083 def vnfd_update(ctx
, name
, content
):
2086 check_client_version(ctx
.obj
, ctx
.command
.name
)
2087 ctx
.obj
.vnfd
.update(name
, content
)
2088 # except ClientException as e:
2093 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
2094 @click.argument('name')
2095 @click.option('--content', default
=None,
2096 help='filename with the VNFD/VNFpkg replacing the current one')
2098 def vnfd_update1(ctx
, name
, content
):
2099 """updates a VNFD/VNFpkg
2101 NAME: name or ID of the VNFD/VNFpkg
2104 vnfd_update(ctx
, name
, content
)
2107 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
2108 @click.argument('name')
2109 @click.option('--content', default
=None,
2110 help='filename with the VNFD/VNFpkg replacing the current one')
2112 def vnfd_update2(ctx
, name
, content
):
2113 """updates a VNFD/VNFpkg
2115 NAME: VNFD yaml file or VNFpkg tar.gz file
2118 vnfd_update(ctx
, name
, content
)
2121 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
2122 @click.argument('name')
2123 @click.option('--content', default
=None,
2124 help='filename with the NFpkg replacing the current one')
2126 def nfpkg_update(ctx
, name
, content
):
2129 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2132 vnfd_update(ctx
, name
, content
)
2135 def nst_update(ctx
, name
, content
):
2138 check_client_version(ctx
.obj
, ctx
.command
.name
)
2139 ctx
.obj
.nst
.update(name
, content
)
2140 # except ClientException as e:
2145 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
2146 @click.argument('name')
2147 @click.option('--content', default
=None,
2148 help='filename with the NST/NSTpkg replacing the current one')
2150 def nst_update1(ctx
, name
, content
):
2151 """updates a Network Slice Template (NST)
2153 NAME: name or ID of the NSD/NSpkg
2156 nst_update(ctx
, name
, content
)
2159 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
2160 @click.argument('name')
2161 @click.option('--content', default
=None,
2162 help='filename with the NST/NSTpkg replacing the current one')
2164 def nst_update2(ctx
, name
, content
):
2165 """updates a Network Slice Template (NST)
2167 NAME: name or ID of the NSD/NSpkg
2170 nst_update(ctx
, name
, content
)
2173 ####################
2175 ####################
2177 def nsd_delete(ctx
, name
, force
):
2181 ctx
.obj
.nsd
.delete(name
)
2183 check_client_version(ctx
.obj
, '--force')
2184 ctx
.obj
.nsd
.delete(name
, force
)
2185 # except ClientException as e:
2190 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
2191 @click.argument('name')
2192 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2194 def nsd_delete1(ctx
, name
, force
):
2195 """deletes a NSD/NSpkg
2197 NAME: name or ID of the NSD/NSpkg to be deleted
2200 nsd_delete(ctx
, name
, force
)
2203 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
2204 @click.argument('name')
2205 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2207 def nsd_delete2(ctx
, name
, force
):
2208 """deletes a NSD/NSpkg
2210 NAME: name or ID of the NSD/NSpkg to be deleted
2213 nsd_delete(ctx
, name
, force
)
2216 def vnfd_delete(ctx
, name
, force
):
2220 ctx
.obj
.vnfd
.delete(name
)
2222 check_client_version(ctx
.obj
, '--force')
2223 ctx
.obj
.vnfd
.delete(name
, force
)
2224 # except ClientException as e:
2229 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
2230 @click.argument('name')
2231 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2233 def vnfd_delete1(ctx
, name
, force
):
2234 """deletes a VNFD/VNFpkg
2236 NAME: name or ID of the VNFD/VNFpkg to be deleted
2239 vnfd_delete(ctx
, name
, force
)
2242 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
2243 @click.argument('name')
2244 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2246 def vnfd_delete2(ctx
, name
, force
):
2247 """deletes a VNFD/VNFpkg
2249 NAME: name or ID of the VNFD/VNFpkg to be deleted
2252 vnfd_delete(ctx
, name
, force
)
2255 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
2256 @click.argument('name')
2257 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2259 def nfpkg_delete(ctx
, name
, force
):
2262 NAME: name or ID of the NFpkg to be deleted
2265 vnfd_delete(ctx
, name
, force
)
2268 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
2269 @click.argument('name')
2270 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2271 @click.option('--config', default
=None,
2272 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2273 "600, skip_terminate_primitives: True}'")
2274 @click.option('--wait',
2278 help='do not return the control immediately, but keep it '
2279 'until the operation is completed, or timeout')
2281 def ns_delete(ctx
, name
, force
, config
, wait
):
2282 """deletes a NS instance
2284 NAME: name or ID of the NS instance to be deleted
2289 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2291 check_client_version(ctx
.obj
, '--force')
2292 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2293 # except ClientException as e:
2298 def nst_delete(ctx
, name
, force
):
2301 check_client_version(ctx
.obj
, ctx
.command
.name
)
2302 ctx
.obj
.nst
.delete(name
, force
)
2303 # except ClientException as e:
2308 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
2309 @click.argument('name')
2310 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2312 def nst_delete1(ctx
, name
, force
):
2313 """deletes a Network Slice Template (NST)
2315 NAME: name or ID of the NST/NSTpkg to be deleted
2318 nst_delete(ctx
, name
, force
)
2321 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
2322 @click.argument('name')
2323 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2325 def nst_delete2(ctx
, name
, force
):
2326 """deletes a Network Slice Template (NST)
2328 NAME: name or ID of the NST/NSTpkg to be deleted
2331 nst_delete(ctx
, name
, force
)
2334 def nsi_delete(ctx
, name
, force
, wait
):
2337 check_client_version(ctx
.obj
, ctx
.command
.name
)
2338 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2339 # except ClientException as e:
2344 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2345 @click.argument('name')
2346 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2347 @click.option('--wait',
2351 help='do not return the control immediately, but keep it '
2352 'until the operation is completed, or timeout')
2354 def nsi_delete1(ctx
, name
, force
, wait
):
2355 """deletes a Network Slice Instance (NSI)
2357 NAME: name or ID of the Network Slice instance to be deleted
2360 nsi_delete(ctx
, name
, force
, wait
=wait
)
2363 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2364 @click.argument('name')
2365 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2367 def nsi_delete2(ctx
, name
, force
, wait
):
2368 """deletes a Network Slice Instance (NSI)
2370 NAME: name or ID of the Network Slice instance to be deleted
2373 nsi_delete(ctx
, name
, force
, wait
=wait
)
2376 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2377 @click.argument('name')
2378 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2380 def pdu_delete(ctx
, name
, force
):
2381 """deletes a Physical Deployment Unit (PDU)
2383 NAME: name or ID of the PDU to be deleted
2387 check_client_version(ctx
.obj
, ctx
.command
.name
)
2388 ctx
.obj
.pdu
.delete(name
, force
)
2389 # except ClientException as e:
2398 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2399 @click.option('--name',
2401 help='Name to create datacenter')
2402 @click.option('--user',
2404 help='VIM username')
2405 @click.option('--password',
2408 confirmation_prompt
=True,
2409 help='VIM password')
2410 @click.option('--auth_url',
2413 @click.option('--tenant',
2415 help='VIM tenant name')
2416 @click.option('--config',
2418 help='VIM specific config parameters')
2419 @click.option('--account_type',
2420 default
='openstack',
2422 @click.option('--description',
2424 help='human readable description')
2425 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2426 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2427 @click.option('--wait',
2431 help='do not return the control immediately, but keep it '
2432 'until the operation is completed, or timeout')
2446 """creates a new VIM account"""
2450 check_client_version(ctx
.obj
, '--sdn_controller')
2451 if sdn_port_mapping
:
2452 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2454 vim
['vim-username'] = user
2455 vim
['vim-password'] = password
2456 vim
['vim-url'] = auth_url
2457 vim
['vim-tenant-name'] = tenant
2458 vim
['vim-type'] = account_type
2459 vim
['description'] = description
2460 vim
['config'] = config
2461 if sdn_controller
or sdn_port_mapping
:
2462 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2464 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2465 # except ClientException as e:
2470 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2471 @click.argument('name')
2472 @click.option('--newname', help='New name for the VIM account')
2473 @click.option('--user', help='VIM username')
2474 @click.option('--password', help='VIM password')
2475 @click.option('--auth_url', help='VIM url')
2476 @click.option('--tenant', help='VIM tenant name')
2477 @click.option('--config', help='VIM specific config parameters')
2478 @click.option('--account_type', help='VIM type')
2479 @click.option('--description', help='human readable description')
2480 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller to be associated with this VIM'
2481 'account. Use empty string to disassociate')
2482 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2483 @click.option('--wait',
2487 help='do not return the control immediately, but keep it '
2488 'until the operation is completed, or timeout')
2503 """updates a VIM account
2505 NAME: name or ID of the VIM account
2509 check_client_version(ctx
.obj
, ctx
.command
.name
)
2511 if newname
: vim
['name'] = newname
2512 if user
: vim
['vim_user'] = user
2513 if password
: vim
['vim_password'] = password
2514 if auth_url
: vim
['vim_url'] = auth_url
2515 if tenant
: vim
['vim-tenant-name'] = tenant
2516 if account_type
: vim
['vim_type'] = account_type
2517 if description
: vim
['description'] = description
2518 if config
: vim
['config'] = config
2519 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2520 # except ClientException as e:
2525 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2526 @click.argument('name')
2527 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2528 @click.option('--wait',
2532 help='do not return the control immediately, but keep it '
2533 'until the operation is completed, or timeout')
2535 def vim_delete(ctx
, name
, force
, wait
):
2536 """deletes a VIM account
2538 NAME: name or ID of the VIM account to be deleted
2543 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2545 check_client_version(ctx
.obj
, '--force')
2546 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2547 # except ClientException as e:
2552 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2553 #@click.option('--ro_update/--no_ro_update',
2555 # help='update list from RO')
2556 @click.option('--filter', default
=None, multiple
=True,
2557 help='restricts the list to the VIM accounts matching the filter')
2558 @click.option('--long', is_flag
=True,
2559 help='get more details of the NS (project, vim, deployment status, configuration status.')
2561 def vim_list(ctx
, filter, long):
2562 """list all VIM accounts"""
2565 filter='&'.join(filter)
2566 check_client_version(ctx
.obj
, '--filter')
2568 # check_client_version(ctx.obj, '--ro_update', 'v1')
2569 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2570 if fullclassname
== 'osmclient.sol005.client.Client':
2571 resp
= ctx
.obj
.vim
.list(filter)
2573 # resp = ctx.obj.vim.list(ro_update)
2575 table
= PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details'])
2577 table
= PrettyTable(['vim name', 'uuid', 'operational state'])
2580 vim_details
= ctx
.obj
.vim
.get(vim
['uuid'])
2581 if 'vim_password' in vim_details
:
2582 vim_details
['vim_password']='********'
2583 logger
.debug('VIM details: {}'.format(yaml
.safe_dump(vim_details
)))
2584 vim_state
= vim_details
['_admin'].get('operationalState', '-')
2585 error_details
= 'N/A'
2586 if vim_state
== 'ERROR':
2587 error_details
= vim_details
['_admin'].get('detailed-status', 'Not found')
2588 project_list
= ctx
.obj
.project
.list()
2589 vim_project_list
= vim_details
.get('_admin').get('projects_read')
2591 project_name
= 'None'
2592 if vim_project_list
:
2593 project_id
= vim_project_list
[0]
2594 for p
in project_list
:
2595 if p
['_id'] == project_id
:
2596 project_name
= p
['name']
2598 table
.add_row([vim
['name'], vim
['uuid'], '{} ({})'.format(project_name
, project_id
),
2599 vim_state
, wrap_text(text
=error_details
, width
=80)])
2601 table
.add_row([vim
['name'], vim
['uuid'], vim
['_admin'].get('operationalState', '-')])
2606 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2607 @click.argument('name')
2608 @click.option('--filter', multiple
=True,
2609 help='restricts the information to the fields in the filter')
2611 def vim_show(ctx
, name
, filter):
2612 """shows the details of a VIM account
2614 NAME: name or ID of the VIM account
2618 resp
= ctx
.obj
.vim
.get(name
)
2619 if 'vim_password' in resp
:
2620 resp
['vim_password']='********'
2621 # except ClientException as e:
2625 table
= PrettyTable(['key', 'attribute'])
2626 for k
, v
in list(resp
.items()):
2627 if not filter or k
in filter:
2628 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2633 ####################
2635 ####################
2637 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2638 @click.option('--name',
2640 help='Name for the WIM account')
2641 @click.option('--user',
2642 help='WIM username')
2643 @click.option('--password',
2644 help='WIM password')
2645 @click.option('--url',
2648 # @click.option('--tenant',
2649 # help='wIM tenant name')
2650 @click.option('--config',
2652 help='WIM specific config parameters')
2653 @click.option('--wim_type',
2655 @click.option('--description',
2657 help='human readable description')
2658 @click.option('--wim_port_mapping', default
=None,
2659 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2660 "(WAN service endpoint id and info)")
2661 @click.option('--wait',
2665 help='do not return the control immediately, but keep it '
2666 'until the operation is completed, or timeout')
2679 """creates a new WIM account"""
2682 check_client_version(ctx
.obj
, ctx
.command
.name
)
2683 # if sdn_controller:
2684 # check_client_version(ctx.obj, '--sdn_controller')
2685 # if sdn_port_mapping:
2686 # check_client_version(ctx.obj, '--sdn_port_mapping')
2688 if user
: wim
['user'] = user
2689 if password
: wim
['password'] = password
2690 if url
: wim
['wim_url'] = url
2691 # if tenant: wim['tenant'] = tenant
2692 wim
['wim_type'] = wim_type
2693 if description
: wim
['description'] = description
2694 if config
: wim
['config'] = config
2695 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2696 # except ClientException as e:
2701 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2702 @click.argument('name')
2703 @click.option('--newname', help='New name for the WIM account')
2704 @click.option('--user', help='WIM username')
2705 @click.option('--password', help='WIM password')
2706 @click.option('--url', help='WIM url')
2707 @click.option('--config', help='WIM specific config parameters')
2708 @click.option('--wim_type', help='WIM type')
2709 @click.option('--description', help='human readable description')
2710 @click.option('--wim_port_mapping', default
=None,
2711 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2712 "(WAN service endpoint id and info)")
2713 @click.option('--wait',
2717 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2730 """updates a WIM account
2732 NAME: name or ID of the WIM account
2736 check_client_version(ctx
.obj
, ctx
.command
.name
)
2738 if newname
: wim
['name'] = newname
2739 if user
: wim
['user'] = user
2740 if password
: wim
['password'] = password
2741 if url
: wim
['url'] = url
2742 # if tenant: wim['tenant'] = tenant
2743 if wim_type
: wim
['wim_type'] = wim_type
2744 if description
: wim
['description'] = description
2745 if config
: wim
['config'] = config
2746 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2747 # except ClientException as e:
2752 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2753 @click.argument('name')
2754 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2755 @click.option('--wait',
2759 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2761 def wim_delete(ctx
, name
, force
, wait
):
2762 """deletes a WIM account
2764 NAME: name or ID of the WIM account to be deleted
2768 check_client_version(ctx
.obj
, ctx
.command
.name
)
2769 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2770 # except ClientException as e:
2775 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2776 @click.option('--filter', default
=None, multiple
=True,
2777 help='restricts the list to the WIM accounts matching the filter')
2779 def wim_list(ctx
, filter):
2780 """list all WIM accounts"""
2783 check_client_version(ctx
.obj
, ctx
.command
.name
)
2785 filter='&'.join(filter)
2786 resp
= ctx
.obj
.wim
.list(filter)
2787 table
= PrettyTable(['wim name', 'uuid'])
2789 table
.add_row([wim
['name'], wim
['uuid']])
2792 # except ClientException as e:
2797 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2798 @click.argument('name')
2800 def wim_show(ctx
, name
):
2801 """shows the details of a WIM account
2803 NAME: name or ID of the WIM account
2807 check_client_version(ctx
.obj
, ctx
.command
.name
)
2808 resp
= ctx
.obj
.wim
.get(name
)
2809 if 'password' in resp
:
2810 resp
['wim_password']='********'
2811 # except ClientException as e:
2815 table
= PrettyTable(['key', 'attribute'])
2816 for k
, v
in list(resp
.items()):
2817 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2822 ####################
2823 # SDN controller operations
2824 ####################
2826 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2827 @click.option('--name',
2829 help='Name to create sdn controller')
2830 @click.option('--type',
2832 help='SDN controller type')
2833 @click.option('--sdn_controller_version', # hidden=True,
2834 help='Deprecated. Use --config {version: sdn_controller_version}')
2835 @click.option('--url',
2836 help='URL in format http[s]://HOST:IP/')
2837 @click.option('--ip_address', # hidden=True,
2838 help='Deprecated. Use --url')
2839 @click.option('--port', # hidden=True,
2840 help='Deprecated. Use --url')
2841 @click.option('--switch_dpid', # hidden=True,
2842 help='Deprecated. Use --config {switch_id: DPID}')
2843 @click.option('--config',
2844 help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2845 'Openflow Datapath ID), version: version}')
2846 @click.option('--user',
2847 help='SDN controller username')
2848 @click.option('--password',
2850 confirmation_prompt
=True,
2851 help='SDN controller password')
2852 @click.option('--description', default
=None, help='human readable description')
2853 @click.option('--wait',
2857 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2859 def sdnc_create(ctx
, **kwargs
):
2860 """creates a new SDN controller"""
2862 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2863 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2864 if kwargs
.get("port"):
2865 print("option '--port' is deprecated, use '--url' instead")
2866 sdncontroller
["port"] = int(kwargs
["port"])
2867 if kwargs
.get("ip_address"):
2868 print("option '--ip_address' is deprecated, use '--url' instead")
2869 sdncontroller
["ip"] = kwargs
["ip_address"]
2870 if kwargs
.get("switch_dpid"):
2871 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2872 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2873 if kwargs
.get("sdn_controller_version"):
2874 print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2877 check_client_version(ctx
.obj
, ctx
.command
.name
)
2878 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2879 # except ClientException as e:
2883 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2884 @click.argument('name')
2885 @click.option('--newname', help='New name for the SDN controller')
2886 @click.option('--description', default
=None, help='human readable description')
2887 @click.option('--type', help='SDN controller type')
2888 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2889 @click.option('--config', help='Extra information for SDN in yaml format, as '
2890 '{switch_id: identity used for the plugin (e.g. DPID: '
2891 'Openflow Datapath ID), version: version}')
2892 @click.option('--user', help='SDN controller username')
2893 @click.option('--password', help='SDN controller password')
2894 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2895 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2896 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2897 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2898 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2899 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2901 def sdnc_update(ctx
, **kwargs
):
2902 """updates an SDN controller
2904 NAME: name or ID of the SDN controller
2907 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2908 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2909 if kwargs
.get("newname"):
2910 sdncontroller
["name"] = kwargs
["newname"]
2911 if kwargs
.get("port"):
2912 print("option '--port' is deprecated, use '--url' instead")
2913 sdncontroller
["port"] = int(kwargs
["port"])
2914 if kwargs
.get("ip_address"):
2915 print("option '--ip_address' is deprecated, use '--url' instead")
2916 sdncontroller
["ip"] = kwargs
["ip_address"]
2917 if kwargs
.get("switch_dpid"):
2918 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2919 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2920 if kwargs
.get("sdn_controller_version"):
2921 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2925 check_client_version(ctx
.obj
, ctx
.command
.name
)
2926 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2927 # except ClientException as e:
2932 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2933 @click.argument('name')
2934 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2935 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2936 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2938 def sdnc_delete(ctx
, name
, force
, wait
):
2939 """deletes an SDN controller
2941 NAME: name or ID of the SDN controller to be deleted
2945 check_client_version(ctx
.obj
, ctx
.command
.name
)
2946 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2947 # except ClientException as e:
2952 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2953 @click.option('--filter', default
=None, multiple
=True,
2954 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2956 def sdnc_list(ctx
, filter):
2957 """list all SDN controllers"""
2960 check_client_version(ctx
.obj
, ctx
.command
.name
)
2962 filter='&'.join(filter)
2963 resp
= ctx
.obj
.sdnc
.list(filter)
2964 # except ClientException as e:
2967 table
= PrettyTable(['sdnc name', 'id'])
2969 table
.add_row([sdnc
['name'], sdnc
['_id']])
2974 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2975 @click.argument('name')
2977 def sdnc_show(ctx
, name
):
2978 """shows the details of an SDN controller
2980 NAME: name or ID of the SDN controller
2984 check_client_version(ctx
.obj
, ctx
.command
.name
)
2985 resp
= ctx
.obj
.sdnc
.get(name
)
2986 # except ClientException as e:
2990 table
= PrettyTable(['key', 'attribute'])
2991 for k
, v
in list(resp
.items()):
2992 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2997 ###########################
2998 # K8s cluster operations
2999 ###########################
3001 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
3002 @click.argument('name')
3003 @click.option('--creds',
3005 help='credentials file, i.e. a valid `.kube/config` file')
3006 @click.option('--version',
3008 help='Kubernetes version')
3009 @click.option('--vim',
3011 help='VIM target, the VIM where the cluster resides')
3012 @click.option('--k8s-nets',
3014 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) ...]}"')
3015 @click.option('--description',
3017 help='human readable description')
3018 @click.option('--namespace',
3019 default
='kube-system',
3020 help='namespace to be used for its operation, defaults to `kube-system`')
3021 @click.option('--cni',
3023 help='list of CNI plugins, in JSON inline format, used in the cluster')
3024 #@click.option('--skip-init',
3026 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3027 #@click.option('--wait',
3029 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3031 def k8scluster_add(ctx
,
3040 """adds a K8s cluster to OSM
3042 NAME: name of the K8s cluster
3045 check_client_version(ctx
.obj
, ctx
.command
.name
)
3047 cluster
['name'] = name
3048 with
open(creds
, 'r') as cf
:
3049 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3050 cluster
['k8s_version'] = version
3051 cluster
['vim_account'] = vim
3052 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3054 cluster
['description'] = description
3055 if namespace
: cluster
['namespace'] = namespace
3056 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3057 ctx
.obj
.k8scluster
.create(name
, cluster
)
3058 # except ClientException as e:
3063 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
3064 @click.argument('name')
3065 @click.option('--newname', help='New name for the K8s cluster')
3066 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3067 @click.option('--version', help='Kubernetes version')
3068 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3069 @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) ...]}"')
3070 @click.option('--description', help='human readable description')
3071 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3072 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3074 def k8scluster_update(ctx
,
3084 """updates a K8s cluster
3086 NAME: name or ID of the K8s cluster
3089 check_client_version(ctx
.obj
, ctx
.command
.name
)
3091 if newname
: cluster
['name'] = newname
3093 with
open(creds
, 'r') as cf
:
3094 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3095 if version
: cluster
['k8s_version'] = version
3096 if vim
: cluster
['vim_account'] = vim
3097 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3098 if description
: cluster
['description'] = description
3099 if namespace
: cluster
['namespace'] = namespace
3100 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3101 ctx
.obj
.k8scluster
.update(name
, cluster
)
3102 # except ClientException as e:
3107 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
3108 @click.argument('name')
3109 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3110 #@click.option('--wait',
3112 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3114 def k8scluster_delete(ctx
, name
, force
):
3115 """deletes a K8s cluster
3117 NAME: name or ID of the K8s cluster to be deleted
3120 check_client_version(ctx
.obj
, ctx
.command
.name
)
3121 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3122 # except ClientException as e:
3127 @cli_osm.command(name
='k8scluster-list')
3128 @click.option('--filter', default
=None, multiple
=True,
3129 help='restricts the list to the K8s clusters matching the filter')
3130 @click.option('--literal', is_flag
=True,
3131 help='print literally, no pretty table')
3133 def k8scluster_list(ctx
, filter, literal
):
3134 """list all K8s clusters"""
3136 check_client_version(ctx
.obj
, ctx
.command
.name
)
3138 filter='&'.join(filter)
3139 resp
= ctx
.obj
.k8scluster
.list(filter)
3141 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3143 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
3144 for cluster
in resp
:
3145 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
3146 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
3147 trunc_text(cluster
.get('description') or '', 40)])
3150 # except ClientException as e:
3155 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
3156 @click.argument('name')
3157 @click.option('--literal', is_flag
=True,
3158 help='print literally, no pretty table')
3160 def k8scluster_show(ctx
, name
, literal
):
3161 """shows the details of a K8s cluster
3163 NAME: name or ID of the K8s cluster
3166 resp
= ctx
.obj
.k8scluster
.get(name
)
3168 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3170 table
= PrettyTable(['key', 'attribute'])
3171 for k
, v
in list(resp
.items()):
3172 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
3175 # except ClientException as e:
3181 ###########################
3183 ###########################
3185 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
3186 @click.argument('name')
3187 @click.argument('uri')
3188 @click.option('--type',
3189 type=click
.Choice(['helm-chart', 'juju-bundle', 'osm']),
3191 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3192 @click.option('--description',
3194 help='human readable description')
3195 @click.option('--user',
3197 help='OSM repository: The username of the OSM repository')
3198 @click.option('--password',
3200 help='OSM repository: The password of the OSM repository')
3201 #@click.option('--wait',
3203 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3205 def repo_add(ctx
, **kwargs
):
3206 """adds a repo to OSM
3208 NAME: name of the repo
3209 URI: URI of the repo
3212 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
3214 repo
["url"] = repo
.pop("uri")
3215 if repo
["type"] in ['helm-chart', 'juju-bundle']:
3216 ctx
.obj
.repo
.create(repo
['name'], repo
)
3218 ctx
.obj
.osmrepo
.create(repo
['name'], repo
)
3219 # except ClientException as e:
3224 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
3225 @click.argument('name')
3226 @click.option('--newname', help='New name for the repo')
3227 @click.option('--uri', help='URI of the repo')
3228 @click.option('--description', help='human readable description')
3229 #@click.option('--wait',
3231 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3233 def repo_update(ctx
,
3238 """updates a repo in OSM
3240 NAME: name of the repo
3243 check_client_version(ctx
.obj
, ctx
.command
.name
)
3246 repo
['name'] = newname
3249 if description
: repo
['description'] = description
3251 ctx
.obj
.repo
.update(name
, repo
)
3253 ctx
.obj
.osmrepo
.update(name
, repo
)
3255 # except ClientException as e:
3260 @cli_osm.command(name
='repo-index', short_help
='Index a repository from a folder with artifacts')
3261 @click.option('--origin', default
='.', help='origin path where the artifacts are located')
3262 @click.option('--destination', default
='.', help='destination path where the index is deployed')
3264 def repo_index(ctx
, origin
, destination
):
3265 """Index a repository
3267 NAME: name or ID of the repo to be deleted
3269 check_client_version(ctx
.obj
, ctx
.command
.name
)
3270 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
3273 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
3274 @click.argument('name')
3275 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3276 #@click.option('--wait',
3278 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3280 def repo_delete(ctx
, name
, force
):
3283 NAME: name or ID of the repo to be deleted
3287 ctx
.obj
.repo
.delete(name
, force
=force
)
3289 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
3290 # except ClientException as e:
3295 @cli_osm.command(name
='repo-list')
3296 @click.option('--filter', default
=None, multiple
=True,
3297 help='restricts the list to the repos matching the filter')
3298 @click.option('--literal', is_flag
=True,
3299 help='print literally, no pretty table')
3301 def repo_list(ctx
, filter, literal
):
3302 """list all repos"""
3305 check_client_version(ctx
.obj
, ctx
.command
.name
)
3307 filter='&'.join(filter)
3308 resp
= ctx
.obj
.repo
.list(filter)
3309 resp
+= ctx
.obj
.osmrepo
.list(filter)
3311 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3313 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3315 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3316 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description') or '',40)])
3320 # except ClientException as e:
3325 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
3326 @click.argument('name')
3327 @click.option('--literal', is_flag
=True,
3328 help='print literally, no pretty table')
3330 def repo_show(ctx
, name
, literal
):
3331 """shows the details of a repo
3333 NAME: name or ID of the repo
3336 resp
= ctx
.obj
.repo
.get(name
)
3338 resp
= ctx
.obj
.osmrepo
.get(name
)
3342 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3344 table
= PrettyTable(['key', 'attribute'])
3346 for k
, v
in list(resp
.items()):
3347 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3351 # except ClientException as e:
3357 ####################
3358 # Project mgmt operations
3359 ####################
3361 @cli_osm.command(name
='project-create', short_help
='creates a new project')
3362 @click.argument('name')
3363 #@click.option('--description',
3364 # default='no description',
3365 # help='human readable description')
3366 @click.option('--domain-name', 'domain_name',
3368 help='assign to a domain')
3369 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3370 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3371 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3373 def project_create(ctx
, name
, domain_name
, quotas
):
3374 """Creates a new project
3376 NAME: name of the project
3377 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3378 QUOTAS: set quotas for the project
3381 project
= {'name': name
}
3383 project
['domain_name'] = domain_name
3384 quotas_dict
= _process_project_quotas(quotas
)
3386 project
['quotas'] = quotas_dict
3389 check_client_version(ctx
.obj
, ctx
.command
.name
)
3390 ctx
.obj
.project
.create(name
, project
)
3391 # except ClientException as e:
3396 def _process_project_quotas(quota_list
):
3401 for quota
in quota_list
:
3402 for single_quota
in quota
.split(","):
3403 k
, v
= single_quota
.split("=")
3404 quotas_dict
[k
] = None if v
in ('None', 'null', '') else int(v
)
3405 except (ValueError, TypeError):
3406 raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3410 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3411 @click.argument('name')
3412 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3414 def project_delete(ctx
, name
):
3415 """deletes a project
3417 NAME: name or ID of the project to be deleted
3421 check_client_version(ctx
.obj
, ctx
.command
.name
)
3422 ctx
.obj
.project
.delete(name
)
3423 # except ClientException as e:
3428 @cli_osm.command(name
='project-list', short_help
='list all projects')
3429 @click.option('--filter', default
=None, multiple
=True,
3430 help='restricts the list to the projects matching the filter')
3432 def project_list(ctx
, filter):
3433 """list all projects"""
3436 check_client_version(ctx
.obj
, ctx
.command
.name
)
3438 filter='&'.join(filter)
3439 resp
= ctx
.obj
.project
.list(filter)
3440 # except ClientException as e:
3443 table
= PrettyTable(['name', 'id'])
3445 table
.add_row([proj
['name'], proj
['_id']])
3450 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3451 @click.argument('name')
3453 def project_show(ctx
, name
):
3454 """shows the details of a project
3456 NAME: name or ID of the project
3460 check_client_version(ctx
.obj
, ctx
.command
.name
)
3461 resp
= ctx
.obj
.project
.get(name
)
3462 # except ClientException as e:
3466 table
= PrettyTable(['key', 'attribute'])
3467 for k
, v
in resp
.items():
3468 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3473 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3474 @click.argument('project')
3475 @click.option('--name', default
=None,
3476 help='new name for the project')
3477 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3478 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3479 "(use empty to reset quota to default")
3481 def project_update(ctx
, project
, name
, quotas
):
3483 Update a project name
3486 :param project: id or name of the project to modify
3487 :param name: new name for the project
3488 :param quotas: change quotas of the project
3492 project_changes
= {}
3494 project_changes
['name'] = name
3495 quotas_dict
= _process_project_quotas(quotas
)
3497 project_changes
['quotas'] = quotas_dict
3500 check_client_version(ctx
.obj
, ctx
.command
.name
)
3501 ctx
.obj
.project
.update(project
, project_changes
)
3502 # except ClientException as e:
3506 ####################
3507 # User mgmt operations
3508 ####################
3510 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3511 @click.argument('username')
3512 @click.option('--password',
3515 confirmation_prompt
=True,
3516 help='user password')
3517 @click.option('--projects',
3518 # prompt="Comma separate list of projects",
3520 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3521 help='list of project ids that the user belongs to')
3522 @click.option('--project-role-mappings', 'project_role_mappings',
3523 default
=None, multiple
=True,
3524 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3525 @click.option('--domain-name', 'domain_name',
3527 help='assign to a domain')
3529 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
3530 """Creates a new user
3533 USERNAME: name of the user
3534 PASSWORD: password of the user
3535 PROJECTS: projects assigned to user (internal only)
3536 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3537 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3541 user
['username'] = username
3542 user
['password'] = password
3543 user
['projects'] = projects
3544 user
['project_role_mappings'] = project_role_mappings
3546 user
['domain_name'] = domain_name
3549 check_client_version(ctx
.obj
, ctx
.command
.name
)
3550 ctx
.obj
.user
.create(username
, user
)
3551 # except ClientException as e:
3556 @cli_osm.command(name
='user-update', short_help
='updates user information')
3557 @click.argument('username')
3558 @click.option('--password',
3561 # confirmation_prompt=True,
3562 help='user password')
3563 @click.option('--set-username', 'set_username',
3565 help='change username')
3566 @click.option('--set-project', 'set_project',
3567 default
=None, multiple
=True,
3568 help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3569 @click.option('--remove-project', 'remove_project',
3570 default
=None, multiple
=True,
3571 help="removes project from user: 'project'")
3572 @click.option('--add-project-role', 'add_project_role',
3573 default
=None, multiple
=True,
3574 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3575 @click.option('--remove-project-role', 'remove_project_role',
3576 default
=None, multiple
=True,
3577 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3579 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3580 add_project_role
, remove_project_role
):
3581 """Update a user information
3584 USERNAME: name of the user
3585 PASSWORD: new password
3586 SET_USERNAME: new username
3587 SET_PROJECT: creating mappings for project/role(s)
3588 REMOVE_PROJECT: deleting mappings for project/role(s)
3589 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3590 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3594 user
['password'] = password
3595 user
['username'] = set_username
3596 user
['set-project'] = set_project
3597 user
['remove-project'] = remove_project
3598 user
['add-project-role'] = add_project_role
3599 user
['remove-project-role'] = remove_project_role
3602 check_client_version(ctx
.obj
, ctx
.command
.name
)
3603 ctx
.obj
.user
.update(username
, user
)
3604 # except ClientException as e:
3609 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3610 @click.argument('name')
3611 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3613 def user_delete(ctx
, name
):
3617 NAME: name or ID of the user to be deleted
3621 check_client_version(ctx
.obj
, ctx
.command
.name
)
3622 ctx
.obj
.user
.delete(name
)
3623 # except ClientException as e:
3628 @cli_osm.command(name
='user-list', short_help
='list all users')
3629 @click.option('--filter', default
=None, multiple
=True,
3630 help='restricts the list to the users matching the filter')
3632 def user_list(ctx
, filter):
3633 """list all users"""
3635 check_client_version(ctx
.obj
, ctx
.command
.name
)
3637 filter='&'.join(filter)
3638 resp
= ctx
.obj
.user
.list(filter)
3639 # except ClientException as e:
3642 table
= PrettyTable(['name', 'id'])
3644 table
.add_row([user
['username'], user
['_id']])
3649 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3650 @click.argument('name')
3652 def user_show(ctx
, name
):
3653 """shows the details of a user
3655 NAME: name or ID of the user
3659 check_client_version(ctx
.obj
, ctx
.command
.name
)
3660 resp
= ctx
.obj
.user
.get(name
)
3661 if 'password' in resp
:
3662 resp
['password']='********'
3663 # except ClientException as e:
3667 table
= PrettyTable(['key', 'attribute'])
3668 for k
, v
in resp
.items():
3669 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3674 ####################
3675 # Fault Management operations
3676 ####################
3678 @cli_osm.command(name
='ns-alarm-create')
3679 @click.argument('name')
3680 @click.option('--ns', prompt
=True, help='NS instance id or name')
3681 @click.option('--vnf', prompt
=True,
3682 help='VNF name (VNF member index as declared in the NSD)')
3683 @click.option('--vdu', prompt
=True,
3684 help='VDU name (VDU name as declared in the VNFD)')
3685 @click.option('--metric', prompt
=True,
3686 help='Name of the metric (e.g. cpu_utilization)')
3687 @click.option('--severity', default
='WARNING',
3688 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3689 @click.option('--threshold_value', prompt
=True,
3690 help='threshold value that, when crossed, an alarm is triggered')
3691 @click.option('--threshold_operator', prompt
=True,
3692 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3693 @click.option('--statistic', default
='AVERAGE',
3694 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3696 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3697 threshold_value
, threshold_operator
, statistic
):
3698 """creates a new alarm for a NS instance"""
3699 # TODO: Check how to validate threshold_value.
3700 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3703 ns_instance
= ctx
.obj
.ns
.get(ns
)
3705 alarm
['alarm_name'] = name
3706 alarm
['ns_id'] = ns_instance
['_id']
3707 alarm
['correlation_id'] = ns_instance
['_id']
3708 alarm
['vnf_member_index'] = vnf
3709 alarm
['vdu_name'] = vdu
3710 alarm
['metric_name'] = metric
3711 alarm
['severity'] = severity
3712 alarm
['threshold_value'] = int(threshold_value
)
3713 alarm
['operation'] = threshold_operator
3714 alarm
['statistic'] = statistic
3715 check_client_version(ctx
.obj
, ctx
.command
.name
)
3716 ctx
.obj
.ns
.create_alarm(alarm
)
3717 # except ClientException as e:
3722 #@cli_osm.command(name='ns-alarm-delete')
3723 #@click.argument('name')
3724 #@click.pass_context
3725 #def ns_alarm_delete(ctx, name):
3726 # """deletes an alarm
3728 # NAME: name of the alarm to be deleted
3731 # check_client_version(ctx.obj, ctx.command.name)
3732 # ctx.obj.ns.delete_alarm(name)
3733 # except ClientException as e:
3738 ####################
3739 # Performance Management operations
3740 ####################
3742 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3743 @click.option('--ns', prompt
=True, help='NS instance id or name')
3744 @click.option('--vnf', prompt
=True,
3745 help='VNF name (VNF member index as declared in the NSD)')
3746 @click.option('--vdu', prompt
=True,
3747 help='VDU name (VDU name as declared in the VNFD)')
3748 @click.option('--metric', prompt
=True,
3749 help='name of the metric (e.g. cpu_utilization)')
3750 #@click.option('--period', default='1w',
3751 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3752 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3754 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3755 """exports a metric to the internal OSM bus, which can be read by other apps"""
3756 # TODO: Check how to validate interval.
3757 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3760 ns_instance
= ctx
.obj
.ns
.get(ns
)
3762 metric_data
['ns_id'] = ns_instance
['_id']
3763 metric_data
['correlation_id'] = ns_instance
['_id']
3764 metric_data
['vnf_member_index'] = vnf
3765 metric_data
['vdu_name'] = vdu
3766 metric_data
['metric_name'] = metric
3767 metric_data
['collection_unit'] = 'WEEK'
3768 metric_data
['collection_period'] = 1
3769 check_client_version(ctx
.obj
, ctx
.command
.name
)
3771 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3775 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3776 time
.sleep(int(interval
))
3778 # except ClientException as e:
3783 ####################
3785 ####################
3787 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3789 def get_version(ctx
):
3790 """shows client and server versions"""
3792 check_client_version(ctx
.obj
, "version")
3793 print ("Server version: {}".format(ctx
.obj
.get_version()))
3794 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3795 # except ClientException as e:
3799 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3800 @click.argument('filename')
3801 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3802 help='the charm will not be compiled, it is assumed to already exist')
3804 def upload_package(ctx
, filename
, skip_charm_build
):
3805 """uploads a vnf package or ns package
3807 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3811 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3812 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3813 if fullclassname
!= 'osmclient.sol005.client.Client':
3814 ctx
.obj
.package
.wait_for_upload(filename
)
3815 # except ClientException as e:
3820 #@cli_osm.command(name='ns-scaling-show')
3821 #@click.argument('ns_name')
3822 #@click.pass_context
3823 #def show_ns_scaling(ctx, ns_name):
3824 # """shows the status of a NS scaling operation
3826 # NS_NAME: name of the NS instance being scaled
3829 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3830 # resp = ctx.obj.ns.list()
3831 # except ClientException as e:
3835 # table = PrettyTable(
3838 # 'operational status',
3843 # if ns_name == ns['name']:
3844 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3845 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3846 # for record in scaling_records:
3847 # if 'instance' in record:
3848 # instances = record['instance']
3849 # for inst in instances:
3851 # [record['scaling-group-name-ref'],
3852 # inst['instance-id'],
3853 # inst['op-status'],
3854 # time.strftime('%Y-%m-%d %H:%M:%S',
3856 # inst['create-time'])),
3862 #@cli_osm.command(name='ns-scale')
3863 #@click.argument('ns_name')
3864 #@click.option('--ns_scale_group', prompt=True)
3865 #@click.option('--index', prompt=True)
3866 #@click.option('--wait',
3870 # help='do not return the control immediately, but keep it \
3871 # until the operation is completed, or timeout')
3872 #@click.pass_context
3873 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3876 # NS_NAME: name of the NS instance to be scaled
3879 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3880 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3881 # except ClientException as e:
3886 #@cli_osm.command(name='config-agent-list')
3887 #@click.pass_context
3888 #def config_agent_list(ctx):
3889 # """list config agents"""
3891 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3892 # except ClientException as e:
3895 # table = PrettyTable(['name', 'account-type', 'details'])
3896 # for account in ctx.obj.vca.list():
3899 # account['account-type'],
3905 #@cli_osm.command(name='config-agent-delete')
3906 #@click.argument('name')
3907 #@click.pass_context
3908 #def config_agent_delete(ctx, name):
3909 # """deletes a config agent
3911 # NAME: name of the config agent to be deleted
3914 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3915 # ctx.obj.vca.delete(name)
3916 # except ClientException as e:
3921 #@cli_osm.command(name='config-agent-add')
3922 #@click.option('--name',
3924 #@click.option('--account_type',
3926 #@click.option('--server',
3928 #@click.option('--user',
3930 #@click.option('--secret',
3933 # confirmation_prompt=True)
3934 #@click.pass_context
3935 #def config_agent_add(ctx, name, account_type, server, user, secret):
3936 # """adds a config agent"""
3938 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3939 # ctx.obj.vca.create(name, account_type, server, user, secret)
3940 # except ClientException as e:
3945 #@cli_osm.command(name='ro-dump')
3946 #@click.pass_context
3948 # """shows RO agent information"""
3949 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3950 # resp = ctx.obj.vim.get_resource_orchestrator()
3951 # table = PrettyTable(['key', 'attribute'])
3952 # for k, v in list(resp.items()):
3953 # table.add_row([k, json.dumps(v, indent=2)])
3958 #@cli_osm.command(name='vcs-list')
3959 #@click.pass_context
3961 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3962 # resp = ctx.obj.utils.get_vcs_info()
3963 # table = PrettyTable(['component name', 'state'])
3964 # for component in resp:
3965 # table.add_row([component['component_name'], component['state']])
3970 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3971 @click.argument('ns_name')
3972 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3973 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3974 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3975 @click.option('--vdu_count', default
=None, type=int, help='number of vdu instance of this vdu_id')
3976 @click.option('--action_name', prompt
=True, help='action name')
3977 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3978 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3979 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
3980 @click.option('--wait',
3984 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3997 """executes an action/primitive over a NS instance
3999 NS_NAME: name or ID of the NS instance
4003 check_client_version(ctx
.obj
, ctx
.command
.name
)
4006 op_data
['member_vnf_index'] = vnf_name
4008 op_data
['kdu_name'] = kdu_name
4010 op_data
['vdu_id'] = vdu_id
4011 if vdu_count
is not None:
4012 op_data
['vdu_count_index'] = vdu_count
4014 op_data
['timeout_ns_action'] = timeout
4015 op_data
['primitive'] = action_name
4017 with
open(params_file
, 'r') as pf
:
4020 op_data
['primitive_params'] = yaml
.safe_load(params
)
4022 op_data
['primitive_params'] = {}
4023 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
4025 # except ClientException as e:
4030 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
4031 @click.argument('ns_name')
4032 @click.argument('vnf_name')
4033 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
4034 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
4035 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
4036 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4037 @click.option('--wait', required
=False, default
=False, is_flag
=True,
4038 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4049 Executes a VNF scale (adding/removing VDUs)
4052 NS_NAME: name or ID of the NS instance.
4053 VNF_NAME: member-vnf-index in the NS to be scaled.
4057 check_client_version(ctx
.obj
, ctx
.command
.name
)
4058 if not scale_in
and not scale_out
:
4060 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
)
4061 # except ClientException as e:
4066 ##############################
4067 # Role Management Operations #
4068 ##############################
4070 @cli_osm.command(name
='role-create', short_help
='creates a new role')
4071 @click.argument('name')
4072 @click.option('--permissions',
4074 help='role permissions using a dictionary')
4076 def role_create(ctx
, name
, permissions
):
4081 NAME: Name or ID of the role.
4082 DEFINITION: Definition of grant/denial of access to resources.
4086 check_client_version(ctx
.obj
, ctx
.command
.name
)
4087 ctx
.obj
.role
.create(name
, permissions
)
4088 # except ClientException as e:
4093 @cli_osm.command(name
='role-update', short_help
='updates a role')
4094 @click.argument('name')
4095 @click.option('--set-name',
4097 help='change name of rle')
4098 # @click.option('--permissions',
4100 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4101 @click.option('--add',
4103 help='yaml format dictionary with permission: True/False to access grant/denial')
4104 @click.option('--remove',
4106 help='yaml format list to remove a permission')
4108 def role_update(ctx
, name
, set_name
, add
, remove
):
4113 NAME: Name or ID of the role.
4114 DEFINITION: Definition overwrites the old definition.
4115 ADD: Grant/denial of access to resource to add.
4116 REMOVE: Grant/denial of access to resource to remove.
4120 check_client_version(ctx
.obj
, ctx
.command
.name
)
4121 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
4122 # except ClientException as e:
4127 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
4128 @click.argument('name')
4129 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4131 def role_delete(ctx
, name
):
4136 NAME: Name or ID of the role.
4140 check_client_version(ctx
.obj
, ctx
.command
.name
)
4141 ctx
.obj
.role
.delete(name
)
4142 # except ClientException as e:
4147 @cli_osm.command(name
='role-list', short_help
='list all roles')
4148 @click.option('--filter', default
=None, multiple
=True,
4149 help='restricts the list to the projects matching the filter')
4151 def role_list(ctx
, filter):
4157 check_client_version(ctx
.obj
, ctx
.command
.name
)
4159 filter='&'.join(filter)
4160 resp
= ctx
.obj
.role
.list(filter)
4161 # except ClientException as e:
4164 table
= PrettyTable(['name', 'id'])
4166 table
.add_row([role
['name'], role
['_id']])
4171 @cli_osm.command(name
='role-show', short_help
='show specific role')
4172 @click.argument('name')
4174 def role_show(ctx
, name
):
4176 Shows the details of a role.
4179 NAME: Name or ID of the role.
4183 check_client_version(ctx
.obj
, ctx
.command
.name
)
4184 resp
= ctx
.obj
.role
.get(name
)
4185 # except ClientException as e:
4189 table
= PrettyTable(['key', 'attribute'])
4190 for k
, v
in resp
.items():
4191 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4196 @cli_osm.command(name
='package-create',
4197 short_help
='Create a package descriptor')
4198 @click.argument('package-type')
4199 @click.argument('package-name')
4200 @click.option('--base-directory',
4202 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4203 @click.option('--image',
4204 default
="image-name",
4205 help='(VNF) Set the name of the vdu image. Default "image-name"')
4206 @click.option('--vdus',
4208 help='(VNF) Set the number of vdus in a VNF. Default 1')
4209 @click.option('--vcpu',
4211 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4212 @click.option('--memory',
4214 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4215 @click.option('--storage',
4217 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4218 @click.option('--interfaces',
4220 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4221 @click.option('--vendor',
4223 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4224 @click.option('--override',
4227 help='(NS/VNF/NST) Flag for overriding the package if exists.')
4228 @click.option('--detailed',
4231 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4232 @click.option('--netslice-subnets',
4234 help='(NST) Number of netslice subnets. Default 1')
4235 @click.option('--netslice-vlds',
4237 help='(NST) Number of netslice vlds. Default 1')
4239 def package_create(ctx
,
4255 Creates an OSM NS, VNF, NST package
4258 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4259 PACKAGE_NAME: Name of the package to create the folder with the content.
4263 check_client_version(ctx
.obj
, ctx
.command
.name
)
4264 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
4265 resp
= ctx
.obj
.package_tool
.create(package_type
,
4274 interfaces
=interfaces
,
4277 netslice_subnets
=netslice_subnets
,
4278 netslice_vlds
=netslice_vlds
)
4280 # except ClientException as inst:
4281 # print("ERROR: {}".format(inst))
4284 @cli_osm.command(name
='package-validate',
4285 short_help
='Validate a package descriptor')
4286 @click.argument('base-directory',
4289 @click.option('--recursive/--no-recursive',
4291 help='The activated recursive option will validate the yaml files'
4292 ' within the indicated directory and in its subdirectories')
4294 def package_validate(ctx
,
4298 Validate descriptors given a base directory.
4301 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4304 check_client_version(ctx
.obj
, ctx
.command
.name
)
4305 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
4306 table
= PrettyTable()
4307 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
4308 # Print the dictionary generated by the validation function
4309 for result
in results
:
4310 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
4311 table
.sortby
= "VALID"
4312 table
.align
["PATH"] = "l"
4313 table
.align
["TYPE"] = "l"
4314 table
.align
["ERROR"] = "l"
4316 # except ClientException as inst:
4317 # print("ERROR: {}".format(inst))
4320 @cli_osm.command(name
='package-build',
4321 short_help
='Build the tar.gz of the package')
4322 @click.argument('package-folder')
4323 @click.option('--skip-validation',
4326 help='skip package validation')
4327 @click.option('--skip-charm-build', default
=False, is_flag
=True,
4328 help='the charm will not be compiled, it is assumed to already exist')
4330 def package_build(ctx
,
4335 Build the package NS, VNF given the package_folder.
4338 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4341 check_client_version(ctx
.obj
, ctx
.command
.name
)
4342 results
= ctx
.obj
.package_tool
.build(package_folder
,
4343 skip_validation
=skip_validation
,
4344 skip_charm_build
=skip_charm_build
)
4346 # except ClientException as inst:
4347 # print("ERROR: {}".format(inst))
4355 except pycurl
.error
as exc
:
4357 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4358 except ClientException
as exc
:
4359 print("ERROR: {}".format(exc
))
4360 except (FileNotFoundError
, PermissionError
) as exc
:
4361 print("Cannot open file: {}".format(exc
))
4362 except yaml
.YAMLError
as exc
:
4363 print("Invalid YAML format: {}".format(exc
))
4365 # TODO capture other controlled exceptions here
4366 # TODO remove the ClientException captures from all places, unless they do something different
4369 if __name__
== '__main__':