1 # Copyright 2017-2018 Sandvine
2 # Copyright 2018 Telefonica
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
22 from osmclient
import client
23 from osmclient
.common
.exceptions
import ClientException
, NotFound
24 from prettytable
import PrettyTable
33 from datetime
import datetime
38 CONTEXT_SETTINGS
= dict(help_option_names
=['-h', '--help'], max_content_width
=160)
40 def wrap_text(text
, width
):
41 wrapper
= textwrap
.TextWrapper(width
=width
)
42 lines
= text
.splitlines()
43 return "\n".join(map(wrapper
.fill
, lines
))
46 def trunc_text(text
, length
):
47 if len(text
) > length
:
48 return text
[:(length
- 3)] + '...'
53 def check_client_version(obj
, what
, version
='sol005'):
55 Checks the version of the client object and raises error if it not the expected.
57 :param obj: the client object
58 :what: the function or command under evaluation (used when an error is raised)
60 :raises ClientError: if the specified version does not match the client version
63 fullclassname
= obj
.__module
__ + "." + obj
.__class
__.__name
__
64 message
= 'The following commands or options are only supported with the option "--sol005": {}'.format(what
)
66 message
= 'The following commands or options are not supported when using option "--sol005": {}'.format(what
)
67 if fullclassname
!= 'osmclient.{}.client.Client'.format(version
):
68 raise ClientException(message
)
72 @click.group(context_settings
=dict(help_option_names
=['-h', '--help'], max_content_width
=160))
73 @click.option('--hostname',
75 envvar
='OSM_HOSTNAME',
76 help='hostname of server. ' +
77 'Also can set OSM_HOSTNAME in environment')
78 #@click.option('--sol005/--no-sol005',
80 # envvar='OSM_SOL005',
81 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
82 # 'Also can set OSM_SOL005 in environment')
83 @click.option('--user',
86 help='user (defaults to admin). ' +
87 'Also can set OSM_USER in environment')
88 @click.option('--password',
90 envvar
='OSM_PASSWORD',
91 help='password (defaults to admin). ' +
92 'Also can set OSM_PASSWORD in environment')
93 @click.option('--project',
96 help='project (defaults to admin). ' +
97 'Also can set OSM_PROJECT in environment')
98 @click.option('-v', '--verbose', count
=True,
99 help='increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)')
100 @click.option('--all-projects',
103 help='include all projects')
104 @click.option('--public/--no-public', default
=None,
105 help='flag for public items (packages, instances, VIM accounts, etc.)')
106 @click.option('--project-domain-name', 'project_domain_name',
108 envvar
='OSM_PROJECT_DOMAIN_NAME',
109 help='project domain name for keystone authentication (default to None). ' +
110 'Also can set OSM_PROJECT_DOMAIN_NAME in environment')
111 @click.option('--user-domain-name', 'user_domain_name',
113 envvar
='OSM_USER_DOMAIN_NAME',
114 help='user domain name for keystone authentication (default to None). ' +
115 'Also can set OSM_USER_DOMAIN_NAME in environment')
116 #@click.option('--so-port',
118 # envvar='OSM_SO_PORT',
119 # help='hostname of server. ' +
120 # 'Also can set OSM_SO_PORT in environment')
121 #@click.option('--so-project',
123 # envvar='OSM_SO_PROJECT',
124 # help='Project Name in SO. ' +
125 # 'Also can set OSM_SO_PROJECT in environment')
126 #@click.option('--ro-hostname',
128 # envvar='OSM_RO_HOSTNAME',
129 # help='hostname of RO server. ' +
130 # 'Also can set OSM_RO_HOSTNAME in environment')
131 #@click.option('--ro-port',
133 # envvar='OSM_RO_PORT',
134 # help='hostname of RO server. ' +
135 # 'Also can set OSM_RO_PORT in environment')
137 def cli_osm(ctx
, **kwargs
):
139 hostname
= kwargs
.pop("hostname", None)
142 "either hostname option or OSM_HOSTNAME " +
143 "environment variable needs to be specified"))
146 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
147 # if so_port is not None:
148 # kwargs['so_port']=so_port
149 # if so_project is not None:
150 # kwargs['so_project']=so_project
151 # if ro_hostname is not None:
152 # kwargs['ro_host']=ro_hostname
153 # if ro_port is not None:
154 # kwargs['ro_port']=ro_port
155 sol005
= os
.getenv('OSM_SOL005', True)
156 # if user is not None:
157 # kwargs['user']=user
158 # if password is not None:
159 # kwargs['password']=password
160 # if project is not None:
161 # kwargs['project']=project
163 # kwargs['all_projects']=all_projects
164 # if public is not None:
165 # kwargs['public']=public
166 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
167 logger
= logging
.getLogger('osmclient')
174 @cli_osm.command(name
='ns-list', short_help
='list all NS instances')
175 @click.option('--filter', default
=None, multiple
=True,
176 help='restricts the list to the NS instances matching the filter.')
177 @click.option('--long', is_flag
=True,
178 help='get more details of the NS (project, vim, deployment status, configuration status.')
180 def ns_list(ctx
, filter, long):
181 """list all NS instances
185 --filter filterExpr Restricts the list to the NS instances matching the filter
188 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
189 concatenated using the "&" character:
192 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
193 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
194 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
196 value := scalar value
200 * zero or more occurrences
201 ? zero or one occurrence
202 [] grouping of expressions to be used with ? and *
203 "" quotation marks for marking string constants
207 "AttrName" is the name of one attribute in the data type that defines the representation
208 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
209 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
210 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
211 entries, it means that the operator "op" is applied to the attribute addressed by the last
212 <attrName> entry included in the concatenation. All simple filter expressions are combined
213 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
214 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
215 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
216 prefix". If an attribute referenced in an expression is an array, an object that contains a
217 corresponding array shall be considered to match the expression if any of the elements in the
218 array matches all expressions that have the same attribute prefix.
222 --filter admin-status=ENABLED
223 --filter nsd-ref=<NSD_NAME>
224 --filter nsd.vendor=<VENDOR>
225 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
226 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
228 def summarize_deployment_status(status_dict
):
235 net_list
= status_dict
.get('nets',[])
238 if net
['status'] not in status_nets
:
239 status_nets
[net
['status']] = 1
241 status_nets
[net
['status']] +=1
243 for k
,v
in status_nets
.items():
244 message
+= "{}:{},".format(k
,v
)
245 message
+= "TOTAL:{}".format(n_nets
)
246 summary
+= "{}".format(message
)
251 vnf_list
= status_dict
['vnfs']
253 member_vnf_index
= vnf
['member_vnf_index']
254 if member_vnf_index
not in status_vnfs
:
255 status_vnfs
[member_vnf_index
] = {}
256 for vm
in vnf
['vms']:
258 if vm
['status'] not in status_vms
:
259 status_vms
[vm
['status']] = 1
261 status_vms
[vm
['status']] +=1
262 if vm
['status'] not in status_vnfs
[member_vnf_index
]:
263 status_vnfs
[member_vnf_index
][vm
['status']] = 1
265 status_vnfs
[member_vnf_index
][vm
['status']] += 1
267 for k
,v
in status_vms
.items():
268 message
+= "{}:{},".format(k
,v
)
269 message
+= "TOTAL:{}".format(n_vms
)
270 summary
+= "\n{}".format(message
)
272 for k
,v
in status_vnfs
.items():
274 message
= "\n {} VMs: ".format(k
)
275 for k2
,v2
in v
.items():
276 message
+= "{}:{},".format(k2
,v2
)
278 message
+= "TOTAL:{}".format(total
)
282 def summarize_config_status(ee_list
):
290 if ee
['elementType'] not in status_ee
:
291 status_ee
[ee
['elementType']] = {}
292 status_ee
[ee
['elementType']][ee
['status']] = 1
294 if ee
['status'] in status_ee
[ee
['elementType']]:
295 status_ee
[ee
['elementType']][ee
['status']] += 1
297 status_ee
[ee
['elementType']][ee
['status']] = 1
298 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
299 if elementType
in status_ee
:
302 for k
,v
in status_ee
[elementType
].items():
303 message
+= "{}:{},".format(k
,v
)
305 message
+= "TOTAL:{}\n".format(total
)
306 summary
+= "{}: {}".format(elementType
, message
)
307 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
312 check_client_version(ctx
.obj
, '--filter')
313 filter='&'.join(filter)
314 resp
= ctx
.obj
.ns
.list(filter)
316 resp
= ctx
.obj
.ns
.list()
328 'configuration status'])
329 project_list
= ctx
.obj
.project
.list()
330 vim_list
= ctx
.obj
.vim
.list()
340 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
341 if fullclassname
== 'osmclient.sol005.client.Client':
343 logger
.debug('NS info: {}'.format(nsr
))
344 nsr_name
= nsr
['name']
346 date
= datetime
.fromtimestamp(nsr
['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
347 ns_state
= nsr
.get('nsState', nsr
['_admin']['nsState'])
349 deployment_status
= summarize_deployment_status(nsr
.get('deploymentStatus'))
350 config_status
= summarize_config_status(nsr
.get('configurationStatus'))
351 project_id
= nsr
.get('_admin').get('projects_read')[0]
353 for p
in project_list
:
354 if p
['_id'] == project_id
:
355 project_name
= p
['name']
357 #project = '{} ({})'.format(project_name, project_id)
358 project
= project_name
359 vim_id
= nsr
.get('datacenter')
362 if v
['uuid'] == vim_id
:
365 #vim = '{} ({})'.format(vim_name, vim_id)
367 if 'currentOperation' in nsr
:
368 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
370 current_operation
= "{} ({})".format(nsr
['_admin'].get('current-operation','-'), nsr
['_admin']['nslcmop'])
371 error_details
= "N/A"
372 if ns_state
== "BROKEN" or ns_state
== "DEGRADED" or \
373 ('currentOperation' not in nsr
and nsr
.get('errorDescription')):
374 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'], nsr
['errorDetail'])
376 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
377 nsr
= nsopdata
['nsr:nsr']
378 nsr_name
= nsr
['name-ref']
379 nsr_id
= nsr
['ns-instance-config-ref']
382 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
383 ns_state
= deployment_status
384 config_status
= nsr
.get('config-status', 'Not found')
385 current_operation
= "Unknown"
386 error_details
= nsr
.get('detailed-status', 'Not found')
387 if config_status
== "config_not_needed":
388 config_status
= "configured (no charms)"
397 wrap_text(text
=error_details
,width
=40),
409 wrap_text(text
=error_details
,width
=40)])
412 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
413 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
415 def nsd_list(ctx
, filter, long):
418 check_client_version(ctx
.obj
, '--filter')
419 filter='&'.join(filter)
420 resp
= ctx
.obj
.nsd
.list(filter)
422 resp
= ctx
.obj
.nsd
.list()
423 # print(yaml.safe_dump(resp))
424 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
425 if fullclassname
== 'osmclient.sol005.client.Client':
427 table
= PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state',
428 'usage state', 'date', 'last update'])
430 table
= PrettyTable(['nsd name', 'id'])
432 name
= nsd
.get('name','-')
434 onb_state
= nsd
['_admin'].get('onboardingState','-')
435 op_state
= nsd
['_admin'].get('operationalState','-')
436 usage_state
= nsd
['_admin'].get('usageState','-')
437 date
= datetime
.fromtimestamp(nsd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
438 last_update
= datetime
.fromtimestamp(nsd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
439 table
.add_row([name
, nsd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
441 table
.add_row([name
, nsd
['_id']])
443 table
= PrettyTable(['nsd name', 'id'])
445 table
.add_row([nsd
['name'], nsd
['id']])
450 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
451 @click.option('--filter', default
=None, multiple
=True,
452 help='restricts the list to the NSD/NSpkg matching the filter')
453 @click.option('--long', is_flag
=True, help='get more details')
455 def nsd_list1(ctx
, filter, long):
456 """list all NSD/NS pkg in the system"""
458 nsd_list(ctx
, filter, long)
461 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
462 @click.option('--filter', default
=None, multiple
=True,
463 help='restricts the list to the NSD/NSpkg matching the filter')
464 @click.option('--long', is_flag
=True, help='get more details')
466 def nsd_list2(ctx
, filter, long):
467 """list all NS packages"""
469 nsd_list(ctx
, filter, long)
472 def pkg_repo_list(ctx
, pkgtype
, filter, repo
, long):
474 filter='&'.join(filter)
475 resp
= ctx
.obj
.osmrepo
.pkg_list(pkgtype
, filter, repo
)
477 table
= PrettyTable(['nfpkg name', 'vendor', 'version', 'latest', 'description', 'repository'])
479 table
= PrettyTable(['nfpkg name', 'repository'])
481 name
= vnfd
.get('name', '-')
482 repository
= vnfd
.get('repository')
484 vendor
= vnfd
.get('vendor')
485 version
= vnfd
.get('version')
486 description
= vnfd
.get('description')
487 latest
= vnfd
.get('latest')
488 table
.add_row([name
, vendor
, version
, latest
, description
, repository
])
490 table
.add_row([name
, repository
])
494 def vnfd_list(ctx
, nf_type
, filter, long):
497 check_client_version(ctx
.obj
, '--nf_type')
499 check_client_version(ctx
.obj
, '--filter')
501 filter='&'.join(filter)
504 nf_filter
= "_admin.type=vnfd"
505 elif nf_type
== "pnf":
506 nf_filter
= "_admin.type=pnfd"
507 elif nf_type
== "hnf":
508 nf_filter
= "_admin.type=hnfd"
510 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
512 filter = '{}&{}'.format(nf_filter
, filter)
516 resp
= ctx
.obj
.vnfd
.list(filter)
518 resp
= ctx
.obj
.vnfd
.list()
519 # print(yaml.safe_dump(resp))
520 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
521 if fullclassname
== 'osmclient.sol005.client.Client':
523 table
= PrettyTable(['nfpkg name', 'id', 'vendor', 'version', 'onboarding state', 'operational state',
524 'usage state', 'date', 'last update'])
526 table
= PrettyTable(['nfpkg name', 'id'])
528 name
= vnfd
['name'] if 'name' in vnfd
else '-'
530 onb_state
= vnfd
['_admin'].get('onboardingState','-')
531 op_state
= vnfd
['_admin'].get('operationalState','-')
532 vendor
= vnfd
.get('vendor')
533 version
= vnfd
.get('version')
534 usage_state
= vnfd
['_admin'].get('usageState','-')
535 date
= datetime
.fromtimestamp(vnfd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
536 last_update
= datetime
.fromtimestamp(vnfd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
537 table
.add_row([name
, vnfd
['_id'], vendor
, version
, onb_state
, op_state
, usage_state
, date
, last_update
])
539 table
.add_row([name
, vnfd
['_id']])
541 table
= PrettyTable(['nfpkg name', 'id'])
543 table
.add_row([vnfd
['name'], vnfd
['id']])
548 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
549 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
550 @click.option('--filter', default
=None, multiple
=True,
551 help='restricts the list to the NF pkg matching the filter')
552 @click.option('--long', is_flag
=True, help='get more details')
554 def vnfd_list1(ctx
, nf_type
, filter, long):
555 """list all xNF packages (VNF, HNF, PNF)"""
557 vnfd_list(ctx
, nf_type
, filter, long)
560 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
561 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
562 @click.option('--filter', default
=None, multiple
=True,
563 help='restricts the list to the NFpkg matching the filter')
564 @click.option('--long', is_flag
=True, help='get more details')
566 def vnfd_list2(ctx
, nf_type
, filter, long):
567 """list all xNF packages (VNF, HNF, PNF)"""
569 vnfd_list(ctx
, nf_type
, filter, long)
571 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
572 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
573 @click.option('--filter', default
=None, multiple
=True,
574 help='restricts the list to the NFpkg matching the filter')
575 @click.option('--long', is_flag
=True, help='get more details')
577 def nfpkg_list(ctx
, nf_type
, filter, long):
578 """list all xNF packages (VNF, HNF, PNF)"""
581 check_client_version(ctx
.obj
, ctx
.command
.name
)
582 vnfd_list(ctx
, nf_type
, filter, long)
583 # except ClientException as e:
587 @cli_osm.command(name
='vnfpkg-repo-list', short_help
='list all xNF from OSM repositories')
588 @click.option('--filter', default
=None, multiple
=True,
589 help='restricts the list to the NFpkg matching the filter')
590 @click.option('--repo', default
=None,
591 help='restricts the list to a particular OSM repository')
592 @click.option('--long', is_flag
=True, help='get more details')
594 def nfpkg_repo_list1(ctx
, filter, repo
, long):
595 """list xNF packages from OSM repositories"""
597 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
599 @cli_osm.command(name
='nfpkg-repo-list', short_help
='list all xNF from OSM repositories')
600 @click.option('--filter', default
=None, multiple
=True,
601 help='restricts the list to the NFpkg matching the filter')
602 @click.option('--repo', default
=None,
603 help='restricts the list to a particular OSM repository')
604 @click.option('--long', is_flag
=True, help='get more details')
606 def nfpkg_repo_list2(ctx
, filter, repo
, long):
607 """list xNF packages from OSM repositories"""
609 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
611 def vnf_list(ctx
, ns
, filter, long):
615 check_client_version(ctx
.obj
, '--ns')
617 filter='&'.join(filter)
618 check_client_version(ctx
.obj
, '--filter')
619 resp
= ctx
.obj
.vnf
.list(ns
, filter)
621 resp
= ctx
.obj
.vnf
.list()
622 # except ClientException as e:
625 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
626 if fullclassname
== 'osmclient.sol005.client.Client':
627 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
628 'vnfd name', 'vim account id', 'ip address']
630 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
631 'vnfd name', 'vim account id', 'ip address',
632 'date', 'last update']
633 table
= PrettyTable(field_names
)
635 name
= vnfr
['name'] if 'name' in vnfr
else '-'
636 new_row
= [vnfr
['_id'], name
, vnfr
['nsr-id-ref'],
637 vnfr
['member-vnf-index-ref'], vnfr
['vnfd-ref'],
638 vnfr
['vim-account-id'], vnfr
['ip-address']]
640 date
= datetime
.fromtimestamp(vnfr
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
641 last_update
= datetime
.fromtimestamp(vnfr
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
642 new_row
.extend([date
, last_update
])
643 table
.add_row(new_row
)
648 'operational status',
651 if 'mgmt-interface' not in vnfr
:
652 vnfr
['mgmt-interface'] = {}
653 vnfr
['mgmt-interface']['ip-address'] = None
657 vnfr
['operational-status'],
658 vnfr
['config-status']])
663 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
664 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
665 @click.option('--filter', default
=None, multiple
=True,
666 help='restricts the list to the NF instances matching the filter.')
667 @click.option('--long', is_flag
=True, help='get more details')
669 def vnf_list1(ctx
, ns
, filter, long):
670 """list all NF instances"""
672 vnf_list(ctx
, ns
, filter, long)
674 @cli_osm.command(name
='nsd-repo-list', short_help
='list all NS from OSM repositories')
675 @click.option('--filter', default
=None, multiple
=True,
676 help='restricts the list to the NS matching the filter')
677 @click.option('--repo', default
=None,
678 help='restricts the list to a particular OSM repository')
679 @click.option('--long', is_flag
=True, help='get more details')
681 def nspkg_repo_list(ctx
, filter, repo
, long):
682 """list xNF packages from OSM repositories"""
684 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
686 @cli_osm.command(name
='nspkg-repo-list', short_help
='list all NS from OSM repositories')
687 @click.option('--filter', default
=None, multiple
=True,
688 help='restricts the list to the NS matching the filter')
689 @click.option('--repo', default
=None,
690 help='restricts the list to a particular OSM repository')
691 @click.option('--long', is_flag
=True, help='get more details')
693 def nspkg_repo_list2(ctx
, filter, repo
, long):
694 """list xNF packages from OSM repositories"""
696 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
698 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
699 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
700 @click.option('--filter', default
=None, multiple
=True,
701 help='restricts the list to the NF instances matching the filter.')
702 @click.option('--long', is_flag
=True, help='get more details')
704 def nf_list(ctx
, ns
, filter, long):
705 """list all NF instances
709 --ns TEXT NS instance id or name to restrict the VNF list
710 --filter filterExpr Restricts the list to the VNF instances matching the filter
713 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
714 concatenated using the "&" character:
717 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
718 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
719 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
721 value := scalar value
725 * zero or more occurrences
726 ? zero or one occurrence
727 [] grouping of expressions to be used with ? and *
728 "" quotation marks for marking string constants
732 "AttrName" is the name of one attribute in the data type that defines the representation
733 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
734 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
735 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
736 entries, it means that the operator "op" is applied to the attribute addressed by the last
737 <attrName> entry included in the concatenation. All simple filter expressions are combined
738 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
739 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
740 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
741 prefix". If an attribute referenced in an expression is an array, an object that contains a
742 corresponding array shall be considered to match the expression if any of the elements in the
743 array matches all expressions that have the same attribute prefix.
747 --filter vim-account-id=<VIM_ACCOUNT_ID>
748 --filter vnfd-ref=<VNFD_NAME>
749 --filter vdur.ip-address=<IP_ADDRESS>
750 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
753 vnf_list(ctx
, ns
, filter, long)
756 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
757 @click.argument('name')
758 @click.option('--long', is_flag
=True,
759 help='get more details of the NS operation (date, ).')
761 def ns_op_list(ctx
, name
, long):
762 """shows the history of operations over a NS instance
764 NAME: name or ID of the NS instance
766 def formatParams(params
):
767 if params
['lcmOperationType']=='instantiate':
768 params
.pop('nsDescription')
772 elif params
['lcmOperationType']=='action':
773 params
.pop('primitive')
774 params
.pop('lcmOperationType')
775 params
.pop('nsInstanceId')
780 check_client_version(ctx
.obj
, ctx
.command
.name
)
781 resp
= ctx
.obj
.ns
.list_op(name
)
782 # except ClientException as e:
787 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
789 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
791 #print(yaml.safe_dump(resp))
794 if op
['lcmOperationType']=='action':
795 action_name
= op
['operationParams']['primitive']
797 if op
['operationState'] == 'PROCESSING':
798 if op
['queuePosition'] is not None and op
['queuePosition'] > 0:
799 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
800 elif op
['lcmOperationType'] in ('instantiate', 'terminate'):
803 elif op
['operationState'] in ('FAILED', 'FAILED_TEMP'):
804 detail
= op
.get('errorMessage','-')
805 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
806 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
808 table
.add_row([op
['id'],
809 op
['lcmOperationType'],
811 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
812 op
['operationState'],
815 wrap_text(text
=detail
,width
=50)])
817 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
818 op
['operationState'], date
, wrap_text(text
=detail
or "",width
=50)])
823 def nsi_list(ctx
, filter):
824 """list all Network Slice Instances"""
827 check_client_version(ctx
.obj
, ctx
.command
.name
)
829 filter='&'.join(filter)
830 resp
= ctx
.obj
.nsi
.list(filter)
831 # except ClientException as e:
835 ['netslice instance name',
837 'operational status',
841 nsi_name
= nsi
['name']
843 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
844 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
845 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
846 if configstatus
== "config_not_needed":
847 configstatus
= "configured (no charms)"
858 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
859 @click.option('--filter', default
=None, multiple
=True,
860 help='restricts the list to the Network Slice Instances matching the filter')
862 def nsi_list1(ctx
, filter):
863 """list all Network Slice Instances (NSI)"""
865 nsi_list(ctx
, filter)
868 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
869 @click.option('--filter', default
=None, multiple
=True,
870 help='restricts the list to the Network Slice Instances matching the filter')
872 def nsi_list2(ctx
, filter):
873 """list all Network Slice Instances (NSI)"""
875 nsi_list(ctx
, filter)
878 def nst_list(ctx
, filter):
881 check_client_version(ctx
.obj
, ctx
.command
.name
)
883 filter='&'.join(filter)
884 resp
= ctx
.obj
.nst
.list(filter)
885 # except ClientException as e:
888 # print(yaml.safe_dump(resp))
889 table
= PrettyTable(['nst name', 'id'])
891 name
= nst
['name'] if 'name' in nst
else '-'
892 table
.add_row([name
, nst
['_id']])
897 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
898 @click.option('--filter', default
=None, multiple
=True,
899 help='restricts the list to the NST matching the filter')
901 def nst_list1(ctx
, filter):
902 """list all Network Slice Templates (NST) in the system"""
904 nst_list(ctx
, filter)
907 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
908 @click.option('--filter', default
=None, multiple
=True,
909 help='restricts the list to the NST matching the filter')
911 def nst_list2(ctx
, filter):
912 """list all Network Slice Templates (NST) in the system"""
914 nst_list(ctx
, filter)
917 def nsi_op_list(ctx
, name
):
920 check_client_version(ctx
.obj
, ctx
.command
.name
)
921 resp
= ctx
.obj
.nsi
.list_op(name
)
922 # except ClientException as e:
925 table
= PrettyTable(['id', 'operation', 'status'])
927 table
.add_row([op
['id'], op
['lcmOperationType'],
928 op
['operationState']])
933 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
934 @click.argument('name')
936 def nsi_op_list1(ctx
, name
):
937 """shows the history of operations over a Network Slice Instance (NSI)
939 NAME: name or ID of the Network Slice Instance
942 nsi_op_list(ctx
, name
)
945 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
946 @click.argument('name')
948 def nsi_op_list2(ctx
, name
):
949 """shows the history of operations over a Network Slice Instance (NSI)
951 NAME: name or ID of the Network Slice Instance
954 nsi_op_list(ctx
, name
)
957 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
958 @click.option('--filter', default
=None, multiple
=True,
959 help='restricts the list to the Physical Deployment Units matching the filter')
961 def pdu_list(ctx
, filter):
962 """list all Physical Deployment Units (PDU)"""
965 check_client_version(ctx
.obj
, ctx
.command
.name
)
967 filter='&'.join(filter)
968 resp
= ctx
.obj
.pdu
.list(filter)
969 # except ClientException as e:
978 pdu_name
= pdu
['name']
980 pdu_type
= pdu
['type']
981 pdu_ipaddress
= "None"
982 for iface
in pdu
['interfaces']:
984 pdu_ipaddress
= iface
['ip-address']
999 def nsd_show(ctx
, name
, literal
):
1002 resp
= ctx
.obj
.nsd
.get(name
)
1003 # resp = ctx.obj.nsd.get_individual(name)
1004 # except ClientException as e:
1009 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1012 table
= PrettyTable(['field', 'value'])
1013 for k
, v
in list(resp
.items()):
1014 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1019 @cli_osm.command(name
='nsd-show', short_help
='shows the details of a NS package')
1020 @click.option('--literal', is_flag
=True,
1021 help='print literally, no pretty table')
1022 @click.argument('name')
1024 def nsd_show1(ctx
, name
, literal
):
1025 """shows the content of a NSD
1027 NAME: name or ID of the NSD/NSpkg
1030 nsd_show(ctx
, name
, literal
)
1033 @cli_osm.command(name
='nspkg-show', short_help
='shows the details of a NS package')
1034 @click.option('--literal', is_flag
=True,
1035 help='print literally, no pretty table')
1036 @click.argument('name')
1038 def nsd_show2(ctx
, name
, literal
):
1039 """shows the content of a NSD
1041 NAME: name or ID of the NSD/NSpkg
1044 nsd_show(ctx
, name
, literal
)
1047 def vnfd_show(ctx
, name
, literal
):
1050 resp
= ctx
.obj
.vnfd
.get(name
)
1051 # resp = ctx.obj.vnfd.get_individual(name)
1052 # except ClientException as e:
1057 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1060 table
= PrettyTable(['field', 'value'])
1061 for k
, v
in list(resp
.items()):
1062 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1067 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1070 filter='&'.join(filter)
1072 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1075 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1078 catalog
= pkgtype
+ '-catalog'
1079 full_catalog
= pkgtype
+ ':' + catalog
1080 if resp
.get(catalog
):
1081 resp
= resp
.pop(catalog
)[pkgtype
][0]
1082 elif resp
.get(full_catalog
):
1083 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1085 table
= PrettyTable(['field', 'value'])
1086 for k
, v
in list(resp
.items()):
1087 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1092 @cli_osm.command(name
='vnfd-show', short_help
='shows the details of a NF package')
1093 @click.option('--literal', is_flag
=True,
1094 help='print literally, no pretty table')
1095 @click.argument('name')
1097 def vnfd_show1(ctx
, name
, literal
):
1098 """shows the content of a VNFD
1100 NAME: name or ID of the VNFD/VNFpkg
1103 vnfd_show(ctx
, name
, literal
)
1106 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the details of a NF package')
1107 @click.option('--literal', is_flag
=True,
1108 help='print literally, no pretty table')
1109 @click.argument('name')
1111 def vnfd_show2(ctx
, name
, literal
):
1112 """shows the content of a VNFD
1114 NAME: name or ID of the VNFD/VNFpkg
1117 vnfd_show(ctx
, name
, literal
)
1120 @cli_osm.command(name
='vnfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1121 @click.option('--literal', is_flag
=True,
1122 help='print literally, no pretty table')
1123 @click.option('--repo',
1125 help='Repository name')
1126 @click.argument('name')
1127 @click.option('--filter', default
=None, multiple
=True,
1128 help='filter by fields')
1129 @click.option('--version',
1131 help='package version')
1133 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1134 """shows the content of a VNFD in a repository
1136 NAME: name or ID of the VNFD/VNFpkg
1139 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1142 @cli_osm.command(name
='nsd-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1143 @click.option('--literal', is_flag
=True,
1144 help='print literally, no pretty table')
1145 @click.option('--repo',
1147 help='Repository name')
1148 @click.argument('name')
1149 @click.option('--filter', default
=None, multiple
=True,
1150 help='filter by fields')
1151 @click.option('--version',
1153 help='package version')
1155 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1156 """shows the content of a VNFD in a repository
1158 NAME: name or ID of the VNFD/VNFpkg
1161 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1164 @cli_osm.command(name
='nspkg-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1165 @click.option('--literal', is_flag
=True,
1166 help='print literally, no pretty table')
1167 @click.option('--repo',
1169 help='Repository name')
1170 @click.argument('name')
1171 @click.option('--filter', default
=None, multiple
=True,
1172 help='filter by fields')
1173 @click.option('--version',
1175 help='package version')
1177 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1178 """shows the content of a VNFD in a repository
1180 NAME: name or ID of the VNFD/VNFpkg
1183 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1186 @cli_osm.command(name
='nfpkg-show', short_help
='shows the details of a NF package')
1187 @click.option('--literal', is_flag
=True,
1188 help='print literally, no pretty table')
1189 @click.argument('name')
1191 def nfpkg_show(ctx
, name
, literal
):
1192 """shows the content of a NF Descriptor
1194 NAME: name or ID of the NFpkg
1197 vnfd_show(ctx
, name
, literal
)
1200 @cli_osm.command(name
='nfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1201 @click.option('--literal', is_flag
=True,
1202 help='print literally, no pretty table')
1203 @click.option('--repo',
1205 help='Repository name')
1206 @click.argument('name')
1207 @click.option('--filter', default
=None, multiple
=True,
1208 help='filter by fields')
1209 @click.option('--version',
1211 help='package version')
1213 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1214 """shows the content of a VNFD in a repository
1216 NAME: name or ID of the VNFD/VNFpkg
1219 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1222 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
1223 @click.argument('name')
1224 @click.option('--literal', is_flag
=True,
1225 help='print literally, no pretty table')
1226 @click.option('--filter', multiple
=True,
1227 help='restricts the information to the fields in the filter')
1229 def ns_show(ctx
, name
, literal
, filter):
1230 """shows the info of a NS instance
1232 NAME: name or ID of the NS instance
1236 ns
= ctx
.obj
.ns
.get(name
)
1237 # except ClientException as e:
1242 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1245 table
= PrettyTable(['field', 'value'])
1247 for k
, v
in list(ns
.items()):
1248 if not filter or k
in filter:
1249 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1251 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1252 if fullclassname
!= 'osmclient.sol005.client.Client':
1253 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1254 nsr_optdata
= nsopdata
['nsr:nsr']
1255 for k
, v
in list(nsr_optdata
.items()):
1256 if not filter or k
in filter:
1257 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1262 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1263 @click.argument('name')
1264 @click.option('--literal', is_flag
=True,
1265 help='print literally, no pretty table')
1266 @click.option('--filter', multiple
=True,
1267 help='restricts the information to the fields in the filter')
1268 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1270 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1271 """shows the info of a VNF instance
1273 NAME: name or ID of the VNF instance
1275 def print_kdu_status(op_info_status
):
1276 """print KDU status properly formatted
1279 op_status
= yaml
.safe_load(op_info_status
)
1280 if "namespace" in op_status
and "info" in op_status
and \
1281 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1282 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1283 "seconds" in op_status
["info"]["last_deployed"]:
1284 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1285 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1286 print("NAMESPACE: {}".format(op_status
["namespace"]))
1287 status_code
= "UNKNOWN"
1288 if op_status
["info"]["status"]["code"]==1:
1289 status_code
= "DEPLOYED"
1290 print("STATUS: {}".format(status_code
))
1293 print(op_status
["info"]["status"]["resources"])
1294 if "notes" in op_status
["info"]["status"]:
1296 print(op_status
["info"]["status"]["notes"])
1298 print(op_info_status
)
1300 print(op_info_status
)
1305 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1307 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1310 check_client_version(ctx
.obj
, ctx
.command
.name
)
1311 resp
= ctx
.obj
.vnf
.get(name
)
1314 ns_id
= resp
['nsr-id-ref']
1316 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1317 op_data
['kdu_name'] = kdu
1318 op_data
['primitive'] = 'status'
1319 op_data
['primitive_params'] = {}
1320 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1323 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1324 if op_info
['operationState'] == 'COMPLETED':
1325 print_kdu_status(op_info
['detailed-status'])
1329 print ("Could not determine KDU status")
1333 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1336 table
= PrettyTable(['field', 'value'])
1338 for k
, v
in list(resp
.items()):
1339 if not filter or k
in filter:
1340 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1343 # except ClientException as e:
1348 #@cli_osm.command(name='vnf-monitoring-show')
1349 #@click.argument('vnf_name')
1350 #@click.pass_context
1351 #def vnf_monitoring_show(ctx, vnf_name):
1353 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1354 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1355 # except ClientException as e:
1359 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1360 # if resp is not None:
1361 # for monitor in resp:
1365 # monitor['value-integer'],
1366 # monitor['units']])
1371 #@cli_osm.command(name='ns-monitoring-show')
1372 #@click.argument('ns_name')
1373 #@click.pass_context
1374 #def ns_monitoring_show(ctx, ns_name):
1376 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1377 # resp = ctx.obj.ns.get_monitoring(ns_name)
1378 # except ClientException as e:
1382 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1383 # for key, val in list(resp.items()):
1384 # for monitor in val:
1388 # monitor['value-integer'],
1389 # monitor['units']])
1394 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1395 @click.argument('id')
1396 @click.option('--filter', multiple
=True,
1397 help='restricts the information to the fields in the filter')
1398 @click.option('--literal', is_flag
=True,
1399 help='print literally, no pretty table')
1401 def ns_op_show(ctx
, id, filter, literal
):
1402 """shows the detailed info of a NS operation
1404 ID: operation identifier
1408 check_client_version(ctx
.obj
, ctx
.command
.name
)
1409 op_info
= ctx
.obj
.ns
.get_op(id)
1410 # except ClientException as e:
1415 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1418 table
= PrettyTable(['field', 'value'])
1419 for k
, v
in list(op_info
.items()):
1420 if not filter or k
in filter:
1421 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1426 def nst_show(ctx
, name
, literal
):
1429 check_client_version(ctx
.obj
, ctx
.command
.name
)
1430 resp
= ctx
.obj
.nst
.get(name
)
1431 #resp = ctx.obj.nst.get_individual(name)
1432 # except ClientException as e:
1437 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1440 table
= PrettyTable(['field', 'value'])
1441 for k
, v
in list(resp
.items()):
1442 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1447 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1448 @click.option('--literal', is_flag
=True,
1449 help='print literally, no pretty table')
1450 @click.argument('name')
1452 def nst_show1(ctx
, name
, literal
):
1453 """shows the content of a Network Slice Template (NST)
1455 NAME: name or ID of the NST
1458 nst_show(ctx
, name
, literal
)
1461 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1462 @click.option('--literal', is_flag
=True,
1463 help='print literally, no pretty table')
1464 @click.argument('name')
1466 def nst_show2(ctx
, name
, literal
):
1467 """shows the content of a Network Slice Template (NST)
1469 NAME: name or ID of the NST
1472 nst_show(ctx
, name
, literal
)
1475 def nsi_show(ctx
, name
, literal
, filter):
1478 check_client_version(ctx
.obj
, ctx
.command
.name
)
1479 nsi
= ctx
.obj
.nsi
.get(name
)
1480 # except ClientException as e:
1485 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1488 table
= PrettyTable(['field', 'value'])
1490 for k
, v
in list(nsi
.items()):
1491 if not filter or k
in filter:
1492 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1498 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1499 @click.argument('name')
1500 @click.option('--literal', is_flag
=True,
1501 help='print literally, no pretty table')
1502 @click.option('--filter', multiple
=True,
1503 help='restricts the information to the fields in the filter')
1505 def nsi_show1(ctx
, name
, literal
, filter):
1506 """shows the content of a Network Slice Instance (NSI)
1508 NAME: name or ID of the Network Slice Instance
1511 nsi_show(ctx
, name
, literal
, filter)
1514 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1515 @click.argument('name')
1516 @click.option('--literal', is_flag
=True,
1517 help='print literally, no pretty table')
1518 @click.option('--filter', multiple
=True,
1519 help='restricts the information to the fields in the filter')
1521 def nsi_show2(ctx
, name
, literal
, filter):
1522 """shows the content of a Network Slice Instance (NSI)
1524 NAME: name or ID of the Network Slice Instance
1527 nsi_show(ctx
, name
, literal
, filter)
1530 def nsi_op_show(ctx
, id, filter):
1533 check_client_version(ctx
.obj
, ctx
.command
.name
)
1534 op_info
= ctx
.obj
.nsi
.get_op(id)
1535 # except ClientException as e:
1539 table
= PrettyTable(['field', 'value'])
1540 for k
, v
in list(op_info
.items()):
1541 if not filter or k
in filter:
1542 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1547 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1548 @click.argument('id')
1549 @click.option('--filter', multiple
=True,
1550 help='restricts the information to the fields in the filter')
1552 def nsi_op_show1(ctx
, id, filter):
1553 """shows the info of an operation over a Network Slice Instance(NSI)
1555 ID: operation identifier
1558 nsi_op_show(ctx
, id, filter)
1561 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1562 @click.argument('id')
1563 @click.option('--filter', multiple
=True,
1564 help='restricts the information to the fields in the filter')
1566 def nsi_op_show2(ctx
, id, filter):
1567 """shows the info of an operation over a Network Slice Instance(NSI)
1569 ID: operation identifier
1572 nsi_op_show(ctx
, id, filter)
1575 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1576 @click.argument('name')
1577 @click.option('--literal', is_flag
=True,
1578 help='print literally, no pretty table')
1579 @click.option('--filter', multiple
=True,
1580 help='restricts the information to the fields in the filter')
1582 def pdu_show(ctx
, name
, literal
, filter):
1583 """shows the content of a Physical Deployment Unit (PDU)
1585 NAME: name or ID of the PDU
1589 check_client_version(ctx
.obj
, ctx
.command
.name
)
1590 pdu
= ctx
.obj
.pdu
.get(name
)
1591 # except ClientException as e:
1596 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1599 table
= PrettyTable(['field', 'value'])
1601 for k
, v
in list(pdu
.items()):
1602 if not filter or k
in filter:
1603 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1609 ####################
1611 ####################
1613 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1616 check_client_version(ctx
.obj
, ctx
.command
.name
)
1618 filename
= ctx
.obj
.osmrepo
.get_pkg('ns', filename
, repo
, vendor
, version
)
1619 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1620 # except ClientException as e:
1625 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1626 @click.argument('filename')
1627 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1628 help='Deprecated. Use override')
1629 @click.option('--override', 'overwrite', default
=None,
1630 help='overrides fields in descriptor, format: '
1631 '"key1.key2...=value[;key3...=value;...]"')
1632 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1633 help='The charm will not be compiled, it is assumed to already exist')
1634 @click.option('--repo', default
=None,
1635 help='[repository]: Repository name')
1636 @click.option('--vendor', default
=None,
1637 help='[repository]: filter by vendor]')
1638 @click.option('--version', default
='latest',
1639 help='[repository]: filter by version. Default: latest')
1641 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1642 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1645 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1646 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1647 If FILENAME is an NF Package folder, it is built and then onboarded.
1650 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1654 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1655 @click.argument('filename')
1656 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1657 help='Deprecated. Use override')
1658 @click.option('--override', 'overwrite', default
=None,
1659 help='overrides fields in descriptor, format: '
1660 '"key1.key2...=value[;key3...=value;...]"')
1661 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1662 help='The charm will not be compiled, it is assumed to already exist')
1663 @click.option('--repo', default
=None,
1664 help='[repository]: Repository name')
1665 @click.option('--vendor', default
=None,
1666 help='[repository]: filter by vendor]')
1667 @click.option('--version', default
='latest',
1668 help='[repository]: filter by version. Default: latest')
1670 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1671 """onboards a new NSpkg
1673 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1674 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1675 If FILENAME is an NF Package folder, it is built and then onboarded.
1678 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1682 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1683 repo
, vendor
, version
):
1686 check_client_version(ctx
.obj
, ctx
.command
.name
)
1688 filename
= ctx
.obj
.osmrepo
.get_pkg('vnf', filename
, repo
, vendor
, version
)
1689 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1690 override_epa
=override_epa
, override_nonepa
=override_nonepa
,
1691 override_paravirt
=override_paravirt
)
1692 # except ClientException as e:
1697 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1698 @click.argument('filename')
1699 @click.option('--overwrite', 'overwrite', default
=None,
1700 help='overwrite deprecated, use override')
1701 @click.option('--override', 'overwrite', default
=None,
1702 help='overrides fields in descriptor, format: '
1703 '"key1.key2...=value[;key3...=value;...]"')
1704 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1705 help='The charm will not be compiled, it is assumed to already exist')
1706 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1707 help='adds guest-epa parameters to all VDU')
1708 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1709 help='removes all guest-epa parameters from all VDU')
1710 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1711 help='overrides all VDU interfaces to PARAVIRT')
1712 @click.option('--repo', default
=None,
1713 help='[repository]: Repository name')
1714 @click.option('--vendor', default
=None,
1715 help='[repository]: filter by vendor]')
1716 @click.option('--version', default
='latest',
1717 help='[repository]: filter by version. Default: latest')
1719 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1720 repo
,vendor
, version
):
1721 """creates a new VNFD/VNFpkg
1723 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1724 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1725 If FILENAME is an NF Package folder, it is built and then onboarded.
1728 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1729 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1730 repo
=repo
, vendor
=vendor
, version
=version
)
1733 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1734 @click.argument('filename')
1735 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1736 help='Deprecated. Use override')
1737 @click.option('--override', 'overwrite', default
=None,
1738 help='overrides fields in descriptor, format: '
1739 '"key1.key2...=value[;key3...=value;...]"')
1740 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1741 help='The charm will not be compiled, it is assumed to already exist')
1742 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1743 help='adds guest-epa parameters to all VDU')
1744 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1745 help='removes all guest-epa parameters from all VDU')
1746 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1747 help='overrides all VDU interfaces to PARAVIRT')
1748 @click.option('--repo', default
=None,
1749 help='[repository]: Repository name')
1750 @click.option('--vendor', default
=None,
1751 help='[repository]: filter by vendor]')
1752 @click.option('--version', default
='latest',
1753 help='[repository]: filter by version. Default: latest')
1755 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1756 repo
, vendor
, version
):
1757 """creates a new VNFD/VNFpkg
1759 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1760 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1761 If FILENAME is an NF Package folder, it is built and then onboarded.
1764 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1765 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1766 repo
=repo
, vendor
=vendor
, version
=version
)
1768 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1769 @click.argument('filename')
1770 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1771 help='Deprecated. Use override')
1772 @click.option('--override', 'overwrite', default
=None,
1773 help='overrides fields in descriptor, format: '
1774 '"key1.key2...=value[;key3...=value;...]"')
1775 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1776 help='The charm will not be compiled, it is assumed to already exist')
1777 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1778 help='adds guest-epa parameters to all VDU')
1779 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1780 help='removes all guest-epa parameters from all VDU')
1781 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1782 help='overrides all VDU interfaces to PARAVIRT')
1783 @click.option('--repo', default
=None,
1784 help='[repository]: Repository name')
1785 @click.option('--vendor', default
=None,
1786 help='[repository]: filter by vendor]')
1787 @click.option('--version', default
='latest',
1788 help='[repository]: filter by version. Default: latest')
1790 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1791 repo
, vendor
, version
):
1792 """creates a new NFpkg
1795 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1796 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1797 If FILENAME is an NF Package folder, it is built and then onboarded.
1800 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1801 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1802 repo
=repo
, vendor
=vendor
, version
=version
)
1805 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1806 @click.option('--ns_name',
1807 prompt
=True, help='name of the NS instance')
1808 @click.option('--nsd_name',
1809 prompt
=True, help='name of the NS descriptor')
1810 @click.option('--vim_account',
1811 prompt
=True, help='default VIM account id or name for the deployment')
1812 @click.option('--admin_status',
1814 help='administration status')
1815 @click.option('--ssh_keys',
1817 help='comma separated list of public key files to inject to vnfs')
1818 @click.option('--config',
1820 help='ns specific yaml configuration')
1821 @click.option('--config_file',
1823 help='ns specific yaml configuration file')
1824 @click.option('--wait',
1828 help='do not return the control immediately, but keep it '
1829 'until the operation is completed, or timeout')
1840 """creates a new NS instance"""
1844 check_client_version(ctx
.obj
, '--config_file')
1846 raise ClientException('"--config" option is incompatible with "--config_file" option')
1847 with
open(config_file
, 'r') as cf
:
1854 account
=vim_account
,
1856 # except ClientException as e:
1861 def nst_create(ctx
, filename
, overwrite
):
1864 check_client_version(ctx
.obj
, ctx
.command
.name
)
1865 ctx
.obj
.nst
.create(filename
, overwrite
)
1866 # except ClientException as e:
1871 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1872 @click.argument('filename')
1873 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1874 help='Deprecated. Use override')
1875 @click.option('--override', 'overwrite', default
=None,
1876 help='overrides fields in descriptor, format: '
1877 '"key1.key2...=value[;key3...=value;...]"')
1879 def nst_create1(ctx
, filename
, overwrite
):
1880 """creates a new Network Slice Template (NST)
1882 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1885 nst_create(ctx
, filename
, overwrite
)
1888 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1889 @click.argument('filename')
1890 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1891 help='Deprecated. Use override')
1892 @click.option('--override', 'overwrite', default
=None,
1893 help='overrides fields in descriptor, format: '
1894 '"key1.key2...=value[;key3...=value;...]"')
1896 def nst_create2(ctx
, filename
, overwrite
):
1897 """creates a new Network Slice Template (NST)
1899 FILENAME: NST yaml file or NSTpkg tar.gz file
1902 nst_create(ctx
, filename
, overwrite
)
1905 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1906 """creates a new Network Slice Instance (NSI)"""
1909 check_client_version(ctx
.obj
, ctx
.command
.name
)
1912 raise ClientException('"--config" option is incompatible with "--config_file" option')
1913 with
open(config_file
, 'r') as cf
:
1915 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1916 account
=vim_account
, wait
=wait
)
1917 # except ClientException as e:
1922 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1923 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1924 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1925 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1926 @click.option('--ssh_keys', default
=None,
1927 help='comma separated list of keys to inject to vnfs')
1928 @click.option('--config', default
=None,
1929 help='Netslice specific yaml configuration:\n'
1930 'netslice_subnet: [\n'
1931 'id: TEXT, vim_account: TEXT,\n'
1932 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1933 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1934 'additionalParamsForNsi: {param: value, ...}\n'
1935 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1937 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1939 @click.option('--config_file',
1941 help='nsi specific yaml configuration file')
1942 @click.option('--wait',
1946 help='do not return the control immediately, but keep it '
1947 'until the operation is completed, or timeout')
1949 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1950 """creates a new Network Slice Instance (NSI)"""
1952 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1955 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1956 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1957 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1958 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1959 @click.option('--ssh_keys', default
=None,
1960 help='comma separated list of keys to inject to vnfs')
1961 @click.option('--config', default
=None,
1962 help='Netslice specific yaml configuration:\n'
1963 'netslice_subnet: [\n'
1964 'id: TEXT, vim_account: TEXT,\n'
1965 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1966 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1968 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1970 @click.option('--config_file',
1972 help='nsi specific yaml configuration file')
1973 @click.option('--wait',
1977 help='do not return the control immediately, but keep it '
1978 'until the operation is completed, or timeout')
1980 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1981 """creates a new Network Slice Instance (NSI)"""
1983 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1986 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1987 @click.option('--name', help='name of the Physical Deployment Unit')
1988 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1989 @click.option('--interface',
1990 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1991 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1993 @click.option('--description', help='human readable description')
1994 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
1995 @click.option('--descriptor_file', default
=None,
1996 help='PDU descriptor file (as an alternative to using the other arguments')
1998 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
1999 """creates a new Physical Deployment Unit (PDU)"""
2002 check_client_version(ctx
.obj
, ctx
.command
.name
)
2004 if not descriptor_file
:
2006 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
2008 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
2010 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
2012 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
2014 with
open(descriptor_file
, 'r') as df
:
2015 pdu
= yaml
.safe_load(df
.read())
2016 if name
: pdu
["name"] = name
2017 if pdu_type
: pdu
["type"] = pdu_type
2018 if description
: pdu
["description"] = description
2019 if vim_account
: pdu
["vim_accounts"] = vim_account
2022 for iface
in interface
:
2023 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
2024 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
2025 ifaces_list
.append(new_iface
)
2026 pdu
["interfaces"] = ifaces_list
2027 ctx
.obj
.pdu
.create(pdu
)
2028 # except ClientException as e:
2033 ####################
2035 ####################
2037 def nsd_update(ctx
, name
, content
):
2040 check_client_version(ctx
.obj
, ctx
.command
.name
)
2041 ctx
.obj
.nsd
.update(name
, content
)
2042 # except ClientException as e:
2047 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
2048 @click.argument('name')
2049 @click.option('--content', default
=None,
2050 help='filename with the NSD/NSpkg replacing the current one')
2052 def nsd_update1(ctx
, name
, content
):
2053 """updates a NSD/NSpkg
2055 NAME: name or ID of the NSD/NSpkg
2058 nsd_update(ctx
, name
, content
)
2061 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
2062 @click.argument('name')
2063 @click.option('--content', default
=None,
2064 help='filename with the NSD/NSpkg replacing the current one')
2066 def nsd_update2(ctx
, name
, content
):
2067 """updates a NSD/NSpkg
2069 NAME: name or ID of the NSD/NSpkg
2072 nsd_update(ctx
, name
, content
)
2075 def vnfd_update(ctx
, name
, content
):
2078 check_client_version(ctx
.obj
, ctx
.command
.name
)
2079 ctx
.obj
.vnfd
.update(name
, content
)
2080 # except ClientException as e:
2085 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
2086 @click.argument('name')
2087 @click.option('--content', default
=None,
2088 help='filename with the VNFD/VNFpkg replacing the current one')
2090 def vnfd_update1(ctx
, name
, content
):
2091 """updates a VNFD/VNFpkg
2093 NAME: name or ID of the VNFD/VNFpkg
2096 vnfd_update(ctx
, name
, content
)
2099 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
2100 @click.argument('name')
2101 @click.option('--content', default
=None,
2102 help='filename with the VNFD/VNFpkg replacing the current one')
2104 def vnfd_update2(ctx
, name
, content
):
2105 """updates a VNFD/VNFpkg
2107 NAME: VNFD yaml file or VNFpkg tar.gz file
2110 vnfd_update(ctx
, name
, content
)
2113 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
2114 @click.argument('name')
2115 @click.option('--content', default
=None,
2116 help='filename with the NFpkg replacing the current one')
2118 def nfpkg_update(ctx
, name
, content
):
2121 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2124 vnfd_update(ctx
, name
, content
)
2127 def nst_update(ctx
, name
, content
):
2130 check_client_version(ctx
.obj
, ctx
.command
.name
)
2131 ctx
.obj
.nst
.update(name
, content
)
2132 # except ClientException as e:
2137 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
2138 @click.argument('name')
2139 @click.option('--content', default
=None,
2140 help='filename with the NST/NSTpkg replacing the current one')
2142 def nst_update1(ctx
, name
, content
):
2143 """updates a Network Slice Template (NST)
2145 NAME: name or ID of the NSD/NSpkg
2148 nst_update(ctx
, name
, content
)
2151 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
2152 @click.argument('name')
2153 @click.option('--content', default
=None,
2154 help='filename with the NST/NSTpkg replacing the current one')
2156 def nst_update2(ctx
, name
, content
):
2157 """updates a Network Slice Template (NST)
2159 NAME: name or ID of the NSD/NSpkg
2162 nst_update(ctx
, name
, content
)
2165 ####################
2167 ####################
2169 def nsd_delete(ctx
, name
, force
):
2173 ctx
.obj
.nsd
.delete(name
)
2175 check_client_version(ctx
.obj
, '--force')
2176 ctx
.obj
.nsd
.delete(name
, force
)
2177 # except ClientException as e:
2182 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
2183 @click.argument('name')
2184 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2186 def nsd_delete1(ctx
, name
, force
):
2187 """deletes a NSD/NSpkg
2189 NAME: name or ID of the NSD/NSpkg to be deleted
2192 nsd_delete(ctx
, name
, force
)
2195 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
2196 @click.argument('name')
2197 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2199 def nsd_delete2(ctx
, name
, force
):
2200 """deletes a NSD/NSpkg
2202 NAME: name or ID of the NSD/NSpkg to be deleted
2205 nsd_delete(ctx
, name
, force
)
2208 def vnfd_delete(ctx
, name
, force
):
2212 ctx
.obj
.vnfd
.delete(name
)
2214 check_client_version(ctx
.obj
, '--force')
2215 ctx
.obj
.vnfd
.delete(name
, force
)
2216 # except ClientException as e:
2221 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
2222 @click.argument('name')
2223 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2225 def vnfd_delete1(ctx
, name
, force
):
2226 """deletes a VNFD/VNFpkg
2228 NAME: name or ID of the VNFD/VNFpkg to be deleted
2231 vnfd_delete(ctx
, name
, force
)
2234 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
2235 @click.argument('name')
2236 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2238 def vnfd_delete2(ctx
, name
, force
):
2239 """deletes a VNFD/VNFpkg
2241 NAME: name or ID of the VNFD/VNFpkg to be deleted
2244 vnfd_delete(ctx
, name
, force
)
2247 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
2248 @click.argument('name')
2249 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2251 def nfpkg_delete(ctx
, name
, force
):
2254 NAME: name or ID of the NFpkg to be deleted
2257 vnfd_delete(ctx
, name
, force
)
2260 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
2261 @click.argument('name')
2262 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2263 @click.option('--config', default
=None,
2264 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2265 "600, skip_terminate_primitives: True}'")
2266 @click.option('--wait',
2270 help='do not return the control immediately, but keep it '
2271 'until the operation is completed, or timeout')
2273 def ns_delete(ctx
, name
, force
, config
, wait
):
2274 """deletes a NS instance
2276 NAME: name or ID of the NS instance to be deleted
2281 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2283 check_client_version(ctx
.obj
, '--force')
2284 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2285 # except ClientException as e:
2290 def nst_delete(ctx
, name
, force
):
2293 check_client_version(ctx
.obj
, ctx
.command
.name
)
2294 ctx
.obj
.nst
.delete(name
, force
)
2295 # except ClientException as e:
2300 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
2301 @click.argument('name')
2302 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2304 def nst_delete1(ctx
, name
, force
):
2305 """deletes a Network Slice Template (NST)
2307 NAME: name or ID of the NST/NSTpkg to be deleted
2310 nst_delete(ctx
, name
, force
)
2313 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
2314 @click.argument('name')
2315 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2317 def nst_delete2(ctx
, name
, force
):
2318 """deletes a Network Slice Template (NST)
2320 NAME: name or ID of the NST/NSTpkg to be deleted
2323 nst_delete(ctx
, name
, force
)
2326 def nsi_delete(ctx
, name
, force
, wait
):
2329 check_client_version(ctx
.obj
, ctx
.command
.name
)
2330 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2331 # except ClientException as e:
2336 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2337 @click.argument('name')
2338 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2339 @click.option('--wait',
2343 help='do not return the control immediately, but keep it '
2344 'until the operation is completed, or timeout')
2346 def nsi_delete1(ctx
, name
, force
, wait
):
2347 """deletes a Network Slice Instance (NSI)
2349 NAME: name or ID of the Network Slice instance to be deleted
2352 nsi_delete(ctx
, name
, force
, wait
=wait
)
2355 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2356 @click.argument('name')
2357 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2359 def nsi_delete2(ctx
, name
, force
, wait
):
2360 """deletes a Network Slice Instance (NSI)
2362 NAME: name or ID of the Network Slice instance to be deleted
2365 nsi_delete(ctx
, name
, force
, wait
=wait
)
2368 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2369 @click.argument('name')
2370 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2372 def pdu_delete(ctx
, name
, force
):
2373 """deletes a Physical Deployment Unit (PDU)
2375 NAME: name or ID of the PDU to be deleted
2379 check_client_version(ctx
.obj
, ctx
.command
.name
)
2380 ctx
.obj
.pdu
.delete(name
, force
)
2381 # except ClientException as e:
2390 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2391 @click.option('--name',
2393 help='Name to create datacenter')
2394 @click.option('--user',
2396 help='VIM username')
2397 @click.option('--password',
2400 confirmation_prompt
=True,
2401 help='VIM password')
2402 @click.option('--auth_url',
2405 @click.option('--tenant',
2407 help='VIM tenant name')
2408 @click.option('--config',
2410 help='VIM specific config parameters')
2411 @click.option('--account_type',
2412 default
='openstack',
2414 @click.option('--description',
2416 help='human readable description')
2417 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2418 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2419 @click.option('--wait',
2423 help='do not return the control immediately, but keep it '
2424 'until the operation is completed, or timeout')
2438 """creates a new VIM account"""
2442 check_client_version(ctx
.obj
, '--sdn_controller')
2443 if sdn_port_mapping
:
2444 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2446 vim
['vim-username'] = user
2447 vim
['vim-password'] = password
2448 vim
['vim-url'] = auth_url
2449 vim
['vim-tenant-name'] = tenant
2450 vim
['vim-type'] = account_type
2451 vim
['description'] = description
2452 vim
['config'] = config
2453 if sdn_controller
or sdn_port_mapping
:
2454 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2456 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2457 # except ClientException as e:
2462 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2463 @click.argument('name')
2464 @click.option('--newname', help='New name for the VIM account')
2465 @click.option('--user', help='VIM username')
2466 @click.option('--password', help='VIM password')
2467 @click.option('--auth_url', help='VIM url')
2468 @click.option('--tenant', help='VIM tenant name')
2469 @click.option('--config', help='VIM specific config parameters')
2470 @click.option('--account_type', help='VIM type')
2471 @click.option('--description', help='human readable description')
2472 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller to be associated with this VIM'
2473 'account. Use empty string to disassociate')
2474 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2475 @click.option('--wait',
2479 help='do not return the control immediately, but keep it '
2480 'until the operation is completed, or timeout')
2495 """updates a VIM account
2497 NAME: name or ID of the VIM account
2501 check_client_version(ctx
.obj
, ctx
.command
.name
)
2503 if newname
: vim
['name'] = newname
2504 if user
: vim
['vim_user'] = user
2505 if password
: vim
['vim_password'] = password
2506 if auth_url
: vim
['vim_url'] = auth_url
2507 if tenant
: vim
['vim-tenant-name'] = tenant
2508 if account_type
: vim
['vim_type'] = account_type
2509 if description
: vim
['description'] = description
2510 if config
: vim
['config'] = config
2511 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2512 # except ClientException as e:
2517 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2518 @click.argument('name')
2519 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2520 @click.option('--wait',
2524 help='do not return the control immediately, but keep it '
2525 'until the operation is completed, or timeout')
2527 def vim_delete(ctx
, name
, force
, wait
):
2528 """deletes a VIM account
2530 NAME: name or ID of the VIM account to be deleted
2535 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2537 check_client_version(ctx
.obj
, '--force')
2538 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2539 # except ClientException as e:
2544 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2545 #@click.option('--ro_update/--no_ro_update',
2547 # help='update list from RO')
2548 @click.option('--filter', default
=None, multiple
=True,
2549 help='restricts the list to the VIM accounts matching the filter')
2550 @click.option('--long', is_flag
=True,
2551 help='get more details of the NS (project, vim, deployment status, configuration status.')
2553 def vim_list(ctx
, filter, long):
2554 """list all VIM accounts"""
2557 filter='&'.join(filter)
2558 check_client_version(ctx
.obj
, '--filter')
2560 # check_client_version(ctx.obj, '--ro_update', 'v1')
2561 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2562 if fullclassname
== 'osmclient.sol005.client.Client':
2563 resp
= ctx
.obj
.vim
.list(filter)
2565 # resp = ctx.obj.vim.list(ro_update)
2567 table
= PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details'])
2569 table
= PrettyTable(['vim name', 'uuid', 'operational state'])
2572 vim_details
= ctx
.obj
.vim
.get(vim
['uuid'])
2573 if 'vim_password' in vim_details
:
2574 vim_details
['vim_password']='********'
2575 logger
.debug('VIM details: {}'.format(yaml
.safe_dump(vim_details
)))
2576 vim_state
= vim_details
['_admin'].get('operationalState', '-')
2577 error_details
= 'N/A'
2578 if vim_state
== 'ERROR':
2579 error_details
= vim_details
['_admin'].get('detailed-status', 'Not found')
2580 project_list
= ctx
.obj
.project
.list()
2581 vim_project_list
= vim_details
.get('_admin').get('projects_read')
2583 project_name
= 'None'
2584 if vim_project_list
:
2585 project_id
= vim_project_list
[0]
2586 for p
in project_list
:
2587 if p
['_id'] == project_id
:
2588 project_name
= p
['name']
2590 table
.add_row([vim
['name'], vim
['uuid'], '{} ({})'.format(project_name
, project_id
),
2591 vim_state
, wrap_text(text
=error_details
, width
=80)])
2593 table
.add_row([vim
['name'], vim
['uuid'], vim
['_admin'].get('operationalState', '-')])
2598 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2599 @click.argument('name')
2601 def vim_show(ctx
, name
):
2602 """shows the details of a VIM account
2604 NAME: name or ID of the VIM account
2608 resp
= ctx
.obj
.vim
.get(name
)
2609 if 'vim_password' in resp
:
2610 resp
['vim_password']='********'
2611 # except ClientException as e:
2615 table
= PrettyTable(['key', 'attribute'])
2616 for k
, v
in list(resp
.items()):
2617 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2622 ####################
2624 ####################
2626 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2627 @click.option('--name',
2629 help='Name for the WIM account')
2630 @click.option('--user',
2631 help='WIM username')
2632 @click.option('--password',
2633 help='WIM password')
2634 @click.option('--url',
2637 # @click.option('--tenant',
2638 # help='wIM tenant name')
2639 @click.option('--config',
2641 help='WIM specific config parameters')
2642 @click.option('--wim_type',
2644 @click.option('--description',
2646 help='human readable description')
2647 @click.option('--wim_port_mapping', default
=None,
2648 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2649 "(WAN service endpoint id and info)")
2650 @click.option('--wait',
2654 help='do not return the control immediately, but keep it '
2655 'until the operation is completed, or timeout')
2668 """creates a new WIM account"""
2671 check_client_version(ctx
.obj
, ctx
.command
.name
)
2672 # if sdn_controller:
2673 # check_client_version(ctx.obj, '--sdn_controller')
2674 # if sdn_port_mapping:
2675 # check_client_version(ctx.obj, '--sdn_port_mapping')
2677 if user
: wim
['user'] = user
2678 if password
: wim
['password'] = password
2679 if url
: wim
['wim_url'] = url
2680 # if tenant: wim['tenant'] = tenant
2681 wim
['wim_type'] = wim_type
2682 if description
: wim
['description'] = description
2683 if config
: wim
['config'] = config
2684 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2685 # except ClientException as e:
2690 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2691 @click.argument('name')
2692 @click.option('--newname', help='New name for the WIM account')
2693 @click.option('--user', help='WIM username')
2694 @click.option('--password', help='WIM password')
2695 @click.option('--url', help='WIM url')
2696 @click.option('--config', help='WIM specific config parameters')
2697 @click.option('--wim_type', help='WIM type')
2698 @click.option('--description', help='human readable description')
2699 @click.option('--wim_port_mapping', default
=None,
2700 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2701 "(WAN service endpoint id and info)")
2702 @click.option('--wait',
2706 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2719 """updates a WIM account
2721 NAME: name or ID of the WIM account
2725 check_client_version(ctx
.obj
, ctx
.command
.name
)
2727 if newname
: wim
['name'] = newname
2728 if user
: wim
['user'] = user
2729 if password
: wim
['password'] = password
2730 if url
: wim
['url'] = url
2731 # if tenant: wim['tenant'] = tenant
2732 if wim_type
: wim
['wim_type'] = wim_type
2733 if description
: wim
['description'] = description
2734 if config
: wim
['config'] = config
2735 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2736 # except ClientException as e:
2741 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2742 @click.argument('name')
2743 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2744 @click.option('--wait',
2748 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2750 def wim_delete(ctx
, name
, force
, wait
):
2751 """deletes a WIM account
2753 NAME: name or ID of the WIM account to be deleted
2757 check_client_version(ctx
.obj
, ctx
.command
.name
)
2758 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2759 # except ClientException as e:
2764 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2765 @click.option('--filter', default
=None, multiple
=True,
2766 help='restricts the list to the WIM accounts matching the filter')
2768 def wim_list(ctx
, filter):
2769 """list all WIM accounts"""
2772 check_client_version(ctx
.obj
, ctx
.command
.name
)
2774 filter='&'.join(filter)
2775 resp
= ctx
.obj
.wim
.list(filter)
2776 table
= PrettyTable(['wim name', 'uuid'])
2778 table
.add_row([wim
['name'], wim
['uuid']])
2781 # except ClientException as e:
2786 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2787 @click.argument('name')
2789 def wim_show(ctx
, name
):
2790 """shows the details of a WIM account
2792 NAME: name or ID of the WIM account
2796 check_client_version(ctx
.obj
, ctx
.command
.name
)
2797 resp
= ctx
.obj
.wim
.get(name
)
2798 if 'password' in resp
:
2799 resp
['wim_password']='********'
2800 # except ClientException as e:
2804 table
= PrettyTable(['key', 'attribute'])
2805 for k
, v
in list(resp
.items()):
2806 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2811 ####################
2812 # SDN controller operations
2813 ####################
2815 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2816 @click.option('--name',
2818 help='Name to create sdn controller')
2819 @click.option('--type',
2821 help='SDN controller type')
2822 @click.option('--sdn_controller_version', # hidden=True,
2823 help='Deprecated. Use --config {version: sdn_controller_version}')
2824 @click.option('--url',
2825 help='URL in format http[s]://HOST:IP/')
2826 @click.option('--ip_address', # hidden=True,
2827 help='Deprecated. Use --url')
2828 @click.option('--port', # hidden=True,
2829 help='Deprecated. Use --url')
2830 @click.option('--switch_dpid', # hidden=True,
2831 help='Deprecated. Use --config {switch_id: DPID}')
2832 @click.option('--config',
2833 help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2834 'Openflow Datapath ID), version: version}')
2835 @click.option('--user',
2836 help='SDN controller username')
2837 @click.option('--password',
2839 confirmation_prompt
=True,
2840 help='SDN controller password')
2841 @click.option('--description', default
=None, help='human readable description')
2842 @click.option('--wait',
2846 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2848 def sdnc_create(ctx
, **kwargs
):
2849 """creates a new SDN controller"""
2851 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2852 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2853 if kwargs
.get("port"):
2854 print("option '--port' is deprecated, use '--url' instead")
2855 sdncontroller
["port"] = int(kwargs
["port"])
2856 if kwargs
.get("ip_address"):
2857 print("option '--ip_address' is deprecated, use '--url' instead")
2858 sdncontroller
["ip"] = kwargs
["ip_address"]
2859 if kwargs
.get("switch_dpid"):
2860 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2861 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2862 if kwargs
.get("sdn_controller_version"):
2863 print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2866 check_client_version(ctx
.obj
, ctx
.command
.name
)
2867 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2868 # except ClientException as e:
2872 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2873 @click.argument('name')
2874 @click.option('--newname', help='New name for the SDN controller')
2875 @click.option('--description', default
=None, help='human readable description')
2876 @click.option('--type', help='SDN controller type')
2877 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2878 @click.option('--config', help='Extra information for SDN in yaml format, as '
2879 '{switch_id: identity used for the plugin (e.g. DPID: '
2880 'Openflow Datapath ID), version: version}')
2881 @click.option('--user', help='SDN controller username')
2882 @click.option('--password', help='SDN controller password')
2883 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2884 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2885 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2886 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2887 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2888 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2890 def sdnc_update(ctx
, **kwargs
):
2891 """updates an SDN controller
2893 NAME: name or ID of the SDN controller
2896 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2897 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2898 if kwargs
.get("newname"):
2899 sdncontroller
["name"] = kwargs
["newname"]
2900 if kwargs
.get("port"):
2901 print("option '--port' is deprecated, use '--url' instead")
2902 sdncontroller
["port"] = int(kwargs
["port"])
2903 if kwargs
.get("ip_address"):
2904 print("option '--ip_address' is deprecated, use '--url' instead")
2905 sdncontroller
["ip"] = kwargs
["ip_address"]
2906 if kwargs
.get("switch_dpid"):
2907 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2908 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2909 if kwargs
.get("sdn_controller_version"):
2910 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2914 check_client_version(ctx
.obj
, ctx
.command
.name
)
2915 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2916 # except ClientException as e:
2921 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2922 @click.argument('name')
2923 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2924 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2925 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2927 def sdnc_delete(ctx
, name
, force
, wait
):
2928 """deletes an SDN controller
2930 NAME: name or ID of the SDN controller to be deleted
2934 check_client_version(ctx
.obj
, ctx
.command
.name
)
2935 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2936 # except ClientException as e:
2941 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2942 @click.option('--filter', default
=None, multiple
=True,
2943 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2945 def sdnc_list(ctx
, filter):
2946 """list all SDN controllers"""
2949 check_client_version(ctx
.obj
, ctx
.command
.name
)
2951 filter='&'.join(filter)
2952 resp
= ctx
.obj
.sdnc
.list(filter)
2953 # except ClientException as e:
2956 table
= PrettyTable(['sdnc name', 'id'])
2958 table
.add_row([sdnc
['name'], sdnc
['_id']])
2963 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2964 @click.argument('name')
2966 def sdnc_show(ctx
, name
):
2967 """shows the details of an SDN controller
2969 NAME: name or ID of the SDN controller
2973 check_client_version(ctx
.obj
, ctx
.command
.name
)
2974 resp
= ctx
.obj
.sdnc
.get(name
)
2975 # except ClientException as e:
2979 table
= PrettyTable(['key', 'attribute'])
2980 for k
, v
in list(resp
.items()):
2981 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2986 ###########################
2987 # K8s cluster operations
2988 ###########################
2990 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2991 @click.argument('name')
2992 @click.option('--creds',
2994 help='credentials file, i.e. a valid `.kube/config` file')
2995 @click.option('--version',
2997 help='Kubernetes version')
2998 @click.option('--vim',
3000 help='VIM target, the VIM where the cluster resides')
3001 @click.option('--k8s-nets',
3003 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) ...]}"')
3004 @click.option('--description',
3006 help='human readable description')
3007 @click.option('--namespace',
3008 default
='kube-system',
3009 help='namespace to be used for its operation, defaults to `kube-system`')
3010 @click.option('--cni',
3012 help='list of CNI plugins, in JSON inline format, used in the cluster')
3013 #@click.option('--skip-init',
3015 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3016 #@click.option('--wait',
3018 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3020 def k8scluster_add(ctx
,
3029 """adds a K8s cluster to OSM
3031 NAME: name of the K8s cluster
3034 check_client_version(ctx
.obj
, ctx
.command
.name
)
3036 cluster
['name'] = name
3037 with
open(creds
, 'r') as cf
:
3038 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3039 cluster
['k8s_version'] = version
3040 cluster
['vim_account'] = vim
3041 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3043 cluster
['description'] = description
3044 if namespace
: cluster
['namespace'] = namespace
3045 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3046 ctx
.obj
.k8scluster
.create(name
, cluster
)
3047 # except ClientException as e:
3052 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
3053 @click.argument('name')
3054 @click.option('--newname', help='New name for the K8s cluster')
3055 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3056 @click.option('--version', help='Kubernetes version')
3057 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3058 @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) ...]}"')
3059 @click.option('--description', help='human readable description')
3060 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3061 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3063 def k8scluster_update(ctx
,
3073 """updates a K8s cluster
3075 NAME: name or ID of the K8s cluster
3078 check_client_version(ctx
.obj
, ctx
.command
.name
)
3080 if newname
: cluster
['name'] = newname
3082 with
open(creds
, 'r') as cf
:
3083 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3084 if version
: cluster
['k8s_version'] = version
3085 if vim
: cluster
['vim_account'] = vim
3086 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3087 if description
: cluster
['description'] = description
3088 if namespace
: cluster
['namespace'] = namespace
3089 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3090 ctx
.obj
.k8scluster
.update(name
, cluster
)
3091 # except ClientException as e:
3096 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
3097 @click.argument('name')
3098 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3099 #@click.option('--wait',
3101 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3103 def k8scluster_delete(ctx
, name
, force
):
3104 """deletes a K8s cluster
3106 NAME: name or ID of the K8s cluster to be deleted
3109 check_client_version(ctx
.obj
, ctx
.command
.name
)
3110 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3111 # except ClientException as e:
3116 @cli_osm.command(name
='k8scluster-list')
3117 @click.option('--filter', default
=None, multiple
=True,
3118 help='restricts the list to the K8s clusters matching the filter')
3119 @click.option('--literal', is_flag
=True,
3120 help='print literally, no pretty table')
3122 def k8scluster_list(ctx
, filter, literal
):
3123 """list all K8s clusters"""
3125 check_client_version(ctx
.obj
, ctx
.command
.name
)
3127 filter='&'.join(filter)
3128 resp
= ctx
.obj
.k8scluster
.list(filter)
3130 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3132 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
3133 for cluster
in resp
:
3134 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
3135 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
3136 trunc_text(cluster
.get('description') or '', 40)])
3139 # except ClientException as e:
3144 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
3145 @click.argument('name')
3146 @click.option('--literal', is_flag
=True,
3147 help='print literally, no pretty table')
3149 def k8scluster_show(ctx
, name
, literal
):
3150 """shows the details of a K8s cluster
3152 NAME: name or ID of the K8s cluster
3155 resp
= ctx
.obj
.k8scluster
.get(name
)
3157 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3159 table
= PrettyTable(['key', 'attribute'])
3160 for k
, v
in list(resp
.items()):
3161 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
3164 # except ClientException as e:
3170 ###########################
3172 ###########################
3174 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
3175 @click.argument('name')
3176 @click.argument('uri')
3177 @click.option('--type',
3178 type=click
.Choice(['helm-chart', 'juju-bundle', 'osm']),
3180 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3181 @click.option('--description',
3183 help='human readable description')
3184 @click.option('--user',
3186 help='OSM repository: The username of the OSM repository')
3187 @click.option('--password',
3189 help='OSM repository: The password of the OSM repository')
3190 #@click.option('--wait',
3192 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3194 def repo_add(ctx
, **kwargs
):
3195 """adds a repo to OSM
3197 NAME: name of the repo
3198 URI: URI of the repo
3201 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
3203 repo
["url"] = repo
.pop("uri")
3204 if repo
["type"] in ['helm-chart', 'juju-bundle']:
3205 ctx
.obj
.repo
.create(repo
['name'], repo
)
3207 ctx
.obj
.osmrepo
.create(repo
['name'], repo
)
3208 # except ClientException as e:
3213 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
3214 @click.argument('name')
3215 @click.option('--newname', help='New name for the repo')
3216 @click.option('--uri', help='URI of the repo')
3217 @click.option('--description', help='human readable description')
3218 #@click.option('--wait',
3220 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3222 def repo_update(ctx
,
3227 """updates a repo in OSM
3229 NAME: name of the repo
3232 check_client_version(ctx
.obj
, ctx
.command
.name
)
3235 repo
['name'] = newname
3238 if description
: repo
['description'] = description
3240 ctx
.obj
.repo
.update(name
, repo
)
3242 ctx
.obj
.osmrepo
.update(name
, repo
)
3244 # except ClientException as e:
3249 @cli_osm.command(name
='repo-index', short_help
='Index a repository from a folder with artifacts')
3250 @click.option('--origin', default
='.', help='origin path where the artifacts are located')
3251 @click.option('--destination', default
='.', help='destination path where the index is deployed')
3253 def repo_index(ctx
, origin
, destination
):
3254 """Index a repository
3256 NAME: name or ID of the repo to be deleted
3258 check_client_version(ctx
.obj
, ctx
.command
.name
)
3259 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
3262 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
3263 @click.argument('name')
3264 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3265 #@click.option('--wait',
3267 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3269 def repo_delete(ctx
, name
, force
):
3272 NAME: name or ID of the repo to be deleted
3276 ctx
.obj
.repo
.delete(name
, force
=force
)
3278 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
3279 # except ClientException as e:
3284 @cli_osm.command(name
='repo-list')
3285 @click.option('--filter', default
=None, multiple
=True,
3286 help='restricts the list to the repos matching the filter')
3287 @click.option('--literal', is_flag
=True,
3288 help='print literally, no pretty table')
3290 def repo_list(ctx
, filter, literal
):
3291 """list all repos"""
3294 check_client_version(ctx
.obj
, ctx
.command
.name
)
3296 filter='&'.join(filter)
3297 resp
= ctx
.obj
.repo
.list(filter)
3298 resp
+= ctx
.obj
.osmrepo
.list(filter)
3300 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3302 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3304 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3305 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description') or '',40)])
3309 # except ClientException as e:
3314 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
3315 @click.argument('name')
3316 @click.option('--literal', is_flag
=True,
3317 help='print literally, no pretty table')
3319 def repo_show(ctx
, name
, literal
):
3320 """shows the details of a repo
3322 NAME: name or ID of the repo
3325 resp
= ctx
.obj
.repo
.get(name
)
3327 resp
= ctx
.obj
.osmrepo
.get(name
)
3331 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3333 table
= PrettyTable(['key', 'attribute'])
3335 for k
, v
in list(resp
.items()):
3336 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3340 # except ClientException as e:
3346 ####################
3347 # Project mgmt operations
3348 ####################
3350 @cli_osm.command(name
='project-create', short_help
='creates a new project')
3351 @click.argument('name')
3352 #@click.option('--description',
3353 # default='no description',
3354 # help='human readable description')
3355 @click.option('--domain-name', 'domain_name',
3357 help='assign to a domain')
3358 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3359 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3360 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3362 def project_create(ctx
, name
, domain_name
, quotas
):
3363 """Creates a new project
3365 NAME: name of the project
3366 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3367 QUOTAS: set quotas for the project
3370 project
= {'name': name
}
3372 project
['domain_name'] = domain_name
3373 quotas_dict
= _process_project_quotas(quotas
)
3375 project
['quotas'] = quotas_dict
3378 check_client_version(ctx
.obj
, ctx
.command
.name
)
3379 ctx
.obj
.project
.create(name
, project
)
3380 # except ClientException as e:
3385 def _process_project_quotas(quota_list
):
3390 for quota
in quota_list
:
3391 for single_quota
in quota
.split(","):
3392 k
, v
= single_quota
.split("=")
3393 quotas_dict
[k
] = None if v
in ('None', 'null', '') else int(v
)
3394 except (ValueError, TypeError):
3395 raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3399 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3400 @click.argument('name')
3401 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3403 def project_delete(ctx
, name
):
3404 """deletes a project
3406 NAME: name or ID of the project to be deleted
3410 check_client_version(ctx
.obj
, ctx
.command
.name
)
3411 ctx
.obj
.project
.delete(name
)
3412 # except ClientException as e:
3417 @cli_osm.command(name
='project-list', short_help
='list all projects')
3418 @click.option('--filter', default
=None, multiple
=True,
3419 help='restricts the list to the projects matching the filter')
3421 def project_list(ctx
, filter):
3422 """list all projects"""
3425 check_client_version(ctx
.obj
, ctx
.command
.name
)
3427 filter='&'.join(filter)
3428 resp
= ctx
.obj
.project
.list(filter)
3429 # except ClientException as e:
3432 table
= PrettyTable(['name', 'id'])
3434 table
.add_row([proj
['name'], proj
['_id']])
3439 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3440 @click.argument('name')
3442 def project_show(ctx
, name
):
3443 """shows the details of a project
3445 NAME: name or ID of the project
3449 check_client_version(ctx
.obj
, ctx
.command
.name
)
3450 resp
= ctx
.obj
.project
.get(name
)
3451 # except ClientException as e:
3455 table
= PrettyTable(['key', 'attribute'])
3456 for k
, v
in resp
.items():
3457 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3462 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3463 @click.argument('project')
3464 @click.option('--name', default
=None,
3465 help='new name for the project')
3466 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3467 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3468 "(use empty to reset quota to default")
3470 def project_update(ctx
, project
, name
, quotas
):
3472 Update a project name
3475 :param project: id or name of the project to modify
3476 :param name: new name for the project
3477 :param quotas: change quotas of the project
3481 project_changes
= {}
3483 project_changes
['name'] = name
3484 quotas_dict
= _process_project_quotas(quotas
)
3486 project_changes
['quotas'] = quotas_dict
3489 check_client_version(ctx
.obj
, ctx
.command
.name
)
3490 ctx
.obj
.project
.update(project
, project_changes
)
3491 # except ClientException as e:
3495 ####################
3496 # User mgmt operations
3497 ####################
3499 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3500 @click.argument('username')
3501 @click.option('--password',
3504 confirmation_prompt
=True,
3505 help='user password')
3506 @click.option('--projects',
3507 # prompt="Comma separate list of projects",
3509 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3510 help='list of project ids that the user belongs to')
3511 @click.option('--project-role-mappings', 'project_role_mappings',
3512 default
=None, multiple
=True,
3513 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3514 @click.option('--domain-name', 'domain_name',
3516 help='assign to a domain')
3518 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
3519 """Creates a new user
3522 USERNAME: name of the user
3523 PASSWORD: password of the user
3524 PROJECTS: projects assigned to user (internal only)
3525 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3526 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3530 user
['username'] = username
3531 user
['password'] = password
3532 user
['projects'] = projects
3533 user
['project_role_mappings'] = project_role_mappings
3535 user
['domain_name'] = domain_name
3538 check_client_version(ctx
.obj
, ctx
.command
.name
)
3539 ctx
.obj
.user
.create(username
, user
)
3540 # except ClientException as e:
3545 @cli_osm.command(name
='user-update', short_help
='updates user information')
3546 @click.argument('username')
3547 @click.option('--password',
3550 # confirmation_prompt=True,
3551 help='user password')
3552 @click.option('--set-username', 'set_username',
3554 help='change username')
3555 @click.option('--set-project', 'set_project',
3556 default
=None, multiple
=True,
3557 help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3558 @click.option('--remove-project', 'remove_project',
3559 default
=None, multiple
=True,
3560 help="removes project from user: 'project'")
3561 @click.option('--add-project-role', 'add_project_role',
3562 default
=None, multiple
=True,
3563 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3564 @click.option('--remove-project-role', 'remove_project_role',
3565 default
=None, multiple
=True,
3566 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3568 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3569 add_project_role
, remove_project_role
):
3570 """Update a user information
3573 USERNAME: name of the user
3574 PASSWORD: new password
3575 SET_USERNAME: new username
3576 SET_PROJECT: creating mappings for project/role(s)
3577 REMOVE_PROJECT: deleting mappings for project/role(s)
3578 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3579 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3583 user
['password'] = password
3584 user
['username'] = set_username
3585 user
['set-project'] = set_project
3586 user
['remove-project'] = remove_project
3587 user
['add-project-role'] = add_project_role
3588 user
['remove-project-role'] = remove_project_role
3591 check_client_version(ctx
.obj
, ctx
.command
.name
)
3592 ctx
.obj
.user
.update(username
, user
)
3593 # except ClientException as e:
3598 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3599 @click.argument('name')
3600 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3602 def user_delete(ctx
, name
):
3606 NAME: name or ID of the user to be deleted
3610 check_client_version(ctx
.obj
, ctx
.command
.name
)
3611 ctx
.obj
.user
.delete(name
)
3612 # except ClientException as e:
3617 @cli_osm.command(name
='user-list', short_help
='list all users')
3618 @click.option('--filter', default
=None, multiple
=True,
3619 help='restricts the list to the users matching the filter')
3621 def user_list(ctx
, filter):
3622 """list all users"""
3624 check_client_version(ctx
.obj
, ctx
.command
.name
)
3626 filter='&'.join(filter)
3627 resp
= ctx
.obj
.user
.list(filter)
3628 # except ClientException as e:
3631 table
= PrettyTable(['name', 'id'])
3633 table
.add_row([user
['username'], user
['_id']])
3638 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3639 @click.argument('name')
3641 def user_show(ctx
, name
):
3642 """shows the details of a user
3644 NAME: name or ID of the user
3648 check_client_version(ctx
.obj
, ctx
.command
.name
)
3649 resp
= ctx
.obj
.user
.get(name
)
3650 if 'password' in resp
:
3651 resp
['password']='********'
3652 # except ClientException as e:
3656 table
= PrettyTable(['key', 'attribute'])
3657 for k
, v
in resp
.items():
3658 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3663 ####################
3664 # Fault Management operations
3665 ####################
3667 @cli_osm.command(name
='ns-alarm-create')
3668 @click.argument('name')
3669 @click.option('--ns', prompt
=True, help='NS instance id or name')
3670 @click.option('--vnf', prompt
=True,
3671 help='VNF name (VNF member index as declared in the NSD)')
3672 @click.option('--vdu', prompt
=True,
3673 help='VDU name (VDU name as declared in the VNFD)')
3674 @click.option('--metric', prompt
=True,
3675 help='Name of the metric (e.g. cpu_utilization)')
3676 @click.option('--severity', default
='WARNING',
3677 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3678 @click.option('--threshold_value', prompt
=True,
3679 help='threshold value that, when crossed, an alarm is triggered')
3680 @click.option('--threshold_operator', prompt
=True,
3681 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3682 @click.option('--statistic', default
='AVERAGE',
3683 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3685 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3686 threshold_value
, threshold_operator
, statistic
):
3687 """creates a new alarm for a NS instance"""
3688 # TODO: Check how to validate threshold_value.
3689 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3692 ns_instance
= ctx
.obj
.ns
.get(ns
)
3694 alarm
['alarm_name'] = name
3695 alarm
['ns_id'] = ns_instance
['_id']
3696 alarm
['correlation_id'] = ns_instance
['_id']
3697 alarm
['vnf_member_index'] = vnf
3698 alarm
['vdu_name'] = vdu
3699 alarm
['metric_name'] = metric
3700 alarm
['severity'] = severity
3701 alarm
['threshold_value'] = int(threshold_value
)
3702 alarm
['operation'] = threshold_operator
3703 alarm
['statistic'] = statistic
3704 check_client_version(ctx
.obj
, ctx
.command
.name
)
3705 ctx
.obj
.ns
.create_alarm(alarm
)
3706 # except ClientException as e:
3711 #@cli_osm.command(name='ns-alarm-delete')
3712 #@click.argument('name')
3713 #@click.pass_context
3714 #def ns_alarm_delete(ctx, name):
3715 # """deletes an alarm
3717 # NAME: name of the alarm to be deleted
3720 # check_client_version(ctx.obj, ctx.command.name)
3721 # ctx.obj.ns.delete_alarm(name)
3722 # except ClientException as e:
3727 ####################
3728 # Performance Management operations
3729 ####################
3731 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3732 @click.option('--ns', prompt
=True, help='NS instance id or name')
3733 @click.option('--vnf', prompt
=True,
3734 help='VNF name (VNF member index as declared in the NSD)')
3735 @click.option('--vdu', prompt
=True,
3736 help='VDU name (VDU name as declared in the VNFD)')
3737 @click.option('--metric', prompt
=True,
3738 help='name of the metric (e.g. cpu_utilization)')
3739 #@click.option('--period', default='1w',
3740 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3741 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3743 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3744 """exports a metric to the internal OSM bus, which can be read by other apps"""
3745 # TODO: Check how to validate interval.
3746 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3749 ns_instance
= ctx
.obj
.ns
.get(ns
)
3751 metric_data
['ns_id'] = ns_instance
['_id']
3752 metric_data
['correlation_id'] = ns_instance
['_id']
3753 metric_data
['vnf_member_index'] = vnf
3754 metric_data
['vdu_name'] = vdu
3755 metric_data
['metric_name'] = metric
3756 metric_data
['collection_unit'] = 'WEEK'
3757 metric_data
['collection_period'] = 1
3758 check_client_version(ctx
.obj
, ctx
.command
.name
)
3760 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3764 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3765 time
.sleep(int(interval
))
3767 # except ClientException as e:
3772 ####################
3774 ####################
3776 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3778 def get_version(ctx
):
3779 """shows client and server versions"""
3781 check_client_version(ctx
.obj
, "version")
3782 print ("Server version: {}".format(ctx
.obj
.get_version()))
3783 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3784 # except ClientException as e:
3788 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3789 @click.argument('filename')
3790 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3791 help='the charm will not be compiled, it is assumed to already exist')
3793 def upload_package(ctx
, filename
, skip_charm_build
):
3794 """uploads a vnf package or ns package
3796 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3800 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3801 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3802 if fullclassname
!= 'osmclient.sol005.client.Client':
3803 ctx
.obj
.package
.wait_for_upload(filename
)
3804 # except ClientException as e:
3809 #@cli_osm.command(name='ns-scaling-show')
3810 #@click.argument('ns_name')
3811 #@click.pass_context
3812 #def show_ns_scaling(ctx, ns_name):
3813 # """shows the status of a NS scaling operation
3815 # NS_NAME: name of the NS instance being scaled
3818 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3819 # resp = ctx.obj.ns.list()
3820 # except ClientException as e:
3824 # table = PrettyTable(
3827 # 'operational status',
3832 # if ns_name == ns['name']:
3833 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3834 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3835 # for record in scaling_records:
3836 # if 'instance' in record:
3837 # instances = record['instance']
3838 # for inst in instances:
3840 # [record['scaling-group-name-ref'],
3841 # inst['instance-id'],
3842 # inst['op-status'],
3843 # time.strftime('%Y-%m-%d %H:%M:%S',
3845 # inst['create-time'])),
3851 #@cli_osm.command(name='ns-scale')
3852 #@click.argument('ns_name')
3853 #@click.option('--ns_scale_group', prompt=True)
3854 #@click.option('--index', prompt=True)
3855 #@click.option('--wait',
3859 # help='do not return the control immediately, but keep it \
3860 # until the operation is completed, or timeout')
3861 #@click.pass_context
3862 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3865 # NS_NAME: name of the NS instance to be scaled
3868 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3869 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3870 # except ClientException as e:
3875 #@cli_osm.command(name='config-agent-list')
3876 #@click.pass_context
3877 #def config_agent_list(ctx):
3878 # """list config agents"""
3880 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3881 # except ClientException as e:
3884 # table = PrettyTable(['name', 'account-type', 'details'])
3885 # for account in ctx.obj.vca.list():
3888 # account['account-type'],
3894 #@cli_osm.command(name='config-agent-delete')
3895 #@click.argument('name')
3896 #@click.pass_context
3897 #def config_agent_delete(ctx, name):
3898 # """deletes a config agent
3900 # NAME: name of the config agent to be deleted
3903 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3904 # ctx.obj.vca.delete(name)
3905 # except ClientException as e:
3910 #@cli_osm.command(name='config-agent-add')
3911 #@click.option('--name',
3913 #@click.option('--account_type',
3915 #@click.option('--server',
3917 #@click.option('--user',
3919 #@click.option('--secret',
3922 # confirmation_prompt=True)
3923 #@click.pass_context
3924 #def config_agent_add(ctx, name, account_type, server, user, secret):
3925 # """adds a config agent"""
3927 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3928 # ctx.obj.vca.create(name, account_type, server, user, secret)
3929 # except ClientException as e:
3934 #@cli_osm.command(name='ro-dump')
3935 #@click.pass_context
3937 # """shows RO agent information"""
3938 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3939 # resp = ctx.obj.vim.get_resource_orchestrator()
3940 # table = PrettyTable(['key', 'attribute'])
3941 # for k, v in list(resp.items()):
3942 # table.add_row([k, json.dumps(v, indent=2)])
3947 #@cli_osm.command(name='vcs-list')
3948 #@click.pass_context
3950 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3951 # resp = ctx.obj.utils.get_vcs_info()
3952 # table = PrettyTable(['component name', 'state'])
3953 # for component in resp:
3954 # table.add_row([component['component_name'], component['state']])
3959 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3960 @click.argument('ns_name')
3961 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3962 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3963 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3964 @click.option('--vdu_count', default
=None, type=int, help='number of vdu instance of this vdu_id')
3965 @click.option('--action_name', prompt
=True, help='action name')
3966 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3967 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3968 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
3969 @click.option('--wait',
3973 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3986 """executes an action/primitive over a NS instance
3988 NS_NAME: name or ID of the NS instance
3992 check_client_version(ctx
.obj
, ctx
.command
.name
)
3995 op_data
['member_vnf_index'] = vnf_name
3997 op_data
['kdu_name'] = kdu_name
3999 op_data
['vdu_id'] = vdu_id
4000 if vdu_count
is not None:
4001 op_data
['vdu_count_index'] = vdu_count
4003 op_data
['timeout_ns_action'] = timeout
4004 op_data
['primitive'] = action_name
4006 with
open(params_file
, 'r') as pf
:
4009 op_data
['primitive_params'] = yaml
.safe_load(params
)
4011 op_data
['primitive_params'] = {}
4012 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
4014 # except ClientException as e:
4019 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
4020 @click.argument('ns_name')
4021 @click.argument('vnf_name')
4022 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
4023 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
4024 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
4025 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4026 @click.option('--wait', required
=False, default
=False, is_flag
=True,
4027 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4038 Executes a VNF scale (adding/removing VDUs)
4041 NS_NAME: name or ID of the NS instance.
4042 VNF_NAME: member-vnf-index in the NS to be scaled.
4046 check_client_version(ctx
.obj
, ctx
.command
.name
)
4047 if not scale_in
and not scale_out
:
4049 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
)
4050 # except ClientException as e:
4055 ##############################
4056 # Role Management Operations #
4057 ##############################
4059 @cli_osm.command(name
='role-create', short_help
='creates a new role')
4060 @click.argument('name')
4061 @click.option('--permissions',
4063 help='role permissions using a dictionary')
4065 def role_create(ctx
, name
, permissions
):
4070 NAME: Name or ID of the role.
4071 DEFINITION: Definition of grant/denial of access to resources.
4075 check_client_version(ctx
.obj
, ctx
.command
.name
)
4076 ctx
.obj
.role
.create(name
, permissions
)
4077 # except ClientException as e:
4082 @cli_osm.command(name
='role-update', short_help
='updates a role')
4083 @click.argument('name')
4084 @click.option('--set-name',
4086 help='change name of rle')
4087 # @click.option('--permissions',
4089 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4090 @click.option('--add',
4092 help='yaml format dictionary with permission: True/False to access grant/denial')
4093 @click.option('--remove',
4095 help='yaml format list to remove a permission')
4097 def role_update(ctx
, name
, set_name
, add
, remove
):
4102 NAME: Name or ID of the role.
4103 DEFINITION: Definition overwrites the old definition.
4104 ADD: Grant/denial of access to resource to add.
4105 REMOVE: Grant/denial of access to resource to remove.
4109 check_client_version(ctx
.obj
, ctx
.command
.name
)
4110 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
4111 # except ClientException as e:
4116 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
4117 @click.argument('name')
4118 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4120 def role_delete(ctx
, name
):
4125 NAME: Name or ID of the role.
4129 check_client_version(ctx
.obj
, ctx
.command
.name
)
4130 ctx
.obj
.role
.delete(name
)
4131 # except ClientException as e:
4136 @cli_osm.command(name
='role-list', short_help
='list all roles')
4137 @click.option('--filter', default
=None, multiple
=True,
4138 help='restricts the list to the projects matching the filter')
4140 def role_list(ctx
, filter):
4146 check_client_version(ctx
.obj
, ctx
.command
.name
)
4148 filter='&'.join(filter)
4149 resp
= ctx
.obj
.role
.list(filter)
4150 # except ClientException as e:
4153 table
= PrettyTable(['name', 'id'])
4155 table
.add_row([role
['name'], role
['_id']])
4160 @cli_osm.command(name
='role-show', short_help
='show specific role')
4161 @click.argument('name')
4163 def role_show(ctx
, name
):
4165 Shows the details of a role.
4168 NAME: Name or ID of the role.
4172 check_client_version(ctx
.obj
, ctx
.command
.name
)
4173 resp
= ctx
.obj
.role
.get(name
)
4174 # except ClientException as e:
4178 table
= PrettyTable(['key', 'attribute'])
4179 for k
, v
in resp
.items():
4180 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4185 @cli_osm.command(name
='package-create',
4186 short_help
='Create a package descriptor')
4187 @click.argument('package-type')
4188 @click.argument('package-name')
4189 @click.option('--base-directory',
4191 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4192 @click.option('--image',
4193 default
="image-name",
4194 help='(VNF) Set the name of the vdu image. Default "image-name"')
4195 @click.option('--vdus',
4197 help='(VNF) Set the number of vdus in a VNF. Default 1')
4198 @click.option('--vcpu',
4200 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4201 @click.option('--memory',
4203 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4204 @click.option('--storage',
4206 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4207 @click.option('--interfaces',
4209 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4210 @click.option('--vendor',
4212 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4213 @click.option('--override',
4216 help='(NS/VNF/NST) Flag for overriding the package if exists.')
4217 @click.option('--detailed',
4220 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4221 @click.option('--netslice-subnets',
4223 help='(NST) Number of netslice subnets. Default 1')
4224 @click.option('--netslice-vlds',
4226 help='(NST) Number of netslice vlds. Default 1')
4228 def package_create(ctx
,
4244 Creates an OSM NS, VNF, NST package
4247 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4248 PACKAGE_NAME: Name of the package to create the folder with the content.
4252 check_client_version(ctx
.obj
, ctx
.command
.name
)
4253 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
4254 resp
= ctx
.obj
.package_tool
.create(package_type
,
4263 interfaces
=interfaces
,
4266 netslice_subnets
=netslice_subnets
,
4267 netslice_vlds
=netslice_vlds
)
4269 # except ClientException as inst:
4270 # print("ERROR: {}".format(inst))
4273 @cli_osm.command(name
='package-validate',
4274 short_help
='Validate a package descriptor')
4275 @click.argument('base-directory',
4278 @click.option('--recursive/--no-recursive',
4280 help='The activated recursive option will validate the yaml files'
4281 ' within the indicated directory and in its subdirectories')
4283 def package_validate(ctx
,
4287 Validate descriptors given a base directory.
4290 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4293 check_client_version(ctx
.obj
, ctx
.command
.name
)
4294 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
4295 table
= PrettyTable()
4296 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
4297 # Print the dictionary generated by the validation function
4298 for result
in results
:
4299 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
4300 table
.sortby
= "VALID"
4301 table
.align
["PATH"] = "l"
4302 table
.align
["TYPE"] = "l"
4303 table
.align
["ERROR"] = "l"
4305 # except ClientException as inst:
4306 # print("ERROR: {}".format(inst))
4309 @cli_osm.command(name
='package-build',
4310 short_help
='Build the tar.gz of the package')
4311 @click.argument('package-folder')
4312 @click.option('--skip-validation',
4315 help='skip package validation')
4316 @click.option('--skip-charm-build', default
=False, is_flag
=True,
4317 help='the charm will not be compiled, it is assumed to already exist')
4319 def package_build(ctx
,
4324 Build the package NS, VNF given the package_folder.
4327 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4330 check_client_version(ctx
.obj
, ctx
.command
.name
)
4331 results
= ctx
.obj
.package_tool
.build(package_folder
,
4332 skip_validation
=skip_validation
,
4333 skip_charm_build
=skip_charm_build
)
4335 # except ClientException as inst:
4336 # print("ERROR: {}".format(inst))
4344 except pycurl
.error
as exc
:
4346 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4347 except ClientException
as exc
:
4348 print("ERROR: {}".format(exc
))
4349 except (FileNotFoundError
, PermissionError
) as exc
:
4350 print("Cannot open file: {}".format(exc
))
4351 except yaml
.YAMLError
as exc
:
4352 print("Invalid YAML format: {}".format(exc
))
4354 # TODO capture other controlled exceptions here
4355 # TODO remove the ClientException captures from all places, unless they do something different
4358 if __name__
== '__main__':