d71eaaae432e07d4f2aa902fc7db2af86ed57690
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')
2600 @click.option('--filter', multiple
=True,
2601 help='restricts the information to the fields in the filter')
2603 def vim_show(ctx
, name
, filter):
2604 """shows the details of a VIM account
2606 NAME: name or ID of the VIM account
2610 resp
= ctx
.obj
.vim
.get(name
)
2611 if 'vim_password' in resp
:
2612 resp
['vim_password']='********'
2613 # except ClientException as e:
2617 table
= PrettyTable(['key', 'attribute'])
2618 for k
, v
in list(resp
.items()):
2619 if not filter or k
in filter:
2620 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2625 ####################
2627 ####################
2629 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2630 @click.option('--name',
2632 help='Name for the WIM account')
2633 @click.option('--user',
2634 help='WIM username')
2635 @click.option('--password',
2636 help='WIM password')
2637 @click.option('--url',
2640 # @click.option('--tenant',
2641 # help='wIM tenant name')
2642 @click.option('--config',
2644 help='WIM specific config parameters')
2645 @click.option('--wim_type',
2647 @click.option('--description',
2649 help='human readable description')
2650 @click.option('--wim_port_mapping', default
=None,
2651 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2652 "(WAN service endpoint id and info)")
2653 @click.option('--wait',
2657 help='do not return the control immediately, but keep it '
2658 'until the operation is completed, or timeout')
2671 """creates a new WIM account"""
2674 check_client_version(ctx
.obj
, ctx
.command
.name
)
2675 # if sdn_controller:
2676 # check_client_version(ctx.obj, '--sdn_controller')
2677 # if sdn_port_mapping:
2678 # check_client_version(ctx.obj, '--sdn_port_mapping')
2680 if user
: wim
['user'] = user
2681 if password
: wim
['password'] = password
2682 if url
: wim
['wim_url'] = url
2683 # if tenant: wim['tenant'] = tenant
2684 wim
['wim_type'] = wim_type
2685 if description
: wim
['description'] = description
2686 if config
: wim
['config'] = config
2687 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2688 # except ClientException as e:
2693 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2694 @click.argument('name')
2695 @click.option('--newname', help='New name for the WIM account')
2696 @click.option('--user', help='WIM username')
2697 @click.option('--password', help='WIM password')
2698 @click.option('--url', help='WIM url')
2699 @click.option('--config', help='WIM specific config parameters')
2700 @click.option('--wim_type', help='WIM type')
2701 @click.option('--description', help='human readable description')
2702 @click.option('--wim_port_mapping', default
=None,
2703 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2704 "(WAN service endpoint id and info)")
2705 @click.option('--wait',
2709 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2722 """updates a WIM account
2724 NAME: name or ID of the WIM account
2728 check_client_version(ctx
.obj
, ctx
.command
.name
)
2730 if newname
: wim
['name'] = newname
2731 if user
: wim
['user'] = user
2732 if password
: wim
['password'] = password
2733 if url
: wim
['url'] = url
2734 # if tenant: wim['tenant'] = tenant
2735 if wim_type
: wim
['wim_type'] = wim_type
2736 if description
: wim
['description'] = description
2737 if config
: wim
['config'] = config
2738 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2739 # except ClientException as e:
2744 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2745 @click.argument('name')
2746 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2747 @click.option('--wait',
2751 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2753 def wim_delete(ctx
, name
, force
, wait
):
2754 """deletes a WIM account
2756 NAME: name or ID of the WIM account to be deleted
2760 check_client_version(ctx
.obj
, ctx
.command
.name
)
2761 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2762 # except ClientException as e:
2767 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2768 @click.option('--filter', default
=None, multiple
=True,
2769 help='restricts the list to the WIM accounts matching the filter')
2771 def wim_list(ctx
, filter):
2772 """list all WIM accounts"""
2775 check_client_version(ctx
.obj
, ctx
.command
.name
)
2777 filter='&'.join(filter)
2778 resp
= ctx
.obj
.wim
.list(filter)
2779 table
= PrettyTable(['wim name', 'uuid'])
2781 table
.add_row([wim
['name'], wim
['uuid']])
2784 # except ClientException as e:
2789 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2790 @click.argument('name')
2792 def wim_show(ctx
, name
):
2793 """shows the details of a WIM account
2795 NAME: name or ID of the WIM account
2799 check_client_version(ctx
.obj
, ctx
.command
.name
)
2800 resp
= ctx
.obj
.wim
.get(name
)
2801 if 'password' in resp
:
2802 resp
['wim_password']='********'
2803 # except ClientException as e:
2807 table
= PrettyTable(['key', 'attribute'])
2808 for k
, v
in list(resp
.items()):
2809 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2814 ####################
2815 # SDN controller operations
2816 ####################
2818 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2819 @click.option('--name',
2821 help='Name to create sdn controller')
2822 @click.option('--type',
2824 help='SDN controller type')
2825 @click.option('--sdn_controller_version', # hidden=True,
2826 help='Deprecated. Use --config {version: sdn_controller_version}')
2827 @click.option('--url',
2828 help='URL in format http[s]://HOST:IP/')
2829 @click.option('--ip_address', # hidden=True,
2830 help='Deprecated. Use --url')
2831 @click.option('--port', # hidden=True,
2832 help='Deprecated. Use --url')
2833 @click.option('--switch_dpid', # hidden=True,
2834 help='Deprecated. Use --config {switch_id: DPID}')
2835 @click.option('--config',
2836 help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2837 'Openflow Datapath ID), version: version}')
2838 @click.option('--user',
2839 help='SDN controller username')
2840 @click.option('--password',
2842 confirmation_prompt
=True,
2843 help='SDN controller password')
2844 @click.option('--description', default
=None, help='human readable description')
2845 @click.option('--wait',
2849 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2851 def sdnc_create(ctx
, **kwargs
):
2852 """creates a new SDN controller"""
2854 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2855 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2856 if kwargs
.get("port"):
2857 print("option '--port' is deprecated, use '--url' instead")
2858 sdncontroller
["port"] = int(kwargs
["port"])
2859 if kwargs
.get("ip_address"):
2860 print("option '--ip_address' is deprecated, use '--url' instead")
2861 sdncontroller
["ip"] = kwargs
["ip_address"]
2862 if kwargs
.get("switch_dpid"):
2863 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2864 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2865 if kwargs
.get("sdn_controller_version"):
2866 print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2869 check_client_version(ctx
.obj
, ctx
.command
.name
)
2870 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2871 # except ClientException as e:
2875 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2876 @click.argument('name')
2877 @click.option('--newname', help='New name for the SDN controller')
2878 @click.option('--description', default
=None, help='human readable description')
2879 @click.option('--type', help='SDN controller type')
2880 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2881 @click.option('--config', help='Extra information for SDN in yaml format, as '
2882 '{switch_id: identity used for the plugin (e.g. DPID: '
2883 'Openflow Datapath ID), version: version}')
2884 @click.option('--user', help='SDN controller username')
2885 @click.option('--password', help='SDN controller password')
2886 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2887 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2888 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2889 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2890 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2891 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2893 def sdnc_update(ctx
, **kwargs
):
2894 """updates an SDN controller
2896 NAME: name or ID of the SDN controller
2899 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2900 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2901 if kwargs
.get("newname"):
2902 sdncontroller
["name"] = kwargs
["newname"]
2903 if kwargs
.get("port"):
2904 print("option '--port' is deprecated, use '--url' instead")
2905 sdncontroller
["port"] = int(kwargs
["port"])
2906 if kwargs
.get("ip_address"):
2907 print("option '--ip_address' is deprecated, use '--url' instead")
2908 sdncontroller
["ip"] = kwargs
["ip_address"]
2909 if kwargs
.get("switch_dpid"):
2910 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2911 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2912 if kwargs
.get("sdn_controller_version"):
2913 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2917 check_client_version(ctx
.obj
, ctx
.command
.name
)
2918 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2919 # except ClientException as e:
2924 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2925 @click.argument('name')
2926 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2927 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2928 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2930 def sdnc_delete(ctx
, name
, force
, wait
):
2931 """deletes an SDN controller
2933 NAME: name or ID of the SDN controller to be deleted
2937 check_client_version(ctx
.obj
, ctx
.command
.name
)
2938 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2939 # except ClientException as e:
2944 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2945 @click.option('--filter', default
=None, multiple
=True,
2946 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2948 def sdnc_list(ctx
, filter):
2949 """list all SDN controllers"""
2952 check_client_version(ctx
.obj
, ctx
.command
.name
)
2954 filter='&'.join(filter)
2955 resp
= ctx
.obj
.sdnc
.list(filter)
2956 # except ClientException as e:
2959 table
= PrettyTable(['sdnc name', 'id'])
2961 table
.add_row([sdnc
['name'], sdnc
['_id']])
2966 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2967 @click.argument('name')
2969 def sdnc_show(ctx
, name
):
2970 """shows the details of an SDN controller
2972 NAME: name or ID of the SDN controller
2976 check_client_version(ctx
.obj
, ctx
.command
.name
)
2977 resp
= ctx
.obj
.sdnc
.get(name
)
2978 # except ClientException as e:
2982 table
= PrettyTable(['key', 'attribute'])
2983 for k
, v
in list(resp
.items()):
2984 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2989 ###########################
2990 # K8s cluster operations
2991 ###########################
2993 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2994 @click.argument('name')
2995 @click.option('--creds',
2997 help='credentials file, i.e. a valid `.kube/config` file')
2998 @click.option('--version',
3000 help='Kubernetes version')
3001 @click.option('--vim',
3003 help='VIM target, the VIM where the cluster resides')
3004 @click.option('--k8s-nets',
3006 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) ...]}"')
3007 @click.option('--description',
3009 help='human readable description')
3010 @click.option('--namespace',
3011 default
='kube-system',
3012 help='namespace to be used for its operation, defaults to `kube-system`')
3013 @click.option('--cni',
3015 help='list of CNI plugins, in JSON inline format, used in the cluster')
3016 #@click.option('--skip-init',
3018 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3019 #@click.option('--wait',
3021 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3023 def k8scluster_add(ctx
,
3032 """adds a K8s cluster to OSM
3034 NAME: name of the K8s cluster
3037 check_client_version(ctx
.obj
, ctx
.command
.name
)
3039 cluster
['name'] = name
3040 with
open(creds
, 'r') as cf
:
3041 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3042 cluster
['k8s_version'] = version
3043 cluster
['vim_account'] = vim
3044 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3046 cluster
['description'] = description
3047 if namespace
: cluster
['namespace'] = namespace
3048 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3049 ctx
.obj
.k8scluster
.create(name
, cluster
)
3050 # except ClientException as e:
3055 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
3056 @click.argument('name')
3057 @click.option('--newname', help='New name for the K8s cluster')
3058 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3059 @click.option('--version', help='Kubernetes version')
3060 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3061 @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) ...]}"')
3062 @click.option('--description', help='human readable description')
3063 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3064 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3066 def k8scluster_update(ctx
,
3076 """updates a K8s cluster
3078 NAME: name or ID of the K8s cluster
3081 check_client_version(ctx
.obj
, ctx
.command
.name
)
3083 if newname
: cluster
['name'] = newname
3085 with
open(creds
, 'r') as cf
:
3086 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3087 if version
: cluster
['k8s_version'] = version
3088 if vim
: cluster
['vim_account'] = vim
3089 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3090 if description
: cluster
['description'] = description
3091 if namespace
: cluster
['namespace'] = namespace
3092 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3093 ctx
.obj
.k8scluster
.update(name
, cluster
)
3094 # except ClientException as e:
3099 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
3100 @click.argument('name')
3101 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3102 #@click.option('--wait',
3104 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3106 def k8scluster_delete(ctx
, name
, force
):
3107 """deletes a K8s cluster
3109 NAME: name or ID of the K8s cluster to be deleted
3112 check_client_version(ctx
.obj
, ctx
.command
.name
)
3113 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3114 # except ClientException as e:
3119 @cli_osm.command(name
='k8scluster-list')
3120 @click.option('--filter', default
=None, multiple
=True,
3121 help='restricts the list to the K8s clusters matching the filter')
3122 @click.option('--literal', is_flag
=True,
3123 help='print literally, no pretty table')
3125 def k8scluster_list(ctx
, filter, literal
):
3126 """list all K8s clusters"""
3128 check_client_version(ctx
.obj
, ctx
.command
.name
)
3130 filter='&'.join(filter)
3131 resp
= ctx
.obj
.k8scluster
.list(filter)
3133 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3135 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
3136 for cluster
in resp
:
3137 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
3138 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
3139 trunc_text(cluster
.get('description') or '', 40)])
3142 # except ClientException as e:
3147 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
3148 @click.argument('name')
3149 @click.option('--literal', is_flag
=True,
3150 help='print literally, no pretty table')
3152 def k8scluster_show(ctx
, name
, literal
):
3153 """shows the details of a K8s cluster
3155 NAME: name or ID of the K8s cluster
3158 resp
= ctx
.obj
.k8scluster
.get(name
)
3160 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3162 table
= PrettyTable(['key', 'attribute'])
3163 for k
, v
in list(resp
.items()):
3164 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
3167 # except ClientException as e:
3173 ###########################
3175 ###########################
3177 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
3178 @click.argument('name')
3179 @click.argument('uri')
3180 @click.option('--type',
3181 type=click
.Choice(['helm-chart', 'juju-bundle', 'osm']),
3183 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3184 @click.option('--description',
3186 help='human readable description')
3187 @click.option('--user',
3189 help='OSM repository: The username of the OSM repository')
3190 @click.option('--password',
3192 help='OSM repository: The password of the OSM repository')
3193 #@click.option('--wait',
3195 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3197 def repo_add(ctx
, **kwargs
):
3198 """adds a repo to OSM
3200 NAME: name of the repo
3201 URI: URI of the repo
3204 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
3206 repo
["url"] = repo
.pop("uri")
3207 if repo
["type"] in ['helm-chart', 'juju-bundle']:
3208 ctx
.obj
.repo
.create(repo
['name'], repo
)
3210 ctx
.obj
.osmrepo
.create(repo
['name'], repo
)
3211 # except ClientException as e:
3216 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
3217 @click.argument('name')
3218 @click.option('--newname', help='New name for the repo')
3219 @click.option('--uri', help='URI of the repo')
3220 @click.option('--description', help='human readable description')
3221 #@click.option('--wait',
3223 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3225 def repo_update(ctx
,
3230 """updates a repo in OSM
3232 NAME: name of the repo
3235 check_client_version(ctx
.obj
, ctx
.command
.name
)
3238 repo
['name'] = newname
3241 if description
: repo
['description'] = description
3243 ctx
.obj
.repo
.update(name
, repo
)
3245 ctx
.obj
.osmrepo
.update(name
, repo
)
3247 # except ClientException as e:
3252 @cli_osm.command(name
='repo-index', short_help
='Index a repository from a folder with artifacts')
3253 @click.option('--origin', default
='.', help='origin path where the artifacts are located')
3254 @click.option('--destination', default
='.', help='destination path where the index is deployed')
3256 def repo_index(ctx
, origin
, destination
):
3257 """Index a repository
3259 NAME: name or ID of the repo to be deleted
3261 check_client_version(ctx
.obj
, ctx
.command
.name
)
3262 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
3265 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
3266 @click.argument('name')
3267 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3268 #@click.option('--wait',
3270 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3272 def repo_delete(ctx
, name
, force
):
3275 NAME: name or ID of the repo to be deleted
3279 ctx
.obj
.repo
.delete(name
, force
=force
)
3281 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
3282 # except ClientException as e:
3287 @cli_osm.command(name
='repo-list')
3288 @click.option('--filter', default
=None, multiple
=True,
3289 help='restricts the list to the repos matching the filter')
3290 @click.option('--literal', is_flag
=True,
3291 help='print literally, no pretty table')
3293 def repo_list(ctx
, filter, literal
):
3294 """list all repos"""
3297 check_client_version(ctx
.obj
, ctx
.command
.name
)
3299 filter='&'.join(filter)
3300 resp
= ctx
.obj
.repo
.list(filter)
3301 resp
+= ctx
.obj
.osmrepo
.list(filter)
3303 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3305 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3307 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3308 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description') or '',40)])
3312 # except ClientException as e:
3317 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
3318 @click.argument('name')
3319 @click.option('--literal', is_flag
=True,
3320 help='print literally, no pretty table')
3322 def repo_show(ctx
, name
, literal
):
3323 """shows the details of a repo
3325 NAME: name or ID of the repo
3328 resp
= ctx
.obj
.repo
.get(name
)
3330 resp
= ctx
.obj
.osmrepo
.get(name
)
3334 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3336 table
= PrettyTable(['key', 'attribute'])
3338 for k
, v
in list(resp
.items()):
3339 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3343 # except ClientException as e:
3349 ####################
3350 # Project mgmt operations
3351 ####################
3353 @cli_osm.command(name
='project-create', short_help
='creates a new project')
3354 @click.argument('name')
3355 #@click.option('--description',
3356 # default='no description',
3357 # help='human readable description')
3358 @click.option('--domain-name', 'domain_name',
3360 help='assign to a domain')
3361 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3362 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3363 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3365 def project_create(ctx
, name
, domain_name
, quotas
):
3366 """Creates a new project
3368 NAME: name of the project
3369 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3370 QUOTAS: set quotas for the project
3373 project
= {'name': name
}
3375 project
['domain_name'] = domain_name
3376 quotas_dict
= _process_project_quotas(quotas
)
3378 project
['quotas'] = quotas_dict
3381 check_client_version(ctx
.obj
, ctx
.command
.name
)
3382 ctx
.obj
.project
.create(name
, project
)
3383 # except ClientException as e:
3388 def _process_project_quotas(quota_list
):
3393 for quota
in quota_list
:
3394 for single_quota
in quota
.split(","):
3395 k
, v
= single_quota
.split("=")
3396 quotas_dict
[k
] = None if v
in ('None', 'null', '') else int(v
)
3397 except (ValueError, TypeError):
3398 raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3402 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3403 @click.argument('name')
3404 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3406 def project_delete(ctx
, name
):
3407 """deletes a project
3409 NAME: name or ID of the project to be deleted
3413 check_client_version(ctx
.obj
, ctx
.command
.name
)
3414 ctx
.obj
.project
.delete(name
)
3415 # except ClientException as e:
3420 @cli_osm.command(name
='project-list', short_help
='list all projects')
3421 @click.option('--filter', default
=None, multiple
=True,
3422 help='restricts the list to the projects matching the filter')
3424 def project_list(ctx
, filter):
3425 """list all projects"""
3428 check_client_version(ctx
.obj
, ctx
.command
.name
)
3430 filter='&'.join(filter)
3431 resp
= ctx
.obj
.project
.list(filter)
3432 # except ClientException as e:
3435 table
= PrettyTable(['name', 'id'])
3437 table
.add_row([proj
['name'], proj
['_id']])
3442 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3443 @click.argument('name')
3445 def project_show(ctx
, name
):
3446 """shows the details of a project
3448 NAME: name or ID of the project
3452 check_client_version(ctx
.obj
, ctx
.command
.name
)
3453 resp
= ctx
.obj
.project
.get(name
)
3454 # except ClientException as e:
3458 table
= PrettyTable(['key', 'attribute'])
3459 for k
, v
in resp
.items():
3460 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3465 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3466 @click.argument('project')
3467 @click.option('--name', default
=None,
3468 help='new name for the project')
3469 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3470 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3471 "(use empty to reset quota to default")
3473 def project_update(ctx
, project
, name
, quotas
):
3475 Update a project name
3478 :param project: id or name of the project to modify
3479 :param name: new name for the project
3480 :param quotas: change quotas of the project
3484 project_changes
= {}
3486 project_changes
['name'] = name
3487 quotas_dict
= _process_project_quotas(quotas
)
3489 project_changes
['quotas'] = quotas_dict
3492 check_client_version(ctx
.obj
, ctx
.command
.name
)
3493 ctx
.obj
.project
.update(project
, project_changes
)
3494 # except ClientException as e:
3498 ####################
3499 # User mgmt operations
3500 ####################
3502 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3503 @click.argument('username')
3504 @click.option('--password',
3507 confirmation_prompt
=True,
3508 help='user password')
3509 @click.option('--projects',
3510 # prompt="Comma separate list of projects",
3512 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3513 help='list of project ids that the user belongs to')
3514 @click.option('--project-role-mappings', 'project_role_mappings',
3515 default
=None, multiple
=True,
3516 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3517 @click.option('--domain-name', 'domain_name',
3519 help='assign to a domain')
3521 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
3522 """Creates a new user
3525 USERNAME: name of the user
3526 PASSWORD: password of the user
3527 PROJECTS: projects assigned to user (internal only)
3528 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3529 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3533 user
['username'] = username
3534 user
['password'] = password
3535 user
['projects'] = projects
3536 user
['project_role_mappings'] = project_role_mappings
3538 user
['domain_name'] = domain_name
3541 check_client_version(ctx
.obj
, ctx
.command
.name
)
3542 ctx
.obj
.user
.create(username
, user
)
3543 # except ClientException as e:
3548 @cli_osm.command(name
='user-update', short_help
='updates user information')
3549 @click.argument('username')
3550 @click.option('--password',
3553 # confirmation_prompt=True,
3554 help='user password')
3555 @click.option('--set-username', 'set_username',
3557 help='change username')
3558 @click.option('--set-project', 'set_project',
3559 default
=None, multiple
=True,
3560 help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3561 @click.option('--remove-project', 'remove_project',
3562 default
=None, multiple
=True,
3563 help="removes project from user: 'project'")
3564 @click.option('--add-project-role', 'add_project_role',
3565 default
=None, multiple
=True,
3566 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3567 @click.option('--remove-project-role', 'remove_project_role',
3568 default
=None, multiple
=True,
3569 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3571 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3572 add_project_role
, remove_project_role
):
3573 """Update a user information
3576 USERNAME: name of the user
3577 PASSWORD: new password
3578 SET_USERNAME: new username
3579 SET_PROJECT: creating mappings for project/role(s)
3580 REMOVE_PROJECT: deleting mappings for project/role(s)
3581 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3582 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3586 user
['password'] = password
3587 user
['username'] = set_username
3588 user
['set-project'] = set_project
3589 user
['remove-project'] = remove_project
3590 user
['add-project-role'] = add_project_role
3591 user
['remove-project-role'] = remove_project_role
3594 check_client_version(ctx
.obj
, ctx
.command
.name
)
3595 ctx
.obj
.user
.update(username
, user
)
3596 # except ClientException as e:
3601 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3602 @click.argument('name')
3603 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3605 def user_delete(ctx
, name
):
3609 NAME: name or ID of the user to be deleted
3613 check_client_version(ctx
.obj
, ctx
.command
.name
)
3614 ctx
.obj
.user
.delete(name
)
3615 # except ClientException as e:
3620 @cli_osm.command(name
='user-list', short_help
='list all users')
3621 @click.option('--filter', default
=None, multiple
=True,
3622 help='restricts the list to the users matching the filter')
3624 def user_list(ctx
, filter):
3625 """list all users"""
3627 check_client_version(ctx
.obj
, ctx
.command
.name
)
3629 filter='&'.join(filter)
3630 resp
= ctx
.obj
.user
.list(filter)
3631 # except ClientException as e:
3634 table
= PrettyTable(['name', 'id'])
3636 table
.add_row([user
['username'], user
['_id']])
3641 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3642 @click.argument('name')
3644 def user_show(ctx
, name
):
3645 """shows the details of a user
3647 NAME: name or ID of the user
3651 check_client_version(ctx
.obj
, ctx
.command
.name
)
3652 resp
= ctx
.obj
.user
.get(name
)
3653 if 'password' in resp
:
3654 resp
['password']='********'
3655 # except ClientException as e:
3659 table
= PrettyTable(['key', 'attribute'])
3660 for k
, v
in resp
.items():
3661 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3666 ####################
3667 # Fault Management operations
3668 ####################
3670 @cli_osm.command(name
='ns-alarm-create')
3671 @click.argument('name')
3672 @click.option('--ns', prompt
=True, help='NS instance id or name')
3673 @click.option('--vnf', prompt
=True,
3674 help='VNF name (VNF member index as declared in the NSD)')
3675 @click.option('--vdu', prompt
=True,
3676 help='VDU name (VDU name as declared in the VNFD)')
3677 @click.option('--metric', prompt
=True,
3678 help='Name of the metric (e.g. cpu_utilization)')
3679 @click.option('--severity', default
='WARNING',
3680 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3681 @click.option('--threshold_value', prompt
=True,
3682 help='threshold value that, when crossed, an alarm is triggered')
3683 @click.option('--threshold_operator', prompt
=True,
3684 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3685 @click.option('--statistic', default
='AVERAGE',
3686 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3688 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3689 threshold_value
, threshold_operator
, statistic
):
3690 """creates a new alarm for a NS instance"""
3691 # TODO: Check how to validate threshold_value.
3692 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3695 ns_instance
= ctx
.obj
.ns
.get(ns
)
3697 alarm
['alarm_name'] = name
3698 alarm
['ns_id'] = ns_instance
['_id']
3699 alarm
['correlation_id'] = ns_instance
['_id']
3700 alarm
['vnf_member_index'] = vnf
3701 alarm
['vdu_name'] = vdu
3702 alarm
['metric_name'] = metric
3703 alarm
['severity'] = severity
3704 alarm
['threshold_value'] = int(threshold_value
)
3705 alarm
['operation'] = threshold_operator
3706 alarm
['statistic'] = statistic
3707 check_client_version(ctx
.obj
, ctx
.command
.name
)
3708 ctx
.obj
.ns
.create_alarm(alarm
)
3709 # except ClientException as e:
3714 #@cli_osm.command(name='ns-alarm-delete')
3715 #@click.argument('name')
3716 #@click.pass_context
3717 #def ns_alarm_delete(ctx, name):
3718 # """deletes an alarm
3720 # NAME: name of the alarm to be deleted
3723 # check_client_version(ctx.obj, ctx.command.name)
3724 # ctx.obj.ns.delete_alarm(name)
3725 # except ClientException as e:
3730 ####################
3731 # Performance Management operations
3732 ####################
3734 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3735 @click.option('--ns', prompt
=True, help='NS instance id or name')
3736 @click.option('--vnf', prompt
=True,
3737 help='VNF name (VNF member index as declared in the NSD)')
3738 @click.option('--vdu', prompt
=True,
3739 help='VDU name (VDU name as declared in the VNFD)')
3740 @click.option('--metric', prompt
=True,
3741 help='name of the metric (e.g. cpu_utilization)')
3742 #@click.option('--period', default='1w',
3743 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3744 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3746 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3747 """exports a metric to the internal OSM bus, which can be read by other apps"""
3748 # TODO: Check how to validate interval.
3749 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3752 ns_instance
= ctx
.obj
.ns
.get(ns
)
3754 metric_data
['ns_id'] = ns_instance
['_id']
3755 metric_data
['correlation_id'] = ns_instance
['_id']
3756 metric_data
['vnf_member_index'] = vnf
3757 metric_data
['vdu_name'] = vdu
3758 metric_data
['metric_name'] = metric
3759 metric_data
['collection_unit'] = 'WEEK'
3760 metric_data
['collection_period'] = 1
3761 check_client_version(ctx
.obj
, ctx
.command
.name
)
3763 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3767 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3768 time
.sleep(int(interval
))
3770 # except ClientException as e:
3775 ####################
3777 ####################
3779 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3781 def get_version(ctx
):
3782 """shows client and server versions"""
3784 check_client_version(ctx
.obj
, "version")
3785 print ("Server version: {}".format(ctx
.obj
.get_version()))
3786 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3787 # except ClientException as e:
3791 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3792 @click.argument('filename')
3793 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3794 help='the charm will not be compiled, it is assumed to already exist')
3796 def upload_package(ctx
, filename
, skip_charm_build
):
3797 """uploads a vnf package or ns package
3799 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3803 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3804 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3805 if fullclassname
!= 'osmclient.sol005.client.Client':
3806 ctx
.obj
.package
.wait_for_upload(filename
)
3807 # except ClientException as e:
3812 #@cli_osm.command(name='ns-scaling-show')
3813 #@click.argument('ns_name')
3814 #@click.pass_context
3815 #def show_ns_scaling(ctx, ns_name):
3816 # """shows the status of a NS scaling operation
3818 # NS_NAME: name of the NS instance being scaled
3821 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3822 # resp = ctx.obj.ns.list()
3823 # except ClientException as e:
3827 # table = PrettyTable(
3830 # 'operational status',
3835 # if ns_name == ns['name']:
3836 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3837 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3838 # for record in scaling_records:
3839 # if 'instance' in record:
3840 # instances = record['instance']
3841 # for inst in instances:
3843 # [record['scaling-group-name-ref'],
3844 # inst['instance-id'],
3845 # inst['op-status'],
3846 # time.strftime('%Y-%m-%d %H:%M:%S',
3848 # inst['create-time'])),
3854 #@cli_osm.command(name='ns-scale')
3855 #@click.argument('ns_name')
3856 #@click.option('--ns_scale_group', prompt=True)
3857 #@click.option('--index', prompt=True)
3858 #@click.option('--wait',
3862 # help='do not return the control immediately, but keep it \
3863 # until the operation is completed, or timeout')
3864 #@click.pass_context
3865 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3868 # NS_NAME: name of the NS instance to be scaled
3871 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3872 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3873 # except ClientException as e:
3878 #@cli_osm.command(name='config-agent-list')
3879 #@click.pass_context
3880 #def config_agent_list(ctx):
3881 # """list config agents"""
3883 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3884 # except ClientException as e:
3887 # table = PrettyTable(['name', 'account-type', 'details'])
3888 # for account in ctx.obj.vca.list():
3891 # account['account-type'],
3897 #@cli_osm.command(name='config-agent-delete')
3898 #@click.argument('name')
3899 #@click.pass_context
3900 #def config_agent_delete(ctx, name):
3901 # """deletes a config agent
3903 # NAME: name of the config agent to be deleted
3906 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3907 # ctx.obj.vca.delete(name)
3908 # except ClientException as e:
3913 #@cli_osm.command(name='config-agent-add')
3914 #@click.option('--name',
3916 #@click.option('--account_type',
3918 #@click.option('--server',
3920 #@click.option('--user',
3922 #@click.option('--secret',
3925 # confirmation_prompt=True)
3926 #@click.pass_context
3927 #def config_agent_add(ctx, name, account_type, server, user, secret):
3928 # """adds a config agent"""
3930 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3931 # ctx.obj.vca.create(name, account_type, server, user, secret)
3932 # except ClientException as e:
3937 #@cli_osm.command(name='ro-dump')
3938 #@click.pass_context
3940 # """shows RO agent information"""
3941 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3942 # resp = ctx.obj.vim.get_resource_orchestrator()
3943 # table = PrettyTable(['key', 'attribute'])
3944 # for k, v in list(resp.items()):
3945 # table.add_row([k, json.dumps(v, indent=2)])
3950 #@cli_osm.command(name='vcs-list')
3951 #@click.pass_context
3953 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3954 # resp = ctx.obj.utils.get_vcs_info()
3955 # table = PrettyTable(['component name', 'state'])
3956 # for component in resp:
3957 # table.add_row([component['component_name'], component['state']])
3962 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3963 @click.argument('ns_name')
3964 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3965 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3966 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3967 @click.option('--vdu_count', default
=None, type=int, help='number of vdu instance of this vdu_id')
3968 @click.option('--action_name', prompt
=True, help='action name')
3969 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3970 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3971 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
3972 @click.option('--wait',
3976 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3989 """executes an action/primitive over a NS instance
3991 NS_NAME: name or ID of the NS instance
3995 check_client_version(ctx
.obj
, ctx
.command
.name
)
3998 op_data
['member_vnf_index'] = vnf_name
4000 op_data
['kdu_name'] = kdu_name
4002 op_data
['vdu_id'] = vdu_id
4003 if vdu_count
is not None:
4004 op_data
['vdu_count_index'] = vdu_count
4006 op_data
['timeout_ns_action'] = timeout
4007 op_data
['primitive'] = action_name
4009 with
open(params_file
, 'r') as pf
:
4012 op_data
['primitive_params'] = yaml
.safe_load(params
)
4014 op_data
['primitive_params'] = {}
4015 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
4017 # except ClientException as e:
4022 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
4023 @click.argument('ns_name')
4024 @click.argument('vnf_name')
4025 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
4026 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
4027 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
4028 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4029 @click.option('--wait', required
=False, default
=False, is_flag
=True,
4030 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4041 Executes a VNF scale (adding/removing VDUs)
4044 NS_NAME: name or ID of the NS instance.
4045 VNF_NAME: member-vnf-index in the NS to be scaled.
4049 check_client_version(ctx
.obj
, ctx
.command
.name
)
4050 if not scale_in
and not scale_out
:
4052 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
)
4053 # except ClientException as e:
4058 ##############################
4059 # Role Management Operations #
4060 ##############################
4062 @cli_osm.command(name
='role-create', short_help
='creates a new role')
4063 @click.argument('name')
4064 @click.option('--permissions',
4066 help='role permissions using a dictionary')
4068 def role_create(ctx
, name
, permissions
):
4073 NAME: Name or ID of the role.
4074 DEFINITION: Definition of grant/denial of access to resources.
4078 check_client_version(ctx
.obj
, ctx
.command
.name
)
4079 ctx
.obj
.role
.create(name
, permissions
)
4080 # except ClientException as e:
4085 @cli_osm.command(name
='role-update', short_help
='updates a role')
4086 @click.argument('name')
4087 @click.option('--set-name',
4089 help='change name of rle')
4090 # @click.option('--permissions',
4092 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4093 @click.option('--add',
4095 help='yaml format dictionary with permission: True/False to access grant/denial')
4096 @click.option('--remove',
4098 help='yaml format list to remove a permission')
4100 def role_update(ctx
, name
, set_name
, add
, remove
):
4105 NAME: Name or ID of the role.
4106 DEFINITION: Definition overwrites the old definition.
4107 ADD: Grant/denial of access to resource to add.
4108 REMOVE: Grant/denial of access to resource to remove.
4112 check_client_version(ctx
.obj
, ctx
.command
.name
)
4113 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
4114 # except ClientException as e:
4119 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
4120 @click.argument('name')
4121 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4123 def role_delete(ctx
, name
):
4128 NAME: Name or ID of the role.
4132 check_client_version(ctx
.obj
, ctx
.command
.name
)
4133 ctx
.obj
.role
.delete(name
)
4134 # except ClientException as e:
4139 @cli_osm.command(name
='role-list', short_help
='list all roles')
4140 @click.option('--filter', default
=None, multiple
=True,
4141 help='restricts the list to the projects matching the filter')
4143 def role_list(ctx
, filter):
4149 check_client_version(ctx
.obj
, ctx
.command
.name
)
4151 filter='&'.join(filter)
4152 resp
= ctx
.obj
.role
.list(filter)
4153 # except ClientException as e:
4156 table
= PrettyTable(['name', 'id'])
4158 table
.add_row([role
['name'], role
['_id']])
4163 @cli_osm.command(name
='role-show', short_help
='show specific role')
4164 @click.argument('name')
4166 def role_show(ctx
, name
):
4168 Shows the details of a role.
4171 NAME: Name or ID of the role.
4175 check_client_version(ctx
.obj
, ctx
.command
.name
)
4176 resp
= ctx
.obj
.role
.get(name
)
4177 # except ClientException as e:
4181 table
= PrettyTable(['key', 'attribute'])
4182 for k
, v
in resp
.items():
4183 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4188 @cli_osm.command(name
='package-create',
4189 short_help
='Create a package descriptor')
4190 @click.argument('package-type')
4191 @click.argument('package-name')
4192 @click.option('--base-directory',
4194 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4195 @click.option('--image',
4196 default
="image-name",
4197 help='(VNF) Set the name of the vdu image. Default "image-name"')
4198 @click.option('--vdus',
4200 help='(VNF) Set the number of vdus in a VNF. Default 1')
4201 @click.option('--vcpu',
4203 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4204 @click.option('--memory',
4206 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4207 @click.option('--storage',
4209 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4210 @click.option('--interfaces',
4212 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4213 @click.option('--vendor',
4215 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4216 @click.option('--override',
4219 help='(NS/VNF/NST) Flag for overriding the package if exists.')
4220 @click.option('--detailed',
4223 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4224 @click.option('--netslice-subnets',
4226 help='(NST) Number of netslice subnets. Default 1')
4227 @click.option('--netslice-vlds',
4229 help='(NST) Number of netslice vlds. Default 1')
4231 def package_create(ctx
,
4247 Creates an OSM NS, VNF, NST package
4250 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4251 PACKAGE_NAME: Name of the package to create the folder with the content.
4255 check_client_version(ctx
.obj
, ctx
.command
.name
)
4256 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
4257 resp
= ctx
.obj
.package_tool
.create(package_type
,
4266 interfaces
=interfaces
,
4269 netslice_subnets
=netslice_subnets
,
4270 netslice_vlds
=netslice_vlds
)
4272 # except ClientException as inst:
4273 # print("ERROR: {}".format(inst))
4276 @cli_osm.command(name
='package-validate',
4277 short_help
='Validate a package descriptor')
4278 @click.argument('base-directory',
4281 @click.option('--recursive/--no-recursive',
4283 help='The activated recursive option will validate the yaml files'
4284 ' within the indicated directory and in its subdirectories')
4286 def package_validate(ctx
,
4290 Validate descriptors given a base directory.
4293 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4296 check_client_version(ctx
.obj
, ctx
.command
.name
)
4297 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
4298 table
= PrettyTable()
4299 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
4300 # Print the dictionary generated by the validation function
4301 for result
in results
:
4302 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
4303 table
.sortby
= "VALID"
4304 table
.align
["PATH"] = "l"
4305 table
.align
["TYPE"] = "l"
4306 table
.align
["ERROR"] = "l"
4308 # except ClientException as inst:
4309 # print("ERROR: {}".format(inst))
4312 @cli_osm.command(name
='package-build',
4313 short_help
='Build the tar.gz of the package')
4314 @click.argument('package-folder')
4315 @click.option('--skip-validation',
4318 help='skip package validation')
4319 @click.option('--skip-charm-build', default
=False, is_flag
=True,
4320 help='the charm will not be compiled, it is assumed to already exist')
4322 def package_build(ctx
,
4327 Build the package NS, VNF given the package_folder.
4330 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4333 check_client_version(ctx
.obj
, ctx
.command
.name
)
4334 results
= ctx
.obj
.package_tool
.build(package_folder
,
4335 skip_validation
=skip_validation
,
4336 skip_charm_build
=skip_charm_build
)
4338 # except ClientException as inst:
4339 # print("ERROR: {}".format(inst))
4347 except pycurl
.error
as exc
:
4349 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4350 except ClientException
as exc
:
4351 print("ERROR: {}".format(exc
))
4352 except (FileNotFoundError
, PermissionError
) as exc
:
4353 print("Cannot open file: {}".format(exc
))
4354 except yaml
.YAMLError
as exc
:
4355 print("Invalid YAML format: {}".format(exc
))
4357 # TODO capture other controlled exceptions here
4358 # TODO remove the ClientException captures from all places, unless they do something different
4361 if __name__
== '__main__':