54f902be1374876cb280e57fac1951778a7feba2
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
)
384 #vim = '{} ({})'.format(vim_name, vim_id)
386 if 'currentOperation' in nsr
:
387 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
389 current_operation
= "{} ({})".format(nsr
['_admin'].get('current-operation','-'), nsr
['_admin']['nslcmop'])
390 error_details
= "N/A"
391 if ns_state
== "BROKEN" or ns_state
== "DEGRADED" or \
392 ('currentOperation' not in nsr
and nsr
.get('errorDescription')):
393 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'], nsr
['errorDetail'])
395 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
396 nsr
= nsopdata
['nsr:nsr']
397 nsr_name
= nsr
['name-ref']
398 nsr_id
= nsr
['ns-instance-config-ref']
401 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
402 ns_state
= deployment_status
403 config_status
= nsr
.get('config-status', 'Not found')
404 current_operation
= "Unknown"
405 error_details
= nsr
.get('detailed-status', 'Not found')
406 if config_status
== "config_not_needed":
407 config_status
= "configured (no charms)"
416 wrap_text(text
=error_details
,width
=40),
428 wrap_text(text
=error_details
,width
=40)])
431 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
432 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
434 def nsd_list(ctx
, filter, long):
437 check_client_version(ctx
.obj
, '--filter')
438 filter='&'.join(filter)
439 resp
= ctx
.obj
.nsd
.list(filter)
441 resp
= ctx
.obj
.nsd
.list()
442 # print(yaml.safe_dump(resp))
443 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
444 if fullclassname
== 'osmclient.sol005.client.Client':
446 table
= PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state',
447 'usage state', 'date', 'last update'])
449 table
= PrettyTable(['nsd name', 'id'])
451 name
= nsd
.get('id', '-')
453 onb_state
= nsd
['_admin'].get('onboardingState','-')
454 op_state
= nsd
['_admin'].get('operationalState','-')
455 usage_state
= nsd
['_admin'].get('usageState','-')
456 date
= datetime
.fromtimestamp(nsd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
457 last_update
= datetime
.fromtimestamp(nsd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
458 table
.add_row([name
, nsd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
460 table
.add_row([name
, nsd
['_id']])
462 table
= PrettyTable(['nsd name', 'id'])
464 table
.add_row([nsd
['name'], nsd
['id']])
469 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
470 @click.option('--filter', default
=None, multiple
=True,
471 help='restricts the list to the NSD/NSpkg matching the filter')
472 @click.option('--long', is_flag
=True, help='get more details')
474 def nsd_list1(ctx
, filter, long):
475 """list all NSD/NS pkg in the system"""
477 nsd_list(ctx
, filter, long)
480 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
481 @click.option('--filter', default
=None, multiple
=True,
482 help='restricts the list to the NSD/NSpkg matching the filter')
483 @click.option('--long', is_flag
=True, help='get more details')
485 def nsd_list2(ctx
, filter, long):
486 """list all NS packages"""
488 nsd_list(ctx
, filter, long)
491 def pkg_repo_list(ctx
, pkgtype
, filter, repo
, long):
492 resp
= ctx
.obj
.osmrepo
.pkg_list(pkgtype
, filter, repo
)
494 table
= PrettyTable(['nfpkg name', 'vendor', 'version', 'latest', 'description', 'repository'])
496 table
= PrettyTable(['nfpkg name', 'repository'])
498 name
= vnfd
.get('id', vnfd
.get('name','-'))
499 repository
= vnfd
.get('repository')
501 vendor
= vnfd
.get('provider', vnfd
.get('vendor'))
502 version
= vnfd
.get('version')
503 description
= vnfd
.get('description')
504 latest
= vnfd
.get('latest')
505 table
.add_row([name
, vendor
, version
, latest
, description
, repository
])
507 table
.add_row([name
, repository
])
511 def vnfd_list(ctx
, nf_type
, filter, long):
514 check_client_version(ctx
.obj
, '--nf_type')
516 check_client_version(ctx
.obj
, '--filter')
518 filter='&'.join(filter)
521 nf_filter
= "_admin.type=vnfd"
522 elif nf_type
== "pnf":
523 nf_filter
= "_admin.type=pnfd"
524 elif nf_type
== "hnf":
525 nf_filter
= "_admin.type=hnfd"
527 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
529 filter = '{}&{}'.format(nf_filter
, filter)
533 resp
= ctx
.obj
.vnfd
.list(filter)
535 resp
= ctx
.obj
.vnfd
.list()
536 # print(yaml.safe_dump(resp))
537 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
538 if fullclassname
== 'osmclient.sol005.client.Client':
540 table
= PrettyTable(['nfpkg name', 'id', 'desc type', 'vendor', 'version', 'onboarding state', 'operational state',
541 'usage state', 'date', 'last update'])
543 table
= PrettyTable(['nfpkg name', 'id', 'desc type'])
545 name
= vnfd
.get('id', vnfd
.get('name','-'))
546 descriptor_type
= 'sol006' if 'product-name' in vnfd
else 'rel8'
548 onb_state
= vnfd
['_admin'].get('onboardingState','-')
549 op_state
= vnfd
['_admin'].get('operationalState','-')
550 vendor
= vnfd
.get('provider', vnfd
.get('vendor'))
551 version
= vnfd
.get('version')
552 usage_state
= vnfd
['_admin'].get('usageState','-')
553 date
= datetime
.fromtimestamp(vnfd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
554 last_update
= datetime
.fromtimestamp(vnfd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
555 table
.add_row([name
, vnfd
['_id'], descriptor_type
, vendor
, version
, onb_state
, op_state
, usage_state
, date
, last_update
])
557 table
.add_row([name
, vnfd
['_id'], descriptor_type
])
559 table
= PrettyTable(['nfpkg name', 'id'])
561 table
.add_row([vnfd
['name'], vnfd
['id']])
566 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
567 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
568 @click.option('--filter', default
=None, multiple
=True,
569 help='restricts the list to the NF pkg matching the filter')
570 @click.option('--long', is_flag
=True, help='get more details')
572 def vnfd_list1(ctx
, nf_type
, filter, long):
573 """list all xNF packages (VNF, HNF, PNF)"""
575 vnfd_list(ctx
, nf_type
, filter, long)
578 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
579 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
580 @click.option('--filter', default
=None, multiple
=True,
581 help='restricts the list to the NFpkg matching the filter')
582 @click.option('--long', is_flag
=True, help='get more details')
584 def vnfd_list2(ctx
, nf_type
, filter, long):
585 """list all xNF packages (VNF, HNF, PNF)"""
587 vnfd_list(ctx
, nf_type
, filter, long)
590 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
591 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
592 @click.option('--filter', default
=None, multiple
=True,
593 help='restricts the list to the NFpkg matching the filter')
594 @click.option('--long', is_flag
=True, help='get more details')
596 def nfpkg_list(ctx
, nf_type
, filter, long):
597 """list all xNF packages (VNF, HNF, PNF)"""
600 check_client_version(ctx
.obj
, ctx
.command
.name
)
601 vnfd_list(ctx
, nf_type
, filter, long)
602 # except ClientException as e:
607 @cli_osm.command(name
='vnfpkg-repo-list', short_help
='list all xNF from OSM repositories')
608 @click.option('--filter', default
=None, multiple
=True,
609 help='restricts the list to the NFpkg matching the filter')
610 @click.option('--repo', default
=None,
611 help='restricts the list to a particular OSM repository')
612 @click.option('--long', is_flag
=True, help='get more details')
614 def nfpkg_repo_list1(ctx
, filter, repo
, long):
615 """list xNF packages from OSM repositories"""
617 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
619 @cli_osm.command(name
='nfpkg-repo-list', short_help
='list all xNF from OSM repositories')
620 @click.option('--filter', default
=None, multiple
=True,
621 help='restricts the list to the NFpkg matching the filter')
622 @click.option('--repo', default
=None,
623 help='restricts the list to a particular OSM repository')
624 @click.option('--long', is_flag
=True, help='get more details')
626 def nfpkg_repo_list2(ctx
, filter, repo
, long):
627 """list xNF packages from OSM repositories"""
629 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
632 def vnf_list(ctx
, ns
, filter, long):
636 check_client_version(ctx
.obj
, '--ns')
638 filter='&'.join(filter)
639 check_client_version(ctx
.obj
, '--filter')
640 resp
= ctx
.obj
.vnf
.list(ns
, filter)
642 resp
= ctx
.obj
.vnf
.list()
643 # except ClientException as e:
646 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
647 if fullclassname
== 'osmclient.sol005.client.Client':
648 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
649 'vnfd name', 'vim account id', 'ip address']
651 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
652 'vnfd name', 'vim account id', 'ip address',
653 'date', 'last update']
654 table
= PrettyTable(field_names
)
656 name
= vnfr
['name'] if 'name' in vnfr
else '-'
657 new_row
= [vnfr
['_id'], name
, vnfr
['nsr-id-ref'],
658 vnfr
['member-vnf-index-ref'], vnfr
['vnfd-ref'],
659 vnfr
['vim-account-id'], vnfr
['ip-address']]
661 date
= datetime
.fromtimestamp(vnfr
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
662 last_update
= datetime
.fromtimestamp(vnfr
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
663 new_row
.extend([date
, last_update
])
664 table
.add_row(new_row
)
669 'operational status',
672 if 'mgmt-interface' not in vnfr
:
673 vnfr
['mgmt-interface'] = {}
674 vnfr
['mgmt-interface']['ip-address'] = None
678 vnfr
['operational-status'],
679 vnfr
['config-status']])
684 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
685 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
686 @click.option('--filter', default
=None, multiple
=True,
687 help='restricts the list to the NF instances matching the filter.')
688 @click.option('--long', is_flag
=True, help='get more details')
690 def vnf_list1(ctx
, ns
, filter, long):
691 """list all NF instances"""
693 vnf_list(ctx
, ns
, filter, long)
695 @cli_osm.command(name
='nsd-repo-list', short_help
='list all NS from OSM repositories')
696 @click.option('--filter', default
=None, multiple
=True,
697 help='restricts the list to the NS matching the filter')
698 @click.option('--repo', default
=None,
699 help='restricts the list to a particular OSM repository')
700 @click.option('--long', is_flag
=True, help='get more details')
702 def nspkg_repo_list(ctx
, filter, repo
, long):
703 """list xNF packages from OSM repositories"""
705 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
707 @cli_osm.command(name
='nspkg-repo-list', short_help
='list all NS from OSM repositories')
708 @click.option('--filter', default
=None, multiple
=True,
709 help='restricts the list to the NS matching the filter')
710 @click.option('--repo', default
=None,
711 help='restricts the list to a particular OSM repository')
712 @click.option('--long', is_flag
=True, help='get more details')
714 def nspkg_repo_list2(ctx
, filter, repo
, long):
715 """list xNF packages from OSM repositories"""
717 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
719 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
720 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
721 @click.option('--filter', default
=None, multiple
=True,
722 help='restricts the list to the NF instances matching the filter.')
723 @click.option('--long', is_flag
=True, help='get more details')
725 def nf_list(ctx
, ns
, filter, long):
726 """list all NF instances
730 --ns TEXT NS instance id or name to restrict the VNF list
731 --filter filterExpr Restricts the list to the VNF instances matching the filter
734 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
735 concatenated using the "&" character:
738 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
739 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
740 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
742 value := scalar value
746 * zero or more occurrences
747 ? zero or one occurrence
748 [] grouping of expressions to be used with ? and *
749 "" quotation marks for marking string constants
753 "AttrName" is the name of one attribute in the data type that defines the representation
754 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
755 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
756 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
757 entries, it means that the operator "op" is applied to the attribute addressed by the last
758 <attrName> entry included in the concatenation. All simple filter expressions are combined
759 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
760 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
761 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
762 prefix". If an attribute referenced in an expression is an array, an object that contains a
763 corresponding array shall be considered to match the expression if any of the elements in the
764 array matches all expressions that have the same attribute prefix.
768 --filter vim-account-id=<VIM_ACCOUNT_ID>
769 --filter vnfd-ref=<VNFD_NAME>
770 --filter vdur.ip-address=<IP_ADDRESS>
771 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
774 vnf_list(ctx
, ns
, filter, long)
777 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
778 @click.argument('name')
779 @click.option('--long', is_flag
=True,
780 help='get more details of the NS operation (date, ).')
782 def ns_op_list(ctx
, name
, long):
783 """shows the history of operations over a NS instance
785 NAME: name or ID of the NS instance
787 def formatParams(params
):
788 if params
['lcmOperationType']=='instantiate':
789 params
.pop('nsDescription')
793 elif params
['lcmOperationType']=='action':
794 params
.pop('primitive')
795 params
.pop('lcmOperationType')
796 params
.pop('nsInstanceId')
801 check_client_version(ctx
.obj
, ctx
.command
.name
)
802 resp
= ctx
.obj
.ns
.list_op(name
)
803 # except ClientException as e:
808 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
810 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
812 #print(yaml.safe_dump(resp))
815 if op
['lcmOperationType']=='action':
816 action_name
= op
['operationParams']['primitive']
818 if op
['operationState'] == 'PROCESSING':
819 if op
['queuePosition'] is not None and op
['queuePosition'] > 0:
820 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
821 elif op
['lcmOperationType'] in ('instantiate', 'terminate'):
824 elif op
['operationState'] in ('FAILED', 'FAILED_TEMP'):
825 detail
= op
.get('errorMessage','-')
826 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
827 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
829 table
.add_row([op
['id'],
830 op
['lcmOperationType'],
832 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
833 op
['operationState'],
836 wrap_text(text
=detail
,width
=50)])
838 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
839 op
['operationState'], date
, wrap_text(text
=detail
or "",width
=50)])
844 def nsi_list(ctx
, filter):
845 """list all Network Slice Instances"""
848 check_client_version(ctx
.obj
, ctx
.command
.name
)
850 filter='&'.join(filter)
851 resp
= ctx
.obj
.nsi
.list(filter)
852 # except ClientException as e:
856 ['netslice instance name',
858 'operational status',
862 nsi_name
= nsi
['name']
864 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
865 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
866 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
867 if configstatus
== "config_not_needed":
868 configstatus
= "configured (no charms)"
879 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
880 @click.option('--filter', default
=None, multiple
=True,
881 help='restricts the list to the Network Slice Instances matching the filter')
883 def nsi_list1(ctx
, filter):
884 """list all Network Slice Instances (NSI)"""
886 nsi_list(ctx
, filter)
889 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
890 @click.option('--filter', default
=None, multiple
=True,
891 help='restricts the list to the Network Slice Instances matching the filter')
893 def nsi_list2(ctx
, filter):
894 """list all Network Slice Instances (NSI)"""
896 nsi_list(ctx
, filter)
899 def nst_list(ctx
, filter):
902 check_client_version(ctx
.obj
, ctx
.command
.name
)
904 filter='&'.join(filter)
905 resp
= ctx
.obj
.nst
.list(filter)
906 # except ClientException as e:
909 # print(yaml.safe_dump(resp))
910 table
= PrettyTable(['nst name', 'id'])
912 name
= nst
['name'] if 'name' in nst
else '-'
913 table
.add_row([name
, nst
['_id']])
918 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
919 @click.option('--filter', default
=None, multiple
=True,
920 help='restricts the list to the NST matching the filter')
922 def nst_list1(ctx
, filter):
923 """list all Network Slice Templates (NST) in the system"""
925 nst_list(ctx
, filter)
928 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
929 @click.option('--filter', default
=None, multiple
=True,
930 help='restricts the list to the NST matching the filter')
932 def nst_list2(ctx
, filter):
933 """list all Network Slice Templates (NST) in the system"""
935 nst_list(ctx
, filter)
938 def nsi_op_list(ctx
, name
):
941 check_client_version(ctx
.obj
, ctx
.command
.name
)
942 resp
= ctx
.obj
.nsi
.list_op(name
)
943 # except ClientException as e:
946 table
= PrettyTable(['id', 'operation', 'status'])
948 table
.add_row([op
['id'], op
['lcmOperationType'],
949 op
['operationState']])
954 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
955 @click.argument('name')
957 def nsi_op_list1(ctx
, name
):
958 """shows the history of operations over a Network Slice Instance (NSI)
960 NAME: name or ID of the Network Slice Instance
963 nsi_op_list(ctx
, name
)
966 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
967 @click.argument('name')
969 def nsi_op_list2(ctx
, name
):
970 """shows the history of operations over a Network Slice Instance (NSI)
972 NAME: name or ID of the Network Slice Instance
975 nsi_op_list(ctx
, name
)
978 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
979 @click.option('--filter', default
=None, multiple
=True,
980 help='restricts the list to the Physical Deployment Units matching the filter')
982 def pdu_list(ctx
, filter):
983 """list all Physical Deployment Units (PDU)"""
986 check_client_version(ctx
.obj
, ctx
.command
.name
)
988 filter='&'.join(filter)
989 resp
= ctx
.obj
.pdu
.list(filter)
990 # except ClientException as e:
999 pdu_name
= pdu
['name']
1001 pdu_type
= pdu
['type']
1002 pdu_ipaddress
= "None"
1003 for iface
in pdu
['interfaces']:
1005 pdu_ipaddress
= iface
['ip-address']
1016 ####################
1018 ####################
1020 def nsd_show(ctx
, name
, literal
):
1023 resp
= ctx
.obj
.nsd
.get(name
)
1024 # resp = ctx.obj.nsd.get_individual(name)
1025 # except ClientException as e:
1030 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1033 table
= PrettyTable(['field', 'value'])
1034 for k
, v
in list(resp
.items()):
1035 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1040 @cli_osm.command(name
='nsd-show', short_help
='shows the details of a NS package')
1041 @click.option('--literal', is_flag
=True,
1042 help='print literally, no pretty table')
1043 @click.argument('name')
1045 def nsd_show1(ctx
, name
, literal
):
1046 """shows the content of a NSD
1048 NAME: name or ID of the NSD/NSpkg
1051 nsd_show(ctx
, name
, literal
)
1054 @cli_osm.command(name
='nspkg-show', short_help
='shows the details of a NS package')
1055 @click.option('--literal', is_flag
=True,
1056 help='print literally, no pretty table')
1057 @click.argument('name')
1059 def nsd_show2(ctx
, name
, literal
):
1060 """shows the content of a NSD
1062 NAME: name or ID of the NSD/NSpkg
1065 nsd_show(ctx
, name
, literal
)
1068 def vnfd_show(ctx
, name
, literal
):
1071 resp
= ctx
.obj
.vnfd
.get(name
)
1072 # resp = ctx.obj.vnfd.get_individual(name)
1073 # except ClientException as e:
1078 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1081 table
= PrettyTable(['field', 'value'])
1082 for k
, v
in list(resp
.items()):
1083 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1088 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1091 filter='&'.join(filter)
1093 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1096 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1099 catalog
= pkgtype
+ '-catalog'
1100 full_catalog
= pkgtype
+ ':' + catalog
1101 if resp
.get(catalog
):
1102 resp
= resp
.pop(catalog
)[pkgtype
][0]
1103 elif resp
.get(full_catalog
):
1104 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1106 table
= PrettyTable(['field', 'value'])
1107 for k
, v
in list(resp
.items()):
1108 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1113 @cli_osm.command(name
='vnfd-show', short_help
='shows the details of a NF package')
1114 @click.option('--literal', is_flag
=True,
1115 help='print literally, no pretty table')
1116 @click.argument('name')
1118 def vnfd_show1(ctx
, name
, literal
):
1119 """shows the content of a VNFD
1121 NAME: name or ID of the VNFD/VNFpkg
1124 vnfd_show(ctx
, name
, literal
)
1127 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the details of a NF package')
1128 @click.option('--literal', is_flag
=True,
1129 help='print literally, no pretty table')
1130 @click.argument('name')
1132 def vnfd_show2(ctx
, name
, literal
):
1133 """shows the content of a VNFD
1135 NAME: name or ID of the VNFD/VNFpkg
1138 vnfd_show(ctx
, name
, literal
)
1140 @cli_osm.command(name
='vnfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1141 @click.option('--literal', is_flag
=True,
1142 help='print literally, no pretty table')
1143 @click.option('--repo',
1145 help='Repository name')
1146 @click.argument('name')
1147 @click.option('--filter', default
=None, multiple
=True,
1148 help='filter by fields')
1149 @click.option('--version',
1151 help='package version')
1153 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1154 """shows the content of a VNFD in a repository
1156 NAME: name or ID of the VNFD/VNFpkg
1159 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1162 @cli_osm.command(name
='nsd-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1163 @click.option('--literal', is_flag
=True,
1164 help='print literally, no pretty table')
1165 @click.option('--repo',
1167 help='Repository name')
1168 @click.argument('name')
1169 @click.option('--filter', default
=None, multiple
=True,
1170 help='filter by fields')
1171 @click.option('--version',
1173 help='package version')
1175 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1176 """shows the content of a VNFD in a repository
1178 NAME: name or ID of the VNFD/VNFpkg
1181 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1183 @cli_osm.command(name
='nspkg-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1184 @click.option('--literal', is_flag
=True,
1185 help='print literally, no pretty table')
1186 @click.option('--repo',
1188 help='Repository name')
1189 @click.argument('name')
1190 @click.option('--filter', default
=None, multiple
=True,
1191 help='filter by fields')
1192 @click.option('--version',
1194 help='package version')
1196 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1197 """shows the content of a VNFD in a repository
1199 NAME: name or ID of the VNFD/VNFpkg
1202 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1205 @cli_osm.command(name
='nfpkg-show', short_help
='shows the details of a NF package')
1206 @click.option('--literal', is_flag
=True,
1207 help='print literally, no pretty table')
1208 @click.argument('name')
1210 def nfpkg_show(ctx
, name
, literal
):
1211 """shows the content of a NF Descriptor
1213 NAME: name or ID of the NFpkg
1216 vnfd_show(ctx
, name
, literal
)
1219 @cli_osm.command(name
='nfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1220 @click.option('--literal', is_flag
=True,
1221 help='print literally, no pretty table')
1222 @click.option('--repo',
1224 help='Repository name')
1225 @click.argument('name')
1226 @click.option('--filter', default
=None, multiple
=True,
1227 help='filter by fields')
1228 @click.option('--version',
1230 help='package version')
1232 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1233 """shows the content of a VNFD in a repository
1235 NAME: name or ID of the VNFD/VNFpkg
1238 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1241 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
1242 @click.argument('name')
1243 @click.option('--literal', is_flag
=True,
1244 help='print literally, no pretty table')
1245 @click.option('--filter', multiple
=True,
1246 help='restricts the information to the fields in the filter')
1248 def ns_show(ctx
, name
, literal
, filter):
1249 """shows the info of a NS instance
1251 NAME: name or ID of the NS instance
1255 ns
= ctx
.obj
.ns
.get(name
)
1256 # except ClientException as e:
1261 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1264 table
= PrettyTable(['field', 'value'])
1266 for k
, v
in list(ns
.items()):
1267 if not filter or k
in filter:
1268 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1270 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1271 if fullclassname
!= 'osmclient.sol005.client.Client':
1272 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1273 nsr_optdata
= nsopdata
['nsr:nsr']
1274 for k
, v
in list(nsr_optdata
.items()):
1275 if not filter or k
in filter:
1276 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1281 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1282 @click.argument('name')
1283 @click.option('--literal', is_flag
=True,
1284 help='print literally, no pretty table')
1285 @click.option('--filter', multiple
=True,
1286 help='restricts the information to the fields in the filter')
1287 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1289 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1290 """shows the info of a VNF instance
1292 NAME: name or ID of the VNF instance
1294 def print_kdu_status(op_info_status
):
1295 """print KDU status properly formatted
1298 op_status
= yaml
.safe_load(op_info_status
)
1299 if "namespace" in op_status
and "info" in op_status
and \
1300 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1301 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1302 "seconds" in op_status
["info"]["last_deployed"]:
1303 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1304 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1305 print("NAMESPACE: {}".format(op_status
["namespace"]))
1306 status_code
= "UNKNOWN"
1307 if op_status
["info"]["status"]["code"]==1:
1308 status_code
= "DEPLOYED"
1309 print("STATUS: {}".format(status_code
))
1312 print(op_status
["info"]["status"]["resources"])
1313 if "notes" in op_status
["info"]["status"]:
1315 print(op_status
["info"]["status"]["notes"])
1317 print(op_info_status
)
1319 print(op_info_status
)
1324 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1326 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1329 check_client_version(ctx
.obj
, ctx
.command
.name
)
1330 resp
= ctx
.obj
.vnf
.get(name
)
1333 ns_id
= resp
['nsr-id-ref']
1335 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1336 op_data
['kdu_name'] = kdu
1337 op_data
['primitive'] = 'status'
1338 op_data
['primitive_params'] = {}
1339 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1342 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1343 if op_info
['operationState'] == 'COMPLETED':
1344 print_kdu_status(op_info
['detailed-status'])
1348 print ("Could not determine KDU status")
1352 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1355 table
= PrettyTable(['field', 'value'])
1356 for k
, v
in list(resp
.items()):
1357 if not filter or k
in filter:
1358 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1361 # except ClientException as e:
1366 #@cli_osm.command(name='vnf-monitoring-show')
1367 #@click.argument('vnf_name')
1368 #@click.pass_context
1369 #def vnf_monitoring_show(ctx, vnf_name):
1371 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1372 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1373 # except ClientException as e:
1377 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1378 # if resp is not None:
1379 # for monitor in resp:
1383 # monitor['value-integer'],
1384 # monitor['units']])
1389 #@cli_osm.command(name='ns-monitoring-show')
1390 #@click.argument('ns_name')
1391 #@click.pass_context
1392 #def ns_monitoring_show(ctx, ns_name):
1394 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1395 # resp = ctx.obj.ns.get_monitoring(ns_name)
1396 # except ClientException as e:
1400 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1401 # for key, val in list(resp.items()):
1402 # for monitor in val:
1406 # monitor['value-integer'],
1407 # monitor['units']])
1412 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1413 @click.argument('id')
1414 @click.option('--filter', multiple
=True,
1415 help='restricts the information to the fields in the filter')
1416 @click.option('--literal', is_flag
=True,
1417 help='print literally, no pretty table')
1419 def ns_op_show(ctx
, id, filter, literal
):
1420 """shows the detailed info of a NS operation
1422 ID: operation identifier
1426 check_client_version(ctx
.obj
, ctx
.command
.name
)
1427 op_info
= ctx
.obj
.ns
.get_op(id)
1428 # except ClientException as e:
1433 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1436 table
= PrettyTable(['field', 'value'])
1437 for k
, v
in list(op_info
.items()):
1438 if not filter or k
in filter:
1439 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1444 def nst_show(ctx
, name
, literal
):
1447 check_client_version(ctx
.obj
, ctx
.command
.name
)
1448 resp
= ctx
.obj
.nst
.get(name
)
1449 #resp = ctx.obj.nst.get_individual(name)
1450 # except ClientException as e:
1455 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1458 table
= PrettyTable(['field', 'value'])
1459 for k
, v
in list(resp
.items()):
1460 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1465 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1466 @click.option('--literal', is_flag
=True,
1467 help='print literally, no pretty table')
1468 @click.argument('name')
1470 def nst_show1(ctx
, name
, literal
):
1471 """shows the content of a Network Slice Template (NST)
1473 NAME: name or ID of the NST
1476 nst_show(ctx
, name
, literal
)
1479 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1480 @click.option('--literal', is_flag
=True,
1481 help='print literally, no pretty table')
1482 @click.argument('name')
1484 def nst_show2(ctx
, name
, literal
):
1485 """shows the content of a Network Slice Template (NST)
1487 NAME: name or ID of the NST
1490 nst_show(ctx
, name
, literal
)
1493 def nsi_show(ctx
, name
, literal
, filter):
1496 check_client_version(ctx
.obj
, ctx
.command
.name
)
1497 nsi
= ctx
.obj
.nsi
.get(name
)
1498 # except ClientException as e:
1503 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1506 table
= PrettyTable(['field', 'value'])
1508 for k
, v
in list(nsi
.items()):
1509 if not filter or k
in filter:
1510 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1516 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1517 @click.argument('name')
1518 @click.option('--literal', is_flag
=True,
1519 help='print literally, no pretty table')
1520 @click.option('--filter', multiple
=True,
1521 help='restricts the information to the fields in the filter')
1523 def nsi_show1(ctx
, name
, literal
, filter):
1524 """shows the content of a Network Slice Instance (NSI)
1526 NAME: name or ID of the Network Slice Instance
1529 nsi_show(ctx
, name
, literal
, filter)
1532 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1533 @click.argument('name')
1534 @click.option('--literal', is_flag
=True,
1535 help='print literally, no pretty table')
1536 @click.option('--filter', multiple
=True,
1537 help='restricts the information to the fields in the filter')
1539 def nsi_show2(ctx
, name
, literal
, filter):
1540 """shows the content of a Network Slice Instance (NSI)
1542 NAME: name or ID of the Network Slice Instance
1545 nsi_show(ctx
, name
, literal
, filter)
1548 def nsi_op_show(ctx
, id, filter):
1551 check_client_version(ctx
.obj
, ctx
.command
.name
)
1552 op_info
= ctx
.obj
.nsi
.get_op(id)
1553 # except ClientException as e:
1557 table
= PrettyTable(['field', 'value'])
1558 for k
, v
in list(op_info
.items()):
1559 if not filter or k
in filter:
1560 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1565 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1566 @click.argument('id')
1567 @click.option('--filter', multiple
=True,
1568 help='restricts the information to the fields in the filter')
1570 def nsi_op_show1(ctx
, id, filter):
1571 """shows the info of an operation over a Network Slice Instance(NSI)
1573 ID: operation identifier
1576 nsi_op_show(ctx
, id, filter)
1579 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1580 @click.argument('id')
1581 @click.option('--filter', multiple
=True,
1582 help='restricts the information to the fields in the filter')
1584 def nsi_op_show2(ctx
, id, filter):
1585 """shows the info of an operation over a Network Slice Instance(NSI)
1587 ID: operation identifier
1590 nsi_op_show(ctx
, id, filter)
1593 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1594 @click.argument('name')
1595 @click.option('--literal', is_flag
=True,
1596 help='print literally, no pretty table')
1597 @click.option('--filter', multiple
=True,
1598 help='restricts the information to the fields in the filter')
1600 def pdu_show(ctx
, name
, literal
, filter):
1601 """shows the content of a Physical Deployment Unit (PDU)
1603 NAME: name or ID of the PDU
1607 check_client_version(ctx
.obj
, ctx
.command
.name
)
1608 pdu
= ctx
.obj
.pdu
.get(name
)
1609 # except ClientException as e:
1614 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1617 table
= PrettyTable(['field', 'value'])
1619 for k
, v
in list(pdu
.items()):
1620 if not filter or k
in filter:
1621 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1627 ####################
1629 ####################
1631 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1634 check_client_version(ctx
.obj
, ctx
.command
.name
)
1636 filename
= ctx
.obj
.osmrepo
.get_pkg('ns', filename
, repo
, vendor
, version
)
1637 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1638 # except ClientException as e:
1643 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1644 @click.argument('filename')
1645 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1646 help='Deprecated. Use override')
1647 @click.option('--override', 'overwrite', default
=None,
1648 help='overrides fields in descriptor, format: '
1649 '"key1.key2...=value[;key3...=value;...]"')
1650 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1651 help='The charm will not be compiled, it is assumed to already exist')
1652 @click.option('--repo', default
=None,
1653 help='[repository]: Repository name')
1654 @click.option('--vendor', default
=None,
1655 help='[repository]: filter by vendor]')
1656 @click.option('--version', default
='latest',
1657 help='[repository]: filter by version. Default: latest')
1659 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1660 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1663 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1664 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1665 If FILENAME is an NF Package folder, it is built and then onboarded.
1668 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1672 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1673 @click.argument('filename')
1674 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1675 help='Deprecated. Use override')
1676 @click.option('--override', 'overwrite', default
=None,
1677 help='overrides fields in descriptor, format: '
1678 '"key1.key2...=value[;key3...=value;...]"')
1679 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1680 help='The charm will not be compiled, it is assumed to already exist')
1681 @click.option('--repo', default
=None,
1682 help='[repository]: Repository name')
1683 @click.option('--vendor', default
=None,
1684 help='[repository]: filter by vendor]')
1685 @click.option('--version', default
='latest',
1686 help='[repository]: filter by version. Default: latest')
1688 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1689 """onboards a new NSpkg
1691 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1692 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1693 If FILENAME is an NF Package folder, it is built and then onboarded.
1696 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1700 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1701 repo
, vendor
, version
):
1704 check_client_version(ctx
.obj
, ctx
.command
.name
)
1706 filename
= ctx
.obj
.osmrepo
.get_pkg('vnf', filename
, repo
, vendor
, version
)
1707 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1708 override_epa
=override_epa
, override_nonepa
=override_nonepa
,
1709 override_paravirt
=override_paravirt
)
1710 # except ClientException as e:
1715 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1716 @click.argument('filename')
1717 @click.option('--overwrite', 'overwrite', default
=None,
1718 help='overwrite deprecated, use override')
1719 @click.option('--override', 'overwrite', default
=None,
1720 help='overrides fields in descriptor, format: '
1721 '"key1.key2...=value[;key3...=value;...]"')
1722 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1723 help='The charm will not be compiled, it is assumed to already exist')
1724 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1725 help='adds guest-epa parameters to all VDU')
1726 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1727 help='removes all guest-epa parameters from all VDU')
1728 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1729 help='overrides all VDU interfaces to PARAVIRT')
1730 @click.option('--repo', default
=None,
1731 help='[repository]: Repository name')
1732 @click.option('--vendor', default
=None,
1733 help='[repository]: filter by vendor]')
1734 @click.option('--version', default
='latest',
1735 help='[repository]: filter by version. Default: latest')
1737 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1738 repo
,vendor
, version
):
1739 """creates a new VNFD/VNFpkg
1741 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1742 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1743 If FILENAME is an NF Package folder, it is built and then onboarded.
1746 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1747 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1748 repo
=repo
, vendor
=vendor
, version
=version
)
1751 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1752 @click.argument('filename')
1753 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1754 help='Deprecated. Use override')
1755 @click.option('--override', 'overwrite', default
=None,
1756 help='overrides fields in descriptor, format: '
1757 '"key1.key2...=value[;key3...=value;...]"')
1758 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1759 help='The charm will not be compiled, it is assumed to already exist')
1760 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1761 help='adds guest-epa parameters to all VDU')
1762 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1763 help='removes all guest-epa parameters from all VDU')
1764 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1765 help='overrides all VDU interfaces to PARAVIRT')
1766 @click.option('--repo', default
=None,
1767 help='[repository]: Repository name')
1768 @click.option('--vendor', default
=None,
1769 help='[repository]: filter by vendor]')
1770 @click.option('--version', default
='latest',
1771 help='[repository]: filter by version. Default: latest')
1773 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1774 repo
, vendor
, version
):
1775 """creates a new VNFD/VNFpkg
1777 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1778 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1779 If FILENAME is an NF Package folder, it is built and then onboarded.
1782 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1783 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1784 repo
=repo
, vendor
=vendor
, version
=version
)
1786 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1787 @click.argument('filename')
1788 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1789 help='Deprecated. Use override')
1790 @click.option('--override', 'overwrite', default
=None,
1791 help='overrides fields in descriptor, format: '
1792 '"key1.key2...=value[;key3...=value;...]"')
1793 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1794 help='The charm will not be compiled, it is assumed to already exist')
1795 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1796 help='adds guest-epa parameters to all VDU')
1797 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1798 help='removes all guest-epa parameters from all VDU')
1799 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1800 help='overrides all VDU interfaces to PARAVIRT')
1801 @click.option('--repo', default
=None,
1802 help='[repository]: Repository name')
1803 @click.option('--vendor', default
=None,
1804 help='[repository]: filter by vendor]')
1805 @click.option('--version', default
='latest',
1806 help='[repository]: filter by version. Default: latest')
1808 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1809 repo
, vendor
, version
):
1810 """creates a new NFpkg
1813 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1814 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1815 If FILENAME is an NF Package folder, it is built and then onboarded.
1818 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1819 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1820 repo
=repo
, vendor
=vendor
, version
=version
)
1823 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1824 @click.option('--ns_name',
1825 prompt
=True, help='name of the NS instance')
1826 @click.option('--nsd_name',
1827 prompt
=True, help='name of the NS descriptor')
1828 @click.option('--vim_account',
1829 prompt
=True, help='default VIM account id or name for the deployment')
1830 @click.option('--admin_status',
1832 help='administration status')
1833 @click.option('--ssh_keys',
1835 help='comma separated list of public key files to inject to vnfs')
1836 @click.option('--config',
1838 help='ns specific yaml configuration')
1839 @click.option('--config_file',
1841 help='ns specific yaml configuration file')
1842 @click.option('--wait',
1846 help='do not return the control immediately, but keep it '
1847 'until the operation is completed, or timeout')
1858 """creates a new NS instance"""
1862 check_client_version(ctx
.obj
, '--config_file')
1864 raise ClientException('"--config" option is incompatible with "--config_file" option')
1865 with
open(config_file
, 'r') as cf
:
1872 account
=vim_account
,
1874 # except ClientException as e:
1879 def nst_create(ctx
, filename
, overwrite
):
1882 check_client_version(ctx
.obj
, ctx
.command
.name
)
1883 ctx
.obj
.nst
.create(filename
, overwrite
)
1884 # except ClientException as e:
1889 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1890 @click.argument('filename')
1891 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1892 help='Deprecated. Use override')
1893 @click.option('--override', 'overwrite', default
=None,
1894 help='overrides fields in descriptor, format: '
1895 '"key1.key2...=value[;key3...=value;...]"')
1897 def nst_create1(ctx
, filename
, overwrite
):
1898 """creates a new Network Slice Template (NST)
1900 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1903 nst_create(ctx
, filename
, overwrite
)
1906 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1907 @click.argument('filename')
1908 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1909 help='Deprecated. Use override')
1910 @click.option('--override', 'overwrite', default
=None,
1911 help='overrides fields in descriptor, format: '
1912 '"key1.key2...=value[;key3...=value;...]"')
1914 def nst_create2(ctx
, filename
, overwrite
):
1915 """creates a new Network Slice Template (NST)
1917 FILENAME: NST yaml file or NSTpkg tar.gz file
1920 nst_create(ctx
, filename
, overwrite
)
1923 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1924 """creates a new Network Slice Instance (NSI)"""
1927 check_client_version(ctx
.obj
, ctx
.command
.name
)
1930 raise ClientException('"--config" option is incompatible with "--config_file" option')
1931 with
open(config_file
, 'r') as cf
:
1933 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1934 account
=vim_account
, wait
=wait
)
1935 # except ClientException as e:
1940 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1941 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1942 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1943 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1944 @click.option('--ssh_keys', default
=None,
1945 help='comma separated list of keys to inject to vnfs')
1946 @click.option('--config', default
=None,
1947 help='Netslice specific yaml configuration:\n'
1948 'netslice_subnet: [\n'
1949 'id: TEXT, vim_account: TEXT,\n'
1950 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1951 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1952 'additionalParamsForNsi: {param: value, ...}\n'
1953 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1955 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1957 @click.option('--config_file',
1959 help='nsi specific yaml configuration file')
1960 @click.option('--wait',
1964 help='do not return the control immediately, but keep it '
1965 'until the operation is completed, or timeout')
1967 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1968 """creates a new Network Slice Instance (NSI)"""
1970 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1973 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1974 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1975 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1976 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1977 @click.option('--ssh_keys', default
=None,
1978 help='comma separated list of keys to inject to vnfs')
1979 @click.option('--config', default
=None,
1980 help='Netslice specific yaml configuration:\n'
1981 'netslice_subnet: [\n'
1982 'id: TEXT, vim_account: TEXT,\n'
1983 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1984 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1986 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1988 @click.option('--config_file',
1990 help='nsi specific yaml configuration file')
1991 @click.option('--wait',
1995 help='do not return the control immediately, but keep it '
1996 'until the operation is completed, or timeout')
1998 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1999 """creates a new Network Slice Instance (NSI)"""
2001 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
2004 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
2005 @click.option('--name', help='name of the Physical Deployment Unit')
2006 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
2007 @click.option('--interface',
2008 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
2009 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
2011 @click.option('--description', help='human readable description')
2012 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
2013 @click.option('--descriptor_file', default
=None,
2014 help='PDU descriptor file (as an alternative to using the other arguments')
2016 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
2017 """creates a new Physical Deployment Unit (PDU)"""
2020 check_client_version(ctx
.obj
, ctx
.command
.name
)
2022 if not descriptor_file
:
2024 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
2026 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
2028 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
2030 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
2032 with
open(descriptor_file
, 'r') as df
:
2033 pdu
= yaml
.safe_load(df
.read())
2034 if name
: pdu
["name"] = name
2035 if pdu_type
: pdu
["type"] = pdu_type
2036 if description
: pdu
["description"] = description
2037 if vim_account
: pdu
["vim_accounts"] = vim_account
2040 for iface
in interface
:
2041 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
2042 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
2043 ifaces_list
.append(new_iface
)
2044 pdu
["interfaces"] = ifaces_list
2045 ctx
.obj
.pdu
.create(pdu
)
2046 # except ClientException as e:
2051 ####################
2053 ####################
2055 def nsd_update(ctx
, name
, content
):
2058 check_client_version(ctx
.obj
, ctx
.command
.name
)
2059 ctx
.obj
.nsd
.update(name
, content
)
2060 # except ClientException as e:
2065 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
2066 @click.argument('name')
2067 @click.option('--content', default
=None,
2068 help='filename with the NSD/NSpkg replacing the current one')
2070 def nsd_update1(ctx
, name
, content
):
2071 """updates a NSD/NSpkg
2073 NAME: name or ID of the NSD/NSpkg
2076 nsd_update(ctx
, name
, content
)
2079 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
2080 @click.argument('name')
2081 @click.option('--content', default
=None,
2082 help='filename with the NSD/NSpkg replacing the current one')
2084 def nsd_update2(ctx
, name
, content
):
2085 """updates a NSD/NSpkg
2087 NAME: name or ID of the NSD/NSpkg
2090 nsd_update(ctx
, name
, content
)
2093 def vnfd_update(ctx
, name
, content
):
2096 check_client_version(ctx
.obj
, ctx
.command
.name
)
2097 ctx
.obj
.vnfd
.update(name
, content
)
2098 # except ClientException as e:
2103 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
2104 @click.argument('name')
2105 @click.option('--content', default
=None,
2106 help='filename with the VNFD/VNFpkg replacing the current one')
2108 def vnfd_update1(ctx
, name
, content
):
2109 """updates a VNFD/VNFpkg
2111 NAME: name or ID of the VNFD/VNFpkg
2114 vnfd_update(ctx
, name
, content
)
2117 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
2118 @click.argument('name')
2119 @click.option('--content', default
=None,
2120 help='filename with the VNFD/VNFpkg replacing the current one')
2122 def vnfd_update2(ctx
, name
, content
):
2123 """updates a VNFD/VNFpkg
2125 NAME: VNFD yaml file or VNFpkg tar.gz file
2128 vnfd_update(ctx
, name
, content
)
2131 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
2132 @click.argument('name')
2133 @click.option('--content', default
=None,
2134 help='filename with the NFpkg replacing the current one')
2136 def nfpkg_update(ctx
, name
, content
):
2139 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2142 vnfd_update(ctx
, name
, content
)
2145 def nst_update(ctx
, name
, content
):
2148 check_client_version(ctx
.obj
, ctx
.command
.name
)
2149 ctx
.obj
.nst
.update(name
, content
)
2150 # except ClientException as e:
2155 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
2156 @click.argument('name')
2157 @click.option('--content', default
=None,
2158 help='filename with the NST/NSTpkg replacing the current one')
2160 def nst_update1(ctx
, name
, content
):
2161 """updates a Network Slice Template (NST)
2163 NAME: name or ID of the NSD/NSpkg
2166 nst_update(ctx
, name
, content
)
2169 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
2170 @click.argument('name')
2171 @click.option('--content', default
=None,
2172 help='filename with the NST/NSTpkg replacing the current one')
2174 def nst_update2(ctx
, name
, content
):
2175 """updates a Network Slice Template (NST)
2177 NAME: name or ID of the NSD/NSpkg
2180 nst_update(ctx
, name
, content
)
2183 ####################
2185 ####################
2187 def nsd_delete(ctx
, name
, force
):
2191 ctx
.obj
.nsd
.delete(name
)
2193 check_client_version(ctx
.obj
, '--force')
2194 ctx
.obj
.nsd
.delete(name
, force
)
2195 # except ClientException as e:
2200 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
2201 @click.argument('name')
2202 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2204 def nsd_delete1(ctx
, name
, force
):
2205 """deletes a NSD/NSpkg
2207 NAME: name or ID of the NSD/NSpkg to be deleted
2210 nsd_delete(ctx
, name
, force
)
2213 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
2214 @click.argument('name')
2215 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2217 def nsd_delete2(ctx
, name
, force
):
2218 """deletes a NSD/NSpkg
2220 NAME: name or ID of the NSD/NSpkg to be deleted
2223 nsd_delete(ctx
, name
, force
)
2226 def vnfd_delete(ctx
, name
, force
):
2230 ctx
.obj
.vnfd
.delete(name
)
2232 check_client_version(ctx
.obj
, '--force')
2233 ctx
.obj
.vnfd
.delete(name
, force
)
2234 # except ClientException as e:
2239 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
2240 @click.argument('name')
2241 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2243 def vnfd_delete1(ctx
, name
, force
):
2244 """deletes a VNFD/VNFpkg
2246 NAME: name or ID of the VNFD/VNFpkg to be deleted
2249 vnfd_delete(ctx
, name
, force
)
2252 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
2253 @click.argument('name')
2254 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2256 def vnfd_delete2(ctx
, name
, force
):
2257 """deletes a VNFD/VNFpkg
2259 NAME: name or ID of the VNFD/VNFpkg to be deleted
2262 vnfd_delete(ctx
, name
, force
)
2265 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
2266 @click.argument('name')
2267 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2269 def nfpkg_delete(ctx
, name
, force
):
2272 NAME: name or ID of the NFpkg to be deleted
2275 vnfd_delete(ctx
, name
, force
)
2278 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
2279 @click.argument('name')
2280 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2281 @click.option('--config', default
=None,
2282 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2283 "600, skip_terminate_primitives: True}'")
2284 @click.option('--wait',
2288 help='do not return the control immediately, but keep it '
2289 'until the operation is completed, or timeout')
2291 def ns_delete(ctx
, name
, force
, config
, wait
):
2292 """deletes a NS instance
2294 NAME: name or ID of the NS instance to be deleted
2299 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2301 check_client_version(ctx
.obj
, '--force')
2302 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2303 # except ClientException as e:
2308 def nst_delete(ctx
, name
, force
):
2311 check_client_version(ctx
.obj
, ctx
.command
.name
)
2312 ctx
.obj
.nst
.delete(name
, force
)
2313 # except ClientException as e:
2318 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
2319 @click.argument('name')
2320 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2322 def nst_delete1(ctx
, name
, force
):
2323 """deletes a Network Slice Template (NST)
2325 NAME: name or ID of the NST/NSTpkg to be deleted
2328 nst_delete(ctx
, name
, force
)
2331 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
2332 @click.argument('name')
2333 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2335 def nst_delete2(ctx
, name
, force
):
2336 """deletes a Network Slice Template (NST)
2338 NAME: name or ID of the NST/NSTpkg to be deleted
2341 nst_delete(ctx
, name
, force
)
2344 def nsi_delete(ctx
, name
, force
, wait
):
2347 check_client_version(ctx
.obj
, ctx
.command
.name
)
2348 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2349 # except ClientException as e:
2354 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2355 @click.argument('name')
2356 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2357 @click.option('--wait',
2361 help='do not return the control immediately, but keep it '
2362 'until the operation is completed, or timeout')
2364 def nsi_delete1(ctx
, name
, force
, wait
):
2365 """deletes a Network Slice Instance (NSI)
2367 NAME: name or ID of the Network Slice instance to be deleted
2370 nsi_delete(ctx
, name
, force
, wait
=wait
)
2373 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2374 @click.argument('name')
2375 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2377 def nsi_delete2(ctx
, name
, force
, wait
):
2378 """deletes a Network Slice Instance (NSI)
2380 NAME: name or ID of the Network Slice instance to be deleted
2383 nsi_delete(ctx
, name
, force
, wait
=wait
)
2386 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2387 @click.argument('name')
2388 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2390 def pdu_delete(ctx
, name
, force
):
2391 """deletes a Physical Deployment Unit (PDU)
2393 NAME: name or ID of the PDU to be deleted
2397 check_client_version(ctx
.obj
, ctx
.command
.name
)
2398 ctx
.obj
.pdu
.delete(name
, force
)
2399 # except ClientException as e:
2408 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2409 @click.option('--name',
2411 help='Name to create datacenter')
2412 @click.option('--user',
2414 help='VIM username')
2415 @click.option('--password',
2418 confirmation_prompt
=True,
2419 help='VIM password')
2420 @click.option('--auth_url',
2423 @click.option('--tenant',
2425 help='VIM tenant name')
2426 @click.option('--config',
2428 help='VIM specific config parameters')
2429 @click.option('--account_type',
2430 default
='openstack',
2432 @click.option('--description',
2434 help='human readable description')
2435 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2436 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2437 @click.option('--wait',
2441 help='do not return the control immediately, but keep it '
2442 'until the operation is completed, or timeout')
2456 """creates a new VIM account"""
2460 check_client_version(ctx
.obj
, '--sdn_controller')
2461 if sdn_port_mapping
:
2462 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2464 vim
['vim-username'] = user
2465 vim
['vim-password'] = password
2466 vim
['vim-url'] = auth_url
2467 vim
['vim-tenant-name'] = tenant
2468 vim
['vim-type'] = account_type
2469 vim
['description'] = description
2470 vim
['config'] = config
2471 if sdn_controller
or sdn_port_mapping
:
2472 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2474 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2475 # except ClientException as e:
2480 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2481 @click.argument('name')
2482 @click.option('--newname', help='New name for the VIM account')
2483 @click.option('--user', help='VIM username')
2484 @click.option('--password', help='VIM password')
2485 @click.option('--auth_url', help='VIM url')
2486 @click.option('--tenant', help='VIM tenant name')
2487 @click.option('--config', help='VIM specific config parameters')
2488 @click.option('--account_type', help='VIM type')
2489 @click.option('--description', help='human readable description')
2490 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller to be associated with this VIM'
2491 'account. Use empty string to disassociate')
2492 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2493 @click.option('--wait',
2497 help='do not return the control immediately, but keep it '
2498 'until the operation is completed, or timeout')
2513 """updates a VIM account
2515 NAME: name or ID of the VIM account
2519 check_client_version(ctx
.obj
, ctx
.command
.name
)
2521 if newname
: vim
['name'] = newname
2522 if user
: vim
['vim_user'] = user
2523 if password
: vim
['vim_password'] = password
2524 if auth_url
: vim
['vim_url'] = auth_url
2525 if tenant
: vim
['vim-tenant-name'] = tenant
2526 if account_type
: vim
['vim_type'] = account_type
2527 if description
: vim
['description'] = description
2528 if config
: vim
['config'] = config
2529 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2530 # except ClientException as e:
2535 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2536 @click.argument('name')
2537 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2538 @click.option('--wait',
2542 help='do not return the control immediately, but keep it '
2543 'until the operation is completed, or timeout')
2545 def vim_delete(ctx
, name
, force
, wait
):
2546 """deletes a VIM account
2548 NAME: name or ID of the VIM account to be deleted
2553 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2555 check_client_version(ctx
.obj
, '--force')
2556 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2557 # except ClientException as e:
2562 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2563 #@click.option('--ro_update/--no_ro_update',
2565 # help='update list from RO')
2566 @click.option('--filter', default
=None, multiple
=True,
2567 help='restricts the list to the VIM accounts matching the filter')
2568 @click.option('--long', is_flag
=True,
2569 help='get more details of the NS (project, vim, deployment status, configuration status.')
2571 def vim_list(ctx
, filter, long):
2572 """list all VIM accounts"""
2575 filter='&'.join(filter)
2576 check_client_version(ctx
.obj
, '--filter')
2578 # check_client_version(ctx.obj, '--ro_update', 'v1')
2579 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2580 if fullclassname
== 'osmclient.sol005.client.Client':
2581 resp
= ctx
.obj
.vim
.list(filter)
2583 # resp = ctx.obj.vim.list(ro_update)
2585 table
= PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details'])
2586 project_list
= ctx
.obj
.project
.list()
2588 table
= PrettyTable(['vim name', 'uuid', 'operational state'])
2591 if 'vim_password' in vim
:
2592 vim
['vim_password']='********'
2593 logger
.debug('VIM details: {}'.format(yaml
.safe_dump(vim
)))
2594 vim_state
= vim
['_admin'].get('operationalState', '-')
2595 error_details
= 'N/A'
2596 if vim_state
== 'ERROR':
2597 error_details
= vim
['_admin'].get('detailed-status', 'Not found')
2598 project_id
, project_name
= get_project(project_list
, vim
)
2599 #project_info = '{} ({})'.format(project_name, project_id)
2600 project_info
= project_name
2601 table
.add_row([vim
['name'], vim
['uuid'], project_info
,
2602 vim_state
, wrap_text(text
=error_details
, width
=80)])
2604 table
.add_row([vim
['name'], vim
['uuid'], vim
['_admin'].get('operationalState', '-')])
2609 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2610 @click.argument('name')
2611 @click.option('--filter', multiple
=True,
2612 help='restricts the information to the fields in the filter')
2614 def vim_show(ctx
, name
, filter):
2615 """shows the details of a VIM account
2617 NAME: name or ID of the VIM account
2621 resp
= ctx
.obj
.vim
.get(name
)
2622 if 'vim_password' in resp
:
2623 resp
['vim_password']='********'
2624 # except ClientException as e:
2628 table
= PrettyTable(['key', 'attribute'])
2629 for k
, v
in list(resp
.items()):
2630 if not filter or k
in filter:
2631 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2636 ####################
2638 ####################
2640 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2641 @click.option('--name',
2643 help='Name for the WIM account')
2644 @click.option('--user',
2645 help='WIM username')
2646 @click.option('--password',
2647 help='WIM password')
2648 @click.option('--url',
2651 # @click.option('--tenant',
2652 # help='wIM tenant name')
2653 @click.option('--config',
2655 help='WIM specific config parameters')
2656 @click.option('--wim_type',
2658 @click.option('--description',
2660 help='human readable description')
2661 @click.option('--wim_port_mapping', default
=None,
2662 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2663 "(WAN service endpoint id and info)")
2664 @click.option('--wait',
2668 help='do not return the control immediately, but keep it '
2669 'until the operation is completed, or timeout')
2682 """creates a new WIM account"""
2685 check_client_version(ctx
.obj
, ctx
.command
.name
)
2686 # if sdn_controller:
2687 # check_client_version(ctx.obj, '--sdn_controller')
2688 # if sdn_port_mapping:
2689 # check_client_version(ctx.obj, '--sdn_port_mapping')
2691 if user
: wim
['user'] = user
2692 if password
: wim
['password'] = password
2693 if url
: wim
['wim_url'] = url
2694 # if tenant: wim['tenant'] = tenant
2695 wim
['wim_type'] = wim_type
2696 if description
: wim
['description'] = description
2697 if config
: wim
['config'] = config
2698 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2699 # except ClientException as e:
2704 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2705 @click.argument('name')
2706 @click.option('--newname', help='New name for the WIM account')
2707 @click.option('--user', help='WIM username')
2708 @click.option('--password', help='WIM password')
2709 @click.option('--url', help='WIM url')
2710 @click.option('--config', help='WIM specific config parameters')
2711 @click.option('--wim_type', help='WIM type')
2712 @click.option('--description', help='human readable description')
2713 @click.option('--wim_port_mapping', default
=None,
2714 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2715 "(WAN service endpoint id and info)")
2716 @click.option('--wait',
2720 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2733 """updates a WIM account
2735 NAME: name or ID of the WIM account
2739 check_client_version(ctx
.obj
, ctx
.command
.name
)
2741 if newname
: wim
['name'] = newname
2742 if user
: wim
['user'] = user
2743 if password
: wim
['password'] = password
2744 if url
: wim
['url'] = url
2745 # if tenant: wim['tenant'] = tenant
2746 if wim_type
: wim
['wim_type'] = wim_type
2747 if description
: wim
['description'] = description
2748 if config
: wim
['config'] = config
2749 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2750 # except ClientException as e:
2755 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2756 @click.argument('name')
2757 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2758 @click.option('--wait',
2762 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2764 def wim_delete(ctx
, name
, force
, wait
):
2765 """deletes a WIM account
2767 NAME: name or ID of the WIM account to be deleted
2771 check_client_version(ctx
.obj
, ctx
.command
.name
)
2772 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2773 # except ClientException as e:
2778 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2779 @click.option('--filter', default
=None, multiple
=True,
2780 help='restricts the list to the WIM accounts matching the filter')
2782 def wim_list(ctx
, filter):
2783 """list all WIM accounts"""
2786 check_client_version(ctx
.obj
, ctx
.command
.name
)
2788 filter='&'.join(filter)
2789 resp
= ctx
.obj
.wim
.list(filter)
2790 table
= PrettyTable(['wim name', 'uuid'])
2792 table
.add_row([wim
['name'], wim
['uuid']])
2795 # except ClientException as e:
2800 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2801 @click.argument('name')
2803 def wim_show(ctx
, name
):
2804 """shows the details of a WIM account
2806 NAME: name or ID of the WIM account
2810 check_client_version(ctx
.obj
, ctx
.command
.name
)
2811 resp
= ctx
.obj
.wim
.get(name
)
2812 if 'password' in resp
:
2813 resp
['wim_password']='********'
2814 # except ClientException as e:
2818 table
= PrettyTable(['key', 'attribute'])
2819 for k
, v
in list(resp
.items()):
2820 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2825 ####################
2826 # SDN controller operations
2827 ####################
2829 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2830 @click.option('--name',
2832 help='Name to create sdn controller')
2833 @click.option('--type',
2835 help='SDN controller type')
2836 @click.option('--sdn_controller_version', # hidden=True,
2837 help='Deprecated. Use --config {version: sdn_controller_version}')
2838 @click.option('--url',
2839 help='URL in format http[s]://HOST:IP/')
2840 @click.option('--ip_address', # hidden=True,
2841 help='Deprecated. Use --url')
2842 @click.option('--port', # hidden=True,
2843 help='Deprecated. Use --url')
2844 @click.option('--switch_dpid', # hidden=True,
2845 help='Deprecated. Use --config {switch_id: DPID}')
2846 @click.option('--config',
2847 help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2848 'Openflow Datapath ID), version: version}')
2849 @click.option('--user',
2850 help='SDN controller username')
2851 @click.option('--password',
2853 confirmation_prompt
=True,
2854 help='SDN controller password')
2855 @click.option('--description', default
=None, help='human readable description')
2856 @click.option('--wait',
2860 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2862 def sdnc_create(ctx
, **kwargs
):
2863 """creates a new SDN controller"""
2865 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2866 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2867 if kwargs
.get("port"):
2868 print("option '--port' is deprecated, use '--url' instead")
2869 sdncontroller
["port"] = int(kwargs
["port"])
2870 if kwargs
.get("ip_address"):
2871 print("option '--ip_address' is deprecated, use '--url' instead")
2872 sdncontroller
["ip"] = kwargs
["ip_address"]
2873 if kwargs
.get("switch_dpid"):
2874 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2875 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2876 if kwargs
.get("sdn_controller_version"):
2877 print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2880 check_client_version(ctx
.obj
, ctx
.command
.name
)
2881 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2882 # except ClientException as e:
2886 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2887 @click.argument('name')
2888 @click.option('--newname', help='New name for the SDN controller')
2889 @click.option('--description', default
=None, help='human readable description')
2890 @click.option('--type', help='SDN controller type')
2891 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2892 @click.option('--config', help='Extra information for SDN in yaml format, as '
2893 '{switch_id: identity used for the plugin (e.g. DPID: '
2894 'Openflow Datapath ID), version: version}')
2895 @click.option('--user', help='SDN controller username')
2896 @click.option('--password', help='SDN controller password')
2897 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2898 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2899 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2900 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2901 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2902 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2904 def sdnc_update(ctx
, **kwargs
):
2905 """updates an SDN controller
2907 NAME: name or ID of the SDN controller
2910 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2911 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2912 if kwargs
.get("newname"):
2913 sdncontroller
["name"] = kwargs
["newname"]
2914 if kwargs
.get("port"):
2915 print("option '--port' is deprecated, use '--url' instead")
2916 sdncontroller
["port"] = int(kwargs
["port"])
2917 if kwargs
.get("ip_address"):
2918 print("option '--ip_address' is deprecated, use '--url' instead")
2919 sdncontroller
["ip"] = kwargs
["ip_address"]
2920 if kwargs
.get("switch_dpid"):
2921 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2922 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2923 if kwargs
.get("sdn_controller_version"):
2924 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2928 check_client_version(ctx
.obj
, ctx
.command
.name
)
2929 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2930 # except ClientException as e:
2935 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2936 @click.argument('name')
2937 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2938 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2939 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2941 def sdnc_delete(ctx
, name
, force
, wait
):
2942 """deletes an SDN controller
2944 NAME: name or ID of the SDN controller to be deleted
2948 check_client_version(ctx
.obj
, ctx
.command
.name
)
2949 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2950 # except ClientException as e:
2955 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2956 @click.option('--filter', default
=None, multiple
=True,
2957 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2959 def sdnc_list(ctx
, filter):
2960 """list all SDN controllers"""
2963 check_client_version(ctx
.obj
, ctx
.command
.name
)
2965 filter='&'.join(filter)
2966 resp
= ctx
.obj
.sdnc
.list(filter)
2967 # except ClientException as e:
2970 table
= PrettyTable(['sdnc name', 'id'])
2972 table
.add_row([sdnc
['name'], sdnc
['_id']])
2977 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2978 @click.argument('name')
2980 def sdnc_show(ctx
, name
):
2981 """shows the details of an SDN controller
2983 NAME: name or ID of the SDN controller
2987 check_client_version(ctx
.obj
, ctx
.command
.name
)
2988 resp
= ctx
.obj
.sdnc
.get(name
)
2989 # except ClientException as e:
2993 table
= PrettyTable(['key', 'attribute'])
2994 for k
, v
in list(resp
.items()):
2995 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3000 ###########################
3001 # K8s cluster operations
3002 ###########################
3004 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
3005 @click.argument('name')
3006 @click.option('--creds',
3008 help='credentials file, i.e. a valid `.kube/config` file')
3009 @click.option('--version',
3011 help='Kubernetes version')
3012 @click.option('--vim',
3014 help='VIM target, the VIM where the cluster resides')
3015 @click.option('--k8s-nets',
3017 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) ...]}"')
3018 @click.option('--description',
3020 help='human readable description')
3021 @click.option('--namespace',
3022 default
='kube-system',
3023 help='namespace to be used for its operation, defaults to `kube-system`')
3024 @click.option('--cni',
3026 help='list of CNI plugins, in JSON inline format, used in the cluster')
3027 #@click.option('--skip-init',
3029 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3030 #@click.option('--wait',
3032 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3034 def k8scluster_add(ctx
,
3043 """adds a K8s cluster to OSM
3045 NAME: name of the K8s cluster
3048 check_client_version(ctx
.obj
, ctx
.command
.name
)
3050 cluster
['name'] = name
3051 with
open(creds
, 'r') as cf
:
3052 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3053 cluster
['k8s_version'] = version
3054 cluster
['vim_account'] = vim
3055 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3057 cluster
['description'] = description
3058 if namespace
: cluster
['namespace'] = namespace
3059 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3060 ctx
.obj
.k8scluster
.create(name
, cluster
)
3061 # except ClientException as e:
3066 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
3067 @click.argument('name')
3068 @click.option('--newname', help='New name for the K8s cluster')
3069 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3070 @click.option('--version', help='Kubernetes version')
3071 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3072 @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) ...]}"')
3073 @click.option('--description', help='human readable description')
3074 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3075 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3077 def k8scluster_update(ctx
,
3087 """updates a K8s cluster
3089 NAME: name or ID of the K8s cluster
3092 check_client_version(ctx
.obj
, ctx
.command
.name
)
3094 if newname
: cluster
['name'] = newname
3096 with
open(creds
, 'r') as cf
:
3097 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3098 if version
: cluster
['k8s_version'] = version
3099 if vim
: cluster
['vim_account'] = vim
3100 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3101 if description
: cluster
['description'] = description
3102 if namespace
: cluster
['namespace'] = namespace
3103 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3104 ctx
.obj
.k8scluster
.update(name
, cluster
)
3105 # except ClientException as e:
3110 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
3111 @click.argument('name')
3112 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3113 #@click.option('--wait',
3115 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3117 def k8scluster_delete(ctx
, name
, force
):
3118 """deletes a K8s cluster
3120 NAME: name or ID of the K8s cluster to be deleted
3123 check_client_version(ctx
.obj
, ctx
.command
.name
)
3124 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3125 # except ClientException as e:
3130 @cli_osm.command(name
='k8scluster-list')
3131 @click.option('--filter', default
=None, multiple
=True,
3132 help='restricts the list to the K8s clusters matching the filter')
3133 @click.option('--literal', is_flag
=True,
3134 help='print literally, no pretty table')
3135 @click.option('--long', is_flag
=True, help='get more details')
3137 def k8scluster_list(ctx
, filter, literal
, long):
3138 """list all K8s clusters"""
3140 check_client_version(ctx
.obj
, ctx
.command
.name
)
3142 filter='&'.join(filter)
3143 resp
= ctx
.obj
.k8scluster
.list(filter)
3145 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3148 table
= PrettyTable(['Name', 'Id', 'Project', 'Version', 'VIM', 'K8s-nets',
3149 'Operational State', 'Op. state (details)', 'Description', 'Detailed status'])
3150 project_list
= ctx
.obj
.project
.list()
3152 table
= PrettyTable(['Name', 'Id', 'VIM', 'Operational State', 'Op. state details'])
3154 vim_list
= ctx
.obj
.vim
.list()
3157 for cluster
in resp
:
3158 logger
.debug('Cluster details: {}'.format(yaml
.safe_dump(cluster
)))
3159 vim_name
= get_vim_name(vim_list
, cluster
['vim_account'])
3160 #vim_info = '{} ({})'.format(vim_name,cluster['vim_account'])
3162 op_state_details
= "Helm: {}\nJuju: {}".format(
3163 cluster
["_admin"].get("helm-chart", {}).get("operationalState", "-"),
3164 cluster
["_admin"].get("juju-bundle", {}).get("operationalState", "-"))
3166 project_id
, project_name
= get_project(project_list
, cluster
)
3167 #project_info = '{} ({})'.format(project_name, project_id)
3168 project_info
= project_name
3169 detailed_status
= cluster
["_admin"].get("detailed-status","-")
3170 table
.add_row([cluster
['name'], cluster
['_id'], project_info
,
3171 cluster
['k8s_version'], vim_info
,
3172 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
3173 op_state_details
, trunc_text(cluster
.get('description') or '', 40),
3174 wrap_text(text
=detailed_status
, width
=40)])
3176 table
.add_row([cluster
['name'], cluster
['_id'], vim_info
,
3177 cluster
["_admin"]["operationalState"], op_state_details
])
3180 # except ClientException as e:
3185 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
3186 @click.argument('name')
3187 @click.option('--literal', is_flag
=True,
3188 help='print literally, no pretty table')
3190 def k8scluster_show(ctx
, name
, literal
):
3191 """shows the details of a K8s cluster
3193 NAME: name or ID of the K8s cluster
3196 resp
= ctx
.obj
.k8scluster
.get(name
)
3198 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3200 table
= PrettyTable(['key', 'attribute'])
3201 for k
, v
in list(resp
.items()):
3202 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
3205 # except ClientException as e:
3211 ###########################
3213 ###########################
3215 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
3216 @click.argument('name')
3217 @click.argument('uri')
3218 @click.option('--type',
3219 type=click
.Choice(['helm-chart', 'juju-bundle', 'osm']),
3221 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3222 @click.option('--description',
3224 help='human readable description')
3225 @click.option('--user',
3227 help='OSM repository: The username of the OSM repository')
3228 @click.option('--password',
3230 help='OSM repository: The password of the OSM repository')
3231 #@click.option('--wait',
3233 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3235 def repo_add(ctx
, **kwargs
):
3236 """adds a repo to OSM
3238 NAME: name of the repo
3239 URI: URI of the repo
3242 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
3244 repo
["url"] = repo
.pop("uri")
3245 if repo
["type"] in ['helm-chart', 'juju-bundle']:
3246 ctx
.obj
.repo
.create(repo
['name'], repo
)
3248 ctx
.obj
.osmrepo
.create(repo
['name'], repo
)
3249 # except ClientException as e:
3254 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
3255 @click.argument('name')
3256 @click.option('--newname', help='New name for the repo')
3257 @click.option('--uri', help='URI of the repo')
3258 @click.option('--description', help='human readable description')
3259 #@click.option('--wait',
3261 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3263 def repo_update(ctx
,
3268 """updates a repo in OSM
3270 NAME: name of the repo
3273 check_client_version(ctx
.obj
, ctx
.command
.name
)
3276 repo
['name'] = newname
3279 if description
: repo
['description'] = description
3281 ctx
.obj
.repo
.update(name
, repo
)
3283 ctx
.obj
.osmrepo
.update(name
, repo
)
3285 # except ClientException as e:
3290 @cli_osm.command(name
='repo-index', short_help
='Index a repository from a folder with artifacts')
3291 @click.option('--origin', default
='.', help='origin path where the artifacts are located')
3292 @click.option('--destination', default
='.', help='destination path where the index is deployed')
3294 def repo_index(ctx
, origin
, destination
):
3295 """Index a repository
3297 NAME: name or ID of the repo to be deleted
3299 check_client_version(ctx
.obj
, ctx
.command
.name
)
3300 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
3303 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
3304 @click.argument('name')
3305 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3306 #@click.option('--wait',
3308 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3310 def repo_delete(ctx
, name
, force
):
3313 NAME: name or ID of the repo to be deleted
3317 ctx
.obj
.repo
.delete(name
, force
=force
)
3319 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
3320 # except ClientException as e:
3325 @cli_osm.command(name
='repo-list')
3326 @click.option('--filter', default
=None, multiple
=True,
3327 help='restricts the list to the repos matching the filter')
3328 @click.option('--literal', is_flag
=True,
3329 help='print literally, no pretty table')
3331 def repo_list(ctx
, filter, literal
):
3332 """list all repos"""
3335 check_client_version(ctx
.obj
, ctx
.command
.name
)
3337 filter='&'.join(filter)
3338 resp
= ctx
.obj
.repo
.list(filter)
3339 resp
+= ctx
.obj
.osmrepo
.list(filter)
3341 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3343 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3345 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3346 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description') or '',40)])
3350 # except ClientException as e:
3355 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
3356 @click.argument('name')
3357 @click.option('--literal', is_flag
=True,
3358 help='print literally, no pretty table')
3360 def repo_show(ctx
, name
, literal
):
3361 """shows the details of a repo
3363 NAME: name or ID of the repo
3366 resp
= ctx
.obj
.repo
.get(name
)
3368 resp
= ctx
.obj
.osmrepo
.get(name
)
3372 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3374 table
= PrettyTable(['key', 'attribute'])
3376 for k
, v
in list(resp
.items()):
3377 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3381 # except ClientException as e:
3387 ####################
3388 # Project mgmt operations
3389 ####################
3391 @cli_osm.command(name
='project-create', short_help
='creates a new project')
3392 @click.argument('name')
3393 #@click.option('--description',
3394 # default='no description',
3395 # help='human readable description')
3396 @click.option('--domain-name', 'domain_name',
3398 help='assign to a domain')
3399 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3400 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3401 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3403 def project_create(ctx
, name
, domain_name
, quotas
):
3404 """Creates a new project
3406 NAME: name of the project
3407 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3408 QUOTAS: set quotas for the project
3411 project
= {'name': name
}
3413 project
['domain_name'] = domain_name
3414 quotas_dict
= _process_project_quotas(quotas
)
3416 project
['quotas'] = quotas_dict
3419 check_client_version(ctx
.obj
, ctx
.command
.name
)
3420 ctx
.obj
.project
.create(name
, project
)
3421 # except ClientException as e:
3426 def _process_project_quotas(quota_list
):
3431 for quota
in quota_list
:
3432 for single_quota
in quota
.split(","):
3433 k
, v
= single_quota
.split("=")
3434 quotas_dict
[k
] = None if v
in ('None', 'null', '') else int(v
)
3435 except (ValueError, TypeError):
3436 raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3440 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3441 @click.argument('name')
3442 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3444 def project_delete(ctx
, name
):
3445 """deletes a project
3447 NAME: name or ID of the project to be deleted
3451 check_client_version(ctx
.obj
, ctx
.command
.name
)
3452 ctx
.obj
.project
.delete(name
)
3453 # except ClientException as e:
3458 @cli_osm.command(name
='project-list', short_help
='list all projects')
3459 @click.option('--filter', default
=None, multiple
=True,
3460 help='restricts the list to the projects matching the filter')
3462 def project_list(ctx
, filter):
3463 """list all projects"""
3466 check_client_version(ctx
.obj
, ctx
.command
.name
)
3468 filter='&'.join(filter)
3469 resp
= ctx
.obj
.project
.list(filter)
3470 # except ClientException as e:
3473 table
= PrettyTable(['name', 'id'])
3475 table
.add_row([proj
['name'], proj
['_id']])
3480 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3481 @click.argument('name')
3483 def project_show(ctx
, name
):
3484 """shows the details of a project
3486 NAME: name or ID of the project
3490 check_client_version(ctx
.obj
, ctx
.command
.name
)
3491 resp
= ctx
.obj
.project
.get(name
)
3492 # except ClientException as e:
3496 table
= PrettyTable(['key', 'attribute'])
3497 for k
, v
in resp
.items():
3498 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3503 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3504 @click.argument('project')
3505 @click.option('--name', default
=None,
3506 help='new name for the project')
3507 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3508 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3509 "(use empty to reset quota to default")
3511 def project_update(ctx
, project
, name
, quotas
):
3513 Update a project name
3516 :param project: id or name of the project to modify
3517 :param name: new name for the project
3518 :param quotas: change quotas of the project
3522 project_changes
= {}
3524 project_changes
['name'] = name
3525 quotas_dict
= _process_project_quotas(quotas
)
3527 project_changes
['quotas'] = quotas_dict
3530 check_client_version(ctx
.obj
, ctx
.command
.name
)
3531 ctx
.obj
.project
.update(project
, project_changes
)
3532 # except ClientException as e:
3536 ####################
3537 # User mgmt operations
3538 ####################
3540 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3541 @click.argument('username')
3542 @click.option('--password',
3545 confirmation_prompt
=True,
3546 help='user password')
3547 @click.option('--projects',
3548 # prompt="Comma separate list of projects",
3550 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3551 help='list of project ids that the user belongs to')
3552 @click.option('--project-role-mappings', 'project_role_mappings',
3553 default
=None, multiple
=True,
3554 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3555 @click.option('--domain-name', 'domain_name',
3557 help='assign to a domain')
3559 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
3560 """Creates a new user
3563 USERNAME: name of the user
3564 PASSWORD: password of the user
3565 PROJECTS: projects assigned to user (internal only)
3566 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3567 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3571 user
['username'] = username
3572 user
['password'] = password
3573 user
['projects'] = projects
3574 user
['project_role_mappings'] = project_role_mappings
3576 user
['domain_name'] = domain_name
3579 check_client_version(ctx
.obj
, ctx
.command
.name
)
3580 ctx
.obj
.user
.create(username
, user
)
3581 # except ClientException as e:
3586 @cli_osm.command(name
='user-update', short_help
='updates user information')
3587 @click.argument('username')
3588 @click.option('--password',
3591 # confirmation_prompt=True,
3592 help='user password')
3593 @click.option('--set-username', 'set_username',
3595 help='change username')
3596 @click.option('--set-project', 'set_project',
3597 default
=None, multiple
=True,
3598 help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3599 @click.option('--remove-project', 'remove_project',
3600 default
=None, multiple
=True,
3601 help="removes project from user: 'project'")
3602 @click.option('--add-project-role', 'add_project_role',
3603 default
=None, multiple
=True,
3604 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3605 @click.option('--remove-project-role', 'remove_project_role',
3606 default
=None, multiple
=True,
3607 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3609 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3610 add_project_role
, remove_project_role
):
3611 """Update a user information
3614 USERNAME: name of the user
3615 PASSWORD: new password
3616 SET_USERNAME: new username
3617 SET_PROJECT: creating mappings for project/role(s)
3618 REMOVE_PROJECT: deleting mappings for project/role(s)
3619 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3620 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3624 user
['password'] = password
3625 user
['username'] = set_username
3626 user
['set-project'] = set_project
3627 user
['remove-project'] = remove_project
3628 user
['add-project-role'] = add_project_role
3629 user
['remove-project-role'] = remove_project_role
3632 check_client_version(ctx
.obj
, ctx
.command
.name
)
3633 ctx
.obj
.user
.update(username
, user
)
3634 # except ClientException as e:
3639 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3640 @click.argument('name')
3641 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3643 def user_delete(ctx
, name
):
3647 NAME: name or ID of the user to be deleted
3651 check_client_version(ctx
.obj
, ctx
.command
.name
)
3652 ctx
.obj
.user
.delete(name
)
3653 # except ClientException as e:
3658 @cli_osm.command(name
='user-list', short_help
='list all users')
3659 @click.option('--filter', default
=None, multiple
=True,
3660 help='restricts the list to the users matching the filter')
3662 def user_list(ctx
, filter):
3663 """list all users"""
3665 check_client_version(ctx
.obj
, ctx
.command
.name
)
3667 filter='&'.join(filter)
3668 resp
= ctx
.obj
.user
.list(filter)
3669 # except ClientException as e:
3672 table
= PrettyTable(['name', 'id'])
3674 table
.add_row([user
['username'], user
['_id']])
3679 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3680 @click.argument('name')
3682 def user_show(ctx
, name
):
3683 """shows the details of a user
3685 NAME: name or ID of the user
3689 check_client_version(ctx
.obj
, ctx
.command
.name
)
3690 resp
= ctx
.obj
.user
.get(name
)
3691 if 'password' in resp
:
3692 resp
['password']='********'
3693 # except ClientException as e:
3697 table
= PrettyTable(['key', 'attribute'])
3698 for k
, v
in resp
.items():
3699 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3704 ####################
3705 # Fault Management operations
3706 ####################
3708 @cli_osm.command(name
='ns-alarm-create')
3709 @click.argument('name')
3710 @click.option('--ns', prompt
=True, help='NS instance id or name')
3711 @click.option('--vnf', prompt
=True,
3712 help='VNF name (VNF member index as declared in the NSD)')
3713 @click.option('--vdu', prompt
=True,
3714 help='VDU name (VDU name as declared in the VNFD)')
3715 @click.option('--metric', prompt
=True,
3716 help='Name of the metric (e.g. cpu_utilization)')
3717 @click.option('--severity', default
='WARNING',
3718 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3719 @click.option('--threshold_value', prompt
=True,
3720 help='threshold value that, when crossed, an alarm is triggered')
3721 @click.option('--threshold_operator', prompt
=True,
3722 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3723 @click.option('--statistic', default
='AVERAGE',
3724 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3726 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3727 threshold_value
, threshold_operator
, statistic
):
3728 """creates a new alarm for a NS instance"""
3729 # TODO: Check how to validate threshold_value.
3730 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3733 ns_instance
= ctx
.obj
.ns
.get(ns
)
3735 alarm
['alarm_name'] = name
3736 alarm
['ns_id'] = ns_instance
['_id']
3737 alarm
['correlation_id'] = ns_instance
['_id']
3738 alarm
['vnf_member_index'] = vnf
3739 alarm
['vdu_name'] = vdu
3740 alarm
['metric_name'] = metric
3741 alarm
['severity'] = severity
3742 alarm
['threshold_value'] = int(threshold_value
)
3743 alarm
['operation'] = threshold_operator
3744 alarm
['statistic'] = statistic
3745 check_client_version(ctx
.obj
, ctx
.command
.name
)
3746 ctx
.obj
.ns
.create_alarm(alarm
)
3747 # except ClientException as e:
3752 #@cli_osm.command(name='ns-alarm-delete')
3753 #@click.argument('name')
3754 #@click.pass_context
3755 #def ns_alarm_delete(ctx, name):
3756 # """deletes an alarm
3758 # NAME: name of the alarm to be deleted
3761 # check_client_version(ctx.obj, ctx.command.name)
3762 # ctx.obj.ns.delete_alarm(name)
3763 # except ClientException as e:
3768 ####################
3769 # Performance Management operations
3770 ####################
3772 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3773 @click.option('--ns', prompt
=True, help='NS instance id or name')
3774 @click.option('--vnf', prompt
=True,
3775 help='VNF name (VNF member index as declared in the NSD)')
3776 @click.option('--vdu', prompt
=True,
3777 help='VDU name (VDU name as declared in the VNFD)')
3778 @click.option('--metric', prompt
=True,
3779 help='name of the metric (e.g. cpu_utilization)')
3780 #@click.option('--period', default='1w',
3781 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3782 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3784 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3785 """exports a metric to the internal OSM bus, which can be read by other apps"""
3786 # TODO: Check how to validate interval.
3787 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3790 ns_instance
= ctx
.obj
.ns
.get(ns
)
3792 metric_data
['ns_id'] = ns_instance
['_id']
3793 metric_data
['correlation_id'] = ns_instance
['_id']
3794 metric_data
['vnf_member_index'] = vnf
3795 metric_data
['vdu_name'] = vdu
3796 metric_data
['metric_name'] = metric
3797 metric_data
['collection_unit'] = 'WEEK'
3798 metric_data
['collection_period'] = 1
3799 check_client_version(ctx
.obj
, ctx
.command
.name
)
3801 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3805 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3806 time
.sleep(int(interval
))
3808 # except ClientException as e:
3813 ####################
3815 ####################
3817 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3819 def get_version(ctx
):
3820 """shows client and server versions"""
3822 check_client_version(ctx
.obj
, "version")
3823 print ("Server version: {}".format(ctx
.obj
.get_version()))
3824 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3825 # except ClientException as e:
3829 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3830 @click.argument('filename')
3831 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3832 help='the charm will not be compiled, it is assumed to already exist')
3834 def upload_package(ctx
, filename
, skip_charm_build
):
3835 """uploads a vnf package or ns package
3837 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3841 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3842 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3843 if fullclassname
!= 'osmclient.sol005.client.Client':
3844 ctx
.obj
.package
.wait_for_upload(filename
)
3845 # except ClientException as e:
3850 #@cli_osm.command(name='ns-scaling-show')
3851 #@click.argument('ns_name')
3852 #@click.pass_context
3853 #def show_ns_scaling(ctx, ns_name):
3854 # """shows the status of a NS scaling operation
3856 # NS_NAME: name of the NS instance being scaled
3859 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3860 # resp = ctx.obj.ns.list()
3861 # except ClientException as e:
3865 # table = PrettyTable(
3868 # 'operational status',
3873 # if ns_name == ns['name']:
3874 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3875 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3876 # for record in scaling_records:
3877 # if 'instance' in record:
3878 # instances = record['instance']
3879 # for inst in instances:
3881 # [record['scaling-group-name-ref'],
3882 # inst['instance-id'],
3883 # inst['op-status'],
3884 # time.strftime('%Y-%m-%d %H:%M:%S',
3886 # inst['create-time'])),
3892 #@cli_osm.command(name='ns-scale')
3893 #@click.argument('ns_name')
3894 #@click.option('--ns_scale_group', prompt=True)
3895 #@click.option('--index', prompt=True)
3896 #@click.option('--wait',
3900 # help='do not return the control immediately, but keep it \
3901 # until the operation is completed, or timeout')
3902 #@click.pass_context
3903 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3906 # NS_NAME: name of the NS instance to be scaled
3909 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3910 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3911 # except ClientException as e:
3916 #@cli_osm.command(name='config-agent-list')
3917 #@click.pass_context
3918 #def config_agent_list(ctx):
3919 # """list config agents"""
3921 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3922 # except ClientException as e:
3925 # table = PrettyTable(['name', 'account-type', 'details'])
3926 # for account in ctx.obj.vca.list():
3929 # account['account-type'],
3935 #@cli_osm.command(name='config-agent-delete')
3936 #@click.argument('name')
3937 #@click.pass_context
3938 #def config_agent_delete(ctx, name):
3939 # """deletes a config agent
3941 # NAME: name of the config agent to be deleted
3944 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3945 # ctx.obj.vca.delete(name)
3946 # except ClientException as e:
3951 #@cli_osm.command(name='config-agent-add')
3952 #@click.option('--name',
3954 #@click.option('--account_type',
3956 #@click.option('--server',
3958 #@click.option('--user',
3960 #@click.option('--secret',
3963 # confirmation_prompt=True)
3964 #@click.pass_context
3965 #def config_agent_add(ctx, name, account_type, server, user, secret):
3966 # """adds a config agent"""
3968 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3969 # ctx.obj.vca.create(name, account_type, server, user, secret)
3970 # except ClientException as e:
3975 #@cli_osm.command(name='ro-dump')
3976 #@click.pass_context
3978 # """shows RO agent information"""
3979 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3980 # resp = ctx.obj.vim.get_resource_orchestrator()
3981 # table = PrettyTable(['key', 'attribute'])
3982 # for k, v in list(resp.items()):
3983 # table.add_row([k, json.dumps(v, indent=2)])
3988 #@cli_osm.command(name='vcs-list')
3989 #@click.pass_context
3991 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3992 # resp = ctx.obj.utils.get_vcs_info()
3993 # table = PrettyTable(['component name', 'state'])
3994 # for component in resp:
3995 # table.add_row([component['component_name'], component['state']])
4000 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
4001 @click.argument('ns_name')
4002 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
4003 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
4004 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
4005 @click.option('--vdu_count', default
=None, type=int, help='number of vdu instance of this vdu_id')
4006 @click.option('--action_name', prompt
=True, help='action name')
4007 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
4008 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
4009 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4010 @click.option('--wait',
4014 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4027 """executes an action/primitive over a NS instance
4029 NS_NAME: name or ID of the NS instance
4033 check_client_version(ctx
.obj
, ctx
.command
.name
)
4036 op_data
['member_vnf_index'] = vnf_name
4038 op_data
['kdu_name'] = kdu_name
4040 op_data
['vdu_id'] = vdu_id
4041 if vdu_count
is not None:
4042 op_data
['vdu_count_index'] = vdu_count
4044 op_data
['timeout_ns_action'] = timeout
4045 op_data
['primitive'] = action_name
4047 with
open(params_file
, 'r') as pf
:
4050 op_data
['primitive_params'] = yaml
.safe_load(params
)
4052 op_data
['primitive_params'] = {}
4053 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
4055 # except ClientException as e:
4060 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
4061 @click.argument('ns_name')
4062 @click.argument('vnf_name')
4063 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
4064 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
4065 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
4066 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4067 @click.option('--wait', required
=False, default
=False, is_flag
=True,
4068 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4079 Executes a VNF scale (adding/removing VDUs)
4082 NS_NAME: name or ID of the NS instance.
4083 VNF_NAME: member-vnf-index in the NS to be scaled.
4087 check_client_version(ctx
.obj
, ctx
.command
.name
)
4088 if not scale_in
and not scale_out
:
4090 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
)
4091 # except ClientException as e:
4096 ##############################
4097 # Role Management Operations #
4098 ##############################
4100 @cli_osm.command(name
='role-create', short_help
='creates a new role')
4101 @click.argument('name')
4102 @click.option('--permissions',
4104 help='role permissions using a dictionary')
4106 def role_create(ctx
, name
, permissions
):
4111 NAME: Name or ID of the role.
4112 DEFINITION: Definition of grant/denial of access to resources.
4116 check_client_version(ctx
.obj
, ctx
.command
.name
)
4117 ctx
.obj
.role
.create(name
, permissions
)
4118 # except ClientException as e:
4123 @cli_osm.command(name
='role-update', short_help
='updates a role')
4124 @click.argument('name')
4125 @click.option('--set-name',
4127 help='change name of rle')
4128 # @click.option('--permissions',
4130 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4131 @click.option('--add',
4133 help='yaml format dictionary with permission: True/False to access grant/denial')
4134 @click.option('--remove',
4136 help='yaml format list to remove a permission')
4138 def role_update(ctx
, name
, set_name
, add
, remove
):
4143 NAME: Name or ID of the role.
4144 DEFINITION: Definition overwrites the old definition.
4145 ADD: Grant/denial of access to resource to add.
4146 REMOVE: Grant/denial of access to resource to remove.
4150 check_client_version(ctx
.obj
, ctx
.command
.name
)
4151 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
4152 # except ClientException as e:
4157 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
4158 @click.argument('name')
4159 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4161 def role_delete(ctx
, name
):
4166 NAME: Name or ID of the role.
4170 check_client_version(ctx
.obj
, ctx
.command
.name
)
4171 ctx
.obj
.role
.delete(name
)
4172 # except ClientException as e:
4177 @cli_osm.command(name
='role-list', short_help
='list all roles')
4178 @click.option('--filter', default
=None, multiple
=True,
4179 help='restricts the list to the projects matching the filter')
4181 def role_list(ctx
, filter):
4187 check_client_version(ctx
.obj
, ctx
.command
.name
)
4189 filter='&'.join(filter)
4190 resp
= ctx
.obj
.role
.list(filter)
4191 # except ClientException as e:
4194 table
= PrettyTable(['name', 'id'])
4196 table
.add_row([role
['name'], role
['_id']])
4201 @cli_osm.command(name
='role-show', short_help
='show specific role')
4202 @click.argument('name')
4204 def role_show(ctx
, name
):
4206 Shows the details of a role.
4209 NAME: Name or ID of the role.
4213 check_client_version(ctx
.obj
, ctx
.command
.name
)
4214 resp
= ctx
.obj
.role
.get(name
)
4215 # except ClientException as e:
4219 table
= PrettyTable(['key', 'attribute'])
4220 for k
, v
in resp
.items():
4221 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4226 @cli_osm.command(name
='package-create',
4227 short_help
='Create empty NS package structure')
4228 @click.argument('package-type')
4229 @click.argument('package-name')
4230 @click.option('--base-directory',
4232 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4233 @click.option('--image',
4234 default
="image-name",
4235 help='(VNF) Set the name of the vdu image. Default "image-name"')
4236 @click.option('--vdus',
4238 help='(VNF) Set the number of vdus in a VNF. Default 1')
4239 @click.option('--vcpu',
4241 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4242 @click.option('--memory',
4244 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4245 @click.option('--storage',
4247 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4248 @click.option('--interfaces',
4250 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4251 @click.option('--vendor',
4253 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4254 @click.option('--override',
4257 help='(NS/VNF/NST) Flag for overriding the package if exists.')
4258 @click.option('--detailed',
4261 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4262 @click.option('--netslice-subnets',
4264 help='(NST) Number of netslice subnets. Default 1')
4265 @click.option('--netslice-vlds',
4267 help='(NST) Number of netslice vlds. Default 1')
4269 "--old", default
=False, is_flag
=True, help="Support flag for old versions of the OSM IM (OSM<9)"
4272 def package_create(ctx
,
4289 Creates an OSM NS, VNF, NST package
4292 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4293 PACKAGE_NAME: Name of the package to create the folder with the content.
4298 check_client_version(ctx
.obj
, ctx
.command
.name
)
4299 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
4300 resp
= ctx
.obj
.package_tool
.create(package_type
,
4309 interfaces
=interfaces
,
4312 netslice_subnets
=netslice_subnets
,
4313 netslice_vlds
=netslice_vlds
,
4316 # except ClientException as inst:
4317 # print("ERROR: {}".format(inst))
4320 @cli_osm.command(name
='package-validate',
4321 short_help
='Validate descriptors given a base directory')
4322 @click.argument('base-directory',
4325 @click.option('--recursive/--no-recursive',
4327 help='The activated recursive option will validate the yaml files'
4328 ' within the indicated directory and in its subdirectories')
4329 @click.option('--old',
4332 help='Validates also the descriptors using the previous OSM format (pre SOL006)')
4334 def package_validate(ctx
,
4339 Validate descriptors given a base directory.
4342 BASE_DIRECTORY: Base folder for NS, VNF or NST package.
4346 check_client_version(ctx
.obj
, ctx
.command
.name
)
4347 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
, old
)
4348 table
= PrettyTable()
4349 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
4350 # Print the dictionary generated by the validation function
4351 for result
in results
:
4352 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
4353 table
.sortby
= "VALID"
4354 table
.align
["PATH"] = "l"
4355 table
.align
["TYPE"] = "l"
4356 table
.align
["ERROR"] = "l"
4358 # except ClientException as inst:
4359 # print("ERROR: {}".format(inst))
4362 @cli_osm.command(name
='package-translate',
4363 short_help
='Translate descriptors given a base directory')
4364 @click.argument('base-directory',
4367 @click.option('--recursive/--no-recursive',
4369 help='The activated recursive option will translate the yaml files'
4370 ' within the indicated directory and in its subdirectories')
4371 @click.option('--dryrun',
4374 help='Do not translate yet, only make a dry-run to test translation')
4376 def package_translate(ctx
,
4381 Translate descriptors given a base directory.
4384 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4387 check_client_version(ctx
.obj
, ctx
.command
.name
)
4388 results
= ctx
.obj
.package_tool
.translate(base_directory
, recursive
, dryrun
)
4389 table
= PrettyTable()
4390 table
.field_names
= ["CURRENT TYPE", "NEW TYPE", "PATH", "VALID", "TRANSLATED", "ERROR"]
4391 # Print the dictionary generated by the validation function
4392 for result
in results
:
4393 table
.add_row([result
["current type"], result
["new type"], result
["path"], result
["valid"], result
["translated"], result
["error"]])
4394 table
.sortby
= "TRANSLATED"
4395 table
.align
["PATH"] = "l"
4396 table
.align
["TYPE"] = "l"
4397 table
.align
["ERROR"] = "l"
4399 # except ClientException as inst:
4400 # print("ERROR: {}".format(inst))
4403 @cli_osm.command(name
='package-build',
4404 short_help
='Build the tar.gz of the package')
4405 @click.argument('package-folder')
4406 @click.option('--skip-validation',
4409 help='skip package validation')
4410 @click.option('--skip-charm-build', default
=False, is_flag
=True,
4411 help='the charm will not be compiled, it is assumed to already exist')
4413 def package_build(ctx
,
4418 Build the package NS, VNF given the package_folder.
4421 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4425 check_client_version(ctx
.obj
, ctx
.command
.name
)
4426 results
= ctx
.obj
.package_tool
.build(package_folder
,
4427 skip_validation
=skip_validation
,
4428 skip_charm_build
=skip_charm_build
)
4430 # except ClientException as inst:
4431 # print("ERROR: {}".format(inst))
4434 @cli_osm.command(name
='descriptor-translate',
4435 short_help
='Translate input descriptor file from Rel EIGHT OSM descriptors to SOL006 and prints in standard output')
4436 @click.argument('descriptor-file',
4439 def descriptor_translate(ctx
,
4442 Translate input descriptor.
4445 DESCRIPTOR_FILE: Descriptor file for NS, VNF or Network Slice.
4448 check_client_version(ctx
.obj
, ctx
.command
.name
)
4449 result
= ctx
.obj
.package_tool
.descriptor_translate(descriptor_file
)
4457 except pycurl
.error
as exc
:
4459 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4460 except ClientException
as exc
:
4461 print("ERROR: {}".format(exc
))
4462 except (FileNotFoundError
, PermissionError
) as exc
:
4463 print("Cannot open file: {}".format(exc
))
4464 except yaml
.YAMLError
as exc
:
4465 print("Invalid YAML format: {}".format(exc
))
4467 # TODO capture other controlled exceptions here
4468 # TODO remove the ClientException captures from all places, unless they do something different
4471 if __name__
== '__main__':