054bbd1afdf9482ea5c18dd71ac02ed7746d5d8f
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 def get_vim_name(vim_list
, vim_id
):
90 if v
['uuid'] == vim_id
:
96 @click.group(context_settings
=dict(help_option_names
=['-h', '--help'], max_content_width
=160))
97 @click.option('--hostname',
99 envvar
='OSM_HOSTNAME',
100 help='hostname of server. ' +
101 'Also can set OSM_HOSTNAME in environment')
102 #@click.option('--sol005/--no-sol005',
104 # envvar='OSM_SOL005',
105 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
106 # 'Also can set OSM_SOL005 in environment')
107 @click.option('--user',
110 help='user (defaults to admin). ' +
111 'Also can set OSM_USER in environment')
112 @click.option('--password',
114 envvar
='OSM_PASSWORD',
115 help='password (defaults to admin). ' +
116 'Also can set OSM_PASSWORD in environment')
117 @click.option('--project',
119 envvar
='OSM_PROJECT',
120 help='project (defaults to admin). ' +
121 'Also can set OSM_PROJECT in environment')
122 @click.option('-v', '--verbose', count
=True,
123 help='increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)')
124 @click.option('--all-projects',
127 help='include all projects')
128 @click.option('--public/--no-public', default
=None,
129 help='flag for public items (packages, instances, VIM accounts, etc.)')
130 @click.option('--project-domain-name', 'project_domain_name',
132 envvar
='OSM_PROJECT_DOMAIN_NAME',
133 help='project domain name for keystone authentication (default to None). ' +
134 'Also can set OSM_PROJECT_DOMAIN_NAME in environment')
135 @click.option('--user-domain-name', 'user_domain_name',
137 envvar
='OSM_USER_DOMAIN_NAME',
138 help='user domain name for keystone authentication (default to None). ' +
139 'Also can set OSM_USER_DOMAIN_NAME in environment')
140 #@click.option('--so-port',
142 # envvar='OSM_SO_PORT',
143 # help='hostname of server. ' +
144 # 'Also can set OSM_SO_PORT in environment')
145 #@click.option('--so-project',
147 # envvar='OSM_SO_PROJECT',
148 # help='Project Name in SO. ' +
149 # 'Also can set OSM_SO_PROJECT in environment')
150 #@click.option('--ro-hostname',
152 # envvar='OSM_RO_HOSTNAME',
153 # help='hostname of RO server. ' +
154 # 'Also can set OSM_RO_HOSTNAME in environment')
155 #@click.option('--ro-port',
157 # envvar='OSM_RO_PORT',
158 # help='hostname of RO server. ' +
159 # 'Also can set OSM_RO_PORT in environment')
161 def cli_osm(ctx
, **kwargs
):
163 hostname
= kwargs
.pop("hostname", None)
166 "either hostname option or OSM_HOSTNAME " +
167 "environment variable needs to be specified"))
170 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
171 # if so_port is not None:
172 # kwargs['so_port']=so_port
173 # if so_project is not None:
174 # kwargs['so_project']=so_project
175 # if ro_hostname is not None:
176 # kwargs['ro_host']=ro_hostname
177 # if ro_port is not None:
178 # kwargs['ro_port']=ro_port
179 sol005
= os
.getenv('OSM_SOL005', True)
180 # if user is not None:
181 # kwargs['user']=user
182 # if password is not None:
183 # kwargs['password']=password
184 # if project is not None:
185 # kwargs['project']=project
187 # kwargs['all_projects']=all_projects
188 # if public is not None:
189 # kwargs['public']=public
190 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
191 logger
= logging
.getLogger('osmclient')
198 @cli_osm.command(name
='ns-list', short_help
='list all NS instances')
199 @click.option('--filter', default
=None, multiple
=True,
200 help='restricts the list to the NS instances matching the filter.')
201 @click.option('--long', is_flag
=True,
202 help='get more details of the NS (project, vim, deployment status, configuration status.')
204 def ns_list(ctx
, filter, long):
205 """list all NS instances
209 --filter filterExpr Restricts the list to the NS instances matching the filter
212 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
213 concatenated using the "&" character:
216 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
217 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
218 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
220 value := scalar value
224 * zero or more occurrences
225 ? zero or one occurrence
226 [] grouping of expressions to be used with ? and *
227 "" quotation marks for marking string constants
231 "AttrName" is the name of one attribute in the data type that defines the representation
232 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
233 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
234 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
235 entries, it means that the operator "op" is applied to the attribute addressed by the last
236 <attrName> entry included in the concatenation. All simple filter expressions are combined
237 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
238 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
239 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
240 prefix". If an attribute referenced in an expression is an array, an object that contains a
241 corresponding array shall be considered to match the expression if any of the elements in the
242 array matches all expressions that have the same attribute prefix.
246 --filter admin-status=ENABLED
247 --filter nsd-ref=<NSD_NAME>
248 --filter nsd.vendor=<VENDOR>
249 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
250 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
252 def summarize_deployment_status(status_dict
):
259 net_list
= status_dict
.get('nets',[])
262 if net
['status'] not in status_nets
:
263 status_nets
[net
['status']] = 1
265 status_nets
[net
['status']] +=1
267 for k
,v
in status_nets
.items():
268 message
+= "{}:{},".format(k
,v
)
269 message
+= "TOTAL:{}".format(n_nets
)
270 summary
+= "{}".format(message
)
275 vnf_list
= status_dict
['vnfs']
277 member_vnf_index
= vnf
['member_vnf_index']
278 if member_vnf_index
not in status_vnfs
:
279 status_vnfs
[member_vnf_index
] = {}
280 for vm
in vnf
['vms']:
282 if vm
['status'] not in status_vms
:
283 status_vms
[vm
['status']] = 1
285 status_vms
[vm
['status']] +=1
286 if vm
['status'] not in status_vnfs
[member_vnf_index
]:
287 status_vnfs
[member_vnf_index
][vm
['status']] = 1
289 status_vnfs
[member_vnf_index
][vm
['status']] += 1
291 for k
,v
in status_vms
.items():
292 message
+= "{}:{},".format(k
,v
)
293 message
+= "TOTAL:{}".format(n_vms
)
294 summary
+= "\n{}".format(message
)
296 for k
,v
in status_vnfs
.items():
298 message
= "\n {} VMs: ".format(k
)
299 for k2
,v2
in v
.items():
300 message
+= "{}:{},".format(k2
,v2
)
302 message
+= "TOTAL:{}".format(total
)
306 def summarize_config_status(ee_list
):
314 if ee
['elementType'] not in status_ee
:
315 status_ee
[ee
['elementType']] = {}
316 status_ee
[ee
['elementType']][ee
['status']] = 1
318 if ee
['status'] in status_ee
[ee
['elementType']]:
319 status_ee
[ee
['elementType']][ee
['status']] += 1
321 status_ee
[ee
['elementType']][ee
['status']] = 1
322 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
323 if elementType
in status_ee
:
326 for k
,v
in status_ee
[elementType
].items():
327 message
+= "{}:{},".format(k
,v
)
329 message
+= "TOTAL:{}\n".format(total
)
330 summary
+= "{}: {}".format(elementType
, message
)
331 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
336 check_client_version(ctx
.obj
, '--filter')
337 filter='&'.join(filter)
338 resp
= ctx
.obj
.ns
.list(filter)
340 resp
= ctx
.obj
.ns
.list()
352 'configuration status'])
353 project_list
= ctx
.obj
.project
.list()
355 vim_list
= ctx
.obj
.vim
.list()
367 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
368 if fullclassname
== 'osmclient.sol005.client.Client':
370 logger
.debug('NS info: {}'.format(nsr
))
371 nsr_name
= nsr
['name']
373 date
= datetime
.fromtimestamp(nsr
['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
374 ns_state
= nsr
.get('nsState', nsr
['_admin']['nsState'])
376 deployment_status
= summarize_deployment_status(nsr
.get('deploymentStatus'))
377 config_status
= summarize_config_status(nsr
.get('configurationStatus'))
378 project_id
, project_name
= get_project(project_list
, nsr
)
379 #project = '{} ({})'.format(project_name, project_id)
380 project
= project_name
381 vim_id
= nsr
.get('datacenter')
382 vim_name
= get_vim_name(vim_list
, vim_id
)
383 #vim = '{} ({})'.format(vim_name, vim_id)
385 if 'currentOperation' in nsr
:
386 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
388 current_operation
= "{} ({})".format(nsr
['_admin'].get('current-operation','-'), nsr
['_admin']['nslcmop'])
389 error_details
= "N/A"
390 if ns_state
== "BROKEN" or ns_state
== "DEGRADED" or \
391 ('currentOperation' not in nsr
and nsr
.get('errorDescription')):
392 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'], nsr
['errorDetail'])
394 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
395 nsr
= nsopdata
['nsr:nsr']
396 nsr_name
= nsr
['name-ref']
397 nsr_id
= nsr
['ns-instance-config-ref']
400 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
401 ns_state
= deployment_status
402 config_status
= nsr
.get('config-status', 'Not found')
403 current_operation
= "Unknown"
404 error_details
= nsr
.get('detailed-status', 'Not found')
405 if config_status
== "config_not_needed":
406 config_status
= "configured (no charms)"
415 wrap_text(text
=error_details
,width
=40),
427 wrap_text(text
=error_details
,width
=40)])
430 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
431 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
433 def nsd_list(ctx
, filter, long):
436 check_client_version(ctx
.obj
, '--filter')
437 filter='&'.join(filter)
438 resp
= ctx
.obj
.nsd
.list(filter)
440 resp
= ctx
.obj
.nsd
.list()
441 # print(yaml.safe_dump(resp))
442 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
443 if fullclassname
== 'osmclient.sol005.client.Client':
445 table
= PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state',
446 'usage state', 'date', 'last update'])
448 table
= PrettyTable(['nsd name', 'id'])
450 name
= nsd
.get('name','-')
452 onb_state
= nsd
['_admin'].get('onboardingState','-')
453 op_state
= nsd
['_admin'].get('operationalState','-')
454 usage_state
= nsd
['_admin'].get('usageState','-')
455 date
= datetime
.fromtimestamp(nsd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
456 last_update
= datetime
.fromtimestamp(nsd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
457 table
.add_row([name
, nsd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
459 table
.add_row([name
, nsd
['_id']])
461 table
= PrettyTable(['nsd name', 'id'])
463 table
.add_row([nsd
['name'], nsd
['id']])
468 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
469 @click.option('--filter', default
=None, multiple
=True,
470 help='restricts the list to the NSD/NSpkg matching the filter')
471 @click.option('--long', is_flag
=True, help='get more details')
473 def nsd_list1(ctx
, filter, long):
474 """list all NSD/NS pkg in the system"""
476 nsd_list(ctx
, filter, long)
479 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
480 @click.option('--filter', default
=None, multiple
=True,
481 help='restricts the list to the NSD/NSpkg matching the filter')
482 @click.option('--long', is_flag
=True, help='get more details')
484 def nsd_list2(ctx
, filter, long):
485 """list all NS packages"""
487 nsd_list(ctx
, filter, long)
490 def vnfd_list(ctx
, nf_type
, filter, long):
493 check_client_version(ctx
.obj
, '--nf_type')
495 check_client_version(ctx
.obj
, '--filter')
497 filter='&'.join(filter)
500 nf_filter
= "_admin.type=vnfd"
501 elif nf_type
== "pnf":
502 nf_filter
= "_admin.type=pnfd"
503 elif nf_type
== "hnf":
504 nf_filter
= "_admin.type=hnfd"
506 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
508 filter = '{}&{}'.format(nf_filter
, filter)
512 resp
= ctx
.obj
.vnfd
.list(filter)
514 resp
= ctx
.obj
.vnfd
.list()
515 # print(yaml.safe_dump(resp))
516 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
517 if fullclassname
== 'osmclient.sol005.client.Client':
519 table
= PrettyTable(['nfpkg name', 'id', 'vendor', 'version', 'onboarding state', 'operational state',
520 'usage state', 'date', 'last update'])
522 table
= PrettyTable(['nfpkg name', 'id'])
524 name
= vnfd
['name'] if 'name' in vnfd
else '-'
526 onb_state
= vnfd
['_admin'].get('onboardingState','-')
527 op_state
= vnfd
['_admin'].get('operationalState','-')
528 vendor
= vnfd
.get('vendor')
529 version
= vnfd
.get('version')
530 usage_state
= vnfd
['_admin'].get('usageState','-')
531 date
= datetime
.fromtimestamp(vnfd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
532 last_update
= datetime
.fromtimestamp(vnfd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
533 table
.add_row([name
, vnfd
['_id'], vendor
, version
, onb_state
, op_state
, usage_state
, date
, last_update
])
535 table
.add_row([name
, vnfd
['_id']])
537 table
= PrettyTable(['nfpkg name', 'id'])
539 table
.add_row([vnfd
['name'], vnfd
['id']])
544 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
545 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
546 @click.option('--filter', default
=None, multiple
=True,
547 help='restricts the list to the NF pkg matching the filter')
548 @click.option('--long', is_flag
=True, help='get more details')
550 def vnfd_list1(ctx
, nf_type
, filter, long):
551 """list all xNF packages (VNF, HNF, PNF)"""
553 vnfd_list(ctx
, nf_type
, filter, long)
556 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
557 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
558 @click.option('--filter', default
=None, multiple
=True,
559 help='restricts the list to the NFpkg matching the filter')
560 @click.option('--long', is_flag
=True, help='get more details')
562 def vnfd_list2(ctx
, nf_type
, filter, long):
563 """list all xNF packages (VNF, HNF, PNF)"""
565 vnfd_list(ctx
, nf_type
, filter, long)
568 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
569 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
570 @click.option('--filter', default
=None, multiple
=True,
571 help='restricts the list to the NFpkg matching the filter')
572 @click.option('--long', is_flag
=True, help='get more details')
574 def nfpkg_list(ctx
, nf_type
, filter, long):
575 """list all xNF packages (VNF, HNF, PNF)"""
578 check_client_version(ctx
.obj
, ctx
.command
.name
)
579 vnfd_list(ctx
, nf_type
, filter, long)
580 # except ClientException as e:
585 def pkg_repo_list(ctx
, pkgtype
, filter, repo
, long):
587 filter='&'.join(filter)
588 resp
= ctx
.obj
.osmrepo
.pkg_list(pkgtype
, filter, repo
)
590 table
= PrettyTable(['nfpkg name', 'vendor', 'version', 'latest', 'description', 'repository'])
592 table
= PrettyTable(['nfpkg name', 'repository'])
594 name
= vnfd
.get('name', '-')
595 repository
= vnfd
.get('repository')
597 vendor
= vnfd
.get('vendor')
598 version
= vnfd
.get('version')
599 description
= vnfd
.get('description')
600 latest
= vnfd
.get('latest')
601 table
.add_row([name
, vendor
, version
, latest
, description
, repository
])
603 table
.add_row([name
, repository
])
608 @cli_osm.command(name
='vnfpkg-repo-list', short_help
='list all xNF from OSM repositories')
609 @click.option('--filter', default
=None, multiple
=True,
610 help='restricts the list to the NFpkg matching the filter')
611 @click.option('--repo', default
=None,
612 help='restricts the list to a particular OSM repository')
613 @click.option('--long', is_flag
=True, help='get more details')
615 def nfpkg_repo_list1(ctx
, filter, repo
, long):
616 """list xNF packages from OSM repositories"""
618 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
621 @cli_osm.command(name
='nfpkg-repo-list', short_help
='list all xNF from OSM repositories')
622 @click.option('--filter', default
=None, multiple
=True,
623 help='restricts the list to the NFpkg matching the filter')
624 @click.option('--repo', default
=None,
625 help='restricts the list to a particular OSM repository')
626 @click.option('--long', is_flag
=True, help='get more details')
628 def nfpkg_repo_list2(ctx
, filter, repo
, long):
629 """list xNF packages from OSM repositories"""
631 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
634 @cli_osm.command(name
='nsd-repo-list', short_help
='list all NS from OSM repositories')
635 @click.option('--filter', default
=None, multiple
=True,
636 help='restricts the list to the NS matching the filter')
637 @click.option('--repo', default
=None,
638 help='restricts the list to a particular OSM repository')
639 @click.option('--long', is_flag
=True, help='get more details')
641 def nspkg_repo_list(ctx
, filter, repo
, long):
642 """list xNF packages from OSM repositories"""
644 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
647 @cli_osm.command(name
='nspkg-repo-list', short_help
='list all NS from OSM repositories')
648 @click.option('--filter', default
=None, multiple
=True,
649 help='restricts the list to the NS matching the filter')
650 @click.option('--repo', default
=None,
651 help='restricts the list to a particular OSM repository')
652 @click.option('--long', is_flag
=True, help='get more details')
654 def nspkg_repo_list2(ctx
, filter, repo
, long):
655 """list xNF packages from OSM repositories"""
657 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
660 def vnf_list(ctx
, ns
, filter, long):
664 check_client_version(ctx
.obj
, '--ns')
666 filter='&'.join(filter)
667 check_client_version(ctx
.obj
, '--filter')
668 resp
= ctx
.obj
.vnf
.list(ns
, filter)
670 resp
= ctx
.obj
.vnf
.list()
671 # except ClientException as e:
674 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
675 if fullclassname
== 'osmclient.sol005.client.Client':
676 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
677 'vnfd name', 'vim account id', 'ip address']
679 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
680 'vnfd name', 'vim account id', 'ip address',
681 'date', 'last update']
682 table
= PrettyTable(field_names
)
684 name
= vnfr
['name'] if 'name' in vnfr
else '-'
685 new_row
= [vnfr
['_id'], name
, vnfr
['nsr-id-ref'],
686 vnfr
['member-vnf-index-ref'], vnfr
['vnfd-ref'],
687 vnfr
['vim-account-id'], vnfr
['ip-address']]
689 date
= datetime
.fromtimestamp(vnfr
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
690 last_update
= datetime
.fromtimestamp(vnfr
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
691 new_row
.extend([date
, last_update
])
692 table
.add_row(new_row
)
697 'operational status',
700 if 'mgmt-interface' not in vnfr
:
701 vnfr
['mgmt-interface'] = {}
702 vnfr
['mgmt-interface']['ip-address'] = None
706 vnfr
['operational-status'],
707 vnfr
['config-status']])
712 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
713 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
714 @click.option('--filter', default
=None, multiple
=True,
715 help='restricts the list to the NF instances matching the filter.')
716 @click.option('--long', is_flag
=True, help='get more details')
718 def vnf_list1(ctx
, ns
, filter, long):
719 """list all NF instances"""
721 vnf_list(ctx
, ns
, filter, long)
724 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
725 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
726 @click.option('--filter', default
=None, multiple
=True,
727 help='restricts the list to the NF instances matching the filter.')
728 @click.option('--long', is_flag
=True, help='get more details')
730 def nf_list(ctx
, ns
, filter, long):
731 """list all NF instances
735 --ns TEXT NS instance id or name to restrict the VNF list
736 --filter filterExpr Restricts the list to the VNF instances matching the filter
739 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
740 concatenated using the "&" character:
743 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
744 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
745 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
747 value := scalar value
751 * zero or more occurrences
752 ? zero or one occurrence
753 [] grouping of expressions to be used with ? and *
754 "" quotation marks for marking string constants
758 "AttrName" is the name of one attribute in the data type that defines the representation
759 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
760 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
761 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
762 entries, it means that the operator "op" is applied to the attribute addressed by the last
763 <attrName> entry included in the concatenation. All simple filter expressions are combined
764 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
765 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
766 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
767 prefix". If an attribute referenced in an expression is an array, an object that contains a
768 corresponding array shall be considered to match the expression if any of the elements in the
769 array matches all expressions that have the same attribute prefix.
773 --filter vim-account-id=<VIM_ACCOUNT_ID>
774 --filter vnfd-ref=<VNFD_NAME>
775 --filter vdur.ip-address=<IP_ADDRESS>
776 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
779 vnf_list(ctx
, ns
, filter, long)
782 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
783 @click.argument('name')
784 @click.option('--long', is_flag
=True,
785 help='get more details of the NS operation (date, ).')
787 def ns_op_list(ctx
, name
, long):
788 """shows the history of operations over a NS instance
790 NAME: name or ID of the NS instance
792 def formatParams(params
):
793 if params
['lcmOperationType']=='instantiate':
794 params
.pop('nsDescription')
798 elif params
['lcmOperationType']=='action':
799 params
.pop('primitive')
800 params
.pop('lcmOperationType')
801 params
.pop('nsInstanceId')
806 check_client_version(ctx
.obj
, ctx
.command
.name
)
807 resp
= ctx
.obj
.ns
.list_op(name
)
808 # except ClientException as e:
813 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
815 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
817 #print(yaml.safe_dump(resp))
820 if op
['lcmOperationType']=='action':
821 action_name
= op
['operationParams']['primitive']
823 if op
['operationState'] == 'PROCESSING':
824 if op
['queuePosition'] is not None and op
['queuePosition'] > 0:
825 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
826 elif op
['lcmOperationType'] in ('instantiate', 'terminate'):
829 elif op
['operationState'] in ('FAILED', 'FAILED_TEMP'):
830 detail
= op
.get('errorMessage','-')
831 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
832 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
834 table
.add_row([op
['id'],
835 op
['lcmOperationType'],
837 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
838 op
['operationState'],
841 wrap_text(text
=detail
,width
=50)])
843 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
844 op
['operationState'], date
, wrap_text(text
=detail
or "",width
=50)])
849 def nsi_list(ctx
, filter):
850 """list all Network Slice Instances"""
853 check_client_version(ctx
.obj
, ctx
.command
.name
)
855 filter='&'.join(filter)
856 resp
= ctx
.obj
.nsi
.list(filter)
857 # except ClientException as e:
861 ['netslice instance name',
863 'operational status',
867 nsi_name
= nsi
['name']
869 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
870 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
871 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
872 if configstatus
== "config_not_needed":
873 configstatus
= "configured (no charms)"
884 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
885 @click.option('--filter', default
=None, multiple
=True,
886 help='restricts the list to the Network Slice Instances matching the filter')
888 def nsi_list1(ctx
, filter):
889 """list all Network Slice Instances (NSI)"""
891 nsi_list(ctx
, filter)
894 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
895 @click.option('--filter', default
=None, multiple
=True,
896 help='restricts the list to the Network Slice Instances matching the filter')
898 def nsi_list2(ctx
, filter):
899 """list all Network Slice Instances (NSI)"""
901 nsi_list(ctx
, filter)
904 def nst_list(ctx
, filter):
907 check_client_version(ctx
.obj
, ctx
.command
.name
)
909 filter='&'.join(filter)
910 resp
= ctx
.obj
.nst
.list(filter)
911 # except ClientException as e:
914 # print(yaml.safe_dump(resp))
915 table
= PrettyTable(['nst name', 'id'])
917 name
= nst
['name'] if 'name' in nst
else '-'
918 table
.add_row([name
, nst
['_id']])
923 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
924 @click.option('--filter', default
=None, multiple
=True,
925 help='restricts the list to the NST matching the filter')
927 def nst_list1(ctx
, filter):
928 """list all Network Slice Templates (NST) in the system"""
930 nst_list(ctx
, filter)
933 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
934 @click.option('--filter', default
=None, multiple
=True,
935 help='restricts the list to the NST matching the filter')
937 def nst_list2(ctx
, filter):
938 """list all Network Slice Templates (NST) in the system"""
940 nst_list(ctx
, filter)
943 def nsi_op_list(ctx
, name
):
946 check_client_version(ctx
.obj
, ctx
.command
.name
)
947 resp
= ctx
.obj
.nsi
.list_op(name
)
948 # except ClientException as e:
951 table
= PrettyTable(['id', 'operation', 'status'])
953 table
.add_row([op
['id'], op
['lcmOperationType'],
954 op
['operationState']])
959 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
960 @click.argument('name')
962 def nsi_op_list1(ctx
, name
):
963 """shows the history of operations over a Network Slice Instance (NSI)
965 NAME: name or ID of the Network Slice Instance
968 nsi_op_list(ctx
, name
)
971 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
972 @click.argument('name')
974 def nsi_op_list2(ctx
, name
):
975 """shows the history of operations over a Network Slice Instance (NSI)
977 NAME: name or ID of the Network Slice Instance
980 nsi_op_list(ctx
, name
)
983 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
984 @click.option('--filter', default
=None, multiple
=True,
985 help='restricts the list to the Physical Deployment Units matching the filter')
987 def pdu_list(ctx
, filter):
988 """list all Physical Deployment Units (PDU)"""
991 check_client_version(ctx
.obj
, ctx
.command
.name
)
993 filter='&'.join(filter)
994 resp
= ctx
.obj
.pdu
.list(filter)
995 # except ClientException as e:
1004 pdu_name
= pdu
['name']
1006 pdu_type
= pdu
['type']
1007 pdu_ipaddress
= "None"
1008 for iface
in pdu
['interfaces']:
1010 pdu_ipaddress
= iface
['ip-address']
1021 ####################
1023 ####################
1025 def nsd_show(ctx
, name
, literal
):
1028 resp
= ctx
.obj
.nsd
.get(name
)
1029 # resp = ctx.obj.nsd.get_individual(name)
1030 # except ClientException as e:
1035 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1038 table
= PrettyTable(['field', 'value'])
1039 for k
, v
in list(resp
.items()):
1040 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1045 @cli_osm.command(name
='nsd-show', short_help
='shows the details of a NS package')
1046 @click.option('--literal', is_flag
=True,
1047 help='print literally, no pretty table')
1048 @click.argument('name')
1050 def nsd_show1(ctx
, name
, literal
):
1051 """shows the content of a NSD
1053 NAME: name or ID of the NSD/NSpkg
1056 nsd_show(ctx
, name
, literal
)
1059 @cli_osm.command(name
='nspkg-show', short_help
='shows the details of a NS package')
1060 @click.option('--literal', is_flag
=True,
1061 help='print literally, no pretty table')
1062 @click.argument('name')
1064 def nsd_show2(ctx
, name
, literal
):
1065 """shows the content of a NSD
1067 NAME: name or ID of the NSD/NSpkg
1070 nsd_show(ctx
, name
, literal
)
1073 def vnfd_show(ctx
, name
, literal
):
1076 resp
= ctx
.obj
.vnfd
.get(name
)
1077 # resp = ctx.obj.vnfd.get_individual(name)
1078 # except ClientException as e:
1083 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1086 table
= PrettyTable(['field', 'value'])
1087 for k
, v
in list(resp
.items()):
1088 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1093 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1096 filter='&'.join(filter)
1098 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1101 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1104 catalog
= pkgtype
+ '-catalog'
1105 full_catalog
= pkgtype
+ ':' + catalog
1106 if resp
.get(catalog
):
1107 resp
= resp
.pop(catalog
)[pkgtype
][0]
1108 elif resp
.get(full_catalog
):
1109 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1111 table
= PrettyTable(['field', 'value'])
1112 for k
, v
in list(resp
.items()):
1113 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1118 @cli_osm.command(name
='vnfd-show', short_help
='shows the details of a NF package')
1119 @click.option('--literal', is_flag
=True,
1120 help='print literally, no pretty table')
1121 @click.argument('name')
1123 def vnfd_show1(ctx
, name
, literal
):
1124 """shows the content of a VNFD
1126 NAME: name or ID of the VNFD/VNFpkg
1129 vnfd_show(ctx
, name
, literal
)
1132 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the details of a NF package')
1133 @click.option('--literal', is_flag
=True,
1134 help='print literally, no pretty table')
1135 @click.argument('name')
1137 def vnfd_show2(ctx
, name
, literal
):
1138 """shows the content of a VNFD
1140 NAME: name or ID of the VNFD/VNFpkg
1143 vnfd_show(ctx
, name
, literal
)
1146 @cli_osm.command(name
='vnfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1147 @click.option('--literal', is_flag
=True,
1148 help='print literally, no pretty table')
1149 @click.option('--repo',
1151 help='Repository name')
1152 @click.argument('name')
1153 @click.option('--filter', default
=None, multiple
=True,
1154 help='filter by fields')
1155 @click.option('--version',
1157 help='package version')
1159 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1160 """shows the content of a VNFD in a repository
1162 NAME: name or ID of the VNFD/VNFpkg
1165 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1168 @cli_osm.command(name
='nsd-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1169 @click.option('--literal', is_flag
=True,
1170 help='print literally, no pretty table')
1171 @click.option('--repo',
1173 help='Repository name')
1174 @click.argument('name')
1175 @click.option('--filter', default
=None, multiple
=True,
1176 help='filter by fields')
1177 @click.option('--version',
1179 help='package version')
1181 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1182 """shows the content of a VNFD in a repository
1184 NAME: name or ID of the VNFD/VNFpkg
1187 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1190 @cli_osm.command(name
='nspkg-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1191 @click.option('--literal', is_flag
=True,
1192 help='print literally, no pretty table')
1193 @click.option('--repo',
1195 help='Repository name')
1196 @click.argument('name')
1197 @click.option('--filter', default
=None, multiple
=True,
1198 help='filter by fields')
1199 @click.option('--version',
1201 help='package version')
1203 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1204 """shows the content of a VNFD in a repository
1206 NAME: name or ID of the VNFD/VNFpkg
1209 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1212 @cli_osm.command(name
='nfpkg-show', short_help
='shows the details of a NF package')
1213 @click.option('--literal', is_flag
=True,
1214 help='print literally, no pretty table')
1215 @click.argument('name')
1217 def nfpkg_show(ctx
, name
, literal
):
1218 """shows the content of a NF Descriptor
1220 NAME: name or ID of the NFpkg
1223 vnfd_show(ctx
, name
, literal
)
1226 @cli_osm.command(name
='nfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1227 @click.option('--literal', is_flag
=True,
1228 help='print literally, no pretty table')
1229 @click.option('--repo',
1231 help='Repository name')
1232 @click.argument('name')
1233 @click.option('--filter', default
=None, multiple
=True,
1234 help='filter by fields')
1235 @click.option('--version',
1237 help='package version')
1239 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1240 """shows the content of a VNFD in a repository
1242 NAME: name or ID of the VNFD/VNFpkg
1245 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1248 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
1249 @click.argument('name')
1250 @click.option('--literal', is_flag
=True,
1251 help='print literally, no pretty table')
1252 @click.option('--filter', multiple
=True,
1253 help='restricts the information to the fields in the filter')
1255 def ns_show(ctx
, name
, literal
, filter):
1256 """shows the info of a NS instance
1258 NAME: name or ID of the NS instance
1262 ns
= ctx
.obj
.ns
.get(name
)
1263 # except ClientException as e:
1268 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1271 table
= PrettyTable(['field', 'value'])
1273 for k
, v
in list(ns
.items()):
1274 if not filter or k
in filter:
1275 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1277 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1278 if fullclassname
!= 'osmclient.sol005.client.Client':
1279 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1280 nsr_optdata
= nsopdata
['nsr:nsr']
1281 for k
, v
in list(nsr_optdata
.items()):
1282 if not filter or k
in filter:
1283 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1288 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1289 @click.argument('name')
1290 @click.option('--literal', is_flag
=True,
1291 help='print literally, no pretty table')
1292 @click.option('--filter', multiple
=True,
1293 help='restricts the information to the fields in the filter')
1294 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1296 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1297 """shows the info of a VNF instance
1299 NAME: name or ID of the VNF instance
1301 def print_kdu_status(op_info_status
):
1302 """print KDU status properly formatted
1305 op_status
= yaml
.safe_load(op_info_status
)
1306 if "namespace" in op_status
and "info" in op_status
and \
1307 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1308 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1309 "seconds" in op_status
["info"]["last_deployed"]:
1310 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1311 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1312 print("NAMESPACE: {}".format(op_status
["namespace"]))
1313 status_code
= "UNKNOWN"
1314 if op_status
["info"]["status"]["code"]==1:
1315 status_code
= "DEPLOYED"
1316 print("STATUS: {}".format(status_code
))
1319 print(op_status
["info"]["status"]["resources"])
1320 if "notes" in op_status
["info"]["status"]:
1322 print(op_status
["info"]["status"]["notes"])
1324 print(op_info_status
)
1326 print(op_info_status
)
1331 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1333 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1336 check_client_version(ctx
.obj
, ctx
.command
.name
)
1337 resp
= ctx
.obj
.vnf
.get(name
)
1340 ns_id
= resp
['nsr-id-ref']
1342 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1343 op_data
['kdu_name'] = kdu
1344 op_data
['primitive'] = 'status'
1345 op_data
['primitive_params'] = {}
1346 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1349 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1350 if op_info
['operationState'] == 'COMPLETED':
1351 print_kdu_status(op_info
['detailed-status'])
1355 print ("Could not determine KDU status")
1359 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1362 table
= PrettyTable(['field', 'value'])
1364 for k
, v
in list(resp
.items()):
1365 if not filter or k
in filter:
1366 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1369 # except ClientException as e:
1374 #@cli_osm.command(name='vnf-monitoring-show')
1375 #@click.argument('vnf_name')
1376 #@click.pass_context
1377 #def vnf_monitoring_show(ctx, vnf_name):
1379 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1380 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1381 # except ClientException as e:
1385 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1386 # if resp is not None:
1387 # for monitor in resp:
1391 # monitor['value-integer'],
1392 # monitor['units']])
1397 #@cli_osm.command(name='ns-monitoring-show')
1398 #@click.argument('ns_name')
1399 #@click.pass_context
1400 #def ns_monitoring_show(ctx, ns_name):
1402 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1403 # resp = ctx.obj.ns.get_monitoring(ns_name)
1404 # except ClientException as e:
1408 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1409 # for key, val in list(resp.items()):
1410 # for monitor in val:
1414 # monitor['value-integer'],
1415 # monitor['units']])
1420 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1421 @click.argument('id')
1422 @click.option('--filter', multiple
=True,
1423 help='restricts the information to the fields in the filter')
1424 @click.option('--literal', is_flag
=True,
1425 help='print literally, no pretty table')
1427 def ns_op_show(ctx
, id, filter, literal
):
1428 """shows the detailed info of a NS operation
1430 ID: operation identifier
1434 check_client_version(ctx
.obj
, ctx
.command
.name
)
1435 op_info
= ctx
.obj
.ns
.get_op(id)
1436 # except ClientException as e:
1441 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1444 table
= PrettyTable(['field', 'value'])
1445 for k
, v
in list(op_info
.items()):
1446 if not filter or k
in filter:
1447 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1452 def nst_show(ctx
, name
, literal
):
1455 check_client_version(ctx
.obj
, ctx
.command
.name
)
1456 resp
= ctx
.obj
.nst
.get(name
)
1457 #resp = ctx.obj.nst.get_individual(name)
1458 # except ClientException as e:
1463 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1466 table
= PrettyTable(['field', 'value'])
1467 for k
, v
in list(resp
.items()):
1468 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1473 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1474 @click.option('--literal', is_flag
=True,
1475 help='print literally, no pretty table')
1476 @click.argument('name')
1478 def nst_show1(ctx
, name
, literal
):
1479 """shows the content of a Network Slice Template (NST)
1481 NAME: name or ID of the NST
1484 nst_show(ctx
, name
, literal
)
1487 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1488 @click.option('--literal', is_flag
=True,
1489 help='print literally, no pretty table')
1490 @click.argument('name')
1492 def nst_show2(ctx
, name
, literal
):
1493 """shows the content of a Network Slice Template (NST)
1495 NAME: name or ID of the NST
1498 nst_show(ctx
, name
, literal
)
1501 def nsi_show(ctx
, name
, literal
, filter):
1504 check_client_version(ctx
.obj
, ctx
.command
.name
)
1505 nsi
= ctx
.obj
.nsi
.get(name
)
1506 # except ClientException as e:
1511 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1514 table
= PrettyTable(['field', 'value'])
1516 for k
, v
in list(nsi
.items()):
1517 if not filter or k
in filter:
1518 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1524 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1525 @click.argument('name')
1526 @click.option('--literal', is_flag
=True,
1527 help='print literally, no pretty table')
1528 @click.option('--filter', multiple
=True,
1529 help='restricts the information to the fields in the filter')
1531 def nsi_show1(ctx
, name
, literal
, filter):
1532 """shows the content of a Network Slice Instance (NSI)
1534 NAME: name or ID of the Network Slice Instance
1537 nsi_show(ctx
, name
, literal
, filter)
1540 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1541 @click.argument('name')
1542 @click.option('--literal', is_flag
=True,
1543 help='print literally, no pretty table')
1544 @click.option('--filter', multiple
=True,
1545 help='restricts the information to the fields in the filter')
1547 def nsi_show2(ctx
, name
, literal
, filter):
1548 """shows the content of a Network Slice Instance (NSI)
1550 NAME: name or ID of the Network Slice Instance
1553 nsi_show(ctx
, name
, literal
, filter)
1556 def nsi_op_show(ctx
, id, filter):
1559 check_client_version(ctx
.obj
, ctx
.command
.name
)
1560 op_info
= ctx
.obj
.nsi
.get_op(id)
1561 # except ClientException as e:
1565 table
= PrettyTable(['field', 'value'])
1566 for k
, v
in list(op_info
.items()):
1567 if not filter or k
in filter:
1568 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1573 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1574 @click.argument('id')
1575 @click.option('--filter', multiple
=True,
1576 help='restricts the information to the fields in the filter')
1578 def nsi_op_show1(ctx
, id, filter):
1579 """shows the info of an operation over a Network Slice Instance(NSI)
1581 ID: operation identifier
1584 nsi_op_show(ctx
, id, filter)
1587 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1588 @click.argument('id')
1589 @click.option('--filter', multiple
=True,
1590 help='restricts the information to the fields in the filter')
1592 def nsi_op_show2(ctx
, id, filter):
1593 """shows the info of an operation over a Network Slice Instance(NSI)
1595 ID: operation identifier
1598 nsi_op_show(ctx
, id, filter)
1601 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1602 @click.argument('name')
1603 @click.option('--literal', is_flag
=True,
1604 help='print literally, no pretty table')
1605 @click.option('--filter', multiple
=True,
1606 help='restricts the information to the fields in the filter')
1608 def pdu_show(ctx
, name
, literal
, filter):
1609 """shows the content of a Physical Deployment Unit (PDU)
1611 NAME: name or ID of the PDU
1615 check_client_version(ctx
.obj
, ctx
.command
.name
)
1616 pdu
= ctx
.obj
.pdu
.get(name
)
1617 # except ClientException as e:
1622 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1625 table
= PrettyTable(['field', 'value'])
1627 for k
, v
in list(pdu
.items()):
1628 if not filter or k
in filter:
1629 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1635 ####################
1637 ####################
1639 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1642 check_client_version(ctx
.obj
, ctx
.command
.name
)
1644 filename
= ctx
.obj
.osmrepo
.get_pkg('ns', filename
, repo
, vendor
, version
)
1645 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1646 # except ClientException as e:
1651 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1652 @click.argument('filename')
1653 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1654 help='Deprecated. Use override')
1655 @click.option('--override', 'overwrite', default
=None,
1656 help='overrides fields in descriptor, format: '
1657 '"key1.key2...=value[;key3...=value;...]"')
1658 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1659 help='The charm will not be compiled, it is assumed to already exist')
1660 @click.option('--repo', default
=None,
1661 help='[repository]: Repository name')
1662 @click.option('--vendor', default
=None,
1663 help='[repository]: filter by vendor]')
1664 @click.option('--version', default
='latest',
1665 help='[repository]: filter by version. Default: latest')
1667 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1668 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1671 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1672 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1673 If FILENAME is an NF Package folder, it is built and then onboarded.
1676 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1680 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1681 @click.argument('filename')
1682 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1683 help='Deprecated. Use override')
1684 @click.option('--override', 'overwrite', default
=None,
1685 help='overrides fields in descriptor, format: '
1686 '"key1.key2...=value[;key3...=value;...]"')
1687 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1688 help='The charm will not be compiled, it is assumed to already exist')
1689 @click.option('--repo', default
=None,
1690 help='[repository]: Repository name')
1691 @click.option('--vendor', default
=None,
1692 help='[repository]: filter by vendor]')
1693 @click.option('--version', default
='latest',
1694 help='[repository]: filter by version. Default: latest')
1696 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1697 """onboards a new NSpkg
1699 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1700 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1701 If FILENAME is an NF Package folder, it is built and then onboarded.
1704 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1708 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1709 repo
, vendor
, version
):
1712 check_client_version(ctx
.obj
, ctx
.command
.name
)
1714 filename
= ctx
.obj
.osmrepo
.get_pkg('vnf', filename
, repo
, vendor
, version
)
1715 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1716 override_epa
=override_epa
, override_nonepa
=override_nonepa
,
1717 override_paravirt
=override_paravirt
)
1718 # except ClientException as e:
1723 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1724 @click.argument('filename')
1725 @click.option('--overwrite', 'overwrite', default
=None,
1726 help='overwrite deprecated, use override')
1727 @click.option('--override', 'overwrite', default
=None,
1728 help='overrides fields in descriptor, format: '
1729 '"key1.key2...=value[;key3...=value;...]"')
1730 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1731 help='The charm will not be compiled, it is assumed to already exist')
1732 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1733 help='adds guest-epa parameters to all VDU')
1734 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1735 help='removes all guest-epa parameters from all VDU')
1736 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1737 help='overrides all VDU interfaces to PARAVIRT')
1738 @click.option('--repo', default
=None,
1739 help='[repository]: Repository name')
1740 @click.option('--vendor', default
=None,
1741 help='[repository]: filter by vendor]')
1742 @click.option('--version', default
='latest',
1743 help='[repository]: filter by version. Default: latest')
1745 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1746 repo
,vendor
, version
):
1747 """creates a new VNFD/VNFpkg
1749 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1750 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1751 If FILENAME is an NF Package folder, it is built and then onboarded.
1754 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1755 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1756 repo
=repo
, vendor
=vendor
, version
=version
)
1759 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1760 @click.argument('filename')
1761 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1762 help='Deprecated. Use override')
1763 @click.option('--override', 'overwrite', default
=None,
1764 help='overrides fields in descriptor, format: '
1765 '"key1.key2...=value[;key3...=value;...]"')
1766 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1767 help='The charm will not be compiled, it is assumed to already exist')
1768 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1769 help='adds guest-epa parameters to all VDU')
1770 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1771 help='removes all guest-epa parameters from all VDU')
1772 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1773 help='overrides all VDU interfaces to PARAVIRT')
1774 @click.option('--repo', default
=None,
1775 help='[repository]: Repository name')
1776 @click.option('--vendor', default
=None,
1777 help='[repository]: filter by vendor]')
1778 @click.option('--version', default
='latest',
1779 help='[repository]: filter by version. Default: latest')
1781 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1782 repo
, vendor
, version
):
1783 """creates a new VNFD/VNFpkg
1785 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1786 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1787 If FILENAME is an NF Package folder, it is built and then onboarded.
1790 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1791 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1792 repo
=repo
, vendor
=vendor
, version
=version
)
1794 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1795 @click.argument('filename')
1796 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1797 help='Deprecated. Use override')
1798 @click.option('--override', 'overwrite', default
=None,
1799 help='overrides fields in descriptor, format: '
1800 '"key1.key2...=value[;key3...=value;...]"')
1801 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1802 help='The charm will not be compiled, it is assumed to already exist')
1803 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1804 help='adds guest-epa parameters to all VDU')
1805 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1806 help='removes all guest-epa parameters from all VDU')
1807 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1808 help='overrides all VDU interfaces to PARAVIRT')
1809 @click.option('--repo', default
=None,
1810 help='[repository]: Repository name')
1811 @click.option('--vendor', default
=None,
1812 help='[repository]: filter by vendor]')
1813 @click.option('--version', default
='latest',
1814 help='[repository]: filter by version. Default: latest')
1816 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1817 repo
, vendor
, version
):
1818 """creates a new NFpkg
1821 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1822 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1823 If FILENAME is an NF Package folder, it is built and then onboarded.
1826 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1827 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1828 repo
=repo
, vendor
=vendor
, version
=version
)
1831 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1832 @click.option('--ns_name',
1833 prompt
=True, help='name of the NS instance')
1834 @click.option('--nsd_name',
1835 prompt
=True, help='name of the NS descriptor')
1836 @click.option('--vim_account',
1837 prompt
=True, help='default VIM account id or name for the deployment')
1838 @click.option('--admin_status',
1840 help='administration status')
1841 @click.option('--ssh_keys',
1843 help='comma separated list of public key files to inject to vnfs')
1844 @click.option('--config',
1846 help='ns specific yaml configuration')
1847 @click.option('--config_file',
1849 help='ns specific yaml configuration file')
1850 @click.option('--wait',
1854 help='do not return the control immediately, but keep it '
1855 'until the operation is completed, or timeout')
1866 """creates a new NS instance"""
1870 check_client_version(ctx
.obj
, '--config_file')
1872 raise ClientException('"--config" option is incompatible with "--config_file" option')
1873 with
open(config_file
, 'r') as cf
:
1880 account
=vim_account
,
1882 # except ClientException as e:
1887 def nst_create(ctx
, filename
, overwrite
):
1890 check_client_version(ctx
.obj
, ctx
.command
.name
)
1891 ctx
.obj
.nst
.create(filename
, overwrite
)
1892 # except ClientException as e:
1897 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1898 @click.argument('filename')
1899 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1900 help='Deprecated. Use override')
1901 @click.option('--override', 'overwrite', default
=None,
1902 help='overrides fields in descriptor, format: '
1903 '"key1.key2...=value[;key3...=value;...]"')
1905 def nst_create1(ctx
, filename
, overwrite
):
1906 """creates a new Network Slice Template (NST)
1908 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1911 nst_create(ctx
, filename
, overwrite
)
1914 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1915 @click.argument('filename')
1916 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1917 help='Deprecated. Use override')
1918 @click.option('--override', 'overwrite', default
=None,
1919 help='overrides fields in descriptor, format: '
1920 '"key1.key2...=value[;key3...=value;...]"')
1922 def nst_create2(ctx
, filename
, overwrite
):
1923 """creates a new Network Slice Template (NST)
1925 FILENAME: NST yaml file or NSTpkg tar.gz file
1928 nst_create(ctx
, filename
, overwrite
)
1931 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1932 """creates a new Network Slice Instance (NSI)"""
1935 check_client_version(ctx
.obj
, ctx
.command
.name
)
1938 raise ClientException('"--config" option is incompatible with "--config_file" option')
1939 with
open(config_file
, 'r') as cf
:
1941 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1942 account
=vim_account
, wait
=wait
)
1943 # except ClientException as e:
1948 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1949 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1950 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1951 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1952 @click.option('--ssh_keys', default
=None,
1953 help='comma separated list of keys to inject to vnfs')
1954 @click.option('--config', default
=None,
1955 help='Netslice specific yaml configuration:\n'
1956 'netslice_subnet: [\n'
1957 'id: TEXT, vim_account: TEXT,\n'
1958 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1959 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1960 'additionalParamsForNsi: {param: value, ...}\n'
1961 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1963 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1965 @click.option('--config_file',
1967 help='nsi specific yaml configuration file')
1968 @click.option('--wait',
1972 help='do not return the control immediately, but keep it '
1973 'until the operation is completed, or timeout')
1975 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1976 """creates a new Network Slice Instance (NSI)"""
1978 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1981 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1982 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1983 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1984 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1985 @click.option('--ssh_keys', default
=None,
1986 help='comma separated list of keys to inject to vnfs')
1987 @click.option('--config', default
=None,
1988 help='Netslice specific yaml configuration:\n'
1989 'netslice_subnet: [\n'
1990 'id: TEXT, vim_account: TEXT,\n'
1991 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1992 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1994 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1996 @click.option('--config_file',
1998 help='nsi specific yaml configuration file')
1999 @click.option('--wait',
2003 help='do not return the control immediately, but keep it '
2004 'until the operation is completed, or timeout')
2006 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
2007 """creates a new Network Slice Instance (NSI)"""
2009 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
2012 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
2013 @click.option('--name', help='name of the Physical Deployment Unit')
2014 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
2015 @click.option('--interface',
2016 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
2017 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
2019 @click.option('--description', help='human readable description')
2020 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
2021 @click.option('--descriptor_file', default
=None,
2022 help='PDU descriptor file (as an alternative to using the other arguments')
2024 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
2025 """creates a new Physical Deployment Unit (PDU)"""
2028 check_client_version(ctx
.obj
, ctx
.command
.name
)
2030 if not descriptor_file
:
2032 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
2034 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
2036 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
2038 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
2040 with
open(descriptor_file
, 'r') as df
:
2041 pdu
= yaml
.safe_load(df
.read())
2042 if name
: pdu
["name"] = name
2043 if pdu_type
: pdu
["type"] = pdu_type
2044 if description
: pdu
["description"] = description
2045 if vim_account
: pdu
["vim_accounts"] = vim_account
2048 for iface
in interface
:
2049 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
2050 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
2051 ifaces_list
.append(new_iface
)
2052 pdu
["interfaces"] = ifaces_list
2053 ctx
.obj
.pdu
.create(pdu
)
2054 # except ClientException as e:
2059 ####################
2061 ####################
2063 def nsd_update(ctx
, name
, content
):
2066 check_client_version(ctx
.obj
, ctx
.command
.name
)
2067 ctx
.obj
.nsd
.update(name
, content
)
2068 # except ClientException as e:
2073 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
2074 @click.argument('name')
2075 @click.option('--content', default
=None,
2076 help='filename with the NSD/NSpkg replacing the current one')
2078 def nsd_update1(ctx
, name
, content
):
2079 """updates a NSD/NSpkg
2081 NAME: name or ID of the NSD/NSpkg
2084 nsd_update(ctx
, name
, content
)
2087 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
2088 @click.argument('name')
2089 @click.option('--content', default
=None,
2090 help='filename with the NSD/NSpkg replacing the current one')
2092 def nsd_update2(ctx
, name
, content
):
2093 """updates a NSD/NSpkg
2095 NAME: name or ID of the NSD/NSpkg
2098 nsd_update(ctx
, name
, content
)
2101 def vnfd_update(ctx
, name
, content
):
2104 check_client_version(ctx
.obj
, ctx
.command
.name
)
2105 ctx
.obj
.vnfd
.update(name
, content
)
2106 # except ClientException as e:
2111 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
2112 @click.argument('name')
2113 @click.option('--content', default
=None,
2114 help='filename with the VNFD/VNFpkg replacing the current one')
2116 def vnfd_update1(ctx
, name
, content
):
2117 """updates a VNFD/VNFpkg
2119 NAME: name or ID of the VNFD/VNFpkg
2122 vnfd_update(ctx
, name
, content
)
2125 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
2126 @click.argument('name')
2127 @click.option('--content', default
=None,
2128 help='filename with the VNFD/VNFpkg replacing the current one')
2130 def vnfd_update2(ctx
, name
, content
):
2131 """updates a VNFD/VNFpkg
2133 NAME: VNFD yaml file or VNFpkg tar.gz file
2136 vnfd_update(ctx
, name
, content
)
2139 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
2140 @click.argument('name')
2141 @click.option('--content', default
=None,
2142 help='filename with the NFpkg replacing the current one')
2144 def nfpkg_update(ctx
, name
, content
):
2147 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2150 vnfd_update(ctx
, name
, content
)
2153 def nst_update(ctx
, name
, content
):
2156 check_client_version(ctx
.obj
, ctx
.command
.name
)
2157 ctx
.obj
.nst
.update(name
, content
)
2158 # except ClientException as e:
2163 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
2164 @click.argument('name')
2165 @click.option('--content', default
=None,
2166 help='filename with the NST/NSTpkg replacing the current one')
2168 def nst_update1(ctx
, name
, content
):
2169 """updates a Network Slice Template (NST)
2171 NAME: name or ID of the NSD/NSpkg
2174 nst_update(ctx
, name
, content
)
2177 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
2178 @click.argument('name')
2179 @click.option('--content', default
=None,
2180 help='filename with the NST/NSTpkg replacing the current one')
2182 def nst_update2(ctx
, name
, content
):
2183 """updates a Network Slice Template (NST)
2185 NAME: name or ID of the NSD/NSpkg
2188 nst_update(ctx
, name
, content
)
2191 ####################
2193 ####################
2195 def nsd_delete(ctx
, name
, force
):
2199 ctx
.obj
.nsd
.delete(name
)
2201 check_client_version(ctx
.obj
, '--force')
2202 ctx
.obj
.nsd
.delete(name
, force
)
2203 # except ClientException as e:
2208 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
2209 @click.argument('name')
2210 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2212 def nsd_delete1(ctx
, name
, force
):
2213 """deletes a NSD/NSpkg
2215 NAME: name or ID of the NSD/NSpkg to be deleted
2218 nsd_delete(ctx
, name
, force
)
2221 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
2222 @click.argument('name')
2223 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2225 def nsd_delete2(ctx
, name
, force
):
2226 """deletes a NSD/NSpkg
2228 NAME: name or ID of the NSD/NSpkg to be deleted
2231 nsd_delete(ctx
, name
, force
)
2234 def vnfd_delete(ctx
, name
, force
):
2238 ctx
.obj
.vnfd
.delete(name
)
2240 check_client_version(ctx
.obj
, '--force')
2241 ctx
.obj
.vnfd
.delete(name
, force
)
2242 # except ClientException as e:
2247 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
2248 @click.argument('name')
2249 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2251 def vnfd_delete1(ctx
, name
, force
):
2252 """deletes a VNFD/VNFpkg
2254 NAME: name or ID of the VNFD/VNFpkg to be deleted
2257 vnfd_delete(ctx
, name
, force
)
2260 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
2261 @click.argument('name')
2262 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2264 def vnfd_delete2(ctx
, name
, force
):
2265 """deletes a VNFD/VNFpkg
2267 NAME: name or ID of the VNFD/VNFpkg to be deleted
2270 vnfd_delete(ctx
, name
, force
)
2273 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
2274 @click.argument('name')
2275 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2277 def nfpkg_delete(ctx
, name
, force
):
2280 NAME: name or ID of the NFpkg to be deleted
2283 vnfd_delete(ctx
, name
, force
)
2286 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
2287 @click.argument('name')
2288 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2289 @click.option('--config', default
=None,
2290 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2291 "600, skip_terminate_primitives: True}'")
2292 @click.option('--wait',
2296 help='do not return the control immediately, but keep it '
2297 'until the operation is completed, or timeout')
2299 def ns_delete(ctx
, name
, force
, config
, wait
):
2300 """deletes a NS instance
2302 NAME: name or ID of the NS instance to be deleted
2307 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2309 check_client_version(ctx
.obj
, '--force')
2310 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2311 # except ClientException as e:
2316 def nst_delete(ctx
, name
, force
):
2319 check_client_version(ctx
.obj
, ctx
.command
.name
)
2320 ctx
.obj
.nst
.delete(name
, force
)
2321 # except ClientException as e:
2326 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
2327 @click.argument('name')
2328 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2330 def nst_delete1(ctx
, name
, force
):
2331 """deletes a Network Slice Template (NST)
2333 NAME: name or ID of the NST/NSTpkg to be deleted
2336 nst_delete(ctx
, name
, force
)
2339 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
2340 @click.argument('name')
2341 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2343 def nst_delete2(ctx
, name
, force
):
2344 """deletes a Network Slice Template (NST)
2346 NAME: name or ID of the NST/NSTpkg to be deleted
2349 nst_delete(ctx
, name
, force
)
2352 def nsi_delete(ctx
, name
, force
, wait
):
2355 check_client_version(ctx
.obj
, ctx
.command
.name
)
2356 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2357 # except ClientException as e:
2362 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2363 @click.argument('name')
2364 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2365 @click.option('--wait',
2369 help='do not return the control immediately, but keep it '
2370 'until the operation is completed, or timeout')
2372 def nsi_delete1(ctx
, name
, force
, wait
):
2373 """deletes a Network Slice Instance (NSI)
2375 NAME: name or ID of the Network Slice instance to be deleted
2378 nsi_delete(ctx
, name
, force
, wait
=wait
)
2381 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2382 @click.argument('name')
2383 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2385 def nsi_delete2(ctx
, name
, force
, wait
):
2386 """deletes a Network Slice Instance (NSI)
2388 NAME: name or ID of the Network Slice instance to be deleted
2391 nsi_delete(ctx
, name
, force
, wait
=wait
)
2394 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2395 @click.argument('name')
2396 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2398 def pdu_delete(ctx
, name
, force
):
2399 """deletes a Physical Deployment Unit (PDU)
2401 NAME: name or ID of the PDU to be deleted
2405 check_client_version(ctx
.obj
, ctx
.command
.name
)
2406 ctx
.obj
.pdu
.delete(name
, force
)
2407 # except ClientException as e:
2416 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2417 @click.option('--name',
2419 help='Name to create datacenter')
2420 @click.option('--user',
2422 help='VIM username')
2423 @click.option('--password',
2426 confirmation_prompt
=True,
2427 help='VIM password')
2428 @click.option('--auth_url',
2431 @click.option('--tenant',
2433 help='VIM tenant name')
2434 @click.option('--config',
2436 help='VIM specific config parameters')
2437 @click.option('--account_type',
2438 default
='openstack',
2440 @click.option('--description',
2442 help='human readable description')
2443 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2444 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2445 @click.option('--wait',
2449 help='do not return the control immediately, but keep it '
2450 'until the operation is completed, or timeout')
2464 """creates a new VIM account"""
2468 check_client_version(ctx
.obj
, '--sdn_controller')
2469 if sdn_port_mapping
:
2470 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2472 vim
['vim-username'] = user
2473 vim
['vim-password'] = password
2474 vim
['vim-url'] = auth_url
2475 vim
['vim-tenant-name'] = tenant
2476 vim
['vim-type'] = account_type
2477 vim
['description'] = description
2478 vim
['config'] = config
2479 if sdn_controller
or sdn_port_mapping
:
2480 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2482 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2483 # except ClientException as e:
2488 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2489 @click.argument('name')
2490 @click.option('--newname', help='New name for the VIM account')
2491 @click.option('--user', help='VIM username')
2492 @click.option('--password', help='VIM password')
2493 @click.option('--auth_url', help='VIM url')
2494 @click.option('--tenant', help='VIM tenant name')
2495 @click.option('--config', help='VIM specific config parameters')
2496 @click.option('--account_type', help='VIM type')
2497 @click.option('--description', help='human readable description')
2498 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller to be associated with this VIM'
2499 'account. Use empty string to disassociate')
2500 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2501 @click.option('--wait',
2505 help='do not return the control immediately, but keep it '
2506 'until the operation is completed, or timeout')
2521 """updates a VIM account
2523 NAME: name or ID of the VIM account
2527 check_client_version(ctx
.obj
, ctx
.command
.name
)
2529 if newname
: vim
['name'] = newname
2530 if user
: vim
['vim_user'] = user
2531 if password
: vim
['vim_password'] = password
2532 if auth_url
: vim
['vim_url'] = auth_url
2533 if tenant
: vim
['vim-tenant-name'] = tenant
2534 if account_type
: vim
['vim_type'] = account_type
2535 if description
: vim
['description'] = description
2536 if config
: vim
['config'] = config
2537 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2538 # except ClientException as e:
2543 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2544 @click.argument('name')
2545 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2546 @click.option('--wait',
2550 help='do not return the control immediately, but keep it '
2551 'until the operation is completed, or timeout')
2553 def vim_delete(ctx
, name
, force
, wait
):
2554 """deletes a VIM account
2556 NAME: name or ID of the VIM account to be deleted
2561 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2563 check_client_version(ctx
.obj
, '--force')
2564 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2565 # except ClientException as e:
2570 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2571 #@click.option('--ro_update/--no_ro_update',
2573 # help='update list from RO')
2574 @click.option('--filter', default
=None, multiple
=True,
2575 help='restricts the list to the VIM accounts matching the filter')
2576 @click.option('--long', is_flag
=True,
2577 help='get more details of the NS (project, vim, deployment status, configuration status.')
2579 def vim_list(ctx
, filter, long):
2580 """list all VIM accounts"""
2583 filter='&'.join(filter)
2584 check_client_version(ctx
.obj
, '--filter')
2586 # check_client_version(ctx.obj, '--ro_update', 'v1')
2587 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2588 if fullclassname
== 'osmclient.sol005.client.Client':
2589 resp
= ctx
.obj
.vim
.list(filter)
2591 # resp = ctx.obj.vim.list(ro_update)
2593 table
= PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details'])
2594 project_list
= ctx
.obj
.project
.list()
2596 table
= PrettyTable(['vim name', 'uuid', 'operational state'])
2599 if 'vim_password' in vim
:
2600 vim
['vim_password']='********'
2601 logger
.debug('VIM details: {}'.format(yaml
.safe_dump(vim
)))
2602 vim_state
= vim
['_admin'].get('operationalState', '-')
2603 error_details
= 'N/A'
2604 if vim_state
== 'ERROR':
2605 error_details
= vim
['_admin'].get('detailed-status', 'Not found')
2606 project_id
, project_name
= get_project(project_list
, vim
)
2607 #project_info = '{} ({})'.format(project_name, project_id)
2608 project_info
= project_name
2609 table
.add_row([vim
['name'], vim
['uuid'], project_info
,
2610 vim_state
, wrap_text(text
=error_details
, width
=80)])
2612 table
.add_row([vim
['name'], vim
['uuid'], vim
['_admin'].get('operationalState', '-')])
2617 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2618 @click.argument('name')
2619 @click.option('--filter', multiple
=True,
2620 help='restricts the information to the fields in the filter')
2622 def vim_show(ctx
, name
, filter):
2623 """shows the details of a VIM account
2625 NAME: name or ID of the VIM account
2629 resp
= ctx
.obj
.vim
.get(name
)
2630 if 'vim_password' in resp
:
2631 resp
['vim_password']='********'
2632 # except ClientException as e:
2636 table
= PrettyTable(['key', 'attribute'])
2637 for k
, v
in list(resp
.items()):
2638 if not filter or k
in filter:
2639 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2644 ####################
2646 ####################
2648 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2649 @click.option('--name',
2651 help='Name for the WIM account')
2652 @click.option('--user',
2653 help='WIM username')
2654 @click.option('--password',
2655 help='WIM password')
2656 @click.option('--url',
2659 # @click.option('--tenant',
2660 # help='wIM tenant name')
2661 @click.option('--config',
2663 help='WIM specific config parameters')
2664 @click.option('--wim_type',
2666 @click.option('--description',
2668 help='human readable description')
2669 @click.option('--wim_port_mapping', default
=None,
2670 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2671 "(WAN service endpoint id and info)")
2672 @click.option('--wait',
2676 help='do not return the control immediately, but keep it '
2677 'until the operation is completed, or timeout')
2690 """creates a new WIM account"""
2693 check_client_version(ctx
.obj
, ctx
.command
.name
)
2694 # if sdn_controller:
2695 # check_client_version(ctx.obj, '--sdn_controller')
2696 # if sdn_port_mapping:
2697 # check_client_version(ctx.obj, '--sdn_port_mapping')
2699 if user
: wim
['user'] = user
2700 if password
: wim
['password'] = password
2701 if url
: wim
['wim_url'] = url
2702 # if tenant: wim['tenant'] = tenant
2703 wim
['wim_type'] = wim_type
2704 if description
: wim
['description'] = description
2705 if config
: wim
['config'] = config
2706 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2707 # except ClientException as e:
2712 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2713 @click.argument('name')
2714 @click.option('--newname', help='New name for the WIM account')
2715 @click.option('--user', help='WIM username')
2716 @click.option('--password', help='WIM password')
2717 @click.option('--url', help='WIM url')
2718 @click.option('--config', help='WIM specific config parameters')
2719 @click.option('--wim_type', help='WIM type')
2720 @click.option('--description', help='human readable description')
2721 @click.option('--wim_port_mapping', default
=None,
2722 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2723 "(WAN service endpoint id and info)")
2724 @click.option('--wait',
2728 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2741 """updates a WIM account
2743 NAME: name or ID of the WIM account
2747 check_client_version(ctx
.obj
, ctx
.command
.name
)
2749 if newname
: wim
['name'] = newname
2750 if user
: wim
['user'] = user
2751 if password
: wim
['password'] = password
2752 if url
: wim
['url'] = url
2753 # if tenant: wim['tenant'] = tenant
2754 if wim_type
: wim
['wim_type'] = wim_type
2755 if description
: wim
['description'] = description
2756 if config
: wim
['config'] = config
2757 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2758 # except ClientException as e:
2763 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2764 @click.argument('name')
2765 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2766 @click.option('--wait',
2770 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2772 def wim_delete(ctx
, name
, force
, wait
):
2773 """deletes a WIM account
2775 NAME: name or ID of the WIM account to be deleted
2779 check_client_version(ctx
.obj
, ctx
.command
.name
)
2780 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2781 # except ClientException as e:
2786 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2787 @click.option('--filter', default
=None, multiple
=True,
2788 help='restricts the list to the WIM accounts matching the filter')
2790 def wim_list(ctx
, filter):
2791 """list all WIM accounts"""
2794 check_client_version(ctx
.obj
, ctx
.command
.name
)
2796 filter='&'.join(filter)
2797 resp
= ctx
.obj
.wim
.list(filter)
2798 table
= PrettyTable(['wim name', 'uuid'])
2800 table
.add_row([wim
['name'], wim
['uuid']])
2803 # except ClientException as e:
2808 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2809 @click.argument('name')
2811 def wim_show(ctx
, name
):
2812 """shows the details of a WIM account
2814 NAME: name or ID of the WIM account
2818 check_client_version(ctx
.obj
, ctx
.command
.name
)
2819 resp
= ctx
.obj
.wim
.get(name
)
2820 if 'password' in resp
:
2821 resp
['wim_password']='********'
2822 # except ClientException as e:
2826 table
= PrettyTable(['key', 'attribute'])
2827 for k
, v
in list(resp
.items()):
2828 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2833 ####################
2834 # SDN controller operations
2835 ####################
2837 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2838 @click.option('--name',
2840 help='Name to create sdn controller')
2841 @click.option('--type',
2843 help='SDN controller type')
2844 @click.option('--sdn_controller_version', # hidden=True,
2845 help='Deprecated. Use --config {version: sdn_controller_version}')
2846 @click.option('--url',
2847 help='URL in format http[s]://HOST:IP/')
2848 @click.option('--ip_address', # hidden=True,
2849 help='Deprecated. Use --url')
2850 @click.option('--port', # hidden=True,
2851 help='Deprecated. Use --url')
2852 @click.option('--switch_dpid', # hidden=True,
2853 help='Deprecated. Use --config {switch_id: DPID}')
2854 @click.option('--config',
2855 help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2856 'Openflow Datapath ID), version: version}')
2857 @click.option('--user',
2858 help='SDN controller username')
2859 @click.option('--password',
2861 confirmation_prompt
=True,
2862 help='SDN controller password')
2863 @click.option('--description', default
=None, help='human readable description')
2864 @click.option('--wait',
2868 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2870 def sdnc_create(ctx
, **kwargs
):
2871 """creates a new SDN controller"""
2873 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2874 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2875 if kwargs
.get("port"):
2876 print("option '--port' is deprecated, use '--url' instead")
2877 sdncontroller
["port"] = int(kwargs
["port"])
2878 if kwargs
.get("ip_address"):
2879 print("option '--ip_address' is deprecated, use '--url' instead")
2880 sdncontroller
["ip"] = kwargs
["ip_address"]
2881 if kwargs
.get("switch_dpid"):
2882 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2883 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2884 if kwargs
.get("sdn_controller_version"):
2885 print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2888 check_client_version(ctx
.obj
, ctx
.command
.name
)
2889 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2890 # except ClientException as e:
2894 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2895 @click.argument('name')
2896 @click.option('--newname', help='New name for the SDN controller')
2897 @click.option('--description', default
=None, help='human readable description')
2898 @click.option('--type', help='SDN controller type')
2899 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2900 @click.option('--config', help='Extra information for SDN in yaml format, as '
2901 '{switch_id: identity used for the plugin (e.g. DPID: '
2902 'Openflow Datapath ID), version: version}')
2903 @click.option('--user', help='SDN controller username')
2904 @click.option('--password', help='SDN controller password')
2905 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2906 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2907 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2908 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2909 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2910 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2912 def sdnc_update(ctx
, **kwargs
):
2913 """updates an SDN controller
2915 NAME: name or ID of the SDN controller
2918 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2919 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2920 if kwargs
.get("newname"):
2921 sdncontroller
["name"] = kwargs
["newname"]
2922 if kwargs
.get("port"):
2923 print("option '--port' is deprecated, use '--url' instead")
2924 sdncontroller
["port"] = int(kwargs
["port"])
2925 if kwargs
.get("ip_address"):
2926 print("option '--ip_address' is deprecated, use '--url' instead")
2927 sdncontroller
["ip"] = kwargs
["ip_address"]
2928 if kwargs
.get("switch_dpid"):
2929 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2930 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2931 if kwargs
.get("sdn_controller_version"):
2932 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2936 check_client_version(ctx
.obj
, ctx
.command
.name
)
2937 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2938 # except ClientException as e:
2943 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2944 @click.argument('name')
2945 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2946 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2947 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2949 def sdnc_delete(ctx
, name
, force
, wait
):
2950 """deletes an SDN controller
2952 NAME: name or ID of the SDN controller to be deleted
2956 check_client_version(ctx
.obj
, ctx
.command
.name
)
2957 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2958 # except ClientException as e:
2963 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2964 @click.option('--filter', default
=None, multiple
=True,
2965 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2967 def sdnc_list(ctx
, filter):
2968 """list all SDN controllers"""
2971 check_client_version(ctx
.obj
, ctx
.command
.name
)
2973 filter='&'.join(filter)
2974 resp
= ctx
.obj
.sdnc
.list(filter)
2975 # except ClientException as e:
2978 table
= PrettyTable(['sdnc name', 'id'])
2980 table
.add_row([sdnc
['name'], sdnc
['_id']])
2985 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2986 @click.argument('name')
2988 def sdnc_show(ctx
, name
):
2989 """shows the details of an SDN controller
2991 NAME: name or ID of the SDN controller
2995 check_client_version(ctx
.obj
, ctx
.command
.name
)
2996 resp
= ctx
.obj
.sdnc
.get(name
)
2997 # except ClientException as e:
3001 table
= PrettyTable(['key', 'attribute'])
3002 for k
, v
in list(resp
.items()):
3003 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3008 ###########################
3009 # K8s cluster operations
3010 ###########################
3012 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
3013 @click.argument('name')
3014 @click.option('--creds',
3016 help='credentials file, i.e. a valid `.kube/config` file')
3017 @click.option('--version',
3019 help='Kubernetes version')
3020 @click.option('--vim',
3022 help='VIM target, the VIM where the cluster resides')
3023 @click.option('--k8s-nets',
3025 help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"')
3026 @click.option('--description',
3028 help='human readable description')
3029 @click.option('--namespace',
3030 default
='kube-system',
3031 help='namespace to be used for its operation, defaults to `kube-system`')
3032 @click.option('--cni',
3034 help='list of CNI plugins, in JSON inline format, used in the cluster')
3035 #@click.option('--skip-init',
3037 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3038 #@click.option('--wait',
3040 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3042 def k8scluster_add(ctx
,
3051 """adds a K8s cluster to OSM
3053 NAME: name of the K8s cluster
3056 check_client_version(ctx
.obj
, ctx
.command
.name
)
3058 cluster
['name'] = name
3059 with
open(creds
, 'r') as cf
:
3060 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3061 cluster
['k8s_version'] = version
3062 cluster
['vim_account'] = vim
3063 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3065 cluster
['description'] = description
3066 if namespace
: cluster
['namespace'] = namespace
3067 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3068 ctx
.obj
.k8scluster
.create(name
, cluster
)
3069 # except ClientException as e:
3074 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
3075 @click.argument('name')
3076 @click.option('--newname', help='New name for the K8s cluster')
3077 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3078 @click.option('--version', help='Kubernetes version')
3079 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3080 @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) ...]}"')
3081 @click.option('--description', help='human readable description')
3082 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3083 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3085 def k8scluster_update(ctx
,
3095 """updates a K8s cluster
3097 NAME: name or ID of the K8s cluster
3100 check_client_version(ctx
.obj
, ctx
.command
.name
)
3102 if newname
: cluster
['name'] = newname
3104 with
open(creds
, 'r') as cf
:
3105 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3106 if version
: cluster
['k8s_version'] = version
3107 if vim
: cluster
['vim_account'] = vim
3108 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3109 if description
: cluster
['description'] = description
3110 if namespace
: cluster
['namespace'] = namespace
3111 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3112 ctx
.obj
.k8scluster
.update(name
, cluster
)
3113 # except ClientException as e:
3118 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
3119 @click.argument('name')
3120 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3121 #@click.option('--wait',
3123 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3125 def k8scluster_delete(ctx
, name
, force
):
3126 """deletes a K8s cluster
3128 NAME: name or ID of the K8s cluster to be deleted
3131 check_client_version(ctx
.obj
, ctx
.command
.name
)
3132 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3133 # except ClientException as e:
3138 @cli_osm.command(name
='k8scluster-list')
3139 @click.option('--filter', default
=None, multiple
=True,
3140 help='restricts the list to the K8s clusters matching the filter')
3141 @click.option('--literal', is_flag
=True,
3142 help='print literally, no pretty table')
3143 @click.option('--long', is_flag
=True, help='get more details')
3145 def k8scluster_list(ctx
, filter, literal
, long):
3146 """list all K8s clusters"""
3148 check_client_version(ctx
.obj
, ctx
.command
.name
)
3150 filter='&'.join(filter)
3151 resp
= ctx
.obj
.k8scluster
.list(filter)
3153 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3156 table
= PrettyTable(['Name', 'Id', 'Project', 'Version', 'VIM', 'K8s-nets',
3157 'Operational State', 'Op. state (details)', 'Description', 'Detailed status'])
3158 project_list
= ctx
.obj
.project
.list()
3160 table
= PrettyTable(['Name', 'Id', 'VIM', 'Operational State', 'Op. state details'])
3162 vim_list
= ctx
.obj
.vim
.list()
3165 for cluster
in resp
:
3166 vim_name
= get_vim_name(vim_list
, cluster
['vim_account'])
3167 #vim_info = '{} ({})'.format(vim_name,cluster['vim_account'])
3169 op_state_details
= "Helm: {}\nJuju: {}".format(
3170 cluster
["_admin"].get("helm-chart", "-").get("operationalState", "-"),
3171 cluster
["_admin"].get("juju-bundle", "-").get("operationalState", "-"))
3173 logger
.debug('Cluster details: {}'.format(yaml
.safe_dump(cluster
)))
3174 project_id
, project_name
= get_project(project_list
, cluster
)
3175 #project_info = '{} ({})'.format(project_name, project_id)
3176 project_info
= project_name
3177 detailed_status
= cluster
["_admin"].get("detailed-status","-")
3178 table
.add_row([cluster
['name'], cluster
['_id'], project_info
,
3179 cluster
['k8s_version'], vim_info
,
3180 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
3181 op_state_details
, trunc_text(cluster
.get('description') or '', 40),
3182 wrap_text(text
=detailed_status
, width
=40)])
3184 table
.add_row([cluster
['name'], cluster
['_id'], vim_info
,
3185 cluster
["_admin"]["operationalState"], op_state_details
])
3188 # except ClientException as e:
3193 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
3194 @click.argument('name')
3195 @click.option('--literal', is_flag
=True,
3196 help='print literally, no pretty table')
3198 def k8scluster_show(ctx
, name
, literal
):
3199 """shows the details of a K8s cluster
3201 NAME: name or ID of the K8s cluster
3204 resp
= ctx
.obj
.k8scluster
.get(name
)
3206 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3208 table
= PrettyTable(['key', 'attribute'])
3209 for k
, v
in list(resp
.items()):
3210 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
3213 # except ClientException as e:
3219 ###########################
3221 ###########################
3223 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
3224 @click.argument('name')
3225 @click.argument('uri')
3226 @click.option('--type',
3227 type=click
.Choice(['helm-chart', 'juju-bundle', 'osm']),
3229 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3230 @click.option('--description',
3232 help='human readable description')
3233 @click.option('--user',
3235 help='OSM repository: The username of the OSM repository')
3236 @click.option('--password',
3238 help='OSM repository: The password of the OSM repository')
3239 #@click.option('--wait',
3241 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3243 def repo_add(ctx
, **kwargs
):
3244 """adds a repo to OSM
3246 NAME: name of the repo
3247 URI: URI of the repo
3250 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
3252 repo
["url"] = repo
.pop("uri")
3253 if repo
["type"] in ['helm-chart', 'juju-bundle']:
3254 ctx
.obj
.repo
.create(repo
['name'], repo
)
3256 ctx
.obj
.osmrepo
.create(repo
['name'], repo
)
3257 # except ClientException as e:
3262 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
3263 @click.argument('name')
3264 @click.option('--newname', help='New name for the repo')
3265 @click.option('--uri', help='URI of the repo')
3266 @click.option('--description', help='human readable description')
3267 #@click.option('--wait',
3269 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3271 def repo_update(ctx
,
3276 """updates a repo in OSM
3278 NAME: name of the repo
3281 check_client_version(ctx
.obj
, ctx
.command
.name
)
3284 repo
['name'] = newname
3287 if description
: repo
['description'] = description
3289 ctx
.obj
.repo
.update(name
, repo
)
3291 ctx
.obj
.osmrepo
.update(name
, repo
)
3293 # except ClientException as e:
3298 @cli_osm.command(name
='repo-index', short_help
='Index a repository from a folder with artifacts')
3299 @click.option('--origin', default
='.', help='origin path where the artifacts are located')
3300 @click.option('--destination', default
='.', help='destination path where the index is deployed')
3302 def repo_index(ctx
, origin
, destination
):
3303 """Index a repository
3305 NAME: name or ID of the repo to be deleted
3307 check_client_version(ctx
.obj
, ctx
.command
.name
)
3308 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
3311 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
3312 @click.argument('name')
3313 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3314 #@click.option('--wait',
3316 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3318 def repo_delete(ctx
, name
, force
):
3321 NAME: name or ID of the repo to be deleted
3325 ctx
.obj
.repo
.delete(name
, force
=force
)
3327 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
3328 # except ClientException as e:
3333 @cli_osm.command(name
='repo-list')
3334 @click.option('--filter', default
=None, multiple
=True,
3335 help='restricts the list to the repos matching the filter')
3336 @click.option('--literal', is_flag
=True,
3337 help='print literally, no pretty table')
3339 def repo_list(ctx
, filter, literal
):
3340 """list all repos"""
3343 check_client_version(ctx
.obj
, ctx
.command
.name
)
3345 filter='&'.join(filter)
3346 resp
= ctx
.obj
.repo
.list(filter)
3347 resp
+= ctx
.obj
.osmrepo
.list(filter)
3349 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3351 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3353 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3354 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description') or '',40)])
3358 # except ClientException as e:
3363 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
3364 @click.argument('name')
3365 @click.option('--literal', is_flag
=True,
3366 help='print literally, no pretty table')
3368 def repo_show(ctx
, name
, literal
):
3369 """shows the details of a repo
3371 NAME: name or ID of the repo
3374 resp
= ctx
.obj
.repo
.get(name
)
3376 resp
= ctx
.obj
.osmrepo
.get(name
)
3380 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3382 table
= PrettyTable(['key', 'attribute'])
3384 for k
, v
in list(resp
.items()):
3385 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3389 # except ClientException as e:
3395 ####################
3396 # Project mgmt operations
3397 ####################
3399 @cli_osm.command(name
='project-create', short_help
='creates a new project')
3400 @click.argument('name')
3401 #@click.option('--description',
3402 # default='no description',
3403 # help='human readable description')
3404 @click.option('--domain-name', 'domain_name',
3406 help='assign to a domain')
3407 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3408 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3409 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3411 def project_create(ctx
, name
, domain_name
, quotas
):
3412 """Creates a new project
3414 NAME: name of the project
3415 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3416 QUOTAS: set quotas for the project
3419 project
= {'name': name
}
3421 project
['domain_name'] = domain_name
3422 quotas_dict
= _process_project_quotas(quotas
)
3424 project
['quotas'] = quotas_dict
3427 check_client_version(ctx
.obj
, ctx
.command
.name
)
3428 ctx
.obj
.project
.create(name
, project
)
3429 # except ClientException as e:
3434 def _process_project_quotas(quota_list
):
3439 for quota
in quota_list
:
3440 for single_quota
in quota
.split(","):
3441 k
, v
= single_quota
.split("=")
3442 quotas_dict
[k
] = None if v
in ('None', 'null', '') else int(v
)
3443 except (ValueError, TypeError):
3444 raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3448 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3449 @click.argument('name')
3450 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3452 def project_delete(ctx
, name
):
3453 """deletes a project
3455 NAME: name or ID of the project to be deleted
3459 check_client_version(ctx
.obj
, ctx
.command
.name
)
3460 ctx
.obj
.project
.delete(name
)
3461 # except ClientException as e:
3466 @cli_osm.command(name
='project-list', short_help
='list all projects')
3467 @click.option('--filter', default
=None, multiple
=True,
3468 help='restricts the list to the projects matching the filter')
3470 def project_list(ctx
, filter):
3471 """list all projects"""
3474 check_client_version(ctx
.obj
, ctx
.command
.name
)
3476 filter='&'.join(filter)
3477 resp
= ctx
.obj
.project
.list(filter)
3478 # except ClientException as e:
3481 table
= PrettyTable(['name', 'id'])
3483 table
.add_row([proj
['name'], proj
['_id']])
3488 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3489 @click.argument('name')
3491 def project_show(ctx
, name
):
3492 """shows the details of a project
3494 NAME: name or ID of the project
3498 check_client_version(ctx
.obj
, ctx
.command
.name
)
3499 resp
= ctx
.obj
.project
.get(name
)
3500 # except ClientException as e:
3504 table
= PrettyTable(['key', 'attribute'])
3505 for k
, v
in resp
.items():
3506 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3511 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3512 @click.argument('project')
3513 @click.option('--name', default
=None,
3514 help='new name for the project')
3515 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3516 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3517 "(use empty to reset quota to default")
3519 def project_update(ctx
, project
, name
, quotas
):
3521 Update a project name
3524 :param project: id or name of the project to modify
3525 :param name: new name for the project
3526 :param quotas: change quotas of the project
3530 project_changes
= {}
3532 project_changes
['name'] = name
3533 quotas_dict
= _process_project_quotas(quotas
)
3535 project_changes
['quotas'] = quotas_dict
3538 check_client_version(ctx
.obj
, ctx
.command
.name
)
3539 ctx
.obj
.project
.update(project
, project_changes
)
3540 # except ClientException as e:
3544 ####################
3545 # User mgmt operations
3546 ####################
3548 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3549 @click.argument('username')
3550 @click.option('--password',
3553 confirmation_prompt
=True,
3554 help='user password')
3555 @click.option('--projects',
3556 # prompt="Comma separate list of projects",
3558 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3559 help='list of project ids that the user belongs to')
3560 @click.option('--project-role-mappings', 'project_role_mappings',
3561 default
=None, multiple
=True,
3562 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3563 @click.option('--domain-name', 'domain_name',
3565 help='assign to a domain')
3567 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
3568 """Creates a new user
3571 USERNAME: name of the user
3572 PASSWORD: password of the user
3573 PROJECTS: projects assigned to user (internal only)
3574 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3575 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3579 user
['username'] = username
3580 user
['password'] = password
3581 user
['projects'] = projects
3582 user
['project_role_mappings'] = project_role_mappings
3584 user
['domain_name'] = domain_name
3587 check_client_version(ctx
.obj
, ctx
.command
.name
)
3588 ctx
.obj
.user
.create(username
, user
)
3589 # except ClientException as e:
3594 @cli_osm.command(name
='user-update', short_help
='updates user information')
3595 @click.argument('username')
3596 @click.option('--password',
3599 # confirmation_prompt=True,
3600 help='user password')
3601 @click.option('--set-username', 'set_username',
3603 help='change username')
3604 @click.option('--set-project', 'set_project',
3605 default
=None, multiple
=True,
3606 help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3607 @click.option('--remove-project', 'remove_project',
3608 default
=None, multiple
=True,
3609 help="removes project from user: 'project'")
3610 @click.option('--add-project-role', 'add_project_role',
3611 default
=None, multiple
=True,
3612 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3613 @click.option('--remove-project-role', 'remove_project_role',
3614 default
=None, multiple
=True,
3615 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3617 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3618 add_project_role
, remove_project_role
):
3619 """Update a user information
3622 USERNAME: name of the user
3623 PASSWORD: new password
3624 SET_USERNAME: new username
3625 SET_PROJECT: creating mappings for project/role(s)
3626 REMOVE_PROJECT: deleting mappings for project/role(s)
3627 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3628 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3632 user
['password'] = password
3633 user
['username'] = set_username
3634 user
['set-project'] = set_project
3635 user
['remove-project'] = remove_project
3636 user
['add-project-role'] = add_project_role
3637 user
['remove-project-role'] = remove_project_role
3640 check_client_version(ctx
.obj
, ctx
.command
.name
)
3641 ctx
.obj
.user
.update(username
, user
)
3642 # except ClientException as e:
3647 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3648 @click.argument('name')
3649 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3651 def user_delete(ctx
, name
):
3655 NAME: name or ID of the user to be deleted
3659 check_client_version(ctx
.obj
, ctx
.command
.name
)
3660 ctx
.obj
.user
.delete(name
)
3661 # except ClientException as e:
3666 @cli_osm.command(name
='user-list', short_help
='list all users')
3667 @click.option('--filter', default
=None, multiple
=True,
3668 help='restricts the list to the users matching the filter')
3670 def user_list(ctx
, filter):
3671 """list all users"""
3673 check_client_version(ctx
.obj
, ctx
.command
.name
)
3675 filter='&'.join(filter)
3676 resp
= ctx
.obj
.user
.list(filter)
3677 # except ClientException as e:
3680 table
= PrettyTable(['name', 'id'])
3682 table
.add_row([user
['username'], user
['_id']])
3687 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3688 @click.argument('name')
3690 def user_show(ctx
, name
):
3691 """shows the details of a user
3693 NAME: name or ID of the user
3697 check_client_version(ctx
.obj
, ctx
.command
.name
)
3698 resp
= ctx
.obj
.user
.get(name
)
3699 if 'password' in resp
:
3700 resp
['password']='********'
3701 # except ClientException as e:
3705 table
= PrettyTable(['key', 'attribute'])
3706 for k
, v
in resp
.items():
3707 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3712 ####################
3713 # Fault Management operations
3714 ####################
3716 @cli_osm.command(name
='ns-alarm-create')
3717 @click.argument('name')
3718 @click.option('--ns', prompt
=True, help='NS instance id or name')
3719 @click.option('--vnf', prompt
=True,
3720 help='VNF name (VNF member index as declared in the NSD)')
3721 @click.option('--vdu', prompt
=True,
3722 help='VDU name (VDU name as declared in the VNFD)')
3723 @click.option('--metric', prompt
=True,
3724 help='Name of the metric (e.g. cpu_utilization)')
3725 @click.option('--severity', default
='WARNING',
3726 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3727 @click.option('--threshold_value', prompt
=True,
3728 help='threshold value that, when crossed, an alarm is triggered')
3729 @click.option('--threshold_operator', prompt
=True,
3730 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3731 @click.option('--statistic', default
='AVERAGE',
3732 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3734 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3735 threshold_value
, threshold_operator
, statistic
):
3736 """creates a new alarm for a NS instance"""
3737 # TODO: Check how to validate threshold_value.
3738 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3741 ns_instance
= ctx
.obj
.ns
.get(ns
)
3743 alarm
['alarm_name'] = name
3744 alarm
['ns_id'] = ns_instance
['_id']
3745 alarm
['correlation_id'] = ns_instance
['_id']
3746 alarm
['vnf_member_index'] = vnf
3747 alarm
['vdu_name'] = vdu
3748 alarm
['metric_name'] = metric
3749 alarm
['severity'] = severity
3750 alarm
['threshold_value'] = int(threshold_value
)
3751 alarm
['operation'] = threshold_operator
3752 alarm
['statistic'] = statistic
3753 check_client_version(ctx
.obj
, ctx
.command
.name
)
3754 ctx
.obj
.ns
.create_alarm(alarm
)
3755 # except ClientException as e:
3760 #@cli_osm.command(name='ns-alarm-delete')
3761 #@click.argument('name')
3762 #@click.pass_context
3763 #def ns_alarm_delete(ctx, name):
3764 # """deletes an alarm
3766 # NAME: name of the alarm to be deleted
3769 # check_client_version(ctx.obj, ctx.command.name)
3770 # ctx.obj.ns.delete_alarm(name)
3771 # except ClientException as e:
3776 ####################
3777 # Performance Management operations
3778 ####################
3780 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3781 @click.option('--ns', prompt
=True, help='NS instance id or name')
3782 @click.option('--vnf', prompt
=True,
3783 help='VNF name (VNF member index as declared in the NSD)')
3784 @click.option('--vdu', prompt
=True,
3785 help='VDU name (VDU name as declared in the VNFD)')
3786 @click.option('--metric', prompt
=True,
3787 help='name of the metric (e.g. cpu_utilization)')
3788 #@click.option('--period', default='1w',
3789 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3790 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3792 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3793 """exports a metric to the internal OSM bus, which can be read by other apps"""
3794 # TODO: Check how to validate interval.
3795 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3798 ns_instance
= ctx
.obj
.ns
.get(ns
)
3800 metric_data
['ns_id'] = ns_instance
['_id']
3801 metric_data
['correlation_id'] = ns_instance
['_id']
3802 metric_data
['vnf_member_index'] = vnf
3803 metric_data
['vdu_name'] = vdu
3804 metric_data
['metric_name'] = metric
3805 metric_data
['collection_unit'] = 'WEEK'
3806 metric_data
['collection_period'] = 1
3807 check_client_version(ctx
.obj
, ctx
.command
.name
)
3809 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3813 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3814 time
.sleep(int(interval
))
3816 # except ClientException as e:
3821 ####################
3823 ####################
3825 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3827 def get_version(ctx
):
3828 """shows client and server versions"""
3830 check_client_version(ctx
.obj
, "version")
3831 print ("Server version: {}".format(ctx
.obj
.get_version()))
3832 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3833 # except ClientException as e:
3837 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3838 @click.argument('filename')
3839 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3840 help='the charm will not be compiled, it is assumed to already exist')
3842 def upload_package(ctx
, filename
, skip_charm_build
):
3843 """uploads a vnf package or ns package
3845 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3849 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3850 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3851 if fullclassname
!= 'osmclient.sol005.client.Client':
3852 ctx
.obj
.package
.wait_for_upload(filename
)
3853 # except ClientException as e:
3858 #@cli_osm.command(name='ns-scaling-show')
3859 #@click.argument('ns_name')
3860 #@click.pass_context
3861 #def show_ns_scaling(ctx, ns_name):
3862 # """shows the status of a NS scaling operation
3864 # NS_NAME: name of the NS instance being scaled
3867 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3868 # resp = ctx.obj.ns.list()
3869 # except ClientException as e:
3873 # table = PrettyTable(
3876 # 'operational status',
3881 # if ns_name == ns['name']:
3882 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3883 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3884 # for record in scaling_records:
3885 # if 'instance' in record:
3886 # instances = record['instance']
3887 # for inst in instances:
3889 # [record['scaling-group-name-ref'],
3890 # inst['instance-id'],
3891 # inst['op-status'],
3892 # time.strftime('%Y-%m-%d %H:%M:%S',
3894 # inst['create-time'])),
3900 #@cli_osm.command(name='ns-scale')
3901 #@click.argument('ns_name')
3902 #@click.option('--ns_scale_group', prompt=True)
3903 #@click.option('--index', prompt=True)
3904 #@click.option('--wait',
3908 # help='do not return the control immediately, but keep it \
3909 # until the operation is completed, or timeout')
3910 #@click.pass_context
3911 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3914 # NS_NAME: name of the NS instance to be scaled
3917 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3918 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3919 # except ClientException as e:
3924 #@cli_osm.command(name='config-agent-list')
3925 #@click.pass_context
3926 #def config_agent_list(ctx):
3927 # """list config agents"""
3929 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3930 # except ClientException as e:
3933 # table = PrettyTable(['name', 'account-type', 'details'])
3934 # for account in ctx.obj.vca.list():
3937 # account['account-type'],
3943 #@cli_osm.command(name='config-agent-delete')
3944 #@click.argument('name')
3945 #@click.pass_context
3946 #def config_agent_delete(ctx, name):
3947 # """deletes a config agent
3949 # NAME: name of the config agent to be deleted
3952 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3953 # ctx.obj.vca.delete(name)
3954 # except ClientException as e:
3959 #@cli_osm.command(name='config-agent-add')
3960 #@click.option('--name',
3962 #@click.option('--account_type',
3964 #@click.option('--server',
3966 #@click.option('--user',
3968 #@click.option('--secret',
3971 # confirmation_prompt=True)
3972 #@click.pass_context
3973 #def config_agent_add(ctx, name, account_type, server, user, secret):
3974 # """adds a config agent"""
3976 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3977 # ctx.obj.vca.create(name, account_type, server, user, secret)
3978 # except ClientException as e:
3983 #@cli_osm.command(name='ro-dump')
3984 #@click.pass_context
3986 # """shows RO agent information"""
3987 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3988 # resp = ctx.obj.vim.get_resource_orchestrator()
3989 # table = PrettyTable(['key', 'attribute'])
3990 # for k, v in list(resp.items()):
3991 # table.add_row([k, json.dumps(v, indent=2)])
3996 #@cli_osm.command(name='vcs-list')
3997 #@click.pass_context
3999 # check_client_version(ctx.obj, ctx.command.name, 'v1')
4000 # resp = ctx.obj.utils.get_vcs_info()
4001 # table = PrettyTable(['component name', 'state'])
4002 # for component in resp:
4003 # table.add_row([component['component_name'], component['state']])
4008 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
4009 @click.argument('ns_name')
4010 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
4011 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
4012 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
4013 @click.option('--vdu_count', default
=None, type=int, help='number of vdu instance of this vdu_id')
4014 @click.option('--action_name', prompt
=True, help='action name')
4015 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
4016 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
4017 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4018 @click.option('--wait',
4022 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4035 """executes an action/primitive over a NS instance
4037 NS_NAME: name or ID of the NS instance
4041 check_client_version(ctx
.obj
, ctx
.command
.name
)
4044 op_data
['member_vnf_index'] = vnf_name
4046 op_data
['kdu_name'] = kdu_name
4048 op_data
['vdu_id'] = vdu_id
4049 if vdu_count
is not None:
4050 op_data
['vdu_count_index'] = vdu_count
4052 op_data
['timeout_ns_action'] = timeout
4053 op_data
['primitive'] = action_name
4055 with
open(params_file
, 'r') as pf
:
4058 op_data
['primitive_params'] = yaml
.safe_load(params
)
4060 op_data
['primitive_params'] = {}
4061 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
4063 # except ClientException as e:
4068 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
4069 @click.argument('ns_name')
4070 @click.argument('vnf_name')
4071 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
4072 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
4073 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
4074 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4075 @click.option('--wait', required
=False, default
=False, is_flag
=True,
4076 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4087 Executes a VNF scale (adding/removing VDUs)
4090 NS_NAME: name or ID of the NS instance.
4091 VNF_NAME: member-vnf-index in the NS to be scaled.
4095 check_client_version(ctx
.obj
, ctx
.command
.name
)
4096 if not scale_in
and not scale_out
:
4098 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
)
4099 # except ClientException as e:
4104 ##############################
4105 # Role Management Operations #
4106 ##############################
4108 @cli_osm.command(name
='role-create', short_help
='creates a new role')
4109 @click.argument('name')
4110 @click.option('--permissions',
4112 help='role permissions using a dictionary')
4114 def role_create(ctx
, name
, permissions
):
4119 NAME: Name or ID of the role.
4120 DEFINITION: Definition of grant/denial of access to resources.
4124 check_client_version(ctx
.obj
, ctx
.command
.name
)
4125 ctx
.obj
.role
.create(name
, permissions
)
4126 # except ClientException as e:
4131 @cli_osm.command(name
='role-update', short_help
='updates a role')
4132 @click.argument('name')
4133 @click.option('--set-name',
4135 help='change name of rle')
4136 # @click.option('--permissions',
4138 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4139 @click.option('--add',
4141 help='yaml format dictionary with permission: True/False to access grant/denial')
4142 @click.option('--remove',
4144 help='yaml format list to remove a permission')
4146 def role_update(ctx
, name
, set_name
, add
, remove
):
4151 NAME: Name or ID of the role.
4152 DEFINITION: Definition overwrites the old definition.
4153 ADD: Grant/denial of access to resource to add.
4154 REMOVE: Grant/denial of access to resource to remove.
4158 check_client_version(ctx
.obj
, ctx
.command
.name
)
4159 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
4160 # except ClientException as e:
4165 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
4166 @click.argument('name')
4167 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4169 def role_delete(ctx
, name
):
4174 NAME: Name or ID of the role.
4178 check_client_version(ctx
.obj
, ctx
.command
.name
)
4179 ctx
.obj
.role
.delete(name
)
4180 # except ClientException as e:
4185 @cli_osm.command(name
='role-list', short_help
='list all roles')
4186 @click.option('--filter', default
=None, multiple
=True,
4187 help='restricts the list to the projects matching the filter')
4189 def role_list(ctx
, filter):
4195 check_client_version(ctx
.obj
, ctx
.command
.name
)
4197 filter='&'.join(filter)
4198 resp
= ctx
.obj
.role
.list(filter)
4199 # except ClientException as e:
4202 table
= PrettyTable(['name', 'id'])
4204 table
.add_row([role
['name'], role
['_id']])
4209 @cli_osm.command(name
='role-show', short_help
='show specific role')
4210 @click.argument('name')
4212 def role_show(ctx
, name
):
4214 Shows the details of a role.
4217 NAME: Name or ID of the role.
4221 check_client_version(ctx
.obj
, ctx
.command
.name
)
4222 resp
= ctx
.obj
.role
.get(name
)
4223 # except ClientException as e:
4227 table
= PrettyTable(['key', 'attribute'])
4228 for k
, v
in resp
.items():
4229 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4234 @cli_osm.command(name
='package-create',
4235 short_help
='Create a package descriptor')
4236 @click.argument('package-type')
4237 @click.argument('package-name')
4238 @click.option('--base-directory',
4240 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4241 @click.option('--image',
4242 default
="image-name",
4243 help='(VNF) Set the name of the vdu image. Default "image-name"')
4244 @click.option('--vdus',
4246 help='(VNF) Set the number of vdus in a VNF. Default 1')
4247 @click.option('--vcpu',
4249 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4250 @click.option('--memory',
4252 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4253 @click.option('--storage',
4255 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4256 @click.option('--interfaces',
4258 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4259 @click.option('--vendor',
4261 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4262 @click.option('--override',
4265 help='(NS/VNF/NST) Flag for overriding the package if exists.')
4266 @click.option('--detailed',
4269 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4270 @click.option('--netslice-subnets',
4272 help='(NST) Number of netslice subnets. Default 1')
4273 @click.option('--netslice-vlds',
4275 help='(NST) Number of netslice vlds. Default 1')
4277 def package_create(ctx
,
4293 Creates an OSM NS, VNF, NST package
4296 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4297 PACKAGE_NAME: Name of the package to create the folder with the content.
4301 check_client_version(ctx
.obj
, ctx
.command
.name
)
4302 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
4303 resp
= ctx
.obj
.package_tool
.create(package_type
,
4312 interfaces
=interfaces
,
4315 netslice_subnets
=netslice_subnets
,
4316 netslice_vlds
=netslice_vlds
)
4318 # except ClientException as inst:
4319 # print("ERROR: {}".format(inst))
4322 @cli_osm.command(name
='package-validate',
4323 short_help
='Validate a package descriptor')
4324 @click.argument('base-directory',
4327 @click.option('--recursive/--no-recursive',
4329 help='The activated recursive option will validate the yaml files'
4330 ' within the indicated directory and in its subdirectories')
4332 def package_validate(ctx
,
4336 Validate descriptors given a base directory.
4339 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4342 check_client_version(ctx
.obj
, ctx
.command
.name
)
4343 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
4344 table
= PrettyTable()
4345 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
4346 # Print the dictionary generated by the validation function
4347 for result
in results
:
4348 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
4349 table
.sortby
= "VALID"
4350 table
.align
["PATH"] = "l"
4351 table
.align
["TYPE"] = "l"
4352 table
.align
["ERROR"] = "l"
4354 # except ClientException as inst:
4355 # print("ERROR: {}".format(inst))
4358 @cli_osm.command(name
='package-build',
4359 short_help
='Build the tar.gz of the package')
4360 @click.argument('package-folder')
4361 @click.option('--skip-validation',
4364 help='skip package validation')
4365 @click.option('--skip-charm-build', default
=False, is_flag
=True,
4366 help='the charm will not be compiled, it is assumed to already exist')
4368 def package_build(ctx
,
4373 Build the package NS, VNF given the package_folder.
4376 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4379 check_client_version(ctx
.obj
, ctx
.command
.name
)
4380 results
= ctx
.obj
.package_tool
.build(package_folder
,
4381 skip_validation
=skip_validation
,
4382 skip_charm_build
=skip_charm_build
)
4384 # except ClientException as inst:
4385 # print("ERROR: {}".format(inst))
4393 except pycurl
.error
as exc
:
4395 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4396 except ClientException
as exc
:
4397 print("ERROR: {}".format(exc
))
4398 except (FileNotFoundError
, PermissionError
) as exc
:
4399 print("Cannot open file: {}".format(exc
))
4400 except yaml
.YAMLError
as exc
:
4401 print("Invalid YAML format: {}".format(exc
))
4403 # TODO capture other controlled exceptions here
4404 # TODO remove the ClientException captures from all places, unless they do something different
4407 if __name__
== '__main__':