1df00d680df0c86034362233bf5082a259949805
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 def get_project(project_list
, item
):
73 # project_list = ctx.obj.project.list()
74 item_project_list
= item
.get('_admin').get('projects_read')
78 for p1
in item_project_list
:
80 for p2
in project_list
:
81 if p2
['_id'] == project_id
:
82 project_name
= p2
['name']
83 return project_id
, project_name
84 return project_id
, project_name
87 @click.group(context_settings
=dict(help_option_names
=['-h', '--help'], max_content_width
=160))
88 @click.option('--hostname',
90 envvar
='OSM_HOSTNAME',
91 help='hostname of server. ' +
92 'Also can set OSM_HOSTNAME in environment')
93 #@click.option('--sol005/--no-sol005',
95 # envvar='OSM_SOL005',
96 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
97 # 'Also can set OSM_SOL005 in environment')
98 @click.option('--user',
101 help='user (defaults to admin). ' +
102 'Also can set OSM_USER in environment')
103 @click.option('--password',
105 envvar
='OSM_PASSWORD',
106 help='password (defaults to admin). ' +
107 'Also can set OSM_PASSWORD in environment')
108 @click.option('--project',
110 envvar
='OSM_PROJECT',
111 help='project (defaults to admin). ' +
112 'Also can set OSM_PROJECT in environment')
113 @click.option('-v', '--verbose', count
=True,
114 help='increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)')
115 @click.option('--all-projects',
118 help='include all projects')
119 @click.option('--public/--no-public', default
=None,
120 help='flag for public items (packages, instances, VIM accounts, etc.)')
121 @click.option('--project-domain-name', 'project_domain_name',
123 envvar
='OSM_PROJECT_DOMAIN_NAME',
124 help='project domain name for keystone authentication (default to None). ' +
125 'Also can set OSM_PROJECT_DOMAIN_NAME in environment')
126 @click.option('--user-domain-name', 'user_domain_name',
128 envvar
='OSM_USER_DOMAIN_NAME',
129 help='user domain name for keystone authentication (default to None). ' +
130 'Also can set OSM_USER_DOMAIN_NAME in environment')
131 #@click.option('--so-port',
133 # envvar='OSM_SO_PORT',
134 # help='hostname of server. ' +
135 # 'Also can set OSM_SO_PORT in environment')
136 #@click.option('--so-project',
138 # envvar='OSM_SO_PROJECT',
139 # help='Project Name in SO. ' +
140 # 'Also can set OSM_SO_PROJECT in environment')
141 #@click.option('--ro-hostname',
143 # envvar='OSM_RO_HOSTNAME',
144 # help='hostname of RO server. ' +
145 # 'Also can set OSM_RO_HOSTNAME in environment')
146 #@click.option('--ro-port',
148 # envvar='OSM_RO_PORT',
149 # help='hostname of RO server. ' +
150 # 'Also can set OSM_RO_PORT in environment')
152 def cli_osm(ctx
, **kwargs
):
154 hostname
= kwargs
.pop("hostname", None)
157 "either hostname option or OSM_HOSTNAME " +
158 "environment variable needs to be specified"))
161 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
162 # if so_port is not None:
163 # kwargs['so_port']=so_port
164 # if so_project is not None:
165 # kwargs['so_project']=so_project
166 # if ro_hostname is not None:
167 # kwargs['ro_host']=ro_hostname
168 # if ro_port is not None:
169 # kwargs['ro_port']=ro_port
170 sol005
= os
.getenv('OSM_SOL005', True)
171 # if user is not None:
172 # kwargs['user']=user
173 # if password is not None:
174 # kwargs['password']=password
175 # if project is not None:
176 # kwargs['project']=project
178 # kwargs['all_projects']=all_projects
179 # if public is not None:
180 # kwargs['public']=public
181 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
182 logger
= logging
.getLogger('osmclient')
189 @cli_osm.command(name
='ns-list', short_help
='list all NS instances')
190 @click.option('--filter', default
=None, multiple
=True,
191 help='restricts the list to the NS instances matching the filter.')
192 @click.option('--long', is_flag
=True,
193 help='get more details of the NS (project, vim, deployment status, configuration status.')
195 def ns_list(ctx
, filter, long):
196 """list all NS instances
200 --filter filterExpr Restricts the list to the NS instances matching the filter
203 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
204 concatenated using the "&" character:
207 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
208 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
209 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
211 value := scalar value
215 * zero or more occurrences
216 ? zero or one occurrence
217 [] grouping of expressions to be used with ? and *
218 "" quotation marks for marking string constants
222 "AttrName" is the name of one attribute in the data type that defines the representation
223 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
224 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
225 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
226 entries, it means that the operator "op" is applied to the attribute addressed by the last
227 <attrName> entry included in the concatenation. All simple filter expressions are combined
228 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
229 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
230 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
231 prefix". If an attribute referenced in an expression is an array, an object that contains a
232 corresponding array shall be considered to match the expression if any of the elements in the
233 array matches all expressions that have the same attribute prefix.
237 --filter admin-status=ENABLED
238 --filter nsd-ref=<NSD_NAME>
239 --filter nsd.vendor=<VENDOR>
240 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
241 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
243 def summarize_deployment_status(status_dict
):
250 net_list
= status_dict
.get('nets',[])
253 if net
['status'] not in status_nets
:
254 status_nets
[net
['status']] = 1
256 status_nets
[net
['status']] +=1
258 for k
,v
in status_nets
.items():
259 message
+= "{}:{},".format(k
,v
)
260 message
+= "TOTAL:{}".format(n_nets
)
261 summary
+= "{}".format(message
)
266 vnf_list
= status_dict
['vnfs']
268 member_vnf_index
= vnf
['member_vnf_index']
269 if member_vnf_index
not in status_vnfs
:
270 status_vnfs
[member_vnf_index
] = {}
271 for vm
in vnf
['vms']:
273 if vm
['status'] not in status_vms
:
274 status_vms
[vm
['status']] = 1
276 status_vms
[vm
['status']] +=1
277 if vm
['status'] not in status_vnfs
[member_vnf_index
]:
278 status_vnfs
[member_vnf_index
][vm
['status']] = 1
280 status_vnfs
[member_vnf_index
][vm
['status']] += 1
282 for k
,v
in status_vms
.items():
283 message
+= "{}:{},".format(k
,v
)
284 message
+= "TOTAL:{}".format(n_vms
)
285 summary
+= "\n{}".format(message
)
287 for k
,v
in status_vnfs
.items():
289 message
= "\n {} VMs: ".format(k
)
290 for k2
,v2
in v
.items():
291 message
+= "{}:{},".format(k2
,v2
)
293 message
+= "TOTAL:{}".format(total
)
297 def summarize_config_status(ee_list
):
305 if ee
['elementType'] not in status_ee
:
306 status_ee
[ee
['elementType']] = {}
307 status_ee
[ee
['elementType']][ee
['status']] = 1
309 if ee
['status'] in status_ee
[ee
['elementType']]:
310 status_ee
[ee
['elementType']][ee
['status']] += 1
312 status_ee
[ee
['elementType']][ee
['status']] = 1
313 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
314 if elementType
in status_ee
:
317 for k
,v
in status_ee
[elementType
].items():
318 message
+= "{}:{},".format(k
,v
)
320 message
+= "TOTAL:{}\n".format(total
)
321 summary
+= "{}: {}".format(elementType
, message
)
322 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
327 check_client_version(ctx
.obj
, '--filter')
328 filter='&'.join(filter)
329 resp
= ctx
.obj
.ns
.list(filter)
331 resp
= ctx
.obj
.ns
.list()
343 'configuration status'])
344 project_list
= ctx
.obj
.project
.list()
345 vim_list
= ctx
.obj
.vim
.list()
355 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
356 if fullclassname
== 'osmclient.sol005.client.Client':
358 logger
.debug('NS info: {}'.format(nsr
))
359 nsr_name
= nsr
['name']
361 date
= datetime
.fromtimestamp(nsr
['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
362 ns_state
= nsr
.get('nsState', nsr
['_admin']['nsState'])
364 deployment_status
= summarize_deployment_status(nsr
.get('deploymentStatus'))
365 config_status
= summarize_config_status(nsr
.get('configurationStatus'))
366 project_id
= nsr
.get('_admin').get('projects_read')[0]
368 for p
in project_list
:
369 if p
['_id'] == project_id
:
370 project_name
= p
['name']
372 #project = '{} ({})'.format(project_name, project_id)
373 project
= project_name
374 vim_id
= nsr
.get('datacenter')
377 if v
['uuid'] == vim_id
:
380 #vim = '{} ({})'.format(vim_name, vim_id)
382 if 'currentOperation' in nsr
:
383 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
385 current_operation
= "{} ({})".format(nsr
['_admin'].get('current-operation','-'), nsr
['_admin']['nslcmop'])
386 error_details
= "N/A"
387 if ns_state
== "BROKEN" or ns_state
== "DEGRADED" or \
388 ('currentOperation' not in nsr
and nsr
.get('errorDescription')):
389 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'], nsr
['errorDetail'])
391 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
392 nsr
= nsopdata
['nsr:nsr']
393 nsr_name
= nsr
['name-ref']
394 nsr_id
= nsr
['ns-instance-config-ref']
397 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
398 ns_state
= deployment_status
399 config_status
= nsr
.get('config-status', 'Not found')
400 current_operation
= "Unknown"
401 error_details
= nsr
.get('detailed-status', 'Not found')
402 if config_status
== "config_not_needed":
403 config_status
= "configured (no charms)"
412 wrap_text(text
=error_details
,width
=40),
424 wrap_text(text
=error_details
,width
=40)])
427 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
428 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
430 def nsd_list(ctx
, filter, long):
433 check_client_version(ctx
.obj
, '--filter')
434 filter='&'.join(filter)
435 resp
= ctx
.obj
.nsd
.list(filter)
437 resp
= ctx
.obj
.nsd
.list()
438 # print(yaml.safe_dump(resp))
439 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
440 if fullclassname
== 'osmclient.sol005.client.Client':
442 table
= PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state',
443 'usage state', 'date', 'last update'])
445 table
= PrettyTable(['nsd name', 'id'])
447 name
= nsd
.get('name','-')
449 onb_state
= nsd
['_admin'].get('onboardingState','-')
450 op_state
= nsd
['_admin'].get('operationalState','-')
451 usage_state
= nsd
['_admin'].get('usageState','-')
452 date
= datetime
.fromtimestamp(nsd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
453 last_update
= datetime
.fromtimestamp(nsd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
454 table
.add_row([name
, nsd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
456 table
.add_row([name
, nsd
['_id']])
458 table
= PrettyTable(['nsd name', 'id'])
460 table
.add_row([nsd
['name'], nsd
['id']])
465 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
466 @click.option('--filter', default
=None, multiple
=True,
467 help='restricts the list to the NSD/NSpkg matching the filter')
468 @click.option('--long', is_flag
=True, help='get more details')
470 def nsd_list1(ctx
, filter, long):
471 """list all NSD/NS pkg in the system"""
473 nsd_list(ctx
, filter, long)
476 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
477 @click.option('--filter', default
=None, multiple
=True,
478 help='restricts the list to the NSD/NSpkg matching the filter')
479 @click.option('--long', is_flag
=True, help='get more details')
481 def nsd_list2(ctx
, filter, long):
482 """list all NS packages"""
484 nsd_list(ctx
, filter, long)
487 def vnfd_list(ctx
, nf_type
, filter, long):
490 check_client_version(ctx
.obj
, '--nf_type')
492 check_client_version(ctx
.obj
, '--filter')
494 filter='&'.join(filter)
497 nf_filter
= "_admin.type=vnfd"
498 elif nf_type
== "pnf":
499 nf_filter
= "_admin.type=pnfd"
500 elif nf_type
== "hnf":
501 nf_filter
= "_admin.type=hnfd"
503 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
505 filter = '{}&{}'.format(nf_filter
, filter)
509 resp
= ctx
.obj
.vnfd
.list(filter)
511 resp
= ctx
.obj
.vnfd
.list()
512 # print(yaml.safe_dump(resp))
513 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
514 if fullclassname
== 'osmclient.sol005.client.Client':
516 table
= PrettyTable(['nfpkg name', 'id', 'vendor', 'version', 'onboarding state', 'operational state',
517 'usage state', 'date', 'last update'])
519 table
= PrettyTable(['nfpkg name', 'id'])
521 name
= vnfd
['name'] if 'name' in vnfd
else '-'
523 onb_state
= vnfd
['_admin'].get('onboardingState','-')
524 op_state
= vnfd
['_admin'].get('operationalState','-')
525 vendor
= vnfd
.get('vendor')
526 version
= vnfd
.get('version')
527 usage_state
= vnfd
['_admin'].get('usageState','-')
528 date
= datetime
.fromtimestamp(vnfd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
529 last_update
= datetime
.fromtimestamp(vnfd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
530 table
.add_row([name
, vnfd
['_id'], vendor
, version
, onb_state
, op_state
, usage_state
, date
, last_update
])
532 table
.add_row([name
, vnfd
['_id']])
534 table
= PrettyTable(['nfpkg name', 'id'])
536 table
.add_row([vnfd
['name'], vnfd
['id']])
541 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
542 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
543 @click.option('--filter', default
=None, multiple
=True,
544 help='restricts the list to the NF pkg matching the filter')
545 @click.option('--long', is_flag
=True, help='get more details')
547 def vnfd_list1(ctx
, nf_type
, filter, long):
548 """list all xNF packages (VNF, HNF, PNF)"""
550 vnfd_list(ctx
, nf_type
, filter, long)
553 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
554 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
555 @click.option('--filter', default
=None, multiple
=True,
556 help='restricts the list to the NFpkg matching the filter')
557 @click.option('--long', is_flag
=True, help='get more details')
559 def vnfd_list2(ctx
, nf_type
, filter, long):
560 """list all xNF packages (VNF, HNF, PNF)"""
562 vnfd_list(ctx
, nf_type
, filter, long)
565 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
566 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
567 @click.option('--filter', default
=None, multiple
=True,
568 help='restricts the list to the NFpkg matching the filter')
569 @click.option('--long', is_flag
=True, help='get more details')
571 def nfpkg_list(ctx
, nf_type
, filter, long):
572 """list all xNF packages (VNF, HNF, PNF)"""
575 check_client_version(ctx
.obj
, ctx
.command
.name
)
576 vnfd_list(ctx
, nf_type
, filter, long)
577 # except ClientException as e:
582 def pkg_repo_list(ctx
, pkgtype
, filter, repo
, long):
584 filter='&'.join(filter)
585 resp
= ctx
.obj
.osmrepo
.pkg_list(pkgtype
, filter, repo
)
587 table
= PrettyTable(['nfpkg name', 'vendor', 'version', 'latest', 'description', 'repository'])
589 table
= PrettyTable(['nfpkg name', 'repository'])
591 name
= vnfd
.get('name', '-')
592 repository
= vnfd
.get('repository')
594 vendor
= vnfd
.get('vendor')
595 version
= vnfd
.get('version')
596 description
= vnfd
.get('description')
597 latest
= vnfd
.get('latest')
598 table
.add_row([name
, vendor
, version
, latest
, description
, repository
])
600 table
.add_row([name
, repository
])
605 @cli_osm.command(name
='vnfpkg-repo-list', short_help
='list all xNF from OSM repositories')
606 @click.option('--filter', default
=None, multiple
=True,
607 help='restricts the list to the NFpkg matching the filter')
608 @click.option('--repo', default
=None,
609 help='restricts the list to a particular OSM repository')
610 @click.option('--long', is_flag
=True, help='get more details')
612 def nfpkg_repo_list1(ctx
, filter, repo
, long):
613 """list xNF packages from OSM repositories"""
615 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
618 @cli_osm.command(name
='nfpkg-repo-list', short_help
='list all xNF from OSM repositories')
619 @click.option('--filter', default
=None, multiple
=True,
620 help='restricts the list to the NFpkg matching the filter')
621 @click.option('--repo', default
=None,
622 help='restricts the list to a particular OSM repository')
623 @click.option('--long', is_flag
=True, help='get more details')
625 def nfpkg_repo_list2(ctx
, filter, repo
, long):
626 """list xNF packages from OSM repositories"""
628 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
631 @cli_osm.command(name
='nsd-repo-list', short_help
='list all NS from OSM repositories')
632 @click.option('--filter', default
=None, multiple
=True,
633 help='restricts the list to the NS matching the filter')
634 @click.option('--repo', default
=None,
635 help='restricts the list to a particular OSM repository')
636 @click.option('--long', is_flag
=True, help='get more details')
638 def nspkg_repo_list(ctx
, filter, repo
, long):
639 """list xNF packages from OSM repositories"""
641 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
644 @cli_osm.command(name
='nspkg-repo-list', short_help
='list all NS from OSM repositories')
645 @click.option('--filter', default
=None, multiple
=True,
646 help='restricts the list to the NS matching the filter')
647 @click.option('--repo', default
=None,
648 help='restricts the list to a particular OSM repository')
649 @click.option('--long', is_flag
=True, help='get more details')
651 def nspkg_repo_list2(ctx
, filter, repo
, long):
652 """list xNF packages from OSM repositories"""
654 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
657 def vnf_list(ctx
, ns
, filter, long):
661 check_client_version(ctx
.obj
, '--ns')
663 filter='&'.join(filter)
664 check_client_version(ctx
.obj
, '--filter')
665 resp
= ctx
.obj
.vnf
.list(ns
, filter)
667 resp
= ctx
.obj
.vnf
.list()
668 # except ClientException as e:
671 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
672 if fullclassname
== 'osmclient.sol005.client.Client':
673 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
674 'vnfd name', 'vim account id', 'ip address']
676 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
677 'vnfd name', 'vim account id', 'ip address',
678 'date', 'last update']
679 table
= PrettyTable(field_names
)
681 name
= vnfr
['name'] if 'name' in vnfr
else '-'
682 new_row
= [vnfr
['_id'], name
, vnfr
['nsr-id-ref'],
683 vnfr
['member-vnf-index-ref'], vnfr
['vnfd-ref'],
684 vnfr
['vim-account-id'], vnfr
['ip-address']]
686 date
= datetime
.fromtimestamp(vnfr
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
687 last_update
= datetime
.fromtimestamp(vnfr
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
688 new_row
.extend([date
, last_update
])
689 table
.add_row(new_row
)
694 'operational status',
697 if 'mgmt-interface' not in vnfr
:
698 vnfr
['mgmt-interface'] = {}
699 vnfr
['mgmt-interface']['ip-address'] = None
703 vnfr
['operational-status'],
704 vnfr
['config-status']])
709 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
710 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
711 @click.option('--filter', default
=None, multiple
=True,
712 help='restricts the list to the NF instances matching the filter.')
713 @click.option('--long', is_flag
=True, help='get more details')
715 def vnf_list1(ctx
, ns
, filter, long):
716 """list all NF instances"""
718 vnf_list(ctx
, ns
, filter, long)
721 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
722 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
723 @click.option('--filter', default
=None, multiple
=True,
724 help='restricts the list to the NF instances matching the filter.')
725 @click.option('--long', is_flag
=True, help='get more details')
727 def nf_list(ctx
, ns
, filter, long):
728 """list all NF instances
732 --ns TEXT NS instance id or name to restrict the VNF list
733 --filter filterExpr Restricts the list to the VNF instances matching the filter
736 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
737 concatenated using the "&" character:
740 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
741 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
742 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
744 value := scalar value
748 * zero or more occurrences
749 ? zero or one occurrence
750 [] grouping of expressions to be used with ? and *
751 "" quotation marks for marking string constants
755 "AttrName" is the name of one attribute in the data type that defines the representation
756 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
757 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
758 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
759 entries, it means that the operator "op" is applied to the attribute addressed by the last
760 <attrName> entry included in the concatenation. All simple filter expressions are combined
761 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
762 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
763 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
764 prefix". If an attribute referenced in an expression is an array, an object that contains a
765 corresponding array shall be considered to match the expression if any of the elements in the
766 array matches all expressions that have the same attribute prefix.
770 --filter vim-account-id=<VIM_ACCOUNT_ID>
771 --filter vnfd-ref=<VNFD_NAME>
772 --filter vdur.ip-address=<IP_ADDRESS>
773 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
776 vnf_list(ctx
, ns
, filter, long)
779 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
780 @click.argument('name')
781 @click.option('--long', is_flag
=True,
782 help='get more details of the NS operation (date, ).')
784 def ns_op_list(ctx
, name
, long):
785 """shows the history of operations over a NS instance
787 NAME: name or ID of the NS instance
789 def formatParams(params
):
790 if params
['lcmOperationType']=='instantiate':
791 params
.pop('nsDescription')
795 elif params
['lcmOperationType']=='action':
796 params
.pop('primitive')
797 params
.pop('lcmOperationType')
798 params
.pop('nsInstanceId')
803 check_client_version(ctx
.obj
, ctx
.command
.name
)
804 resp
= ctx
.obj
.ns
.list_op(name
)
805 # except ClientException as e:
810 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
812 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
814 #print(yaml.safe_dump(resp))
817 if op
['lcmOperationType']=='action':
818 action_name
= op
['operationParams']['primitive']
820 if op
['operationState'] == 'PROCESSING':
821 if op
['queuePosition'] is not None and op
['queuePosition'] > 0:
822 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
823 elif op
['lcmOperationType'] in ('instantiate', 'terminate'):
826 elif op
['operationState'] in ('FAILED', 'FAILED_TEMP'):
827 detail
= op
.get('errorMessage','-')
828 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
829 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
831 table
.add_row([op
['id'],
832 op
['lcmOperationType'],
834 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
835 op
['operationState'],
838 wrap_text(text
=detail
,width
=50)])
840 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
841 op
['operationState'], date
, wrap_text(text
=detail
or "",width
=50)])
846 def nsi_list(ctx
, filter):
847 """list all Network Slice Instances"""
850 check_client_version(ctx
.obj
, ctx
.command
.name
)
852 filter='&'.join(filter)
853 resp
= ctx
.obj
.nsi
.list(filter)
854 # except ClientException as e:
858 ['netslice instance name',
860 'operational status',
864 nsi_name
= nsi
['name']
866 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
867 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
868 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
869 if configstatus
== "config_not_needed":
870 configstatus
= "configured (no charms)"
881 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
882 @click.option('--filter', default
=None, multiple
=True,
883 help='restricts the list to the Network Slice Instances matching the filter')
885 def nsi_list1(ctx
, filter):
886 """list all Network Slice Instances (NSI)"""
888 nsi_list(ctx
, filter)
891 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
892 @click.option('--filter', default
=None, multiple
=True,
893 help='restricts the list to the Network Slice Instances matching the filter')
895 def nsi_list2(ctx
, filter):
896 """list all Network Slice Instances (NSI)"""
898 nsi_list(ctx
, filter)
901 def nst_list(ctx
, filter):
904 check_client_version(ctx
.obj
, ctx
.command
.name
)
906 filter='&'.join(filter)
907 resp
= ctx
.obj
.nst
.list(filter)
908 # except ClientException as e:
911 # print(yaml.safe_dump(resp))
912 table
= PrettyTable(['nst name', 'id'])
914 name
= nst
['name'] if 'name' in nst
else '-'
915 table
.add_row([name
, nst
['_id']])
920 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
921 @click.option('--filter', default
=None, multiple
=True,
922 help='restricts the list to the NST matching the filter')
924 def nst_list1(ctx
, filter):
925 """list all Network Slice Templates (NST) in the system"""
927 nst_list(ctx
, filter)
930 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
931 @click.option('--filter', default
=None, multiple
=True,
932 help='restricts the list to the NST matching the filter')
934 def nst_list2(ctx
, filter):
935 """list all Network Slice Templates (NST) in the system"""
937 nst_list(ctx
, filter)
940 def nsi_op_list(ctx
, name
):
943 check_client_version(ctx
.obj
, ctx
.command
.name
)
944 resp
= ctx
.obj
.nsi
.list_op(name
)
945 # except ClientException as e:
948 table
= PrettyTable(['id', 'operation', 'status'])
950 table
.add_row([op
['id'], op
['lcmOperationType'],
951 op
['operationState']])
956 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
957 @click.argument('name')
959 def nsi_op_list1(ctx
, name
):
960 """shows the history of operations over a Network Slice Instance (NSI)
962 NAME: name or ID of the Network Slice Instance
965 nsi_op_list(ctx
, name
)
968 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
969 @click.argument('name')
971 def nsi_op_list2(ctx
, name
):
972 """shows the history of operations over a Network Slice Instance (NSI)
974 NAME: name or ID of the Network Slice Instance
977 nsi_op_list(ctx
, name
)
980 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
981 @click.option('--filter', default
=None, multiple
=True,
982 help='restricts the list to the Physical Deployment Units matching the filter')
984 def pdu_list(ctx
, filter):
985 """list all Physical Deployment Units (PDU)"""
988 check_client_version(ctx
.obj
, ctx
.command
.name
)
990 filter='&'.join(filter)
991 resp
= ctx
.obj
.pdu
.list(filter)
992 # except ClientException as e:
1001 pdu_name
= pdu
['name']
1003 pdu_type
= pdu
['type']
1004 pdu_ipaddress
= "None"
1005 for iface
in pdu
['interfaces']:
1007 pdu_ipaddress
= iface
['ip-address']
1018 ####################
1020 ####################
1022 def nsd_show(ctx
, name
, literal
):
1025 resp
= ctx
.obj
.nsd
.get(name
)
1026 # resp = ctx.obj.nsd.get_individual(name)
1027 # except ClientException as e:
1032 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1035 table
= PrettyTable(['field', 'value'])
1036 for k
, v
in list(resp
.items()):
1037 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1042 @cli_osm.command(name
='nsd-show', short_help
='shows the details of a NS package')
1043 @click.option('--literal', is_flag
=True,
1044 help='print literally, no pretty table')
1045 @click.argument('name')
1047 def nsd_show1(ctx
, name
, literal
):
1048 """shows the content of a NSD
1050 NAME: name or ID of the NSD/NSpkg
1053 nsd_show(ctx
, name
, literal
)
1056 @cli_osm.command(name
='nspkg-show', short_help
='shows the details of a NS package')
1057 @click.option('--literal', is_flag
=True,
1058 help='print literally, no pretty table')
1059 @click.argument('name')
1061 def nsd_show2(ctx
, name
, literal
):
1062 """shows the content of a NSD
1064 NAME: name or ID of the NSD/NSpkg
1067 nsd_show(ctx
, name
, literal
)
1070 def vnfd_show(ctx
, name
, literal
):
1073 resp
= ctx
.obj
.vnfd
.get(name
)
1074 # resp = ctx.obj.vnfd.get_individual(name)
1075 # except ClientException as e:
1080 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1083 table
= PrettyTable(['field', 'value'])
1084 for k
, v
in list(resp
.items()):
1085 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1090 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1093 filter='&'.join(filter)
1095 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1098 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1101 catalog
= pkgtype
+ '-catalog'
1102 full_catalog
= pkgtype
+ ':' + catalog
1103 if resp
.get(catalog
):
1104 resp
= resp
.pop(catalog
)[pkgtype
][0]
1105 elif resp
.get(full_catalog
):
1106 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1108 table
= PrettyTable(['field', 'value'])
1109 for k
, v
in list(resp
.items()):
1110 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1115 @cli_osm.command(name
='vnfd-show', short_help
='shows the details of a NF package')
1116 @click.option('--literal', is_flag
=True,
1117 help='print literally, no pretty table')
1118 @click.argument('name')
1120 def vnfd_show1(ctx
, name
, literal
):
1121 """shows the content of a VNFD
1123 NAME: name or ID of the VNFD/VNFpkg
1126 vnfd_show(ctx
, name
, literal
)
1129 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the details of a NF package')
1130 @click.option('--literal', is_flag
=True,
1131 help='print literally, no pretty table')
1132 @click.argument('name')
1134 def vnfd_show2(ctx
, name
, literal
):
1135 """shows the content of a VNFD
1137 NAME: name or ID of the VNFD/VNFpkg
1140 vnfd_show(ctx
, name
, literal
)
1143 @cli_osm.command(name
='vnfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1144 @click.option('--literal', is_flag
=True,
1145 help='print literally, no pretty table')
1146 @click.option('--repo',
1148 help='Repository name')
1149 @click.argument('name')
1150 @click.option('--filter', default
=None, multiple
=True,
1151 help='filter by fields')
1152 @click.option('--version',
1154 help='package version')
1156 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1157 """shows the content of a VNFD in a repository
1159 NAME: name or ID of the VNFD/VNFpkg
1162 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1165 @cli_osm.command(name
='nsd-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1166 @click.option('--literal', is_flag
=True,
1167 help='print literally, no pretty table')
1168 @click.option('--repo',
1170 help='Repository name')
1171 @click.argument('name')
1172 @click.option('--filter', default
=None, multiple
=True,
1173 help='filter by fields')
1174 @click.option('--version',
1176 help='package version')
1178 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1179 """shows the content of a VNFD in a repository
1181 NAME: name or ID of the VNFD/VNFpkg
1184 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1187 @cli_osm.command(name
='nspkg-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1188 @click.option('--literal', is_flag
=True,
1189 help='print literally, no pretty table')
1190 @click.option('--repo',
1192 help='Repository name')
1193 @click.argument('name')
1194 @click.option('--filter', default
=None, multiple
=True,
1195 help='filter by fields')
1196 @click.option('--version',
1198 help='package version')
1200 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1201 """shows the content of a VNFD in a repository
1203 NAME: name or ID of the VNFD/VNFpkg
1206 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1209 @cli_osm.command(name
='nfpkg-show', short_help
='shows the details of a NF package')
1210 @click.option('--literal', is_flag
=True,
1211 help='print literally, no pretty table')
1212 @click.argument('name')
1214 def nfpkg_show(ctx
, name
, literal
):
1215 """shows the content of a NF Descriptor
1217 NAME: name or ID of the NFpkg
1220 vnfd_show(ctx
, name
, literal
)
1223 @cli_osm.command(name
='nfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1224 @click.option('--literal', is_flag
=True,
1225 help='print literally, no pretty table')
1226 @click.option('--repo',
1228 help='Repository name')
1229 @click.argument('name')
1230 @click.option('--filter', default
=None, multiple
=True,
1231 help='filter by fields')
1232 @click.option('--version',
1234 help='package version')
1236 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1237 """shows the content of a VNFD in a repository
1239 NAME: name or ID of the VNFD/VNFpkg
1242 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1245 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
1246 @click.argument('name')
1247 @click.option('--literal', is_flag
=True,
1248 help='print literally, no pretty table')
1249 @click.option('--filter', multiple
=True,
1250 help='restricts the information to the fields in the filter')
1252 def ns_show(ctx
, name
, literal
, filter):
1253 """shows the info of a NS instance
1255 NAME: name or ID of the NS instance
1259 ns
= ctx
.obj
.ns
.get(name
)
1260 # except ClientException as e:
1265 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1268 table
= PrettyTable(['field', 'value'])
1270 for k
, v
in list(ns
.items()):
1271 if not filter or k
in filter:
1272 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1274 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1275 if fullclassname
!= 'osmclient.sol005.client.Client':
1276 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1277 nsr_optdata
= nsopdata
['nsr:nsr']
1278 for k
, v
in list(nsr_optdata
.items()):
1279 if not filter or k
in filter:
1280 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1285 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1286 @click.argument('name')
1287 @click.option('--literal', is_flag
=True,
1288 help='print literally, no pretty table')
1289 @click.option('--filter', multiple
=True,
1290 help='restricts the information to the fields in the filter')
1291 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1293 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1294 """shows the info of a VNF instance
1296 NAME: name or ID of the VNF instance
1298 def print_kdu_status(op_info_status
):
1299 """print KDU status properly formatted
1302 op_status
= yaml
.safe_load(op_info_status
)
1303 if "namespace" in op_status
and "info" in op_status
and \
1304 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1305 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1306 "seconds" in op_status
["info"]["last_deployed"]:
1307 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1308 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1309 print("NAMESPACE: {}".format(op_status
["namespace"]))
1310 status_code
= "UNKNOWN"
1311 if op_status
["info"]["status"]["code"]==1:
1312 status_code
= "DEPLOYED"
1313 print("STATUS: {}".format(status_code
))
1316 print(op_status
["info"]["status"]["resources"])
1317 if "notes" in op_status
["info"]["status"]:
1319 print(op_status
["info"]["status"]["notes"])
1321 print(op_info_status
)
1323 print(op_info_status
)
1328 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1330 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1333 check_client_version(ctx
.obj
, ctx
.command
.name
)
1334 resp
= ctx
.obj
.vnf
.get(name
)
1337 ns_id
= resp
['nsr-id-ref']
1339 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1340 op_data
['kdu_name'] = kdu
1341 op_data
['primitive'] = 'status'
1342 op_data
['primitive_params'] = {}
1343 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1346 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1347 if op_info
['operationState'] == 'COMPLETED':
1348 print_kdu_status(op_info
['detailed-status'])
1352 print ("Could not determine KDU status")
1356 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1359 table
= PrettyTable(['field', 'value'])
1361 for k
, v
in list(resp
.items()):
1362 if not filter or k
in filter:
1363 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1366 # except ClientException as e:
1371 #@cli_osm.command(name='vnf-monitoring-show')
1372 #@click.argument('vnf_name')
1373 #@click.pass_context
1374 #def vnf_monitoring_show(ctx, vnf_name):
1376 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1377 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1378 # except ClientException as e:
1382 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1383 # if resp is not None:
1384 # for monitor in resp:
1388 # monitor['value-integer'],
1389 # monitor['units']])
1394 #@cli_osm.command(name='ns-monitoring-show')
1395 #@click.argument('ns_name')
1396 #@click.pass_context
1397 #def ns_monitoring_show(ctx, ns_name):
1399 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1400 # resp = ctx.obj.ns.get_monitoring(ns_name)
1401 # except ClientException as e:
1405 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1406 # for key, val in list(resp.items()):
1407 # for monitor in val:
1411 # monitor['value-integer'],
1412 # monitor['units']])
1417 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1418 @click.argument('id')
1419 @click.option('--filter', multiple
=True,
1420 help='restricts the information to the fields in the filter')
1421 @click.option('--literal', is_flag
=True,
1422 help='print literally, no pretty table')
1424 def ns_op_show(ctx
, id, filter, literal
):
1425 """shows the detailed info of a NS operation
1427 ID: operation identifier
1431 check_client_version(ctx
.obj
, ctx
.command
.name
)
1432 op_info
= ctx
.obj
.ns
.get_op(id)
1433 # except ClientException as e:
1438 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1441 table
= PrettyTable(['field', 'value'])
1442 for k
, v
in list(op_info
.items()):
1443 if not filter or k
in filter:
1444 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1449 def nst_show(ctx
, name
, literal
):
1452 check_client_version(ctx
.obj
, ctx
.command
.name
)
1453 resp
= ctx
.obj
.nst
.get(name
)
1454 #resp = ctx.obj.nst.get_individual(name)
1455 # except ClientException as e:
1460 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1463 table
= PrettyTable(['field', 'value'])
1464 for k
, v
in list(resp
.items()):
1465 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1470 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1471 @click.option('--literal', is_flag
=True,
1472 help='print literally, no pretty table')
1473 @click.argument('name')
1475 def nst_show1(ctx
, name
, literal
):
1476 """shows the content of a Network Slice Template (NST)
1478 NAME: name or ID of the NST
1481 nst_show(ctx
, name
, literal
)
1484 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1485 @click.option('--literal', is_flag
=True,
1486 help='print literally, no pretty table')
1487 @click.argument('name')
1489 def nst_show2(ctx
, name
, literal
):
1490 """shows the content of a Network Slice Template (NST)
1492 NAME: name or ID of the NST
1495 nst_show(ctx
, name
, literal
)
1498 def nsi_show(ctx
, name
, literal
, filter):
1501 check_client_version(ctx
.obj
, ctx
.command
.name
)
1502 nsi
= ctx
.obj
.nsi
.get(name
)
1503 # except ClientException as e:
1508 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1511 table
= PrettyTable(['field', 'value'])
1513 for k
, v
in list(nsi
.items()):
1514 if not filter or k
in filter:
1515 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1521 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1522 @click.argument('name')
1523 @click.option('--literal', is_flag
=True,
1524 help='print literally, no pretty table')
1525 @click.option('--filter', multiple
=True,
1526 help='restricts the information to the fields in the filter')
1528 def nsi_show1(ctx
, name
, literal
, filter):
1529 """shows the content of a Network Slice Instance (NSI)
1531 NAME: name or ID of the Network Slice Instance
1534 nsi_show(ctx
, name
, literal
, filter)
1537 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1538 @click.argument('name')
1539 @click.option('--literal', is_flag
=True,
1540 help='print literally, no pretty table')
1541 @click.option('--filter', multiple
=True,
1542 help='restricts the information to the fields in the filter')
1544 def nsi_show2(ctx
, name
, literal
, filter):
1545 """shows the content of a Network Slice Instance (NSI)
1547 NAME: name or ID of the Network Slice Instance
1550 nsi_show(ctx
, name
, literal
, filter)
1553 def nsi_op_show(ctx
, id, filter):
1556 check_client_version(ctx
.obj
, ctx
.command
.name
)
1557 op_info
= ctx
.obj
.nsi
.get_op(id)
1558 # except ClientException as e:
1562 table
= PrettyTable(['field', 'value'])
1563 for k
, v
in list(op_info
.items()):
1564 if not filter or k
in filter:
1565 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1570 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1571 @click.argument('id')
1572 @click.option('--filter', multiple
=True,
1573 help='restricts the information to the fields in the filter')
1575 def nsi_op_show1(ctx
, id, filter):
1576 """shows the info of an operation over a Network Slice Instance(NSI)
1578 ID: operation identifier
1581 nsi_op_show(ctx
, id, filter)
1584 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1585 @click.argument('id')
1586 @click.option('--filter', multiple
=True,
1587 help='restricts the information to the fields in the filter')
1589 def nsi_op_show2(ctx
, id, filter):
1590 """shows the info of an operation over a Network Slice Instance(NSI)
1592 ID: operation identifier
1595 nsi_op_show(ctx
, id, filter)
1598 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1599 @click.argument('name')
1600 @click.option('--literal', is_flag
=True,
1601 help='print literally, no pretty table')
1602 @click.option('--filter', multiple
=True,
1603 help='restricts the information to the fields in the filter')
1605 def pdu_show(ctx
, name
, literal
, filter):
1606 """shows the content of a Physical Deployment Unit (PDU)
1608 NAME: name or ID of the PDU
1612 check_client_version(ctx
.obj
, ctx
.command
.name
)
1613 pdu
= ctx
.obj
.pdu
.get(name
)
1614 # except ClientException as e:
1619 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1622 table
= PrettyTable(['field', 'value'])
1624 for k
, v
in list(pdu
.items()):
1625 if not filter or k
in filter:
1626 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1632 ####################
1634 ####################
1636 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1639 check_client_version(ctx
.obj
, ctx
.command
.name
)
1641 filename
= ctx
.obj
.osmrepo
.get_pkg('ns', filename
, repo
, vendor
, version
)
1642 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1643 # except ClientException as e:
1648 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1649 @click.argument('filename')
1650 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1651 help='Deprecated. Use override')
1652 @click.option('--override', 'overwrite', default
=None,
1653 help='overrides fields in descriptor, format: '
1654 '"key1.key2...=value[;key3...=value;...]"')
1655 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1656 help='The charm will not be compiled, it is assumed to already exist')
1657 @click.option('--repo', default
=None,
1658 help='[repository]: Repository name')
1659 @click.option('--vendor', default
=None,
1660 help='[repository]: filter by vendor]')
1661 @click.option('--version', default
='latest',
1662 help='[repository]: filter by version. Default: latest')
1664 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1665 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1668 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1669 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1670 If FILENAME is an NF Package folder, it is built and then onboarded.
1673 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1677 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1678 @click.argument('filename')
1679 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1680 help='Deprecated. Use override')
1681 @click.option('--override', 'overwrite', default
=None,
1682 help='overrides fields in descriptor, format: '
1683 '"key1.key2...=value[;key3...=value;...]"')
1684 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1685 help='The charm will not be compiled, it is assumed to already exist')
1686 @click.option('--repo', default
=None,
1687 help='[repository]: Repository name')
1688 @click.option('--vendor', default
=None,
1689 help='[repository]: filter by vendor]')
1690 @click.option('--version', default
='latest',
1691 help='[repository]: filter by version. Default: latest')
1693 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1694 """onboards a new NSpkg
1696 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1697 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1698 If FILENAME is an NF Package folder, it is built and then onboarded.
1701 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1705 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1706 repo
, vendor
, version
):
1709 check_client_version(ctx
.obj
, ctx
.command
.name
)
1711 filename
= ctx
.obj
.osmrepo
.get_pkg('vnf', filename
, repo
, vendor
, version
)
1712 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1713 override_epa
=override_epa
, override_nonepa
=override_nonepa
,
1714 override_paravirt
=override_paravirt
)
1715 # except ClientException as e:
1720 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1721 @click.argument('filename')
1722 @click.option('--overwrite', 'overwrite', default
=None,
1723 help='overwrite deprecated, use override')
1724 @click.option('--override', 'overwrite', default
=None,
1725 help='overrides fields in descriptor, format: '
1726 '"key1.key2...=value[;key3...=value;...]"')
1727 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1728 help='The charm will not be compiled, it is assumed to already exist')
1729 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1730 help='adds guest-epa parameters to all VDU')
1731 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1732 help='removes all guest-epa parameters from all VDU')
1733 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1734 help='overrides all VDU interfaces to PARAVIRT')
1735 @click.option('--repo', default
=None,
1736 help='[repository]: Repository name')
1737 @click.option('--vendor', default
=None,
1738 help='[repository]: filter by vendor]')
1739 @click.option('--version', default
='latest',
1740 help='[repository]: filter by version. Default: latest')
1742 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1743 repo
,vendor
, version
):
1744 """creates a new VNFD/VNFpkg
1746 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1747 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1748 If FILENAME is an NF Package folder, it is built and then onboarded.
1751 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1752 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1753 repo
=repo
, vendor
=vendor
, version
=version
)
1756 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1757 @click.argument('filename')
1758 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1759 help='Deprecated. Use override')
1760 @click.option('--override', 'overwrite', default
=None,
1761 help='overrides fields in descriptor, format: '
1762 '"key1.key2...=value[;key3...=value;...]"')
1763 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1764 help='The charm will not be compiled, it is assumed to already exist')
1765 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1766 help='adds guest-epa parameters to all VDU')
1767 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1768 help='removes all guest-epa parameters from all VDU')
1769 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1770 help='overrides all VDU interfaces to PARAVIRT')
1771 @click.option('--repo', default
=None,
1772 help='[repository]: Repository name')
1773 @click.option('--vendor', default
=None,
1774 help='[repository]: filter by vendor]')
1775 @click.option('--version', default
='latest',
1776 help='[repository]: filter by version. Default: latest')
1778 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1779 repo
, vendor
, version
):
1780 """creates a new VNFD/VNFpkg
1782 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1783 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1784 If FILENAME is an NF Package folder, it is built and then onboarded.
1787 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1788 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1789 repo
=repo
, vendor
=vendor
, version
=version
)
1791 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1792 @click.argument('filename')
1793 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1794 help='Deprecated. Use override')
1795 @click.option('--override', 'overwrite', default
=None,
1796 help='overrides fields in descriptor, format: '
1797 '"key1.key2...=value[;key3...=value;...]"')
1798 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1799 help='The charm will not be compiled, it is assumed to already exist')
1800 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1801 help='adds guest-epa parameters to all VDU')
1802 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1803 help='removes all guest-epa parameters from all VDU')
1804 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1805 help='overrides all VDU interfaces to PARAVIRT')
1806 @click.option('--repo', default
=None,
1807 help='[repository]: Repository name')
1808 @click.option('--vendor', default
=None,
1809 help='[repository]: filter by vendor]')
1810 @click.option('--version', default
='latest',
1811 help='[repository]: filter by version. Default: latest')
1813 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1814 repo
, vendor
, version
):
1815 """creates a new NFpkg
1818 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1819 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1820 If FILENAME is an NF Package folder, it is built and then onboarded.
1823 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1824 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1825 repo
=repo
, vendor
=vendor
, version
=version
)
1828 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1829 @click.option('--ns_name',
1830 prompt
=True, help='name of the NS instance')
1831 @click.option('--nsd_name',
1832 prompt
=True, help='name of the NS descriptor')
1833 @click.option('--vim_account',
1834 prompt
=True, help='default VIM account id or name for the deployment')
1835 @click.option('--admin_status',
1837 help='administration status')
1838 @click.option('--ssh_keys',
1840 help='comma separated list of public key files to inject to vnfs')
1841 @click.option('--config',
1843 help='ns specific yaml configuration')
1844 @click.option('--config_file',
1846 help='ns specific yaml configuration file')
1847 @click.option('--wait',
1851 help='do not return the control immediately, but keep it '
1852 'until the operation is completed, or timeout')
1863 """creates a new NS instance"""
1867 check_client_version(ctx
.obj
, '--config_file')
1869 raise ClientException('"--config" option is incompatible with "--config_file" option')
1870 with
open(config_file
, 'r') as cf
:
1877 account
=vim_account
,
1879 # except ClientException as e:
1884 def nst_create(ctx
, filename
, overwrite
):
1887 check_client_version(ctx
.obj
, ctx
.command
.name
)
1888 ctx
.obj
.nst
.create(filename
, overwrite
)
1889 # except ClientException as e:
1894 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1895 @click.argument('filename')
1896 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1897 help='Deprecated. Use override')
1898 @click.option('--override', 'overwrite', default
=None,
1899 help='overrides fields in descriptor, format: '
1900 '"key1.key2...=value[;key3...=value;...]"')
1902 def nst_create1(ctx
, filename
, overwrite
):
1903 """creates a new Network Slice Template (NST)
1905 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1908 nst_create(ctx
, filename
, overwrite
)
1911 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1912 @click.argument('filename')
1913 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1914 help='Deprecated. Use override')
1915 @click.option('--override', 'overwrite', default
=None,
1916 help='overrides fields in descriptor, format: '
1917 '"key1.key2...=value[;key3...=value;...]"')
1919 def nst_create2(ctx
, filename
, overwrite
):
1920 """creates a new Network Slice Template (NST)
1922 FILENAME: NST yaml file or NSTpkg tar.gz file
1925 nst_create(ctx
, filename
, overwrite
)
1928 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1929 """creates a new Network Slice Instance (NSI)"""
1932 check_client_version(ctx
.obj
, ctx
.command
.name
)
1935 raise ClientException('"--config" option is incompatible with "--config_file" option')
1936 with
open(config_file
, 'r') as cf
:
1938 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1939 account
=vim_account
, wait
=wait
)
1940 # except ClientException as e:
1945 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1946 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1947 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1948 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1949 @click.option('--ssh_keys', default
=None,
1950 help='comma separated list of keys to inject to vnfs')
1951 @click.option('--config', default
=None,
1952 help='Netslice specific yaml configuration:\n'
1953 'netslice_subnet: [\n'
1954 'id: TEXT, vim_account: TEXT,\n'
1955 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1956 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1957 'additionalParamsForNsi: {param: value, ...}\n'
1958 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1960 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1962 @click.option('--config_file',
1964 help='nsi specific yaml configuration file')
1965 @click.option('--wait',
1969 help='do not return the control immediately, but keep it '
1970 'until the operation is completed, or timeout')
1972 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1973 """creates a new Network Slice Instance (NSI)"""
1975 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1978 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1979 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1980 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1981 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1982 @click.option('--ssh_keys', default
=None,
1983 help='comma separated list of keys to inject to vnfs')
1984 @click.option('--config', default
=None,
1985 help='Netslice specific yaml configuration:\n'
1986 'netslice_subnet: [\n'
1987 'id: TEXT, vim_account: TEXT,\n'
1988 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1989 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1991 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1993 @click.option('--config_file',
1995 help='nsi specific yaml configuration file')
1996 @click.option('--wait',
2000 help='do not return the control immediately, but keep it '
2001 'until the operation is completed, or timeout')
2003 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
2004 """creates a new Network Slice Instance (NSI)"""
2006 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
2009 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
2010 @click.option('--name', help='name of the Physical Deployment Unit')
2011 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
2012 @click.option('--interface',
2013 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
2014 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
2016 @click.option('--description', help='human readable description')
2017 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
2018 @click.option('--descriptor_file', default
=None,
2019 help='PDU descriptor file (as an alternative to using the other arguments')
2021 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
2022 """creates a new Physical Deployment Unit (PDU)"""
2025 check_client_version(ctx
.obj
, ctx
.command
.name
)
2027 if not descriptor_file
:
2029 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
2031 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
2033 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
2035 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
2037 with
open(descriptor_file
, 'r') as df
:
2038 pdu
= yaml
.safe_load(df
.read())
2039 if name
: pdu
["name"] = name
2040 if pdu_type
: pdu
["type"] = pdu_type
2041 if description
: pdu
["description"] = description
2042 if vim_account
: pdu
["vim_accounts"] = vim_account
2045 for iface
in interface
:
2046 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
2047 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
2048 ifaces_list
.append(new_iface
)
2049 pdu
["interfaces"] = ifaces_list
2050 ctx
.obj
.pdu
.create(pdu
)
2051 # except ClientException as e:
2056 ####################
2058 ####################
2060 def nsd_update(ctx
, name
, content
):
2063 check_client_version(ctx
.obj
, ctx
.command
.name
)
2064 ctx
.obj
.nsd
.update(name
, content
)
2065 # except ClientException as e:
2070 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
2071 @click.argument('name')
2072 @click.option('--content', default
=None,
2073 help='filename with the NSD/NSpkg replacing the current one')
2075 def nsd_update1(ctx
, name
, content
):
2076 """updates a NSD/NSpkg
2078 NAME: name or ID of the NSD/NSpkg
2081 nsd_update(ctx
, name
, content
)
2084 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
2085 @click.argument('name')
2086 @click.option('--content', default
=None,
2087 help='filename with the NSD/NSpkg replacing the current one')
2089 def nsd_update2(ctx
, name
, content
):
2090 """updates a NSD/NSpkg
2092 NAME: name or ID of the NSD/NSpkg
2095 nsd_update(ctx
, name
, content
)
2098 def vnfd_update(ctx
, name
, content
):
2101 check_client_version(ctx
.obj
, ctx
.command
.name
)
2102 ctx
.obj
.vnfd
.update(name
, content
)
2103 # except ClientException as e:
2108 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
2109 @click.argument('name')
2110 @click.option('--content', default
=None,
2111 help='filename with the VNFD/VNFpkg replacing the current one')
2113 def vnfd_update1(ctx
, name
, content
):
2114 """updates a VNFD/VNFpkg
2116 NAME: name or ID of the VNFD/VNFpkg
2119 vnfd_update(ctx
, name
, content
)
2122 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
2123 @click.argument('name')
2124 @click.option('--content', default
=None,
2125 help='filename with the VNFD/VNFpkg replacing the current one')
2127 def vnfd_update2(ctx
, name
, content
):
2128 """updates a VNFD/VNFpkg
2130 NAME: VNFD yaml file or VNFpkg tar.gz file
2133 vnfd_update(ctx
, name
, content
)
2136 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
2137 @click.argument('name')
2138 @click.option('--content', default
=None,
2139 help='filename with the NFpkg replacing the current one')
2141 def nfpkg_update(ctx
, name
, content
):
2144 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2147 vnfd_update(ctx
, name
, content
)
2150 def nst_update(ctx
, name
, content
):
2153 check_client_version(ctx
.obj
, ctx
.command
.name
)
2154 ctx
.obj
.nst
.update(name
, content
)
2155 # except ClientException as e:
2160 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
2161 @click.argument('name')
2162 @click.option('--content', default
=None,
2163 help='filename with the NST/NSTpkg replacing the current one')
2165 def nst_update1(ctx
, name
, content
):
2166 """updates a Network Slice Template (NST)
2168 NAME: name or ID of the NSD/NSpkg
2171 nst_update(ctx
, name
, content
)
2174 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
2175 @click.argument('name')
2176 @click.option('--content', default
=None,
2177 help='filename with the NST/NSTpkg replacing the current one')
2179 def nst_update2(ctx
, name
, content
):
2180 """updates a Network Slice Template (NST)
2182 NAME: name or ID of the NSD/NSpkg
2185 nst_update(ctx
, name
, content
)
2188 ####################
2190 ####################
2192 def nsd_delete(ctx
, name
, force
):
2196 ctx
.obj
.nsd
.delete(name
)
2198 check_client_version(ctx
.obj
, '--force')
2199 ctx
.obj
.nsd
.delete(name
, force
)
2200 # except ClientException as e:
2205 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
2206 @click.argument('name')
2207 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2209 def nsd_delete1(ctx
, name
, force
):
2210 """deletes a NSD/NSpkg
2212 NAME: name or ID of the NSD/NSpkg to be deleted
2215 nsd_delete(ctx
, name
, force
)
2218 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
2219 @click.argument('name')
2220 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2222 def nsd_delete2(ctx
, name
, force
):
2223 """deletes a NSD/NSpkg
2225 NAME: name or ID of the NSD/NSpkg to be deleted
2228 nsd_delete(ctx
, name
, force
)
2231 def vnfd_delete(ctx
, name
, force
):
2235 ctx
.obj
.vnfd
.delete(name
)
2237 check_client_version(ctx
.obj
, '--force')
2238 ctx
.obj
.vnfd
.delete(name
, force
)
2239 # except ClientException as e:
2244 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
2245 @click.argument('name')
2246 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2248 def vnfd_delete1(ctx
, name
, force
):
2249 """deletes a VNFD/VNFpkg
2251 NAME: name or ID of the VNFD/VNFpkg to be deleted
2254 vnfd_delete(ctx
, name
, force
)
2257 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
2258 @click.argument('name')
2259 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2261 def vnfd_delete2(ctx
, name
, force
):
2262 """deletes a VNFD/VNFpkg
2264 NAME: name or ID of the VNFD/VNFpkg to be deleted
2267 vnfd_delete(ctx
, name
, force
)
2270 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
2271 @click.argument('name')
2272 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2274 def nfpkg_delete(ctx
, name
, force
):
2277 NAME: name or ID of the NFpkg to be deleted
2280 vnfd_delete(ctx
, name
, force
)
2283 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
2284 @click.argument('name')
2285 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2286 @click.option('--config', default
=None,
2287 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2288 "600, skip_terminate_primitives: True}'")
2289 @click.option('--wait',
2293 help='do not return the control immediately, but keep it '
2294 'until the operation is completed, or timeout')
2296 def ns_delete(ctx
, name
, force
, config
, wait
):
2297 """deletes a NS instance
2299 NAME: name or ID of the NS instance to be deleted
2304 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2306 check_client_version(ctx
.obj
, '--force')
2307 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2308 # except ClientException as e:
2313 def nst_delete(ctx
, name
, force
):
2316 check_client_version(ctx
.obj
, ctx
.command
.name
)
2317 ctx
.obj
.nst
.delete(name
, force
)
2318 # except ClientException as e:
2323 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
2324 @click.argument('name')
2325 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2327 def nst_delete1(ctx
, name
, force
):
2328 """deletes a Network Slice Template (NST)
2330 NAME: name or ID of the NST/NSTpkg to be deleted
2333 nst_delete(ctx
, name
, force
)
2336 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
2337 @click.argument('name')
2338 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2340 def nst_delete2(ctx
, name
, force
):
2341 """deletes a Network Slice Template (NST)
2343 NAME: name or ID of the NST/NSTpkg to be deleted
2346 nst_delete(ctx
, name
, force
)
2349 def nsi_delete(ctx
, name
, force
, wait
):
2352 check_client_version(ctx
.obj
, ctx
.command
.name
)
2353 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2354 # except ClientException as e:
2359 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2360 @click.argument('name')
2361 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2362 @click.option('--wait',
2366 help='do not return the control immediately, but keep it '
2367 'until the operation is completed, or timeout')
2369 def nsi_delete1(ctx
, name
, force
, wait
):
2370 """deletes a Network Slice Instance (NSI)
2372 NAME: name or ID of the Network Slice instance to be deleted
2375 nsi_delete(ctx
, name
, force
, wait
=wait
)
2378 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2379 @click.argument('name')
2380 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2382 def nsi_delete2(ctx
, name
, force
, wait
):
2383 """deletes a Network Slice Instance (NSI)
2385 NAME: name or ID of the Network Slice instance to be deleted
2388 nsi_delete(ctx
, name
, force
, wait
=wait
)
2391 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2392 @click.argument('name')
2393 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2395 def pdu_delete(ctx
, name
, force
):
2396 """deletes a Physical Deployment Unit (PDU)
2398 NAME: name or ID of the PDU to be deleted
2402 check_client_version(ctx
.obj
, ctx
.command
.name
)
2403 ctx
.obj
.pdu
.delete(name
, force
)
2404 # except ClientException as e:
2413 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2414 @click.option('--name',
2416 help='Name to create datacenter')
2417 @click.option('--user',
2419 help='VIM username')
2420 @click.option('--password',
2423 confirmation_prompt
=True,
2424 help='VIM password')
2425 @click.option('--auth_url',
2428 @click.option('--tenant',
2430 help='VIM tenant name')
2431 @click.option('--config',
2433 help='VIM specific config parameters')
2434 @click.option('--account_type',
2435 default
='openstack',
2437 @click.option('--description',
2439 help='human readable description')
2440 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2441 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2442 @click.option('--wait',
2446 help='do not return the control immediately, but keep it '
2447 'until the operation is completed, or timeout')
2461 """creates a new VIM account"""
2465 check_client_version(ctx
.obj
, '--sdn_controller')
2466 if sdn_port_mapping
:
2467 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2469 vim
['vim-username'] = user
2470 vim
['vim-password'] = password
2471 vim
['vim-url'] = auth_url
2472 vim
['vim-tenant-name'] = tenant
2473 vim
['vim-type'] = account_type
2474 vim
['description'] = description
2475 vim
['config'] = config
2476 if sdn_controller
or sdn_port_mapping
:
2477 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2479 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2480 # except ClientException as e:
2485 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2486 @click.argument('name')
2487 @click.option('--newname', help='New name for the VIM account')
2488 @click.option('--user', help='VIM username')
2489 @click.option('--password', help='VIM password')
2490 @click.option('--auth_url', help='VIM url')
2491 @click.option('--tenant', help='VIM tenant name')
2492 @click.option('--config', help='VIM specific config parameters')
2493 @click.option('--account_type', help='VIM type')
2494 @click.option('--description', help='human readable description')
2495 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller to be associated with this VIM'
2496 'account. Use empty string to disassociate')
2497 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2498 @click.option('--wait',
2502 help='do not return the control immediately, but keep it '
2503 'until the operation is completed, or timeout')
2518 """updates a VIM account
2520 NAME: name or ID of the VIM account
2524 check_client_version(ctx
.obj
, ctx
.command
.name
)
2526 if newname
: vim
['name'] = newname
2527 if user
: vim
['vim_user'] = user
2528 if password
: vim
['vim_password'] = password
2529 if auth_url
: vim
['vim_url'] = auth_url
2530 if tenant
: vim
['vim-tenant-name'] = tenant
2531 if account_type
: vim
['vim_type'] = account_type
2532 if description
: vim
['description'] = description
2533 if config
: vim
['config'] = config
2534 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2535 # except ClientException as e:
2540 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2541 @click.argument('name')
2542 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2543 @click.option('--wait',
2547 help='do not return the control immediately, but keep it '
2548 'until the operation is completed, or timeout')
2550 def vim_delete(ctx
, name
, force
, wait
):
2551 """deletes a VIM account
2553 NAME: name or ID of the VIM account to be deleted
2558 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2560 check_client_version(ctx
.obj
, '--force')
2561 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2562 # except ClientException as e:
2567 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2568 #@click.option('--ro_update/--no_ro_update',
2570 # help='update list from RO')
2571 @click.option('--filter', default
=None, multiple
=True,
2572 help='restricts the list to the VIM accounts matching the filter')
2573 @click.option('--long', is_flag
=True,
2574 help='get more details of the NS (project, vim, deployment status, configuration status.')
2576 def vim_list(ctx
, filter, long):
2577 """list all VIM accounts"""
2580 filter='&'.join(filter)
2581 check_client_version(ctx
.obj
, '--filter')
2583 # check_client_version(ctx.obj, '--ro_update', 'v1')
2584 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2585 if fullclassname
== 'osmclient.sol005.client.Client':
2586 resp
= ctx
.obj
.vim
.list(filter)
2588 # resp = ctx.obj.vim.list(ro_update)
2590 table
= PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details'])
2591 project_list
= ctx
.obj
.project
.list()
2593 table
= PrettyTable(['vim name', 'uuid', 'operational state'])
2596 if 'vim_password' in vim
:
2597 vim
['vim_password']='********'
2598 logger
.debug('VIM details: {}'.format(yaml
.safe_dump(vim
)))
2599 vim_state
= vim
['_admin'].get('operationalState', '-')
2600 error_details
= 'N/A'
2601 if vim_state
== 'ERROR':
2602 error_details
= vim
['_admin'].get('detailed-status', 'Not found')
2603 project_id
, project_name
= get_project(project_list
, vim
)
2604 #project_info = '{} ({})'.format(project_name, project_id)
2605 project_info
= project_name
2606 table
.add_row([vim
['name'], vim
['uuid'], project_info
,
2607 vim_state
, wrap_text(text
=error_details
, width
=80)])
2609 table
.add_row([vim
['name'], vim
['uuid'], vim
['_admin'].get('operationalState', '-')])
2614 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2615 @click.argument('name')
2616 @click.option('--filter', multiple
=True,
2617 help='restricts the information to the fields in the filter')
2619 def vim_show(ctx
, name
, filter):
2620 """shows the details of a VIM account
2622 NAME: name or ID of the VIM account
2626 resp
= ctx
.obj
.vim
.get(name
)
2627 if 'vim_password' in resp
:
2628 resp
['vim_password']='********'
2629 # except ClientException as e:
2633 table
= PrettyTable(['key', 'attribute'])
2634 for k
, v
in list(resp
.items()):
2635 if not filter or k
in filter:
2636 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2641 ####################
2643 ####################
2645 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2646 @click.option('--name',
2648 help='Name for the WIM account')
2649 @click.option('--user',
2650 help='WIM username')
2651 @click.option('--password',
2652 help='WIM password')
2653 @click.option('--url',
2656 # @click.option('--tenant',
2657 # help='wIM tenant name')
2658 @click.option('--config',
2660 help='WIM specific config parameters')
2661 @click.option('--wim_type',
2663 @click.option('--description',
2665 help='human readable description')
2666 @click.option('--wim_port_mapping', default
=None,
2667 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2668 "(WAN service endpoint id and info)")
2669 @click.option('--wait',
2673 help='do not return the control immediately, but keep it '
2674 'until the operation is completed, or timeout')
2687 """creates a new WIM account"""
2690 check_client_version(ctx
.obj
, ctx
.command
.name
)
2691 # if sdn_controller:
2692 # check_client_version(ctx.obj, '--sdn_controller')
2693 # if sdn_port_mapping:
2694 # check_client_version(ctx.obj, '--sdn_port_mapping')
2696 if user
: wim
['user'] = user
2697 if password
: wim
['password'] = password
2698 if url
: wim
['wim_url'] = url
2699 # if tenant: wim['tenant'] = tenant
2700 wim
['wim_type'] = wim_type
2701 if description
: wim
['description'] = description
2702 if config
: wim
['config'] = config
2703 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2704 # except ClientException as e:
2709 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2710 @click.argument('name')
2711 @click.option('--newname', help='New name for the WIM account')
2712 @click.option('--user', help='WIM username')
2713 @click.option('--password', help='WIM password')
2714 @click.option('--url', help='WIM url')
2715 @click.option('--config', help='WIM specific config parameters')
2716 @click.option('--wim_type', help='WIM type')
2717 @click.option('--description', help='human readable description')
2718 @click.option('--wim_port_mapping', default
=None,
2719 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2720 "(WAN service endpoint id and info)")
2721 @click.option('--wait',
2725 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2738 """updates a WIM account
2740 NAME: name or ID of the WIM account
2744 check_client_version(ctx
.obj
, ctx
.command
.name
)
2746 if newname
: wim
['name'] = newname
2747 if user
: wim
['user'] = user
2748 if password
: wim
['password'] = password
2749 if url
: wim
['url'] = url
2750 # if tenant: wim['tenant'] = tenant
2751 if wim_type
: wim
['wim_type'] = wim_type
2752 if description
: wim
['description'] = description
2753 if config
: wim
['config'] = config
2754 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2755 # except ClientException as e:
2760 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2761 @click.argument('name')
2762 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2763 @click.option('--wait',
2767 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2769 def wim_delete(ctx
, name
, force
, wait
):
2770 """deletes a WIM account
2772 NAME: name or ID of the WIM account to be deleted
2776 check_client_version(ctx
.obj
, ctx
.command
.name
)
2777 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2778 # except ClientException as e:
2783 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2784 @click.option('--filter', default
=None, multiple
=True,
2785 help='restricts the list to the WIM accounts matching the filter')
2787 def wim_list(ctx
, filter):
2788 """list all WIM accounts"""
2791 check_client_version(ctx
.obj
, ctx
.command
.name
)
2793 filter='&'.join(filter)
2794 resp
= ctx
.obj
.wim
.list(filter)
2795 table
= PrettyTable(['wim name', 'uuid'])
2797 table
.add_row([wim
['name'], wim
['uuid']])
2800 # except ClientException as e:
2805 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2806 @click.argument('name')
2808 def wim_show(ctx
, name
):
2809 """shows the details of a WIM account
2811 NAME: name or ID of the WIM account
2815 check_client_version(ctx
.obj
, ctx
.command
.name
)
2816 resp
= ctx
.obj
.wim
.get(name
)
2817 if 'password' in resp
:
2818 resp
['wim_password']='********'
2819 # except ClientException as e:
2823 table
= PrettyTable(['key', 'attribute'])
2824 for k
, v
in list(resp
.items()):
2825 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2830 ####################
2831 # SDN controller operations
2832 ####################
2834 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2835 @click.option('--name',
2837 help='Name to create sdn controller')
2838 @click.option('--type',
2840 help='SDN controller type')
2841 @click.option('--sdn_controller_version', # hidden=True,
2842 help='Deprecated. Use --config {version: sdn_controller_version}')
2843 @click.option('--url',
2844 help='URL in format http[s]://HOST:IP/')
2845 @click.option('--ip_address', # hidden=True,
2846 help='Deprecated. Use --url')
2847 @click.option('--port', # hidden=True,
2848 help='Deprecated. Use --url')
2849 @click.option('--switch_dpid', # hidden=True,
2850 help='Deprecated. Use --config {switch_id: DPID}')
2851 @click.option('--config',
2852 help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2853 'Openflow Datapath ID), version: version}')
2854 @click.option('--user',
2855 help='SDN controller username')
2856 @click.option('--password',
2858 confirmation_prompt
=True,
2859 help='SDN controller password')
2860 @click.option('--description', default
=None, help='human readable description')
2861 @click.option('--wait',
2865 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2867 def sdnc_create(ctx
, **kwargs
):
2868 """creates a new SDN controller"""
2870 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2871 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2872 if kwargs
.get("port"):
2873 print("option '--port' is deprecated, use '--url' instead")
2874 sdncontroller
["port"] = int(kwargs
["port"])
2875 if kwargs
.get("ip_address"):
2876 print("option '--ip_address' is deprecated, use '--url' instead")
2877 sdncontroller
["ip"] = kwargs
["ip_address"]
2878 if kwargs
.get("switch_dpid"):
2879 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2880 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2881 if kwargs
.get("sdn_controller_version"):
2882 print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2885 check_client_version(ctx
.obj
, ctx
.command
.name
)
2886 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2887 # except ClientException as e:
2891 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2892 @click.argument('name')
2893 @click.option('--newname', help='New name for the SDN controller')
2894 @click.option('--description', default
=None, help='human readable description')
2895 @click.option('--type', help='SDN controller type')
2896 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2897 @click.option('--config', help='Extra information for SDN in yaml format, as '
2898 '{switch_id: identity used for the plugin (e.g. DPID: '
2899 'Openflow Datapath ID), version: version}')
2900 @click.option('--user', help='SDN controller username')
2901 @click.option('--password', help='SDN controller password')
2902 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2903 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2904 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2905 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2906 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2907 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2909 def sdnc_update(ctx
, **kwargs
):
2910 """updates an SDN controller
2912 NAME: name or ID of the SDN controller
2915 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2916 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2917 if kwargs
.get("newname"):
2918 sdncontroller
["name"] = kwargs
["newname"]
2919 if kwargs
.get("port"):
2920 print("option '--port' is deprecated, use '--url' instead")
2921 sdncontroller
["port"] = int(kwargs
["port"])
2922 if kwargs
.get("ip_address"):
2923 print("option '--ip_address' is deprecated, use '--url' instead")
2924 sdncontroller
["ip"] = kwargs
["ip_address"]
2925 if kwargs
.get("switch_dpid"):
2926 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2927 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2928 if kwargs
.get("sdn_controller_version"):
2929 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2933 check_client_version(ctx
.obj
, ctx
.command
.name
)
2934 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2935 # except ClientException as e:
2940 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2941 @click.argument('name')
2942 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2943 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2944 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2946 def sdnc_delete(ctx
, name
, force
, wait
):
2947 """deletes an SDN controller
2949 NAME: name or ID of the SDN controller to be deleted
2953 check_client_version(ctx
.obj
, ctx
.command
.name
)
2954 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2955 # except ClientException as e:
2960 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2961 @click.option('--filter', default
=None, multiple
=True,
2962 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2964 def sdnc_list(ctx
, filter):
2965 """list all SDN controllers"""
2968 check_client_version(ctx
.obj
, ctx
.command
.name
)
2970 filter='&'.join(filter)
2971 resp
= ctx
.obj
.sdnc
.list(filter)
2972 # except ClientException as e:
2975 table
= PrettyTable(['sdnc name', 'id'])
2977 table
.add_row([sdnc
['name'], sdnc
['_id']])
2982 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2983 @click.argument('name')
2985 def sdnc_show(ctx
, name
):
2986 """shows the details of an SDN controller
2988 NAME: name or ID of the SDN controller
2992 check_client_version(ctx
.obj
, ctx
.command
.name
)
2993 resp
= ctx
.obj
.sdnc
.get(name
)
2994 # except ClientException as e:
2998 table
= PrettyTable(['key', 'attribute'])
2999 for k
, v
in list(resp
.items()):
3000 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3005 ###########################
3006 # K8s cluster operations
3007 ###########################
3009 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
3010 @click.argument('name')
3011 @click.option('--creds',
3013 help='credentials file, i.e. a valid `.kube/config` file')
3014 @click.option('--version',
3016 help='Kubernetes version')
3017 @click.option('--vim',
3019 help='VIM target, the VIM where the cluster resides')
3020 @click.option('--k8s-nets',
3022 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) ...]}"')
3023 @click.option('--description',
3025 help='human readable description')
3026 @click.option('--namespace',
3027 default
='kube-system',
3028 help='namespace to be used for its operation, defaults to `kube-system`')
3029 @click.option('--cni',
3031 help='list of CNI plugins, in JSON inline format, used in the cluster')
3032 #@click.option('--skip-init',
3034 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3035 #@click.option('--wait',
3037 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3039 def k8scluster_add(ctx
,
3048 """adds a K8s cluster to OSM
3050 NAME: name of the K8s cluster
3053 check_client_version(ctx
.obj
, ctx
.command
.name
)
3055 cluster
['name'] = name
3056 with
open(creds
, 'r') as cf
:
3057 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3058 cluster
['k8s_version'] = version
3059 cluster
['vim_account'] = vim
3060 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3062 cluster
['description'] = description
3063 if namespace
: cluster
['namespace'] = namespace
3064 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3065 ctx
.obj
.k8scluster
.create(name
, cluster
)
3066 # except ClientException as e:
3071 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
3072 @click.argument('name')
3073 @click.option('--newname', help='New name for the K8s cluster')
3074 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3075 @click.option('--version', help='Kubernetes version')
3076 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3077 @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) ...]}"')
3078 @click.option('--description', help='human readable description')
3079 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3080 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3082 def k8scluster_update(ctx
,
3092 """updates a K8s cluster
3094 NAME: name or ID of the K8s cluster
3097 check_client_version(ctx
.obj
, ctx
.command
.name
)
3099 if newname
: cluster
['name'] = newname
3101 with
open(creds
, 'r') as cf
:
3102 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3103 if version
: cluster
['k8s_version'] = version
3104 if vim
: cluster
['vim_account'] = vim
3105 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3106 if description
: cluster
['description'] = description
3107 if namespace
: cluster
['namespace'] = namespace
3108 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3109 ctx
.obj
.k8scluster
.update(name
, cluster
)
3110 # except ClientException as e:
3115 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
3116 @click.argument('name')
3117 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3118 #@click.option('--wait',
3120 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3122 def k8scluster_delete(ctx
, name
, force
):
3123 """deletes a K8s cluster
3125 NAME: name or ID of the K8s cluster to be deleted
3128 check_client_version(ctx
.obj
, ctx
.command
.name
)
3129 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3130 # except ClientException as e:
3135 @cli_osm.command(name
='k8scluster-list')
3136 @click.option('--filter', default
=None, multiple
=True,
3137 help='restricts the list to the K8s clusters matching the filter')
3138 @click.option('--literal', is_flag
=True,
3139 help='print literally, no pretty table')
3140 @click.option('--long', is_flag
=True, help='get more details')
3142 def k8scluster_list(ctx
, filter, literal
, long):
3143 """list all K8s clusters"""
3145 check_client_version(ctx
.obj
, ctx
.command
.name
)
3147 filter='&'.join(filter)
3148 resp
= ctx
.obj
.k8scluster
.list(filter)
3150 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3153 table
= PrettyTable(['Name', 'Id', 'Project', 'Version', 'VIM', 'K8s-nets',
3154 'Operational State', 'Op. state (details)', 'Description', 'Detailed status'])
3155 project_list
= ctx
.obj
.project
.list()
3157 table
= PrettyTable(['Name', 'Id', 'VIM', 'Operational State', 'Op. state details'])
3158 for cluster
in resp
:
3159 op_state_details
= "Helm: {}\nJuju: {}".format(
3160 cluster
["_admin"].get("helm-chart", "-").get("operationalState", "-"),
3161 cluster
["_admin"].get("juju-bundle", "-").get("operationalState", "-"))
3163 logger
.debug('Cluster details: {}'.format(yaml
.safe_dump(cluster
)))
3164 project_id
, project_name
= get_project(project_list
, cluster
)
3165 #project_info = '{} ({})'.format(project_name, project_id)
3166 project_info
= project_name
3167 detailed_status
= cluster
["_admin"].get("detailed-status","-")
3168 table
.add_row([cluster
['name'], cluster
['_id'], project_info
,
3169 cluster
['k8s_version'], cluster
['vim_account'],
3170 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
3171 op_state_details
, trunc_text(cluster
.get('description') or '', 40),
3172 wrap_text(text
=detailed_status
, width
=40)])
3174 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['vim_account'],
3175 cluster
["_admin"]["operationalState"], op_state_details
])
3178 # except ClientException as e:
3183 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
3184 @click.argument('name')
3185 @click.option('--literal', is_flag
=True,
3186 help='print literally, no pretty table')
3188 def k8scluster_show(ctx
, name
, literal
):
3189 """shows the details of a K8s cluster
3191 NAME: name or ID of the K8s cluster
3194 resp
= ctx
.obj
.k8scluster
.get(name
)
3196 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3198 table
= PrettyTable(['key', 'attribute'])
3199 for k
, v
in list(resp
.items()):
3200 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
3203 # except ClientException as e:
3209 ###########################
3211 ###########################
3213 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
3214 @click.argument('name')
3215 @click.argument('uri')
3216 @click.option('--type',
3217 type=click
.Choice(['helm-chart', 'juju-bundle', 'osm']),
3219 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3220 @click.option('--description',
3222 help='human readable description')
3223 @click.option('--user',
3225 help='OSM repository: The username of the OSM repository')
3226 @click.option('--password',
3228 help='OSM repository: The password of the OSM repository')
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_add(ctx
, **kwargs
):
3234 """adds a repo to OSM
3236 NAME: name of the repo
3237 URI: URI of the repo
3240 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
3242 repo
["url"] = repo
.pop("uri")
3243 if repo
["type"] in ['helm-chart', 'juju-bundle']:
3244 ctx
.obj
.repo
.create(repo
['name'], repo
)
3246 ctx
.obj
.osmrepo
.create(repo
['name'], repo
)
3247 # except ClientException as e:
3252 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
3253 @click.argument('name')
3254 @click.option('--newname', help='New name for the repo')
3255 @click.option('--uri', help='URI of the repo')
3256 @click.option('--description', help='human readable description')
3257 #@click.option('--wait',
3259 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3261 def repo_update(ctx
,
3266 """updates a repo in OSM
3268 NAME: name of the repo
3271 check_client_version(ctx
.obj
, ctx
.command
.name
)
3274 repo
['name'] = newname
3277 if description
: repo
['description'] = description
3279 ctx
.obj
.repo
.update(name
, repo
)
3281 ctx
.obj
.osmrepo
.update(name
, repo
)
3283 # except ClientException as e:
3288 @cli_osm.command(name
='repo-index', short_help
='Index a repository from a folder with artifacts')
3289 @click.option('--origin', default
='.', help='origin path where the artifacts are located')
3290 @click.option('--destination', default
='.', help='destination path where the index is deployed')
3292 def repo_index(ctx
, origin
, destination
):
3293 """Index a repository
3295 NAME: name or ID of the repo to be deleted
3297 check_client_version(ctx
.obj
, ctx
.command
.name
)
3298 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
3301 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
3302 @click.argument('name')
3303 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3304 #@click.option('--wait',
3306 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3308 def repo_delete(ctx
, name
, force
):
3311 NAME: name or ID of the repo to be deleted
3315 ctx
.obj
.repo
.delete(name
, force
=force
)
3317 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
3318 # except ClientException as e:
3323 @cli_osm.command(name
='repo-list')
3324 @click.option('--filter', default
=None, multiple
=True,
3325 help='restricts the list to the repos matching the filter')
3326 @click.option('--literal', is_flag
=True,
3327 help='print literally, no pretty table')
3329 def repo_list(ctx
, filter, literal
):
3330 """list all repos"""
3333 check_client_version(ctx
.obj
, ctx
.command
.name
)
3335 filter='&'.join(filter)
3336 resp
= ctx
.obj
.repo
.list(filter)
3337 resp
+= ctx
.obj
.osmrepo
.list(filter)
3339 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3341 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3343 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3344 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description') or '',40)])
3348 # except ClientException as e:
3353 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
3354 @click.argument('name')
3355 @click.option('--literal', is_flag
=True,
3356 help='print literally, no pretty table')
3358 def repo_show(ctx
, name
, literal
):
3359 """shows the details of a repo
3361 NAME: name or ID of the repo
3364 resp
= ctx
.obj
.repo
.get(name
)
3366 resp
= ctx
.obj
.osmrepo
.get(name
)
3370 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3372 table
= PrettyTable(['key', 'attribute'])
3374 for k
, v
in list(resp
.items()):
3375 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3379 # except ClientException as e:
3385 ####################
3386 # Project mgmt operations
3387 ####################
3389 @cli_osm.command(name
='project-create', short_help
='creates a new project')
3390 @click.argument('name')
3391 #@click.option('--description',
3392 # default='no description',
3393 # help='human readable description')
3394 @click.option('--domain-name', 'domain_name',
3396 help='assign to a domain')
3397 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3398 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3399 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3401 def project_create(ctx
, name
, domain_name
, quotas
):
3402 """Creates a new project
3404 NAME: name of the project
3405 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3406 QUOTAS: set quotas for the project
3409 project
= {'name': name
}
3411 project
['domain_name'] = domain_name
3412 quotas_dict
= _process_project_quotas(quotas
)
3414 project
['quotas'] = quotas_dict
3417 check_client_version(ctx
.obj
, ctx
.command
.name
)
3418 ctx
.obj
.project
.create(name
, project
)
3419 # except ClientException as e:
3424 def _process_project_quotas(quota_list
):
3429 for quota
in quota_list
:
3430 for single_quota
in quota
.split(","):
3431 k
, v
= single_quota
.split("=")
3432 quotas_dict
[k
] = None if v
in ('None', 'null', '') else int(v
)
3433 except (ValueError, TypeError):
3434 raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3438 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3439 @click.argument('name')
3440 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3442 def project_delete(ctx
, name
):
3443 """deletes a project
3445 NAME: name or ID of the project to be deleted
3449 check_client_version(ctx
.obj
, ctx
.command
.name
)
3450 ctx
.obj
.project
.delete(name
)
3451 # except ClientException as e:
3456 @cli_osm.command(name
='project-list', short_help
='list all projects')
3457 @click.option('--filter', default
=None, multiple
=True,
3458 help='restricts the list to the projects matching the filter')
3460 def project_list(ctx
, filter):
3461 """list all projects"""
3464 check_client_version(ctx
.obj
, ctx
.command
.name
)
3466 filter='&'.join(filter)
3467 resp
= ctx
.obj
.project
.list(filter)
3468 # except ClientException as e:
3471 table
= PrettyTable(['name', 'id'])
3473 table
.add_row([proj
['name'], proj
['_id']])
3478 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3479 @click.argument('name')
3481 def project_show(ctx
, name
):
3482 """shows the details of a project
3484 NAME: name or ID of the project
3488 check_client_version(ctx
.obj
, ctx
.command
.name
)
3489 resp
= ctx
.obj
.project
.get(name
)
3490 # except ClientException as e:
3494 table
= PrettyTable(['key', 'attribute'])
3495 for k
, v
in resp
.items():
3496 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3501 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3502 @click.argument('project')
3503 @click.option('--name', default
=None,
3504 help='new name for the project')
3505 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3506 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3507 "(use empty to reset quota to default")
3509 def project_update(ctx
, project
, name
, quotas
):
3511 Update a project name
3514 :param project: id or name of the project to modify
3515 :param name: new name for the project
3516 :param quotas: change quotas of the project
3520 project_changes
= {}
3522 project_changes
['name'] = name
3523 quotas_dict
= _process_project_quotas(quotas
)
3525 project_changes
['quotas'] = quotas_dict
3528 check_client_version(ctx
.obj
, ctx
.command
.name
)
3529 ctx
.obj
.project
.update(project
, project_changes
)
3530 # except ClientException as e:
3534 ####################
3535 # User mgmt operations
3536 ####################
3538 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3539 @click.argument('username')
3540 @click.option('--password',
3543 confirmation_prompt
=True,
3544 help='user password')
3545 @click.option('--projects',
3546 # prompt="Comma separate list of projects",
3548 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3549 help='list of project ids that the user belongs to')
3550 @click.option('--project-role-mappings', 'project_role_mappings',
3551 default
=None, multiple
=True,
3552 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3553 @click.option('--domain-name', 'domain_name',
3555 help='assign to a domain')
3557 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
3558 """Creates a new user
3561 USERNAME: name of the user
3562 PASSWORD: password of the user
3563 PROJECTS: projects assigned to user (internal only)
3564 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3565 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3569 user
['username'] = username
3570 user
['password'] = password
3571 user
['projects'] = projects
3572 user
['project_role_mappings'] = project_role_mappings
3574 user
['domain_name'] = domain_name
3577 check_client_version(ctx
.obj
, ctx
.command
.name
)
3578 ctx
.obj
.user
.create(username
, user
)
3579 # except ClientException as e:
3584 @cli_osm.command(name
='user-update', short_help
='updates user information')
3585 @click.argument('username')
3586 @click.option('--password',
3589 # confirmation_prompt=True,
3590 help='user password')
3591 @click.option('--set-username', 'set_username',
3593 help='change username')
3594 @click.option('--set-project', 'set_project',
3595 default
=None, multiple
=True,
3596 help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3597 @click.option('--remove-project', 'remove_project',
3598 default
=None, multiple
=True,
3599 help="removes project from user: 'project'")
3600 @click.option('--add-project-role', 'add_project_role',
3601 default
=None, multiple
=True,
3602 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3603 @click.option('--remove-project-role', 'remove_project_role',
3604 default
=None, multiple
=True,
3605 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3607 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3608 add_project_role
, remove_project_role
):
3609 """Update a user information
3612 USERNAME: name of the user
3613 PASSWORD: new password
3614 SET_USERNAME: new username
3615 SET_PROJECT: creating mappings for project/role(s)
3616 REMOVE_PROJECT: deleting mappings for project/role(s)
3617 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3618 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3622 user
['password'] = password
3623 user
['username'] = set_username
3624 user
['set-project'] = set_project
3625 user
['remove-project'] = remove_project
3626 user
['add-project-role'] = add_project_role
3627 user
['remove-project-role'] = remove_project_role
3630 check_client_version(ctx
.obj
, ctx
.command
.name
)
3631 ctx
.obj
.user
.update(username
, user
)
3632 # except ClientException as e:
3637 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3638 @click.argument('name')
3639 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3641 def user_delete(ctx
, name
):
3645 NAME: name or ID of the user to be deleted
3649 check_client_version(ctx
.obj
, ctx
.command
.name
)
3650 ctx
.obj
.user
.delete(name
)
3651 # except ClientException as e:
3656 @cli_osm.command(name
='user-list', short_help
='list all users')
3657 @click.option('--filter', default
=None, multiple
=True,
3658 help='restricts the list to the users matching the filter')
3660 def user_list(ctx
, filter):
3661 """list all users"""
3663 check_client_version(ctx
.obj
, ctx
.command
.name
)
3665 filter='&'.join(filter)
3666 resp
= ctx
.obj
.user
.list(filter)
3667 # except ClientException as e:
3670 table
= PrettyTable(['name', 'id'])
3672 table
.add_row([user
['username'], user
['_id']])
3677 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3678 @click.argument('name')
3680 def user_show(ctx
, name
):
3681 """shows the details of a user
3683 NAME: name or ID of the user
3687 check_client_version(ctx
.obj
, ctx
.command
.name
)
3688 resp
= ctx
.obj
.user
.get(name
)
3689 if 'password' in resp
:
3690 resp
['password']='********'
3691 # except ClientException as e:
3695 table
= PrettyTable(['key', 'attribute'])
3696 for k
, v
in resp
.items():
3697 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3702 ####################
3703 # Fault Management operations
3704 ####################
3706 @cli_osm.command(name
='ns-alarm-create')
3707 @click.argument('name')
3708 @click.option('--ns', prompt
=True, help='NS instance id or name')
3709 @click.option('--vnf', prompt
=True,
3710 help='VNF name (VNF member index as declared in the NSD)')
3711 @click.option('--vdu', prompt
=True,
3712 help='VDU name (VDU name as declared in the VNFD)')
3713 @click.option('--metric', prompt
=True,
3714 help='Name of the metric (e.g. cpu_utilization)')
3715 @click.option('--severity', default
='WARNING',
3716 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3717 @click.option('--threshold_value', prompt
=True,
3718 help='threshold value that, when crossed, an alarm is triggered')
3719 @click.option('--threshold_operator', prompt
=True,
3720 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3721 @click.option('--statistic', default
='AVERAGE',
3722 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3724 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3725 threshold_value
, threshold_operator
, statistic
):
3726 """creates a new alarm for a NS instance"""
3727 # TODO: Check how to validate threshold_value.
3728 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3731 ns_instance
= ctx
.obj
.ns
.get(ns
)
3733 alarm
['alarm_name'] = name
3734 alarm
['ns_id'] = ns_instance
['_id']
3735 alarm
['correlation_id'] = ns_instance
['_id']
3736 alarm
['vnf_member_index'] = vnf
3737 alarm
['vdu_name'] = vdu
3738 alarm
['metric_name'] = metric
3739 alarm
['severity'] = severity
3740 alarm
['threshold_value'] = int(threshold_value
)
3741 alarm
['operation'] = threshold_operator
3742 alarm
['statistic'] = statistic
3743 check_client_version(ctx
.obj
, ctx
.command
.name
)
3744 ctx
.obj
.ns
.create_alarm(alarm
)
3745 # except ClientException as e:
3750 #@cli_osm.command(name='ns-alarm-delete')
3751 #@click.argument('name')
3752 #@click.pass_context
3753 #def ns_alarm_delete(ctx, name):
3754 # """deletes an alarm
3756 # NAME: name of the alarm to be deleted
3759 # check_client_version(ctx.obj, ctx.command.name)
3760 # ctx.obj.ns.delete_alarm(name)
3761 # except ClientException as e:
3766 ####################
3767 # Performance Management operations
3768 ####################
3770 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3771 @click.option('--ns', prompt
=True, help='NS instance id or name')
3772 @click.option('--vnf', prompt
=True,
3773 help='VNF name (VNF member index as declared in the NSD)')
3774 @click.option('--vdu', prompt
=True,
3775 help='VDU name (VDU name as declared in the VNFD)')
3776 @click.option('--metric', prompt
=True,
3777 help='name of the metric (e.g. cpu_utilization)')
3778 #@click.option('--period', default='1w',
3779 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3780 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3782 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3783 """exports a metric to the internal OSM bus, which can be read by other apps"""
3784 # TODO: Check how to validate interval.
3785 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3788 ns_instance
= ctx
.obj
.ns
.get(ns
)
3790 metric_data
['ns_id'] = ns_instance
['_id']
3791 metric_data
['correlation_id'] = ns_instance
['_id']
3792 metric_data
['vnf_member_index'] = vnf
3793 metric_data
['vdu_name'] = vdu
3794 metric_data
['metric_name'] = metric
3795 metric_data
['collection_unit'] = 'WEEK'
3796 metric_data
['collection_period'] = 1
3797 check_client_version(ctx
.obj
, ctx
.command
.name
)
3799 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3803 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3804 time
.sleep(int(interval
))
3806 # except ClientException as e:
3811 ####################
3813 ####################
3815 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3817 def get_version(ctx
):
3818 """shows client and server versions"""
3820 check_client_version(ctx
.obj
, "version")
3821 print ("Server version: {}".format(ctx
.obj
.get_version()))
3822 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3823 # except ClientException as e:
3827 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3828 @click.argument('filename')
3829 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3830 help='the charm will not be compiled, it is assumed to already exist')
3832 def upload_package(ctx
, filename
, skip_charm_build
):
3833 """uploads a vnf package or ns package
3835 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3839 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3840 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3841 if fullclassname
!= 'osmclient.sol005.client.Client':
3842 ctx
.obj
.package
.wait_for_upload(filename
)
3843 # except ClientException as e:
3848 #@cli_osm.command(name='ns-scaling-show')
3849 #@click.argument('ns_name')
3850 #@click.pass_context
3851 #def show_ns_scaling(ctx, ns_name):
3852 # """shows the status of a NS scaling operation
3854 # NS_NAME: name of the NS instance being scaled
3857 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3858 # resp = ctx.obj.ns.list()
3859 # except ClientException as e:
3863 # table = PrettyTable(
3866 # 'operational status',
3871 # if ns_name == ns['name']:
3872 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3873 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3874 # for record in scaling_records:
3875 # if 'instance' in record:
3876 # instances = record['instance']
3877 # for inst in instances:
3879 # [record['scaling-group-name-ref'],
3880 # inst['instance-id'],
3881 # inst['op-status'],
3882 # time.strftime('%Y-%m-%d %H:%M:%S',
3884 # inst['create-time'])),
3890 #@cli_osm.command(name='ns-scale')
3891 #@click.argument('ns_name')
3892 #@click.option('--ns_scale_group', prompt=True)
3893 #@click.option('--index', prompt=True)
3894 #@click.option('--wait',
3898 # help='do not return the control immediately, but keep it \
3899 # until the operation is completed, or timeout')
3900 #@click.pass_context
3901 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3904 # NS_NAME: name of the NS instance to be scaled
3907 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3908 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3909 # except ClientException as e:
3914 #@cli_osm.command(name='config-agent-list')
3915 #@click.pass_context
3916 #def config_agent_list(ctx):
3917 # """list config agents"""
3919 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3920 # except ClientException as e:
3923 # table = PrettyTable(['name', 'account-type', 'details'])
3924 # for account in ctx.obj.vca.list():
3927 # account['account-type'],
3933 #@cli_osm.command(name='config-agent-delete')
3934 #@click.argument('name')
3935 #@click.pass_context
3936 #def config_agent_delete(ctx, name):
3937 # """deletes a config agent
3939 # NAME: name of the config agent to be deleted
3942 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3943 # ctx.obj.vca.delete(name)
3944 # except ClientException as e:
3949 #@cli_osm.command(name='config-agent-add')
3950 #@click.option('--name',
3952 #@click.option('--account_type',
3954 #@click.option('--server',
3956 #@click.option('--user',
3958 #@click.option('--secret',
3961 # confirmation_prompt=True)
3962 #@click.pass_context
3963 #def config_agent_add(ctx, name, account_type, server, user, secret):
3964 # """adds a config agent"""
3966 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3967 # ctx.obj.vca.create(name, account_type, server, user, secret)
3968 # except ClientException as e:
3973 #@cli_osm.command(name='ro-dump')
3974 #@click.pass_context
3976 # """shows RO agent information"""
3977 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3978 # resp = ctx.obj.vim.get_resource_orchestrator()
3979 # table = PrettyTable(['key', 'attribute'])
3980 # for k, v in list(resp.items()):
3981 # table.add_row([k, json.dumps(v, indent=2)])
3986 #@cli_osm.command(name='vcs-list')
3987 #@click.pass_context
3989 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3990 # resp = ctx.obj.utils.get_vcs_info()
3991 # table = PrettyTable(['component name', 'state'])
3992 # for component in resp:
3993 # table.add_row([component['component_name'], component['state']])
3998 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3999 @click.argument('ns_name')
4000 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
4001 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
4002 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
4003 @click.option('--vdu_count', default
=None, type=int, help='number of vdu instance of this vdu_id')
4004 @click.option('--action_name', prompt
=True, help='action name')
4005 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
4006 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
4007 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4008 @click.option('--wait',
4012 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4025 """executes an action/primitive over a NS instance
4027 NS_NAME: name or ID of the NS instance
4031 check_client_version(ctx
.obj
, ctx
.command
.name
)
4034 op_data
['member_vnf_index'] = vnf_name
4036 op_data
['kdu_name'] = kdu_name
4038 op_data
['vdu_id'] = vdu_id
4039 if vdu_count
is not None:
4040 op_data
['vdu_count_index'] = vdu_count
4042 op_data
['timeout_ns_action'] = timeout
4043 op_data
['primitive'] = action_name
4045 with
open(params_file
, 'r') as pf
:
4048 op_data
['primitive_params'] = yaml
.safe_load(params
)
4050 op_data
['primitive_params'] = {}
4051 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
4053 # except ClientException as e:
4058 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
4059 @click.argument('ns_name')
4060 @click.argument('vnf_name')
4061 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
4062 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
4063 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
4064 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4065 @click.option('--wait', required
=False, default
=False, is_flag
=True,
4066 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4077 Executes a VNF scale (adding/removing VDUs)
4080 NS_NAME: name or ID of the NS instance.
4081 VNF_NAME: member-vnf-index in the NS to be scaled.
4085 check_client_version(ctx
.obj
, ctx
.command
.name
)
4086 if not scale_in
and not scale_out
:
4088 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
)
4089 # except ClientException as e:
4094 ##############################
4095 # Role Management Operations #
4096 ##############################
4098 @cli_osm.command(name
='role-create', short_help
='creates a new role')
4099 @click.argument('name')
4100 @click.option('--permissions',
4102 help='role permissions using a dictionary')
4104 def role_create(ctx
, name
, permissions
):
4109 NAME: Name or ID of the role.
4110 DEFINITION: Definition of grant/denial of access to resources.
4114 check_client_version(ctx
.obj
, ctx
.command
.name
)
4115 ctx
.obj
.role
.create(name
, permissions
)
4116 # except ClientException as e:
4121 @cli_osm.command(name
='role-update', short_help
='updates a role')
4122 @click.argument('name')
4123 @click.option('--set-name',
4125 help='change name of rle')
4126 # @click.option('--permissions',
4128 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4129 @click.option('--add',
4131 help='yaml format dictionary with permission: True/False to access grant/denial')
4132 @click.option('--remove',
4134 help='yaml format list to remove a permission')
4136 def role_update(ctx
, name
, set_name
, add
, remove
):
4141 NAME: Name or ID of the role.
4142 DEFINITION: Definition overwrites the old definition.
4143 ADD: Grant/denial of access to resource to add.
4144 REMOVE: Grant/denial of access to resource to remove.
4148 check_client_version(ctx
.obj
, ctx
.command
.name
)
4149 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
4150 # except ClientException as e:
4155 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
4156 @click.argument('name')
4157 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4159 def role_delete(ctx
, name
):
4164 NAME: Name or ID of the role.
4168 check_client_version(ctx
.obj
, ctx
.command
.name
)
4169 ctx
.obj
.role
.delete(name
)
4170 # except ClientException as e:
4175 @cli_osm.command(name
='role-list', short_help
='list all roles')
4176 @click.option('--filter', default
=None, multiple
=True,
4177 help='restricts the list to the projects matching the filter')
4179 def role_list(ctx
, filter):
4185 check_client_version(ctx
.obj
, ctx
.command
.name
)
4187 filter='&'.join(filter)
4188 resp
= ctx
.obj
.role
.list(filter)
4189 # except ClientException as e:
4192 table
= PrettyTable(['name', 'id'])
4194 table
.add_row([role
['name'], role
['_id']])
4199 @cli_osm.command(name
='role-show', short_help
='show specific role')
4200 @click.argument('name')
4202 def role_show(ctx
, name
):
4204 Shows the details of a role.
4207 NAME: Name or ID of the role.
4211 check_client_version(ctx
.obj
, ctx
.command
.name
)
4212 resp
= ctx
.obj
.role
.get(name
)
4213 # except ClientException as e:
4217 table
= PrettyTable(['key', 'attribute'])
4218 for k
, v
in resp
.items():
4219 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4224 @cli_osm.command(name
='package-create',
4225 short_help
='Create a package descriptor')
4226 @click.argument('package-type')
4227 @click.argument('package-name')
4228 @click.option('--base-directory',
4230 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4231 @click.option('--image',
4232 default
="image-name",
4233 help='(VNF) Set the name of the vdu image. Default "image-name"')
4234 @click.option('--vdus',
4236 help='(VNF) Set the number of vdus in a VNF. Default 1')
4237 @click.option('--vcpu',
4239 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4240 @click.option('--memory',
4242 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4243 @click.option('--storage',
4245 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4246 @click.option('--interfaces',
4248 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4249 @click.option('--vendor',
4251 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4252 @click.option('--override',
4255 help='(NS/VNF/NST) Flag for overriding the package if exists.')
4256 @click.option('--detailed',
4259 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4260 @click.option('--netslice-subnets',
4262 help='(NST) Number of netslice subnets. Default 1')
4263 @click.option('--netslice-vlds',
4265 help='(NST) Number of netslice vlds. Default 1')
4267 def package_create(ctx
,
4283 Creates an OSM NS, VNF, NST package
4286 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4287 PACKAGE_NAME: Name of the package to create the folder with the content.
4291 check_client_version(ctx
.obj
, ctx
.command
.name
)
4292 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
4293 resp
= ctx
.obj
.package_tool
.create(package_type
,
4302 interfaces
=interfaces
,
4305 netslice_subnets
=netslice_subnets
,
4306 netslice_vlds
=netslice_vlds
)
4308 # except ClientException as inst:
4309 # print("ERROR: {}".format(inst))
4312 @cli_osm.command(name
='package-validate',
4313 short_help
='Validate a package descriptor')
4314 @click.argument('base-directory',
4317 @click.option('--recursive/--no-recursive',
4319 help='The activated recursive option will validate the yaml files'
4320 ' within the indicated directory and in its subdirectories')
4322 def package_validate(ctx
,
4326 Validate descriptors given a base directory.
4329 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4332 check_client_version(ctx
.obj
, ctx
.command
.name
)
4333 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
4334 table
= PrettyTable()
4335 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
4336 # Print the dictionary generated by the validation function
4337 for result
in results
:
4338 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
4339 table
.sortby
= "VALID"
4340 table
.align
["PATH"] = "l"
4341 table
.align
["TYPE"] = "l"
4342 table
.align
["ERROR"] = "l"
4344 # except ClientException as inst:
4345 # print("ERROR: {}".format(inst))
4348 @cli_osm.command(name
='package-build',
4349 short_help
='Build the tar.gz of the package')
4350 @click.argument('package-folder')
4351 @click.option('--skip-validation',
4354 help='skip package validation')
4355 @click.option('--skip-charm-build', default
=False, is_flag
=True,
4356 help='the charm will not be compiled, it is assumed to already exist')
4358 def package_build(ctx
,
4363 Build the package NS, VNF given the package_folder.
4366 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4369 check_client_version(ctx
.obj
, ctx
.command
.name
)
4370 results
= ctx
.obj
.package_tool
.build(package_folder
,
4371 skip_validation
=skip_validation
,
4372 skip_charm_build
=skip_charm_build
)
4374 # except ClientException as inst:
4375 # print("ERROR: {}".format(inst))
4383 except pycurl
.error
as exc
:
4385 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4386 except ClientException
as exc
:
4387 print("ERROR: {}".format(exc
))
4388 except (FileNotFoundError
, PermissionError
) as exc
:
4389 print("Cannot open file: {}".format(exc
))
4390 except yaml
.YAMLError
as exc
:
4391 print("Invalid YAML format: {}".format(exc
))
4393 # TODO capture other controlled exceptions here
4394 # TODO remove the ClientException captures from all places, unless they do something different
4397 if __name__
== '__main__':