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
36 def wrap_text(text
, width
):
37 wrapper
= textwrap
.TextWrapper(width
=width
)
38 lines
= text
.splitlines()
39 return "\n".join(map(wrapper
.fill
, lines
))
42 def trunc_text(text
, length
):
43 if len(text
) > length
:
44 return text
[:(length
- 3)] + '...'
49 def check_client_version(obj
, what
, version
='sol005'):
51 Checks the version of the client object and raises error if it not the expected.
53 :param obj: the client object
54 :what: the function or command under evaluation (used when an error is raised)
56 :raises ClientError: if the specified version does not match the client version
59 fullclassname
= obj
.__module
__ + "." + obj
.__class
__.__name
__
60 message
= 'The following commands or options are only supported with the option "--sol005": {}'.format(what
)
62 message
= 'The following commands or options are not supported when using option "--sol005": {}'.format(what
)
63 if fullclassname
!= 'osmclient.{}.client.Client'.format(version
):
64 raise ClientException(message
)
68 def get_project(project_list
, item
):
69 # project_list = ctx.obj.project.list()
70 item_project_list
= item
.get('_admin', {}).get('projects_read')
74 for p1
in item_project_list
:
76 for p2
in project_list
:
77 if p2
['_id'] == project_id
:
78 project_name
= p2
['name']
79 return project_id
, project_name
80 return project_id
, project_name
83 def get_vim_name(vim_list
, vim_id
):
86 if v
['uuid'] == vim_id
:
92 @click.group(context_settings
=dict(help_option_names
=['-h', '--help'], max_content_width
=160))
93 @click.option('--hostname',
95 envvar
='OSM_HOSTNAME',
96 help='hostname of server. ' +
97 'Also can set OSM_HOSTNAME in environment')
98 #@click.option('--sol005/--no-sol005',
100 # envvar='OSM_SOL005',
101 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
102 # 'Also can set OSM_SOL005 in environment')
103 @click.option('--user',
106 help='user (defaults to admin). ' +
107 'Also can set OSM_USER in environment')
108 @click.option('--password',
110 envvar
='OSM_PASSWORD',
111 help='password (defaults to admin). ' +
112 'Also can set OSM_PASSWORD in environment')
113 @click.option('--project',
115 envvar
='OSM_PROJECT',
116 help='project (defaults to admin). ' +
117 'Also can set OSM_PROJECT in environment')
118 @click.option('-v', '--verbose', count
=True,
119 help='increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)')
120 @click.option('--all-projects',
123 help='include all projects')
124 @click.option('--public/--no-public', default
=None,
125 help='flag for public items (packages, instances, VIM accounts, etc.)')
126 @click.option('--project-domain-name', 'project_domain_name',
128 envvar
='OSM_PROJECT_DOMAIN_NAME',
129 help='project domain name for keystone authentication (default to None). ' +
130 'Also can set OSM_PROJECT_DOMAIN_NAME in environment')
131 @click.option('--user-domain-name', 'user_domain_name',
133 envvar
='OSM_USER_DOMAIN_NAME',
134 help='user domain name for keystone authentication (default to None). ' +
135 'Also can set OSM_USER_DOMAIN_NAME in environment')
136 #@click.option('--so-port',
138 # envvar='OSM_SO_PORT',
139 # help='hostname of server. ' +
140 # 'Also can set OSM_SO_PORT in environment')
141 #@click.option('--so-project',
143 # envvar='OSM_SO_PROJECT',
144 # help='Project Name in SO. ' +
145 # 'Also can set OSM_SO_PROJECT in environment')
146 #@click.option('--ro-hostname',
148 # envvar='OSM_RO_HOSTNAME',
149 # help='hostname of RO server. ' +
150 # 'Also can set OSM_RO_HOSTNAME in environment')
151 #@click.option('--ro-port',
153 # envvar='OSM_RO_PORT',
154 # help='hostname of RO server. ' +
155 # 'Also can set OSM_RO_PORT in environment')
157 def cli_osm(ctx
, **kwargs
):
159 hostname
= kwargs
.pop("hostname", None)
162 "either hostname option or OSM_HOSTNAME " +
163 "environment variable needs to be specified"))
166 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
167 # if so_port is not None:
168 # kwargs['so_port']=so_port
169 # if so_project is not None:
170 # kwargs['so_project']=so_project
171 # if ro_hostname is not None:
172 # kwargs['ro_host']=ro_hostname
173 # if ro_port is not None:
174 # kwargs['ro_port']=ro_port
175 sol005
= os
.getenv('OSM_SOL005', True)
176 # if user is not None:
177 # kwargs['user']=user
178 # if password is not None:
179 # kwargs['password']=password
180 # if project is not None:
181 # kwargs['project']=project
183 # kwargs['all_projects']=all_projects
184 # if public is not None:
185 # kwargs['public']=public
186 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
187 logger
= logging
.getLogger('osmclient')
194 @cli_osm.command(name
='ns-list', short_help
='list all NS instances')
195 @click.option('--filter', default
=None, multiple
=True,
196 help='restricts the list to the NS instances matching the filter.')
197 @click.option('--long', is_flag
=True,
198 help='get more details of the NS (project, vim, deployment status, configuration status.')
200 def ns_list(ctx
, filter, long):
201 """list all NS instances
205 --filter filterExpr Restricts the list to the NS instances matching the filter
208 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
209 concatenated using the "&" character:
212 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
213 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
214 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
216 value := scalar value
220 * zero or more occurrences
221 ? zero or one occurrence
222 [] grouping of expressions to be used with ? and *
223 "" quotation marks for marking string constants
227 "AttrName" is the name of one attribute in the data type that defines the representation
228 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
229 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
230 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
231 entries, it means that the operator "op" is applied to the attribute addressed by the last
232 <attrName> entry included in the concatenation. All simple filter expressions are combined
233 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
234 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
235 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
236 prefix". If an attribute referenced in an expression is an array, an object that contains a
237 corresponding array shall be considered to match the expression if any of the elements in the
238 array matches all expressions that have the same attribute prefix.
242 --filter admin-status=ENABLED
243 --filter nsd-ref=<NSD_NAME>
244 --filter nsd.vendor=<VENDOR>
245 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
246 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
248 def summarize_deployment_status(status_dict
):
255 net_list
= status_dict
.get('nets',[])
258 if net
['status'] not in status_nets
:
259 status_nets
[net
['status']] = 1
261 status_nets
[net
['status']] +=1
263 for k
,v
in status_nets
.items():
264 message
+= "{}:{},".format(k
,v
)
265 message
+= "TOTAL:{}".format(n_nets
)
266 summary
+= "{}".format(message
)
271 vnf_list
= status_dict
['vnfs']
273 member_vnf_index
= vnf
['member_vnf_index']
274 if member_vnf_index
not in status_vnfs
:
275 status_vnfs
[member_vnf_index
] = {}
276 for vm
in vnf
['vms']:
278 if vm
['status'] not in status_vms
:
279 status_vms
[vm
['status']] = 1
281 status_vms
[vm
['status']] +=1
282 if vm
['status'] not in status_vnfs
[member_vnf_index
]:
283 status_vnfs
[member_vnf_index
][vm
['status']] = 1
285 status_vnfs
[member_vnf_index
][vm
['status']] += 1
287 for k
,v
in status_vms
.items():
288 message
+= "{}:{},".format(k
,v
)
289 message
+= "TOTAL:{}".format(n_vms
)
290 summary
+= "\n{}".format(message
)
292 for k
,v
in status_vnfs
.items():
294 message
= "\n {} VMs: ".format(k
)
295 for k2
,v2
in v
.items():
296 message
+= "{}:{},".format(k2
,v2
)
298 message
+= "TOTAL:{}".format(total
)
302 def summarize_config_status(ee_list
):
310 if ee
['elementType'] not in status_ee
:
311 status_ee
[ee
['elementType']] = {}
312 status_ee
[ee
['elementType']][ee
['status']] = 1
314 if ee
['status'] in status_ee
[ee
['elementType']]:
315 status_ee
[ee
['elementType']][ee
['status']] += 1
317 status_ee
[ee
['elementType']][ee
['status']] = 1
318 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
319 if elementType
in status_ee
:
322 for k
,v
in status_ee
[elementType
].items():
323 message
+= "{}:{},".format(k
,v
)
325 message
+= "TOTAL:{}\n".format(total
)
326 summary
+= "{}: {}".format(elementType
, message
)
327 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
332 check_client_version(ctx
.obj
, '--filter')
333 filter='&'.join(filter)
334 resp
= ctx
.obj
.ns
.list(filter)
336 resp
= ctx
.obj
.ns
.list()
348 'configuration status'])
349 project_list
= ctx
.obj
.project
.list()
351 vim_list
= ctx
.obj
.vim
.list()
363 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
364 if fullclassname
== 'osmclient.sol005.client.Client':
366 logger
.debug('NS info: {}'.format(nsr
))
367 nsr_name
= nsr
['name']
369 date
= datetime
.fromtimestamp(nsr
['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
370 ns_state
= nsr
.get('nsState', nsr
['_admin']['nsState'])
372 deployment_status
= summarize_deployment_status(nsr
.get('deploymentStatus'))
373 config_status
= summarize_config_status(nsr
.get('configurationStatus'))
374 project_id
, project_name
= get_project(project_list
, nsr
)
375 #project = '{} ({})'.format(project_name, project_id)
376 project
= project_name
377 vim_id
= nsr
.get('datacenter')
378 vim_name
= get_vim_name(vim_list
, vim_id
)
380 #vim = '{} ({})'.format(vim_name, vim_id)
382 if 'currentOperation' in nsr
:
383 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
385 current_operation
= "{} ({})".format(nsr
['_admin'].get('current-operation','-'), nsr
['_admin']['nslcmop'])
386 error_details
= "N/A"
387 if ns_state
== "BROKEN" or ns_state
== "DEGRADED" or \
388 ('currentOperation' not in nsr
and nsr
.get('errorDescription')):
389 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'], nsr
['errorDetail'])
391 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
392 nsr
= nsopdata
['nsr:nsr']
393 nsr_name
= nsr
['name-ref']
394 nsr_id
= nsr
['ns-instance-config-ref']
397 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
398 ns_state
= deployment_status
399 config_status
= nsr
.get('config-status', 'Not found')
400 current_operation
= "Unknown"
401 error_details
= nsr
.get('detailed-status', 'Not found')
402 if config_status
== "config_not_needed":
403 config_status
= "configured (no charms)"
412 wrap_text(text
=error_details
,width
=40),
424 wrap_text(text
=error_details
,width
=40)])
427 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
428 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
430 def nsd_list(ctx
, filter, long):
433 check_client_version(ctx
.obj
, '--filter')
434 filter='&'.join(filter)
435 resp
= ctx
.obj
.nsd
.list(filter)
437 resp
= ctx
.obj
.nsd
.list()
438 # print(yaml.safe_dump(resp))
439 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
440 if fullclassname
== 'osmclient.sol005.client.Client':
442 table
= PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state',
443 'usage state', 'date', 'last update'])
445 table
= PrettyTable(['nsd name', 'id'])
447 name
= nsd
.get('id', '-')
449 onb_state
= nsd
['_admin'].get('onboardingState','-')
450 op_state
= nsd
['_admin'].get('operationalState','-')
451 usage_state
= nsd
['_admin'].get('usageState','-')
452 date
= datetime
.fromtimestamp(nsd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
453 last_update
= datetime
.fromtimestamp(nsd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
454 table
.add_row([name
, nsd
['_id'], onb_state
, op_state
, usage_state
, date
, last_update
])
456 table
.add_row([name
, nsd
['_id']])
458 table
= PrettyTable(['nsd name', 'id'])
460 table
.add_row([nsd
['name'], nsd
['id']])
465 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
466 @click.option('--filter', default
=None, multiple
=True,
467 help='restricts the list to the NSD/NSpkg matching the filter')
468 @click.option('--long', is_flag
=True, help='get more details')
470 def nsd_list1(ctx
, filter, long):
471 """list all NSD/NS pkg in the system"""
473 nsd_list(ctx
, filter, long)
476 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
477 @click.option('--filter', default
=None, multiple
=True,
478 help='restricts the list to the NSD/NSpkg matching the filter')
479 @click.option('--long', is_flag
=True, help='get more details')
481 def nsd_list2(ctx
, filter, long):
482 """list all NS packages"""
484 nsd_list(ctx
, filter, long)
487 def pkg_repo_list(ctx
, pkgtype
, filter, repo
, long):
488 resp
= ctx
.obj
.osmrepo
.pkg_list(pkgtype
, filter, repo
)
490 table
= PrettyTable(['nfpkg name', 'vendor', 'version', 'latest', 'description', 'repository'])
492 table
= PrettyTable(['nfpkg name', 'repository'])
494 name
= vnfd
.get('id', vnfd
.get('name','-'))
495 repository
= vnfd
.get('repository')
497 vendor
= vnfd
.get('provider', vnfd
.get('vendor'))
498 version
= vnfd
.get('version')
499 description
= vnfd
.get('description')
500 latest
= vnfd
.get('latest')
501 table
.add_row([name
, vendor
, version
, latest
, description
, repository
])
503 table
.add_row([name
, repository
])
507 def vnfd_list(ctx
, nf_type
, filter, long):
510 check_client_version(ctx
.obj
, '--nf_type')
512 check_client_version(ctx
.obj
, '--filter')
514 filter='&'.join(filter)
517 nf_filter
= "_admin.type=vnfd"
518 elif nf_type
== "pnf":
519 nf_filter
= "_admin.type=pnfd"
520 elif nf_type
== "hnf":
521 nf_filter
= "_admin.type=hnfd"
523 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
525 filter = '{}&{}'.format(nf_filter
, filter)
529 resp
= ctx
.obj
.vnfd
.list(filter)
531 resp
= ctx
.obj
.vnfd
.list()
532 # print(yaml.safe_dump(resp))
533 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
534 if fullclassname
== 'osmclient.sol005.client.Client':
536 table
= PrettyTable(['nfpkg name', 'id', 'desc type', 'vendor', 'version', 'onboarding state', 'operational state',
537 'usage state', 'date', 'last update'])
539 table
= PrettyTable(['nfpkg name', 'id', 'desc type'])
541 name
= vnfd
.get('id', vnfd
.get('name','-'))
542 descriptor_type
= 'sol006' if 'product-name' in vnfd
else 'rel8'
544 onb_state
= vnfd
['_admin'].get('onboardingState','-')
545 op_state
= vnfd
['_admin'].get('operationalState','-')
546 vendor
= vnfd
.get('provider', vnfd
.get('vendor'))
547 version
= vnfd
.get('version')
548 usage_state
= vnfd
['_admin'].get('usageState','-')
549 date
= datetime
.fromtimestamp(vnfd
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
550 last_update
= datetime
.fromtimestamp(vnfd
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
551 table
.add_row([name
, vnfd
['_id'], descriptor_type
, vendor
, version
, onb_state
, op_state
, usage_state
, date
, last_update
])
553 table
.add_row([name
, vnfd
['_id'], descriptor_type
])
555 table
= PrettyTable(['nfpkg name', 'id'])
557 table
.add_row([vnfd
['name'], vnfd
['id']])
562 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
563 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
564 @click.option('--filter', default
=None, multiple
=True,
565 help='restricts the list to the NF pkg matching the filter')
566 @click.option('--long', is_flag
=True, help='get more details')
568 def vnfd_list1(ctx
, nf_type
, filter, long):
569 """list all xNF packages (VNF, HNF, PNF)"""
571 vnfd_list(ctx
, nf_type
, filter, long)
574 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
575 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
576 @click.option('--filter', default
=None, multiple
=True,
577 help='restricts the list to the NFpkg matching the filter')
578 @click.option('--long', is_flag
=True, help='get more details')
580 def vnfd_list2(ctx
, nf_type
, filter, long):
581 """list all xNF packages (VNF, HNF, PNF)"""
583 vnfd_list(ctx
, nf_type
, filter, long)
586 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
587 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
588 @click.option('--filter', default
=None, multiple
=True,
589 help='restricts the list to the NFpkg matching the filter')
590 @click.option('--long', is_flag
=True, help='get more details')
592 def nfpkg_list(ctx
, nf_type
, filter, long):
593 """list all xNF packages (VNF, HNF, PNF)"""
596 check_client_version(ctx
.obj
, ctx
.command
.name
)
597 vnfd_list(ctx
, nf_type
, filter, long)
598 # except ClientException as e:
603 @cli_osm.command(name
='vnfpkg-repo-list', short_help
='list all xNF from OSM repositories')
604 @click.option('--filter', default
=None, multiple
=True,
605 help='restricts the list to the NFpkg matching the filter')
606 @click.option('--repo', default
=None,
607 help='restricts the list to a particular OSM repository')
608 @click.option('--long', is_flag
=True, help='get more details')
610 def nfpkg_repo_list1(ctx
, filter, repo
, long):
611 """list xNF packages from OSM repositories"""
613 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
615 @cli_osm.command(name
='nfpkg-repo-list', short_help
='list all xNF from OSM repositories')
616 @click.option('--filter', default
=None, multiple
=True,
617 help='restricts the list to the NFpkg matching the filter')
618 @click.option('--repo', default
=None,
619 help='restricts the list to a particular OSM repository')
620 @click.option('--long', is_flag
=True, help='get more details')
622 def nfpkg_repo_list2(ctx
, filter, repo
, long):
623 """list xNF packages from OSM repositories"""
625 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
628 def vnf_list(ctx
, ns
, filter, long):
632 check_client_version(ctx
.obj
, '--ns')
634 filter='&'.join(filter)
635 check_client_version(ctx
.obj
, '--filter')
636 resp
= ctx
.obj
.vnf
.list(ns
, filter)
638 resp
= ctx
.obj
.vnf
.list()
639 # except ClientException as e:
642 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
643 if fullclassname
== 'osmclient.sol005.client.Client':
644 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
645 'vnfd name', 'vim account id', 'ip address']
647 field_names
= ['vnf id', 'name', 'ns id', 'vnf member index',
648 'vnfd name', 'vim account id', 'ip address',
649 'date', 'last update']
650 table
= PrettyTable(field_names
)
652 name
= vnfr
['name'] if 'name' in vnfr
else '-'
653 new_row
= [vnfr
['_id'], name
, vnfr
['nsr-id-ref'],
654 vnfr
['member-vnf-index-ref'], vnfr
['vnfd-ref'],
655 vnfr
['vim-account-id'], vnfr
['ip-address']]
657 date
= datetime
.fromtimestamp(vnfr
['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
658 last_update
= datetime
.fromtimestamp(vnfr
['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
659 new_row
.extend([date
, last_update
])
660 table
.add_row(new_row
)
665 'operational status',
668 if 'mgmt-interface' not in vnfr
:
669 vnfr
['mgmt-interface'] = {}
670 vnfr
['mgmt-interface']['ip-address'] = None
674 vnfr
['operational-status'],
675 vnfr
['config-status']])
680 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
681 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
682 @click.option('--filter', default
=None, multiple
=True,
683 help='restricts the list to the NF instances matching the filter.')
684 @click.option('--long', is_flag
=True, help='get more details')
686 def vnf_list1(ctx
, ns
, filter, long):
687 """list all NF instances"""
689 vnf_list(ctx
, ns
, filter, long)
691 @cli_osm.command(name
='nsd-repo-list', short_help
='list all NS from OSM repositories')
692 @click.option('--filter', default
=None, multiple
=True,
693 help='restricts the list to the NS matching the filter')
694 @click.option('--repo', default
=None,
695 help='restricts the list to a particular OSM repository')
696 @click.option('--long', is_flag
=True, help='get more details')
698 def nspkg_repo_list(ctx
, filter, repo
, long):
699 """list xNF packages from OSM repositories"""
701 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
703 @cli_osm.command(name
='nspkg-repo-list', short_help
='list all NS from OSM repositories')
704 @click.option('--filter', default
=None, multiple
=True,
705 help='restricts the list to the NS matching the filter')
706 @click.option('--repo', default
=None,
707 help='restricts the list to a particular OSM repository')
708 @click.option('--long', is_flag
=True, help='get more details')
710 def nspkg_repo_list2(ctx
, filter, repo
, long):
711 """list xNF packages from OSM repositories"""
713 pkg_repo_list(ctx
, pkgtype
, filter, repo
, long)
715 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
716 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
717 @click.option('--filter', default
=None, multiple
=True,
718 help='restricts the list to the NF instances matching the filter.')
719 @click.option('--long', is_flag
=True, help='get more details')
721 def nf_list(ctx
, ns
, filter, long):
722 """list all NF instances
726 --ns TEXT NS instance id or name to restrict the VNF list
727 --filter filterExpr Restricts the list to the VNF instances matching the filter
730 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
731 concatenated using the "&" character:
734 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
735 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
736 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
738 value := scalar value
742 * zero or more occurrences
743 ? zero or one occurrence
744 [] grouping of expressions to be used with ? and *
745 "" quotation marks for marking string constants
749 "AttrName" is the name of one attribute in the data type that defines the representation
750 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
751 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
752 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
753 entries, it means that the operator "op" is applied to the attribute addressed by the last
754 <attrName> entry included in the concatenation. All simple filter expressions are combined
755 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
756 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
757 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
758 prefix". If an attribute referenced in an expression is an array, an object that contains a
759 corresponding array shall be considered to match the expression if any of the elements in the
760 array matches all expressions that have the same attribute prefix.
764 --filter vim-account-id=<VIM_ACCOUNT_ID>
765 --filter vnfd-ref=<VNFD_NAME>
766 --filter vdur.ip-address=<IP_ADDRESS>
767 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
770 vnf_list(ctx
, ns
, filter, long)
773 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
774 @click.argument('name')
775 @click.option('--long', is_flag
=True,
776 help='get more details of the NS operation (date, ).')
778 def ns_op_list(ctx
, name
, long):
779 """shows the history of operations over a NS instance
781 NAME: name or ID of the NS instance
783 def formatParams(params
):
784 if params
['lcmOperationType']=='instantiate':
785 params
.pop('nsDescription')
789 elif params
['lcmOperationType']=='action':
790 params
.pop('primitive')
791 params
.pop('lcmOperationType')
792 params
.pop('nsInstanceId')
797 check_client_version(ctx
.obj
, ctx
.command
.name
)
798 resp
= ctx
.obj
.ns
.list_op(name
)
799 # except ClientException as e:
804 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
806 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
808 #print(yaml.safe_dump(resp))
811 if op
['lcmOperationType']=='action':
812 action_name
= op
['operationParams']['primitive']
814 if op
['operationState'] == 'PROCESSING':
815 if op
['queuePosition'] is not None and op
['queuePosition'] > 0:
816 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
817 elif op
['lcmOperationType'] in ('instantiate', 'terminate'):
820 elif op
['operationState'] in ('FAILED', 'FAILED_TEMP'):
821 detail
= op
.get('errorMessage','-')
822 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
823 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
825 table
.add_row([op
['id'],
826 op
['lcmOperationType'],
828 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
829 op
['operationState'],
832 wrap_text(text
=detail
,width
=50)])
834 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
835 op
['operationState'], date
, wrap_text(text
=detail
or "",width
=50)])
840 def nsi_list(ctx
, filter):
841 """list all Network Slice Instances"""
844 check_client_version(ctx
.obj
, ctx
.command
.name
)
846 filter='&'.join(filter)
847 resp
= ctx
.obj
.nsi
.list(filter)
848 # except ClientException as e:
852 ['netslice instance name',
854 'operational status',
858 nsi_name
= nsi
['name']
860 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
861 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
862 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
863 if configstatus
== "config_not_needed":
864 configstatus
= "configured (no charms)"
875 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
876 @click.option('--filter', default
=None, multiple
=True,
877 help='restricts the list to the Network Slice Instances matching the filter')
879 def nsi_list1(ctx
, filter):
880 """list all Network Slice Instances (NSI)"""
882 nsi_list(ctx
, filter)
885 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
886 @click.option('--filter', default
=None, multiple
=True,
887 help='restricts the list to the Network Slice Instances matching the filter')
889 def nsi_list2(ctx
, filter):
890 """list all Network Slice Instances (NSI)"""
892 nsi_list(ctx
, filter)
895 def nst_list(ctx
, filter):
898 check_client_version(ctx
.obj
, ctx
.command
.name
)
900 filter='&'.join(filter)
901 resp
= ctx
.obj
.nst
.list(filter)
902 # except ClientException as e:
905 # print(yaml.safe_dump(resp))
906 table
= PrettyTable(['nst name', 'id'])
908 name
= nst
['name'] if 'name' in nst
else '-'
909 table
.add_row([name
, nst
['_id']])
914 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
915 @click.option('--filter', default
=None, multiple
=True,
916 help='restricts the list to the NST matching the filter')
918 def nst_list1(ctx
, filter):
919 """list all Network Slice Templates (NST) in the system"""
921 nst_list(ctx
, filter)
924 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
925 @click.option('--filter', default
=None, multiple
=True,
926 help='restricts the list to the NST matching the filter')
928 def nst_list2(ctx
, filter):
929 """list all Network Slice Templates (NST) in the system"""
931 nst_list(ctx
, filter)
934 def nsi_op_list(ctx
, name
):
937 check_client_version(ctx
.obj
, ctx
.command
.name
)
938 resp
= ctx
.obj
.nsi
.list_op(name
)
939 # except ClientException as e:
942 table
= PrettyTable(['id', 'operation', 'status'])
944 table
.add_row([op
['id'], op
['lcmOperationType'],
945 op
['operationState']])
950 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
951 @click.argument('name')
953 def nsi_op_list1(ctx
, name
):
954 """shows the history of operations over a Network Slice Instance (NSI)
956 NAME: name or ID of the Network Slice Instance
959 nsi_op_list(ctx
, name
)
962 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
963 @click.argument('name')
965 def nsi_op_list2(ctx
, name
):
966 """shows the history of operations over a Network Slice Instance (NSI)
968 NAME: name or ID of the Network Slice Instance
971 nsi_op_list(ctx
, name
)
974 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
975 @click.option('--filter', default
=None, multiple
=True,
976 help='restricts the list to the Physical Deployment Units matching the filter')
978 def pdu_list(ctx
, filter):
979 """list all Physical Deployment Units (PDU)"""
982 check_client_version(ctx
.obj
, ctx
.command
.name
)
984 filter='&'.join(filter)
985 resp
= ctx
.obj
.pdu
.list(filter)
986 # except ClientException as e:
995 pdu_name
= pdu
['name']
997 pdu_type
= pdu
['type']
998 pdu_ipaddress
= "None"
999 for iface
in pdu
['interfaces']:
1001 pdu_ipaddress
= iface
['ip-address']
1012 ####################
1014 ####################
1016 def nsd_show(ctx
, name
, literal
):
1019 resp
= ctx
.obj
.nsd
.get(name
)
1020 # resp = ctx.obj.nsd.get_individual(name)
1021 # except ClientException as e:
1026 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1029 table
= PrettyTable(['field', 'value'])
1030 for k
, v
in list(resp
.items()):
1031 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1036 @cli_osm.command(name
='nsd-show', short_help
='shows the details of a NS package')
1037 @click.option('--literal', is_flag
=True,
1038 help='print literally, no pretty table')
1039 @click.argument('name')
1041 def nsd_show1(ctx
, name
, literal
):
1042 """shows the content of a NSD
1044 NAME: name or ID of the NSD/NSpkg
1047 nsd_show(ctx
, name
, literal
)
1050 @cli_osm.command(name
='nspkg-show', short_help
='shows the details of a NS package')
1051 @click.option('--literal', is_flag
=True,
1052 help='print literally, no pretty table')
1053 @click.argument('name')
1055 def nsd_show2(ctx
, name
, literal
):
1056 """shows the content of a NSD
1058 NAME: name or ID of the NSD/NSpkg
1061 nsd_show(ctx
, name
, literal
)
1064 def vnfd_show(ctx
, name
, literal
):
1067 resp
= ctx
.obj
.vnfd
.get(name
)
1068 # resp = ctx.obj.vnfd.get_individual(name)
1069 # except ClientException as e:
1074 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1077 table
= PrettyTable(['field', 'value'])
1078 for k
, v
in list(resp
.items()):
1079 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1084 def pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
):
1087 filter='&'.join(filter)
1089 resp
= ctx
.obj
.osmrepo
.pkg_get(pkgtype
, name
, repo
, version
, filter)
1092 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1095 catalog
= pkgtype
+ '-catalog'
1096 full_catalog
= pkgtype
+ ':' + catalog
1097 if resp
.get(catalog
):
1098 resp
= resp
.pop(catalog
)[pkgtype
][0]
1099 elif resp
.get(full_catalog
):
1100 resp
= resp
.pop(full_catalog
)[pkgtype
][0]
1102 table
= PrettyTable(['field', 'value'])
1103 for k
, v
in list(resp
.items()):
1104 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2), width
=100)])
1109 @cli_osm.command(name
='vnfd-show', short_help
='shows the details of a NF package')
1110 @click.option('--literal', is_flag
=True,
1111 help='print literally, no pretty table')
1112 @click.argument('name')
1114 def vnfd_show1(ctx
, name
, literal
):
1115 """shows the content of a VNFD
1117 NAME: name or ID of the VNFD/VNFpkg
1120 vnfd_show(ctx
, name
, literal
)
1123 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the details of a NF package')
1124 @click.option('--literal', is_flag
=True,
1125 help='print literally, no pretty table')
1126 @click.argument('name')
1128 def vnfd_show2(ctx
, name
, literal
):
1129 """shows the content of a VNFD
1131 NAME: name or ID of the VNFD/VNFpkg
1134 vnfd_show(ctx
, name
, literal
)
1136 @cli_osm.command(name
='vnfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1137 @click.option('--literal', is_flag
=True,
1138 help='print literally, no pretty table')
1139 @click.option('--repo',
1141 help='Repository name')
1142 @click.argument('name')
1143 @click.option('--filter', default
=None, multiple
=True,
1144 help='filter by fields')
1145 @click.option('--version',
1147 help='package version')
1149 def vnfd_show3(ctx
, name
, repo
, version
, literal
=None, filter=None):
1150 """shows the content of a VNFD in a repository
1152 NAME: name or ID of the VNFD/VNFpkg
1155 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1158 @cli_osm.command(name
='nsd-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1159 @click.option('--literal', is_flag
=True,
1160 help='print literally, no pretty table')
1161 @click.option('--repo',
1163 help='Repository name')
1164 @click.argument('name')
1165 @click.option('--filter', default
=None, multiple
=True,
1166 help='filter by fields')
1167 @click.option('--version',
1169 help='package version')
1171 def nsd_repo_show(ctx
, name
, repo
, version
, literal
=None, filter=None):
1172 """shows the content of a VNFD in a repository
1174 NAME: name or ID of the VNFD/VNFpkg
1177 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1179 @cli_osm.command(name
='nspkg-repo-show', short_help
='shows the details of a NS package in an OSM repository')
1180 @click.option('--literal', is_flag
=True,
1181 help='print literally, no pretty table')
1182 @click.option('--repo',
1184 help='Repository name')
1185 @click.argument('name')
1186 @click.option('--filter', default
=None, multiple
=True,
1187 help='filter by fields')
1188 @click.option('--version',
1190 help='package version')
1192 def nsd_repo_show2(ctx
, name
, repo
, version
, literal
=None, filter=None):
1193 """shows the content of a VNFD in a repository
1195 NAME: name or ID of the VNFD/VNFpkg
1198 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1201 @cli_osm.command(name
='nfpkg-show', short_help
='shows the details of a NF package')
1202 @click.option('--literal', is_flag
=True,
1203 help='print literally, no pretty table')
1204 @click.argument('name')
1206 def nfpkg_show(ctx
, name
, literal
):
1207 """shows the content of a NF Descriptor
1209 NAME: name or ID of the NFpkg
1212 vnfd_show(ctx
, name
, literal
)
1215 @cli_osm.command(name
='nfpkg-repo-show', short_help
='shows the details of a NF package in an OSM repository')
1216 @click.option('--literal', is_flag
=True,
1217 help='print literally, no pretty table')
1218 @click.option('--repo',
1220 help='Repository name')
1221 @click.argument('name')
1222 @click.option('--filter', default
=None, multiple
=True,
1223 help='filter by fields')
1224 @click.option('--version',
1226 help='package version')
1228 def vnfd_show4(ctx
, name
, repo
, version
, literal
=None, filter=None):
1229 """shows the content of a VNFD in a repository
1231 NAME: name or ID of the VNFD/VNFpkg
1234 pkg_repo_show(ctx
, pkgtype
, name
, repo
, version
, filter, literal
)
1237 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
1238 @click.argument('name')
1239 @click.option('--literal', is_flag
=True,
1240 help='print literally, no pretty table')
1241 @click.option('--filter', multiple
=True,
1242 help='restricts the information to the fields in the filter')
1244 def ns_show(ctx
, name
, literal
, filter):
1245 """shows the info of a NS instance
1247 NAME: name or ID of the NS instance
1251 ns
= ctx
.obj
.ns
.get(name
)
1252 # except ClientException as e:
1257 print(yaml
.safe_dump(ns
, indent
=4, default_flow_style
=False))
1260 table
= PrettyTable(['field', 'value'])
1262 for k
, v
in list(ns
.items()):
1263 if not filter or k
in filter:
1264 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
1266 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
1267 if fullclassname
!= 'osmclient.sol005.client.Client':
1268 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
1269 nsr_optdata
= nsopdata
['nsr:nsr']
1270 for k
, v
in list(nsr_optdata
.items()):
1271 if not filter or k
in filter:
1272 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1277 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1278 @click.argument('name')
1279 @click.option('--literal', is_flag
=True,
1280 help='print literally, no pretty table')
1281 @click.option('--filter', multiple
=True,
1282 help='restricts the information to the fields in the filter')
1283 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1285 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1286 """shows the info of a VNF instance
1288 NAME: name or ID of the VNF instance
1290 def print_kdu_status(op_info_status
):
1291 """print KDU status properly formatted
1294 op_status
= yaml
.safe_load(op_info_status
)
1295 if "namespace" in op_status
and "info" in op_status
and \
1296 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1297 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1298 "seconds" in op_status
["info"]["last_deployed"]:
1299 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1300 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1301 print("NAMESPACE: {}".format(op_status
["namespace"]))
1302 status_code
= "UNKNOWN"
1303 if op_status
["info"]["status"]["code"]==1:
1304 status_code
= "DEPLOYED"
1305 print("STATUS: {}".format(status_code
))
1308 print(op_status
["info"]["status"]["resources"])
1309 if "notes" in op_status
["info"]["status"]:
1311 print(op_status
["info"]["status"]["notes"])
1313 print(op_info_status
)
1315 print(op_info_status
)
1320 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1322 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1325 check_client_version(ctx
.obj
, ctx
.command
.name
)
1326 resp
= ctx
.obj
.vnf
.get(name
)
1329 ns_id
= resp
['nsr-id-ref']
1331 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1332 op_data
['kdu_name'] = kdu
1333 op_data
['primitive'] = 'status'
1334 op_data
['primitive_params'] = {}
1335 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1338 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1339 if op_info
['operationState'] == 'COMPLETED':
1340 print_kdu_status(op_info
['detailed-status'])
1344 print ("Could not determine KDU status")
1348 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1351 table
= PrettyTable(['field', 'value'])
1352 for k
, v
in list(resp
.items()):
1353 if not filter or k
in filter:
1354 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1357 # except ClientException as e:
1362 #@cli_osm.command(name='vnf-monitoring-show')
1363 #@click.argument('vnf_name')
1364 #@click.pass_context
1365 #def vnf_monitoring_show(ctx, vnf_name):
1367 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1368 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1369 # except ClientException as e:
1373 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1374 # if resp is not None:
1375 # for monitor in resp:
1379 # monitor['value-integer'],
1380 # monitor['units']])
1385 #@cli_osm.command(name='ns-monitoring-show')
1386 #@click.argument('ns_name')
1387 #@click.pass_context
1388 #def ns_monitoring_show(ctx, ns_name):
1390 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1391 # resp = ctx.obj.ns.get_monitoring(ns_name)
1392 # except ClientException as e:
1396 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1397 # for key, val in list(resp.items()):
1398 # for monitor in val:
1402 # monitor['value-integer'],
1403 # monitor['units']])
1408 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1409 @click.argument('id')
1410 @click.option('--filter', multiple
=True,
1411 help='restricts the information to the fields in the filter')
1412 @click.option('--literal', is_flag
=True,
1413 help='print literally, no pretty table')
1415 def ns_op_show(ctx
, id, filter, literal
):
1416 """shows the detailed info of a NS operation
1418 ID: operation identifier
1422 check_client_version(ctx
.obj
, ctx
.command
.name
)
1423 op_info
= ctx
.obj
.ns
.get_op(id)
1424 # except ClientException as e:
1429 print(yaml
.safe_dump(op_info
, indent
=4, default_flow_style
=False))
1432 table
= PrettyTable(['field', 'value'])
1433 for k
, v
in list(op_info
.items()):
1434 if not filter or k
in filter:
1435 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1440 def nst_show(ctx
, name
, literal
):
1443 check_client_version(ctx
.obj
, ctx
.command
.name
)
1444 resp
= ctx
.obj
.nst
.get(name
)
1445 #resp = ctx.obj.nst.get_individual(name)
1446 # except ClientException as e:
1451 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
1454 table
= PrettyTable(['field', 'value'])
1455 for k
, v
in list(resp
.items()):
1456 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1461 @cli_osm.command(name
='nst-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_show1(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 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1476 @click.option('--literal', is_flag
=True,
1477 help='print literally, no pretty table')
1478 @click.argument('name')
1480 def nst_show2(ctx
, name
, literal
):
1481 """shows the content of a Network Slice Template (NST)
1483 NAME: name or ID of the NST
1486 nst_show(ctx
, name
, literal
)
1489 def nsi_show(ctx
, name
, literal
, filter):
1492 check_client_version(ctx
.obj
, ctx
.command
.name
)
1493 nsi
= ctx
.obj
.nsi
.get(name
)
1494 # except ClientException as e:
1499 print(yaml
.safe_dump(nsi
, indent
=4, default_flow_style
=False))
1502 table
= PrettyTable(['field', 'value'])
1504 for k
, v
in list(nsi
.items()):
1505 if not filter or k
in filter:
1506 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1512 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1513 @click.argument('name')
1514 @click.option('--literal', is_flag
=True,
1515 help='print literally, no pretty table')
1516 @click.option('--filter', multiple
=True,
1517 help='restricts the information to the fields in the filter')
1519 def nsi_show1(ctx
, name
, literal
, filter):
1520 """shows the content of a Network Slice Instance (NSI)
1522 NAME: name or ID of the Network Slice Instance
1525 nsi_show(ctx
, name
, literal
, filter)
1528 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1529 @click.argument('name')
1530 @click.option('--literal', is_flag
=True,
1531 help='print literally, no pretty table')
1532 @click.option('--filter', multiple
=True,
1533 help='restricts the information to the fields in the filter')
1535 def nsi_show2(ctx
, name
, literal
, filter):
1536 """shows the content of a Network Slice Instance (NSI)
1538 NAME: name or ID of the Network Slice Instance
1541 nsi_show(ctx
, name
, literal
, filter)
1544 def nsi_op_show(ctx
, id, filter):
1547 check_client_version(ctx
.obj
, ctx
.command
.name
)
1548 op_info
= ctx
.obj
.nsi
.get_op(id)
1549 # except ClientException as e:
1553 table
= PrettyTable(['field', 'value'])
1554 for k
, v
in list(op_info
.items()):
1555 if not filter or k
in filter:
1556 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1561 @cli_osm.command(name
='nsi-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_show1(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
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1576 @click.argument('id')
1577 @click.option('--filter', multiple
=True,
1578 help='restricts the information to the fields in the filter')
1580 def nsi_op_show2(ctx
, id, filter):
1581 """shows the info of an operation over a Network Slice Instance(NSI)
1583 ID: operation identifier
1586 nsi_op_show(ctx
, id, filter)
1589 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1590 @click.argument('name')
1591 @click.option('--literal', is_flag
=True,
1592 help='print literally, no pretty table')
1593 @click.option('--filter', multiple
=True,
1594 help='restricts the information to the fields in the filter')
1596 def pdu_show(ctx
, name
, literal
, filter):
1597 """shows the content of a Physical Deployment Unit (PDU)
1599 NAME: name or ID of the PDU
1603 check_client_version(ctx
.obj
, ctx
.command
.name
)
1604 pdu
= ctx
.obj
.pdu
.get(name
)
1605 # except ClientException as e:
1610 print(yaml
.safe_dump(pdu
, indent
=4, default_flow_style
=False))
1613 table
= PrettyTable(['field', 'value'])
1615 for k
, v
in list(pdu
.items()):
1616 if not filter or k
in filter:
1617 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1623 ####################
1625 ####################
1627 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1630 check_client_version(ctx
.obj
, ctx
.command
.name
)
1632 filename
= ctx
.obj
.osmrepo
.get_pkg('ns', filename
, repo
, vendor
, version
)
1633 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1634 # except ClientException as e:
1639 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1640 @click.argument('filename')
1641 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1642 help='Deprecated. Use override')
1643 @click.option('--override', 'overwrite', default
=None,
1644 help='overrides fields in descriptor, format: '
1645 '"key1.key2...=value[;key3...=value;...]"')
1646 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1647 help='The charm will not be compiled, it is assumed to already exist')
1648 @click.option('--repo', default
=None,
1649 help='[repository]: Repository name')
1650 @click.option('--vendor', default
=None,
1651 help='[repository]: filter by vendor]')
1652 @click.option('--version', default
='latest',
1653 help='[repository]: filter by version. Default: latest')
1655 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1656 """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1659 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1660 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1661 If FILENAME is an NF Package folder, it is built and then onboarded.
1664 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1668 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1669 @click.argument('filename')
1670 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1671 help='Deprecated. Use override')
1672 @click.option('--override', 'overwrite', default
=None,
1673 help='overrides fields in descriptor, format: '
1674 '"key1.key2...=value[;key3...=value;...]"')
1675 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1676 help='The charm will not be compiled, it is assumed to already exist')
1677 @click.option('--repo', default
=None,
1678 help='[repository]: Repository name')
1679 @click.option('--vendor', default
=None,
1680 help='[repository]: filter by vendor]')
1681 @click.option('--version', default
='latest',
1682 help='[repository]: filter by version. Default: latest')
1684 def nsd_pkg_create(ctx
, filename
, overwrite
, skip_charm_build
, repo
, vendor
, version
):
1685 """onboards a new NSpkg
1687 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1688 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1689 If FILENAME is an NF Package folder, it is built and then onboarded.
1692 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
, repo
=repo
, vendor
=vendor
,
1696 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1697 repo
, vendor
, version
):
1700 check_client_version(ctx
.obj
, ctx
.command
.name
)
1702 filename
= ctx
.obj
.osmrepo
.get_pkg('vnf', filename
, repo
, vendor
, version
)
1703 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1704 override_epa
=override_epa
, override_nonepa
=override_nonepa
,
1705 override_paravirt
=override_paravirt
)
1706 # except ClientException as e:
1711 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1712 @click.argument('filename')
1713 @click.option('--overwrite', 'overwrite', default
=None,
1714 help='overwrite deprecated, use override')
1715 @click.option('--override', 'overwrite', default
=None,
1716 help='overrides fields in descriptor, format: '
1717 '"key1.key2...=value[;key3...=value;...]"')
1718 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1719 help='The charm will not be compiled, it is assumed to already exist')
1720 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1721 help='adds guest-epa parameters to all VDU')
1722 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1723 help='removes all guest-epa parameters from all VDU')
1724 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1725 help='overrides all VDU interfaces to PARAVIRT')
1726 @click.option('--repo', default
=None,
1727 help='[repository]: Repository name')
1728 @click.option('--vendor', default
=None,
1729 help='[repository]: filter by vendor]')
1730 @click.option('--version', default
='latest',
1731 help='[repository]: filter by version. Default: latest')
1733 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1734 repo
,vendor
, version
):
1735 """creates a new VNFD/VNFpkg
1737 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1738 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1739 If FILENAME is an NF Package folder, it is built and then onboarded.
1742 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1743 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1744 repo
=repo
, vendor
=vendor
, version
=version
)
1747 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1748 @click.argument('filename')
1749 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1750 help='Deprecated. Use override')
1751 @click.option('--override', 'overwrite', default
=None,
1752 help='overrides fields in descriptor, format: '
1753 '"key1.key2...=value[;key3...=value;...]"')
1754 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1755 help='The charm will not be compiled, it is assumed to already exist')
1756 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1757 help='adds guest-epa parameters to all VDU')
1758 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1759 help='removes all guest-epa parameters from all VDU')
1760 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1761 help='overrides all VDU interfaces to PARAVIRT')
1762 @click.option('--repo', default
=None,
1763 help='[repository]: Repository name')
1764 @click.option('--vendor', default
=None,
1765 help='[repository]: filter by vendor]')
1766 @click.option('--version', default
='latest',
1767 help='[repository]: filter by version. Default: latest')
1769 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1770 repo
, vendor
, version
):
1771 """creates a new VNFD/VNFpkg
1773 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1774 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1775 If FILENAME is an NF Package folder, it is built and then onboarded.
1778 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1779 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1780 repo
=repo
, vendor
=vendor
, version
=version
)
1782 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1783 @click.argument('filename')
1784 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1785 help='Deprecated. Use override')
1786 @click.option('--override', 'overwrite', default
=None,
1787 help='overrides fields in descriptor, format: '
1788 '"key1.key2...=value[;key3...=value;...]"')
1789 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1790 help='The charm will not be compiled, it is assumed to already exist')
1791 @click.option('--override-epa', required
=False, default
=False, is_flag
=True,
1792 help='adds guest-epa parameters to all VDU')
1793 @click.option('--override-nonepa', required
=False, default
=False, is_flag
=True,
1794 help='removes all guest-epa parameters from all VDU')
1795 @click.option('--override-paravirt', required
=False, default
=False, is_flag
=True,
1796 help='overrides all VDU interfaces to PARAVIRT')
1797 @click.option('--repo', default
=None,
1798 help='[repository]: Repository name')
1799 @click.option('--vendor', default
=None,
1800 help='[repository]: filter by vendor]')
1801 @click.option('--version', default
='latest',
1802 help='[repository]: filter by version. Default: latest')
1804 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
, override_epa
, override_nonepa
, override_paravirt
,
1805 repo
, vendor
, version
):
1806 """creates a new NFpkg
1809 FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1810 If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1811 If FILENAME is an NF Package folder, it is built and then onboarded.
1814 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
,
1815 override_epa
=override_epa
, override_nonepa
=override_nonepa
, override_paravirt
=override_paravirt
,
1816 repo
=repo
, vendor
=vendor
, version
=version
)
1819 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1820 @click.option('--ns_name',
1821 prompt
=True, help='name of the NS instance')
1822 @click.option('--nsd_name',
1823 prompt
=True, help='name of the NS descriptor')
1824 @click.option('--vim_account',
1825 prompt
=True, help='default VIM account id or name for the deployment')
1826 @click.option('--admin_status',
1828 help='administration status')
1829 @click.option('--ssh_keys',
1831 help='comma separated list of public key files to inject to vnfs')
1832 @click.option('--config',
1834 help='ns specific yaml configuration')
1835 @click.option('--config_file',
1837 help='ns specific yaml configuration file')
1838 @click.option('--wait',
1842 help='do not return the control immediately, but keep it '
1843 'until the operation is completed, or timeout')
1854 """creates a new NS instance"""
1858 check_client_version(ctx
.obj
, '--config_file')
1860 raise ClientException('"--config" option is incompatible with "--config_file" option')
1861 with
open(config_file
, 'r') as cf
:
1868 account
=vim_account
,
1870 # except ClientException as e:
1875 def nst_create(ctx
, filename
, overwrite
):
1878 check_client_version(ctx
.obj
, ctx
.command
.name
)
1879 ctx
.obj
.nst
.create(filename
, overwrite
)
1880 # except ClientException as e:
1885 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1886 @click.argument('filename')
1887 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1888 help='Deprecated. Use override')
1889 @click.option('--override', 'overwrite', default
=None,
1890 help='overrides fields in descriptor, format: '
1891 '"key1.key2...=value[;key3...=value;...]"')
1893 def nst_create1(ctx
, filename
, overwrite
):
1894 """creates a new Network Slice Template (NST)
1896 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1899 nst_create(ctx
, filename
, overwrite
)
1902 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1903 @click.argument('filename')
1904 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1905 help='Deprecated. Use override')
1906 @click.option('--override', 'overwrite', default
=None,
1907 help='overrides fields in descriptor, format: '
1908 '"key1.key2...=value[;key3...=value;...]"')
1910 def nst_create2(ctx
, filename
, overwrite
):
1911 """creates a new Network Slice Template (NST)
1913 FILENAME: NST yaml file or NSTpkg tar.gz file
1916 nst_create(ctx
, filename
, overwrite
)
1919 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1920 """creates a new Network Slice Instance (NSI)"""
1923 check_client_version(ctx
.obj
, ctx
.command
.name
)
1926 raise ClientException('"--config" option is incompatible with "--config_file" option')
1927 with
open(config_file
, 'r') as cf
:
1929 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1930 account
=vim_account
, wait
=wait
)
1931 # except ClientException as e:
1936 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1937 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1938 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1939 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1940 @click.option('--ssh_keys', default
=None,
1941 help='comma separated list of keys to inject to vnfs')
1942 @click.option('--config', default
=None,
1943 help='Netslice specific yaml configuration:\n'
1944 'netslice_subnet: [\n'
1945 'id: TEXT, vim_account: TEXT,\n'
1946 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1947 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1948 'additionalParamsForNsi: {param: value, ...}\n'
1949 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1951 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1953 @click.option('--config_file',
1955 help='nsi specific yaml configuration file')
1956 @click.option('--wait',
1960 help='do not return the control immediately, but keep it '
1961 'until the operation is completed, or timeout')
1963 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1964 """creates a new Network Slice Instance (NSI)"""
1966 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1969 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1970 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1971 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1972 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1973 @click.option('--ssh_keys', default
=None,
1974 help='comma separated list of keys to inject to vnfs')
1975 @click.option('--config', default
=None,
1976 help='Netslice specific yaml configuration:\n'
1977 'netslice_subnet: [\n'
1978 'id: TEXT, vim_account: TEXT,\n'
1979 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1980 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1982 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1984 @click.option('--config_file',
1986 help='nsi specific yaml configuration file')
1987 @click.option('--wait',
1991 help='do not return the control immediately, but keep it '
1992 'until the operation is completed, or timeout')
1994 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1995 """creates a new Network Slice Instance (NSI)"""
1997 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
2000 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
2001 @click.option('--name', help='name of the Physical Deployment Unit')
2002 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
2003 @click.option('--interface',
2004 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
2005 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
2007 @click.option('--description', help='human readable description')
2008 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
2009 @click.option('--descriptor_file', default
=None,
2010 help='PDU descriptor file (as an alternative to using the other arguments')
2012 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
2013 """creates a new Physical Deployment Unit (PDU)"""
2016 check_client_version(ctx
.obj
, ctx
.command
.name
)
2018 if not descriptor_file
:
2020 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
2022 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
2024 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
2026 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
2028 with
open(descriptor_file
, 'r') as df
:
2029 pdu
= yaml
.safe_load(df
.read())
2030 if name
: pdu
["name"] = name
2031 if pdu_type
: pdu
["type"] = pdu_type
2032 if description
: pdu
["description"] = description
2033 if vim_account
: pdu
["vim_accounts"] = vim_account
2036 for iface
in interface
:
2037 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
2038 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
2039 ifaces_list
.append(new_iface
)
2040 pdu
["interfaces"] = ifaces_list
2041 ctx
.obj
.pdu
.create(pdu
)
2042 # except ClientException as e:
2047 ####################
2049 ####################
2051 def nsd_update(ctx
, name
, content
):
2054 check_client_version(ctx
.obj
, ctx
.command
.name
)
2055 ctx
.obj
.nsd
.update(name
, content
)
2056 # except ClientException as e:
2061 @cli_osm.command(name
='nsd-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_update1(ctx
, name
, content
):
2067 """updates a NSD/NSpkg
2069 NAME: name or ID of the NSD/NSpkg
2072 nsd_update(ctx
, name
, content
)
2075 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
2076 @click.argument('name')
2077 @click.option('--content', default
=None,
2078 help='filename with the NSD/NSpkg replacing the current one')
2080 def nsd_update2(ctx
, name
, content
):
2081 """updates a NSD/NSpkg
2083 NAME: name or ID of the NSD/NSpkg
2086 nsd_update(ctx
, name
, content
)
2089 def vnfd_update(ctx
, name
, content
):
2092 check_client_version(ctx
.obj
, ctx
.command
.name
)
2093 ctx
.obj
.vnfd
.update(name
, content
)
2094 # except ClientException as e:
2099 @cli_osm.command(name
='vnfd-update', short_help
='updates a new 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_update1(ctx
, name
, content
):
2105 """updates a VNFD/VNFpkg
2107 NAME: name or ID of the VNFD/VNFpkg
2110 vnfd_update(ctx
, name
, content
)
2113 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
2114 @click.argument('name')
2115 @click.option('--content', default
=None,
2116 help='filename with the VNFD/VNFpkg replacing the current one')
2118 def vnfd_update2(ctx
, name
, content
):
2119 """updates a VNFD/VNFpkg
2121 NAME: VNFD yaml file or VNFpkg tar.gz file
2124 vnfd_update(ctx
, name
, content
)
2127 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
2128 @click.argument('name')
2129 @click.option('--content', default
=None,
2130 help='filename with the NFpkg replacing the current one')
2132 def nfpkg_update(ctx
, name
, content
):
2135 NAME: NF Descriptor yaml file or NFpkg tar.gz file
2138 vnfd_update(ctx
, name
, content
)
2141 def nst_update(ctx
, name
, content
):
2144 check_client_version(ctx
.obj
, ctx
.command
.name
)
2145 ctx
.obj
.nst
.update(name
, content
)
2146 # except ClientException as e:
2151 @cli_osm.command(name
='nst-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_update1(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 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
2166 @click.argument('name')
2167 @click.option('--content', default
=None,
2168 help='filename with the NST/NSTpkg replacing the current one')
2170 def nst_update2(ctx
, name
, content
):
2171 """updates a Network Slice Template (NST)
2173 NAME: name or ID of the NSD/NSpkg
2176 nst_update(ctx
, name
, content
)
2179 ####################
2181 ####################
2183 def nsd_delete(ctx
, name
, force
):
2187 ctx
.obj
.nsd
.delete(name
)
2189 check_client_version(ctx
.obj
, '--force')
2190 ctx
.obj
.nsd
.delete(name
, force
)
2191 # except ClientException as e:
2196 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
2197 @click.argument('name')
2198 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2200 def nsd_delete1(ctx
, name
, force
):
2201 """deletes a NSD/NSpkg
2203 NAME: name or ID of the NSD/NSpkg to be deleted
2206 nsd_delete(ctx
, name
, force
)
2209 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
2210 @click.argument('name')
2211 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2213 def nsd_delete2(ctx
, name
, force
):
2214 """deletes a NSD/NSpkg
2216 NAME: name or ID of the NSD/NSpkg to be deleted
2219 nsd_delete(ctx
, name
, force
)
2222 def vnfd_delete(ctx
, name
, force
):
2226 ctx
.obj
.vnfd
.delete(name
)
2228 check_client_version(ctx
.obj
, '--force')
2229 ctx
.obj
.vnfd
.delete(name
, force
)
2230 # except ClientException as e:
2235 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
2236 @click.argument('name')
2237 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2239 def vnfd_delete1(ctx
, name
, force
):
2240 """deletes a VNFD/VNFpkg
2242 NAME: name or ID of the VNFD/VNFpkg to be deleted
2245 vnfd_delete(ctx
, name
, force
)
2248 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
2249 @click.argument('name')
2250 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2252 def vnfd_delete2(ctx
, name
, force
):
2253 """deletes a VNFD/VNFpkg
2255 NAME: name or ID of the VNFD/VNFpkg to be deleted
2258 vnfd_delete(ctx
, name
, force
)
2261 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
2262 @click.argument('name')
2263 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2265 def nfpkg_delete(ctx
, name
, force
):
2268 NAME: name or ID of the NFpkg to be deleted
2271 vnfd_delete(ctx
, name
, force
)
2274 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
2275 @click.argument('name')
2276 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2277 @click.option('--config', default
=None,
2278 help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2279 "600, skip_terminate_primitives: True}'")
2280 @click.option('--wait',
2284 help='do not return the control immediately, but keep it '
2285 'until the operation is completed, or timeout')
2287 def ns_delete(ctx
, name
, force
, config
, wait
):
2288 """deletes a NS instance
2290 NAME: name or ID of the NS instance to be deleted
2295 ctx
.obj
.ns
.delete(name
, config
=config
, wait
=wait
)
2297 check_client_version(ctx
.obj
, '--force')
2298 ctx
.obj
.ns
.delete(name
, force
, config
=config
, wait
=wait
)
2299 # except ClientException as e:
2304 def nst_delete(ctx
, name
, force
):
2307 check_client_version(ctx
.obj
, ctx
.command
.name
)
2308 ctx
.obj
.nst
.delete(name
, force
)
2309 # except ClientException as e:
2314 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
2315 @click.argument('name')
2316 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2318 def nst_delete1(ctx
, name
, force
):
2319 """deletes a Network Slice Template (NST)
2321 NAME: name or ID of the NST/NSTpkg to be deleted
2324 nst_delete(ctx
, name
, force
)
2327 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
2328 @click.argument('name')
2329 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2331 def nst_delete2(ctx
, name
, force
):
2332 """deletes a Network Slice Template (NST)
2334 NAME: name or ID of the NST/NSTpkg to be deleted
2337 nst_delete(ctx
, name
, force
)
2340 def nsi_delete(ctx
, name
, force
, wait
):
2343 check_client_version(ctx
.obj
, ctx
.command
.name
)
2344 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
2345 # except ClientException as e:
2350 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
2351 @click.argument('name')
2352 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2353 @click.option('--wait',
2357 help='do not return the control immediately, but keep it '
2358 'until the operation is completed, or timeout')
2360 def nsi_delete1(ctx
, name
, force
, wait
):
2361 """deletes a Network Slice Instance (NSI)
2363 NAME: name or ID of the Network Slice instance to be deleted
2366 nsi_delete(ctx
, name
, force
, wait
=wait
)
2369 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2370 @click.argument('name')
2371 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2373 def nsi_delete2(ctx
, name
, force
, wait
):
2374 """deletes a Network Slice Instance (NSI)
2376 NAME: name or ID of the Network Slice instance to be deleted
2379 nsi_delete(ctx
, name
, force
, wait
=wait
)
2382 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2383 @click.argument('name')
2384 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2386 def pdu_delete(ctx
, name
, force
):
2387 """deletes a Physical Deployment Unit (PDU)
2389 NAME: name or ID of the PDU to be deleted
2393 check_client_version(ctx
.obj
, ctx
.command
.name
)
2394 ctx
.obj
.pdu
.delete(name
, force
)
2395 # except ClientException as e:
2404 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2405 @click.option('--name',
2407 help='Name to create datacenter')
2408 @click.option('--user',
2410 help='VIM username')
2411 @click.option('--password',
2414 confirmation_prompt
=True,
2415 help='VIM password')
2416 @click.option('--auth_url',
2419 @click.option('--tenant',
2421 help='VIM tenant name')
2422 @click.option('--config',
2424 help='VIM specific config parameters')
2425 @click.option('--account_type',
2426 default
='openstack',
2428 @click.option('--description',
2430 help='human readable description')
2431 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2432 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2433 @click.option('--wait',
2437 help='do not return the control immediately, but keep it '
2438 'until the operation is completed, or timeout')
2452 """creates a new VIM account"""
2456 check_client_version(ctx
.obj
, '--sdn_controller')
2457 if sdn_port_mapping
:
2458 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2460 vim
['vim-username'] = user
2461 vim
['vim-password'] = password
2462 vim
['vim-url'] = auth_url
2463 vim
['vim-tenant-name'] = tenant
2464 vim
['vim-type'] = account_type
2465 vim
['description'] = description
2466 vim
['config'] = config
2467 if sdn_controller
or sdn_port_mapping
:
2468 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2470 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2471 # except ClientException as e:
2476 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2477 @click.argument('name')
2478 @click.option('--newname', help='New name for the VIM account')
2479 @click.option('--user', help='VIM username')
2480 @click.option('--password', help='VIM password')
2481 @click.option('--auth_url', help='VIM url')
2482 @click.option('--tenant', help='VIM tenant name')
2483 @click.option('--config', help='VIM specific config parameters')
2484 @click.option('--account_type', help='VIM type')
2485 @click.option('--description', help='human readable description')
2486 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller to be associated with this VIM'
2487 'account. Use empty string to disassociate')
2488 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2489 @click.option('--wait',
2493 help='do not return the control immediately, but keep it '
2494 'until the operation is completed, or timeout')
2509 """updates a VIM account
2511 NAME: name or ID of the VIM account
2515 check_client_version(ctx
.obj
, ctx
.command
.name
)
2517 if newname
: vim
['name'] = newname
2518 if user
: vim
['vim_user'] = user
2519 if password
: vim
['vim_password'] = password
2520 if auth_url
: vim
['vim_url'] = auth_url
2521 if tenant
: vim
['vim-tenant-name'] = tenant
2522 if account_type
: vim
['vim_type'] = account_type
2523 if description
: vim
['description'] = description
2524 if config
: vim
['config'] = config
2525 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2526 # except ClientException as e:
2531 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2532 @click.argument('name')
2533 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2534 @click.option('--wait',
2538 help='do not return the control immediately, but keep it '
2539 'until the operation is completed, or timeout')
2541 def vim_delete(ctx
, name
, force
, wait
):
2542 """deletes a VIM account
2544 NAME: name or ID of the VIM account to be deleted
2549 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2551 check_client_version(ctx
.obj
, '--force')
2552 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2553 # except ClientException as e:
2558 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2559 #@click.option('--ro_update/--no_ro_update',
2561 # help='update list from RO')
2562 @click.option('--filter', default
=None, multiple
=True,
2563 help='restricts the list to the VIM accounts matching the filter')
2564 @click.option('--long', is_flag
=True,
2565 help='get more details of the NS (project, vim, deployment status, configuration status.')
2567 def vim_list(ctx
, filter, long):
2568 """list all VIM accounts"""
2571 filter='&'.join(filter)
2572 check_client_version(ctx
.obj
, '--filter')
2574 # check_client_version(ctx.obj, '--ro_update', 'v1')
2575 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2576 if fullclassname
== 'osmclient.sol005.client.Client':
2577 resp
= ctx
.obj
.vim
.list(filter)
2579 # resp = ctx.obj.vim.list(ro_update)
2581 table
= PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details'])
2582 project_list
= ctx
.obj
.project
.list()
2584 table
= PrettyTable(['vim name', 'uuid', 'operational state'])
2587 if 'vim_password' in vim
:
2588 vim
['vim_password']='********'
2589 logger
.debug('VIM details: {}'.format(yaml
.safe_dump(vim
)))
2590 vim_state
= vim
['_admin'].get('operationalState', '-')
2591 error_details
= 'N/A'
2592 if vim_state
== 'ERROR':
2593 error_details
= vim
['_admin'].get('detailed-status', 'Not found')
2594 project_id
, project_name
= get_project(project_list
, vim
)
2595 #project_info = '{} ({})'.format(project_name, project_id)
2596 project_info
= project_name
2597 table
.add_row([vim
['name'], vim
['uuid'], project_info
,
2598 vim_state
, wrap_text(text
=error_details
, width
=80)])
2600 table
.add_row([vim
['name'], vim
['uuid'], vim
['_admin'].get('operationalState', '-')])
2605 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2606 @click.argument('name')
2607 @click.option('--filter', multiple
=True,
2608 help='restricts the information to the fields in the filter')
2610 def vim_show(ctx
, name
, filter):
2611 """shows the details of a VIM account
2613 NAME: name or ID of the VIM account
2617 resp
= ctx
.obj
.vim
.get(name
)
2618 if 'vim_password' in resp
:
2619 resp
['vim_password']='********'
2620 # except ClientException as e:
2624 table
= PrettyTable(['key', 'attribute'])
2625 for k
, v
in list(resp
.items()):
2626 if not filter or k
in filter:
2627 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2632 ####################
2634 ####################
2636 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2637 @click.option('--name',
2639 help='Name for the WIM account')
2640 @click.option('--user',
2641 help='WIM username')
2642 @click.option('--password',
2643 help='WIM password')
2644 @click.option('--url',
2647 # @click.option('--tenant',
2648 # help='wIM tenant name')
2649 @click.option('--config',
2651 help='WIM specific config parameters')
2652 @click.option('--wim_type',
2654 @click.option('--description',
2656 help='human readable description')
2657 @click.option('--wim_port_mapping', default
=None,
2658 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2659 "(WAN service endpoint id and info)")
2660 @click.option('--wait',
2664 help='do not return the control immediately, but keep it '
2665 'until the operation is completed, or timeout')
2678 """creates a new WIM account"""
2681 check_client_version(ctx
.obj
, ctx
.command
.name
)
2682 # if sdn_controller:
2683 # check_client_version(ctx.obj, '--sdn_controller')
2684 # if sdn_port_mapping:
2685 # check_client_version(ctx.obj, '--sdn_port_mapping')
2687 if user
: wim
['user'] = user
2688 if password
: wim
['password'] = password
2689 if url
: wim
['wim_url'] = url
2690 # if tenant: wim['tenant'] = tenant
2691 wim
['wim_type'] = wim_type
2692 if description
: wim
['description'] = description
2693 if config
: wim
['config'] = config
2694 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2695 # except ClientException as e:
2700 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2701 @click.argument('name')
2702 @click.option('--newname', help='New name for the WIM account')
2703 @click.option('--user', help='WIM username')
2704 @click.option('--password', help='WIM password')
2705 @click.option('--url', help='WIM url')
2706 @click.option('--config', help='WIM specific config parameters')
2707 @click.option('--wim_type', help='WIM type')
2708 @click.option('--description', help='human readable description')
2709 @click.option('--wim_port_mapping', default
=None,
2710 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2711 "(WAN service endpoint id and info)")
2712 @click.option('--wait',
2716 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2729 """updates a WIM account
2731 NAME: name or ID of the WIM account
2735 check_client_version(ctx
.obj
, ctx
.command
.name
)
2737 if newname
: wim
['name'] = newname
2738 if user
: wim
['user'] = user
2739 if password
: wim
['password'] = password
2740 if url
: wim
['url'] = url
2741 # if tenant: wim['tenant'] = tenant
2742 if wim_type
: wim
['wim_type'] = wim_type
2743 if description
: wim
['description'] = description
2744 if config
: wim
['config'] = config
2745 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2746 # except ClientException as e:
2751 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2752 @click.argument('name')
2753 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2754 @click.option('--wait',
2758 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2760 def wim_delete(ctx
, name
, force
, wait
):
2761 """deletes a WIM account
2763 NAME: name or ID of the WIM account to be deleted
2767 check_client_version(ctx
.obj
, ctx
.command
.name
)
2768 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2769 # except ClientException as e:
2774 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2775 @click.option('--filter', default
=None, multiple
=True,
2776 help='restricts the list to the WIM accounts matching the filter')
2778 def wim_list(ctx
, filter):
2779 """list all WIM accounts"""
2782 check_client_version(ctx
.obj
, ctx
.command
.name
)
2784 filter='&'.join(filter)
2785 resp
= ctx
.obj
.wim
.list(filter)
2786 table
= PrettyTable(['wim name', 'uuid'])
2788 table
.add_row([wim
['name'], wim
['uuid']])
2791 # except ClientException as e:
2796 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2797 @click.argument('name')
2799 def wim_show(ctx
, name
):
2800 """shows the details of a WIM account
2802 NAME: name or ID of the WIM account
2806 check_client_version(ctx
.obj
, ctx
.command
.name
)
2807 resp
= ctx
.obj
.wim
.get(name
)
2808 if 'password' in resp
:
2809 resp
['wim_password']='********'
2810 # except ClientException as e:
2814 table
= PrettyTable(['key', 'attribute'])
2815 for k
, v
in list(resp
.items()):
2816 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2821 ####################
2822 # SDN controller operations
2823 ####################
2825 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2826 @click.option('--name',
2828 help='Name to create sdn controller')
2829 @click.option('--type',
2831 help='SDN controller type')
2832 @click.option('--sdn_controller_version', # hidden=True,
2833 help='Deprecated. Use --config {version: sdn_controller_version}')
2834 @click.option('--url',
2835 help='URL in format http[s]://HOST:IP/')
2836 @click.option('--ip_address', # hidden=True,
2837 help='Deprecated. Use --url')
2838 @click.option('--port', # hidden=True,
2839 help='Deprecated. Use --url')
2840 @click.option('--switch_dpid', # hidden=True,
2841 help='Deprecated. Use --config {switch_id: DPID}')
2842 @click.option('--config',
2843 help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2844 'Openflow Datapath ID), version: version}')
2845 @click.option('--user',
2846 help='SDN controller username')
2847 @click.option('--password',
2849 confirmation_prompt
=True,
2850 help='SDN controller password')
2851 @click.option('--description', default
=None, help='human readable description')
2852 @click.option('--wait',
2856 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2858 def sdnc_create(ctx
, **kwargs
):
2859 """creates a new SDN controller"""
2861 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2862 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2863 if kwargs
.get("port"):
2864 print("option '--port' is deprecated, use '--url' instead")
2865 sdncontroller
["port"] = int(kwargs
["port"])
2866 if kwargs
.get("ip_address"):
2867 print("option '--ip_address' is deprecated, use '--url' instead")
2868 sdncontroller
["ip"] = kwargs
["ip_address"]
2869 if kwargs
.get("switch_dpid"):
2870 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2871 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2872 if kwargs
.get("sdn_controller_version"):
2873 print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2876 check_client_version(ctx
.obj
, ctx
.command
.name
)
2877 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2878 # except ClientException as e:
2882 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2883 @click.argument('name')
2884 @click.option('--newname', help='New name for the SDN controller')
2885 @click.option('--description', default
=None, help='human readable description')
2886 @click.option('--type', help='SDN controller type')
2887 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2888 @click.option('--config', help='Extra information for SDN in yaml format, as '
2889 '{switch_id: identity used for the plugin (e.g. DPID: '
2890 'Openflow Datapath ID), version: version}')
2891 @click.option('--user', help='SDN controller username')
2892 @click.option('--password', help='SDN controller password')
2893 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2894 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2895 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2896 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2897 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2898 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2900 def sdnc_update(ctx
, **kwargs
):
2901 """updates an SDN controller
2903 NAME: name or ID of the SDN controller
2906 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2907 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2908 if kwargs
.get("newname"):
2909 sdncontroller
["name"] = kwargs
["newname"]
2910 if kwargs
.get("port"):
2911 print("option '--port' is deprecated, use '--url' instead")
2912 sdncontroller
["port"] = int(kwargs
["port"])
2913 if kwargs
.get("ip_address"):
2914 print("option '--ip_address' is deprecated, use '--url' instead")
2915 sdncontroller
["ip"] = kwargs
["ip_address"]
2916 if kwargs
.get("switch_dpid"):
2917 print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2918 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2919 if kwargs
.get("sdn_controller_version"):
2920 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2924 check_client_version(ctx
.obj
, ctx
.command
.name
)
2925 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2926 # except ClientException as e:
2931 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2932 @click.argument('name')
2933 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2934 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2935 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2937 def sdnc_delete(ctx
, name
, force
, wait
):
2938 """deletes an SDN controller
2940 NAME: name or ID of the SDN controller to be deleted
2944 check_client_version(ctx
.obj
, ctx
.command
.name
)
2945 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2946 # except ClientException as e:
2951 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2952 @click.option('--filter', default
=None, multiple
=True,
2953 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2955 def sdnc_list(ctx
, filter):
2956 """list all SDN controllers"""
2959 check_client_version(ctx
.obj
, ctx
.command
.name
)
2961 filter='&'.join(filter)
2962 resp
= ctx
.obj
.sdnc
.list(filter)
2963 # except ClientException as e:
2966 table
= PrettyTable(['sdnc name', 'id'])
2968 table
.add_row([sdnc
['name'], sdnc
['_id']])
2973 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2974 @click.argument('name')
2976 def sdnc_show(ctx
, name
):
2977 """shows the details of an SDN controller
2979 NAME: name or ID of the SDN controller
2983 check_client_version(ctx
.obj
, ctx
.command
.name
)
2984 resp
= ctx
.obj
.sdnc
.get(name
)
2985 # except ClientException as e:
2989 table
= PrettyTable(['key', 'attribute'])
2990 for k
, v
in list(resp
.items()):
2991 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2996 ###########################
2997 # K8s cluster operations
2998 ###########################
3000 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
3001 @click.argument('name')
3002 @click.option('--creds',
3004 help='credentials file, i.e. a valid `.kube/config` file')
3005 @click.option('--version',
3007 help='Kubernetes version')
3008 @click.option('--vim',
3010 help='VIM target, the VIM where the cluster resides')
3011 @click.option('--k8s-nets',
3013 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) ...]}"')
3014 @click.option('--description',
3016 help='human readable description')
3017 @click.option('--namespace',
3018 default
='kube-system',
3019 help='namespace to be used for its operation, defaults to `kube-system`')
3020 @click.option('--cni',
3022 help='list of CNI plugins, in JSON inline format, used in the cluster')
3023 #@click.option('--skip-init',
3025 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
3026 #@click.option('--wait',
3028 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3030 def k8scluster_add(ctx
,
3039 """adds a K8s cluster to OSM
3041 NAME: name of the K8s cluster
3044 check_client_version(ctx
.obj
, ctx
.command
.name
)
3046 cluster
['name'] = name
3047 with
open(creds
, 'r') as cf
:
3048 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3049 cluster
['k8s_version'] = version
3050 cluster
['vim_account'] = vim
3051 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3053 cluster
['description'] = description
3054 if namespace
: cluster
['namespace'] = namespace
3055 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3056 ctx
.obj
.k8scluster
.create(name
, cluster
)
3057 # except ClientException as e:
3062 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
3063 @click.argument('name')
3064 @click.option('--newname', help='New name for the K8s cluster')
3065 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3066 @click.option('--version', help='Kubernetes version')
3067 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3068 @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) ...]}"')
3069 @click.option('--description', help='human readable description')
3070 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3071 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3073 def k8scluster_update(ctx
,
3083 """updates a K8s cluster
3085 NAME: name or ID of the K8s cluster
3088 check_client_version(ctx
.obj
, ctx
.command
.name
)
3090 if newname
: cluster
['name'] = newname
3092 with
open(creds
, 'r') as cf
:
3093 cluster
['credentials'] = yaml
.safe_load(cf
.read())
3094 if version
: cluster
['k8s_version'] = version
3095 if vim
: cluster
['vim_account'] = vim
3096 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
3097 if description
: cluster
['description'] = description
3098 if namespace
: cluster
['namespace'] = namespace
3099 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
3100 ctx
.obj
.k8scluster
.update(name
, cluster
)
3101 # except ClientException as e:
3106 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
3107 @click.argument('name')
3108 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3109 #@click.option('--wait',
3111 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3113 def k8scluster_delete(ctx
, name
, force
):
3114 """deletes a K8s cluster
3116 NAME: name or ID of the K8s cluster to be deleted
3119 check_client_version(ctx
.obj
, ctx
.command
.name
)
3120 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
3121 # except ClientException as e:
3126 @cli_osm.command(name
='k8scluster-list')
3127 @click.option('--filter', default
=None, multiple
=True,
3128 help='restricts the list to the K8s clusters matching the filter')
3129 @click.option('--literal', is_flag
=True,
3130 help='print literally, no pretty table')
3131 @click.option('--long', is_flag
=True, help='get more details')
3133 def k8scluster_list(ctx
, filter, literal
, long):
3134 """list all K8s clusters"""
3136 check_client_version(ctx
.obj
, ctx
.command
.name
)
3138 filter='&'.join(filter)
3139 resp
= ctx
.obj
.k8scluster
.list(filter)
3141 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3144 table
= PrettyTable(['Name', 'Id', 'Project', 'Version', 'VIM', 'K8s-nets',
3145 'Operational State', 'Op. state (details)', 'Description', 'Detailed status'])
3146 project_list
= ctx
.obj
.project
.list()
3148 table
= PrettyTable(['Name', 'Id', 'VIM', 'Operational State', 'Op. state details'])
3150 vim_list
= ctx
.obj
.vim
.list()
3153 for cluster
in resp
:
3154 logger
.debug('Cluster details: {}'.format(yaml
.safe_dump(cluster
)))
3155 vim_name
= get_vim_name(vim_list
, cluster
['vim_account'])
3156 #vim_info = '{} ({})'.format(vim_name,cluster['vim_account'])
3158 op_state_details
= "Helm: {}\nJuju: {}".format(
3159 cluster
["_admin"].get("helm-chart", {}).get("operationalState", "-"),
3160 cluster
["_admin"].get("juju-bundle", {}).get("operationalState", "-"))
3162 project_id
, project_name
= get_project(project_list
, cluster
)
3163 #project_info = '{} ({})'.format(project_name, project_id)
3164 project_info
= project_name
3165 detailed_status
= cluster
["_admin"].get("detailed-status","-")
3166 table
.add_row([cluster
['name'], cluster
['_id'], project_info
,
3167 cluster
['k8s_version'], vim_info
,
3168 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
3169 op_state_details
, trunc_text(cluster
.get('description') or '', 40),
3170 wrap_text(text
=detailed_status
, width
=40)])
3172 table
.add_row([cluster
['name'], cluster
['_id'], vim_info
,
3173 cluster
["_admin"]["operationalState"], op_state_details
])
3176 # except ClientException as e:
3181 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
3182 @click.argument('name')
3183 @click.option('--literal', is_flag
=True,
3184 help='print literally, no pretty table')
3186 def k8scluster_show(ctx
, name
, literal
):
3187 """shows the details of a K8s cluster
3189 NAME: name or ID of the K8s cluster
3192 resp
= ctx
.obj
.k8scluster
.get(name
)
3194 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3196 table
= PrettyTable(['key', 'attribute'])
3197 for k
, v
in list(resp
.items()):
3198 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
3201 # except ClientException as e:
3207 ###########################
3209 ###########################
3211 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
3212 @click.argument('name')
3213 @click.argument('uri')
3214 @click.option('--type',
3215 type=click
.Choice(['helm-chart', 'juju-bundle', 'osm']),
3217 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3218 @click.option('--description',
3220 help='human readable description')
3221 @click.option('--user',
3223 help='OSM repository: The username of the OSM repository')
3224 @click.option('--password',
3226 help='OSM repository: The password of the OSM repository')
3227 #@click.option('--wait',
3229 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3231 def repo_add(ctx
, **kwargs
):
3232 """adds a repo to OSM
3234 NAME: name of the repo
3235 URI: URI of the repo
3238 kwargs
= {k
: v
for k
, v
in kwargs
.items() if v
is not None}
3240 repo
["url"] = repo
.pop("uri")
3241 if repo
["type"] in ['helm-chart', 'juju-bundle']:
3242 ctx
.obj
.repo
.create(repo
['name'], repo
)
3244 ctx
.obj
.osmrepo
.create(repo
['name'], repo
)
3245 # except ClientException as e:
3250 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
3251 @click.argument('name')
3252 @click.option('--newname', help='New name for the repo')
3253 @click.option('--uri', help='URI of the repo')
3254 @click.option('--description', help='human readable description')
3255 #@click.option('--wait',
3257 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3259 def repo_update(ctx
,
3264 """updates a repo in OSM
3266 NAME: name of the repo
3269 check_client_version(ctx
.obj
, ctx
.command
.name
)
3272 repo
['name'] = newname
3275 if description
: repo
['description'] = description
3277 ctx
.obj
.repo
.update(name
, repo
)
3279 ctx
.obj
.osmrepo
.update(name
, repo
)
3281 # except ClientException as e:
3286 @cli_osm.command(name
='repo-index', short_help
='Index a repository from a folder with artifacts')
3287 @click.option('--origin', default
='.', help='origin path where the artifacts are located')
3288 @click.option('--destination', default
='.', help='destination path where the index is deployed')
3290 def repo_index(ctx
, origin
, destination
):
3291 """Index a repository
3293 NAME: name or ID of the repo to be deleted
3295 check_client_version(ctx
.obj
, ctx
.command
.name
)
3296 ctx
.obj
.osmrepo
.repo_index(origin
, destination
)
3299 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
3300 @click.argument('name')
3301 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
3302 #@click.option('--wait',
3304 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3306 def repo_delete(ctx
, name
, force
):
3309 NAME: name or ID of the repo to be deleted
3313 ctx
.obj
.repo
.delete(name
, force
=force
)
3315 ctx
.obj
.osmrepo
.delete(name
, force
=force
)
3316 # except ClientException as e:
3321 @cli_osm.command(name
='repo-list')
3322 @click.option('--filter', default
=None, multiple
=True,
3323 help='restricts the list to the repos matching the filter')
3324 @click.option('--literal', is_flag
=True,
3325 help='print literally, no pretty table')
3327 def repo_list(ctx
, filter, literal
):
3328 """list all repos"""
3331 check_client_version(ctx
.obj
, ctx
.command
.name
)
3333 filter='&'.join(filter)
3334 resp
= ctx
.obj
.repo
.list(filter)
3335 resp
+= ctx
.obj
.osmrepo
.list(filter)
3337 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3339 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3341 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3342 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description') or '',40)])
3346 # except ClientException as e:
3351 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
3352 @click.argument('name')
3353 @click.option('--literal', is_flag
=True,
3354 help='print literally, no pretty table')
3356 def repo_show(ctx
, name
, literal
):
3357 """shows the details of a repo
3359 NAME: name or ID of the repo
3362 resp
= ctx
.obj
.repo
.get(name
)
3364 resp
= ctx
.obj
.osmrepo
.get(name
)
3368 print(yaml
.safe_dump(resp
, indent
=4, default_flow_style
=False))
3370 table
= PrettyTable(['key', 'attribute'])
3372 for k
, v
in list(resp
.items()):
3373 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3377 # except ClientException as e:
3383 ####################
3384 # Project mgmt operations
3385 ####################
3387 @cli_osm.command(name
='project-create', short_help
='creates a new project')
3388 @click.argument('name')
3389 #@click.option('--description',
3390 # default='no description',
3391 # help='human readable description')
3392 @click.option('--domain-name', 'domain_name',
3394 help='assign to a domain')
3395 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3396 help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3397 "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3399 def project_create(ctx
, name
, domain_name
, quotas
):
3400 """Creates a new project
3402 NAME: name of the project
3403 DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3404 QUOTAS: set quotas for the project
3407 project
= {'name': name
}
3409 project
['domain_name'] = domain_name
3410 quotas_dict
= _process_project_quotas(quotas
)
3412 project
['quotas'] = quotas_dict
3415 check_client_version(ctx
.obj
, ctx
.command
.name
)
3416 ctx
.obj
.project
.create(name
, project
)
3417 # except ClientException as e:
3422 def _process_project_quotas(quota_list
):
3427 for quota
in quota_list
:
3428 for single_quota
in quota
.split(","):
3429 k
, v
= single_quota
.split("=")
3430 quotas_dict
[k
] = None if v
in ('None', 'null', '') else int(v
)
3431 except (ValueError, TypeError):
3432 raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3436 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
3437 @click.argument('name')
3438 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3440 def project_delete(ctx
, name
):
3441 """deletes a project
3443 NAME: name or ID of the project to be deleted
3447 check_client_version(ctx
.obj
, ctx
.command
.name
)
3448 ctx
.obj
.project
.delete(name
)
3449 # except ClientException as e:
3454 @cli_osm.command(name
='project-list', short_help
='list all projects')
3455 @click.option('--filter', default
=None, multiple
=True,
3456 help='restricts the list to the projects matching the filter')
3458 def project_list(ctx
, filter):
3459 """list all projects"""
3462 check_client_version(ctx
.obj
, ctx
.command
.name
)
3464 filter='&'.join(filter)
3465 resp
= ctx
.obj
.project
.list(filter)
3466 # except ClientException as e:
3469 table
= PrettyTable(['name', 'id'])
3471 table
.add_row([proj
['name'], proj
['_id']])
3476 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
3477 @click.argument('name')
3479 def project_show(ctx
, name
):
3480 """shows the details of a project
3482 NAME: name or ID of the project
3486 check_client_version(ctx
.obj
, ctx
.command
.name
)
3487 resp
= ctx
.obj
.project
.get(name
)
3488 # except ClientException as e:
3492 table
= PrettyTable(['key', 'attribute'])
3493 for k
, v
in resp
.items():
3494 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3499 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3500 @click.argument('project')
3501 @click.option('--name', default
=None,
3502 help='new name for the project')
3503 @click.option('--quotas', 'quotas', multiple
=True, default
=None,
3504 help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3505 "(use empty to reset quota to default")
3507 def project_update(ctx
, project
, name
, quotas
):
3509 Update a project name
3512 :param project: id or name of the project to modify
3513 :param name: new name for the project
3514 :param quotas: change quotas of the project
3518 project_changes
= {}
3520 project_changes
['name'] = name
3521 quotas_dict
= _process_project_quotas(quotas
)
3523 project_changes
['quotas'] = quotas_dict
3526 check_client_version(ctx
.obj
, ctx
.command
.name
)
3527 ctx
.obj
.project
.update(project
, project_changes
)
3528 # except ClientException as e:
3532 ####################
3533 # User mgmt operations
3534 ####################
3536 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3537 @click.argument('username')
3538 @click.option('--password',
3541 confirmation_prompt
=True,
3542 help='user password')
3543 @click.option('--projects',
3544 # prompt="Comma separate list of projects",
3546 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3547 help='list of project ids that the user belongs to')
3548 @click.option('--project-role-mappings', 'project_role_mappings',
3549 default
=None, multiple
=True,
3550 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3551 @click.option('--domain-name', 'domain_name',
3553 help='assign to a domain')
3555 def user_create(ctx
, username
, password
, projects
, project_role_mappings
, domain_name
):
3556 """Creates a new user
3559 USERNAME: name of the user
3560 PASSWORD: password of the user
3561 PROJECTS: projects assigned to user (internal only)
3562 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3563 DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3567 user
['username'] = username
3568 user
['password'] = password
3569 user
['projects'] = projects
3570 user
['project_role_mappings'] = project_role_mappings
3572 user
['domain_name'] = domain_name
3575 check_client_version(ctx
.obj
, ctx
.command
.name
)
3576 ctx
.obj
.user
.create(username
, user
)
3577 # except ClientException as e:
3582 @cli_osm.command(name
='user-update', short_help
='updates user information')
3583 @click.argument('username')
3584 @click.option('--password',
3587 # confirmation_prompt=True,
3588 help='user password')
3589 @click.option('--set-username', 'set_username',
3591 help='change username')
3592 @click.option('--set-project', 'set_project',
3593 default
=None, multiple
=True,
3594 help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3595 @click.option('--remove-project', 'remove_project',
3596 default
=None, multiple
=True,
3597 help="removes project from user: 'project'")
3598 @click.option('--add-project-role', 'add_project_role',
3599 default
=None, multiple
=True,
3600 help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3601 @click.option('--remove-project-role', 'remove_project_role',
3602 default
=None, multiple
=True,
3603 help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3605 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3606 add_project_role
, remove_project_role
):
3607 """Update a user information
3610 USERNAME: name of the user
3611 PASSWORD: new password
3612 SET_USERNAME: new username
3613 SET_PROJECT: creating mappings for project/role(s)
3614 REMOVE_PROJECT: deleting mappings for project/role(s)
3615 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3616 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3620 user
['password'] = password
3621 user
['username'] = set_username
3622 user
['set-project'] = set_project
3623 user
['remove-project'] = remove_project
3624 user
['add-project-role'] = add_project_role
3625 user
['remove-project-role'] = remove_project_role
3628 check_client_version(ctx
.obj
, ctx
.command
.name
)
3629 ctx
.obj
.user
.update(username
, user
)
3630 # except ClientException as e:
3635 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3636 @click.argument('name')
3637 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3639 def user_delete(ctx
, name
):
3643 NAME: name or ID of the user to be deleted
3647 check_client_version(ctx
.obj
, ctx
.command
.name
)
3648 ctx
.obj
.user
.delete(name
)
3649 # except ClientException as e:
3654 @cli_osm.command(name
='user-list', short_help
='list all users')
3655 @click.option('--filter', default
=None, multiple
=True,
3656 help='restricts the list to the users matching the filter')
3658 def user_list(ctx
, filter):
3659 """list all users"""
3661 check_client_version(ctx
.obj
, ctx
.command
.name
)
3663 filter='&'.join(filter)
3664 resp
= ctx
.obj
.user
.list(filter)
3665 # except ClientException as e:
3668 table
= PrettyTable(['name', 'id'])
3670 table
.add_row([user
['username'], user
['_id']])
3675 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3676 @click.argument('name')
3678 def user_show(ctx
, name
):
3679 """shows the details of a user
3681 NAME: name or ID of the user
3685 check_client_version(ctx
.obj
, ctx
.command
.name
)
3686 resp
= ctx
.obj
.user
.get(name
)
3687 if 'password' in resp
:
3688 resp
['password']='********'
3689 # except ClientException as e:
3693 table
= PrettyTable(['key', 'attribute'])
3694 for k
, v
in resp
.items():
3695 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3700 ####################
3701 # Fault Management operations
3702 ####################
3704 @cli_osm.command(name
='ns-alarm-create')
3705 @click.argument('name')
3706 @click.option('--ns', prompt
=True, help='NS instance id or name')
3707 @click.option('--vnf', prompt
=True,
3708 help='VNF name (VNF member index as declared in the NSD)')
3709 @click.option('--vdu', prompt
=True,
3710 help='VDU name (VDU name as declared in the VNFD)')
3711 @click.option('--metric', prompt
=True,
3712 help='Name of the metric (e.g. cpu_utilization)')
3713 @click.option('--severity', default
='WARNING',
3714 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3715 @click.option('--threshold_value', prompt
=True,
3716 help='threshold value that, when crossed, an alarm is triggered')
3717 @click.option('--threshold_operator', prompt
=True,
3718 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3719 @click.option('--statistic', default
='AVERAGE',
3720 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3722 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3723 threshold_value
, threshold_operator
, statistic
):
3724 """creates a new alarm for a NS instance"""
3725 # TODO: Check how to validate threshold_value.
3726 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3729 ns_instance
= ctx
.obj
.ns
.get(ns
)
3731 alarm
['alarm_name'] = name
3732 alarm
['ns_id'] = ns_instance
['_id']
3733 alarm
['correlation_id'] = ns_instance
['_id']
3734 alarm
['vnf_member_index'] = vnf
3735 alarm
['vdu_name'] = vdu
3736 alarm
['metric_name'] = metric
3737 alarm
['severity'] = severity
3738 alarm
['threshold_value'] = int(threshold_value
)
3739 alarm
['operation'] = threshold_operator
3740 alarm
['statistic'] = statistic
3741 check_client_version(ctx
.obj
, ctx
.command
.name
)
3742 ctx
.obj
.ns
.create_alarm(alarm
)
3743 # except ClientException as e:
3748 #@cli_osm.command(name='ns-alarm-delete')
3749 #@click.argument('name')
3750 #@click.pass_context
3751 #def ns_alarm_delete(ctx, name):
3752 # """deletes an alarm
3754 # NAME: name of the alarm to be deleted
3757 # check_client_version(ctx.obj, ctx.command.name)
3758 # ctx.obj.ns.delete_alarm(name)
3759 # except ClientException as e:
3764 ####################
3765 # Performance Management operations
3766 ####################
3768 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3769 @click.option('--ns', prompt
=True, help='NS instance id or name')
3770 @click.option('--vnf', prompt
=True,
3771 help='VNF name (VNF member index as declared in the NSD)')
3772 @click.option('--vdu', prompt
=True,
3773 help='VDU name (VDU name as declared in the VNFD)')
3774 @click.option('--metric', prompt
=True,
3775 help='name of the metric (e.g. cpu_utilization)')
3776 #@click.option('--period', default='1w',
3777 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3778 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3780 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3781 """exports a metric to the internal OSM bus, which can be read by other apps"""
3782 # TODO: Check how to validate interval.
3783 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3786 ns_instance
= ctx
.obj
.ns
.get(ns
)
3788 metric_data
['ns_id'] = ns_instance
['_id']
3789 metric_data
['correlation_id'] = ns_instance
['_id']
3790 metric_data
['vnf_member_index'] = vnf
3791 metric_data
['vdu_name'] = vdu
3792 metric_data
['metric_name'] = metric
3793 metric_data
['collection_unit'] = 'WEEK'
3794 metric_data
['collection_period'] = 1
3795 check_client_version(ctx
.obj
, ctx
.command
.name
)
3797 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3801 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3802 time
.sleep(int(interval
))
3804 # except ClientException as e:
3809 ####################
3811 ####################
3813 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3815 def get_version(ctx
):
3816 """shows client and server versions"""
3818 check_client_version(ctx
.obj
, "version")
3819 print ("Server version: {}".format(ctx
.obj
.get_version()))
3820 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3821 # except ClientException as e:
3825 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3826 @click.argument('filename')
3827 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3828 help='the charm will not be compiled, it is assumed to already exist')
3830 def upload_package(ctx
, filename
, skip_charm_build
):
3831 """uploads a vnf package or ns package
3833 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3837 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3838 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3839 if fullclassname
!= 'osmclient.sol005.client.Client':
3840 ctx
.obj
.package
.wait_for_upload(filename
)
3841 # except ClientException as e:
3846 #@cli_osm.command(name='ns-scaling-show')
3847 #@click.argument('ns_name')
3848 #@click.pass_context
3849 #def show_ns_scaling(ctx, ns_name):
3850 # """shows the status of a NS scaling operation
3852 # NS_NAME: name of the NS instance being scaled
3855 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3856 # resp = ctx.obj.ns.list()
3857 # except ClientException as e:
3861 # table = PrettyTable(
3864 # 'operational status',
3869 # if ns_name == ns['name']:
3870 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3871 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3872 # for record in scaling_records:
3873 # if 'instance' in record:
3874 # instances = record['instance']
3875 # for inst in instances:
3877 # [record['scaling-group-name-ref'],
3878 # inst['instance-id'],
3879 # inst['op-status'],
3880 # time.strftime('%Y-%m-%d %H:%M:%S',
3882 # inst['create-time'])),
3888 #@cli_osm.command(name='ns-scale')
3889 #@click.argument('ns_name')
3890 #@click.option('--ns_scale_group', prompt=True)
3891 #@click.option('--index', prompt=True)
3892 #@click.option('--wait',
3896 # help='do not return the control immediately, but keep it \
3897 # until the operation is completed, or timeout')
3898 #@click.pass_context
3899 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3902 # NS_NAME: name of the NS instance to be scaled
3905 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3906 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3907 # except ClientException as e:
3912 #@cli_osm.command(name='config-agent-list')
3913 #@click.pass_context
3914 #def config_agent_list(ctx):
3915 # """list config agents"""
3917 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3918 # except ClientException as e:
3921 # table = PrettyTable(['name', 'account-type', 'details'])
3922 # for account in ctx.obj.vca.list():
3925 # account['account-type'],
3931 #@cli_osm.command(name='config-agent-delete')
3932 #@click.argument('name')
3933 #@click.pass_context
3934 #def config_agent_delete(ctx, name):
3935 # """deletes a config agent
3937 # NAME: name of the config agent to be deleted
3940 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3941 # ctx.obj.vca.delete(name)
3942 # except ClientException as e:
3947 #@cli_osm.command(name='config-agent-add')
3948 #@click.option('--name',
3950 #@click.option('--account_type',
3952 #@click.option('--server',
3954 #@click.option('--user',
3956 #@click.option('--secret',
3959 # confirmation_prompt=True)
3960 #@click.pass_context
3961 #def config_agent_add(ctx, name, account_type, server, user, secret):
3962 # """adds a config agent"""
3964 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3965 # ctx.obj.vca.create(name, account_type, server, user, secret)
3966 # except ClientException as e:
3971 #@cli_osm.command(name='ro-dump')
3972 #@click.pass_context
3974 # """shows RO agent information"""
3975 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3976 # resp = ctx.obj.vim.get_resource_orchestrator()
3977 # table = PrettyTable(['key', 'attribute'])
3978 # for k, v in list(resp.items()):
3979 # table.add_row([k, json.dumps(v, indent=2)])
3984 #@cli_osm.command(name='vcs-list')
3985 #@click.pass_context
3987 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3988 # resp = ctx.obj.utils.get_vcs_info()
3989 # table = PrettyTable(['component name', 'state'])
3990 # for component in resp:
3991 # table.add_row([component['component_name'], component['state']])
3996 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3997 @click.argument('ns_name')
3998 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3999 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
4000 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
4001 @click.option('--vdu_count', default
=None, type=int, help='number of vdu instance of this vdu_id')
4002 @click.option('--action_name', prompt
=True, help='action name')
4003 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
4004 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
4005 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4006 @click.option('--wait',
4010 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4023 """executes an action/primitive over a NS instance
4025 NS_NAME: name or ID of the NS instance
4029 check_client_version(ctx
.obj
, ctx
.command
.name
)
4032 op_data
['member_vnf_index'] = vnf_name
4034 op_data
['kdu_name'] = kdu_name
4036 op_data
['vdu_id'] = vdu_id
4037 if vdu_count
is not None:
4038 op_data
['vdu_count_index'] = vdu_count
4040 op_data
['timeout_ns_action'] = timeout
4041 op_data
['primitive'] = action_name
4043 with
open(params_file
, 'r') as pf
:
4046 op_data
['primitive_params'] = yaml
.safe_load(params
)
4048 op_data
['primitive_params'] = {}
4049 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
4051 # except ClientException as e:
4056 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
4057 @click.argument('ns_name')
4058 @click.argument('vnf_name')
4059 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
4060 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
4061 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
4062 @click.option('--timeout', required
=False, default
=None, type=int, help='timeout in seconds')
4063 @click.option('--wait', required
=False, default
=False, is_flag
=True,
4064 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4075 Executes a VNF scale (adding/removing VDUs)
4078 NS_NAME: name or ID of the NS instance.
4079 VNF_NAME: member-vnf-index in the NS to be scaled.
4083 check_client_version(ctx
.obj
, ctx
.command
.name
)
4084 if not scale_in
and not scale_out
:
4086 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
)
4087 # except ClientException as e:
4092 ##############################
4093 # Role Management Operations #
4094 ##############################
4096 @cli_osm.command(name
='role-create', short_help
='creates a new role')
4097 @click.argument('name')
4098 @click.option('--permissions',
4100 help='role permissions using a dictionary')
4102 def role_create(ctx
, name
, permissions
):
4107 NAME: Name or ID of the role.
4108 DEFINITION: Definition of grant/denial of access to resources.
4112 check_client_version(ctx
.obj
, ctx
.command
.name
)
4113 ctx
.obj
.role
.create(name
, permissions
)
4114 # except ClientException as e:
4119 @cli_osm.command(name
='role-update', short_help
='updates a role')
4120 @click.argument('name')
4121 @click.option('--set-name',
4123 help='change name of rle')
4124 # @click.option('--permissions',
4126 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4127 @click.option('--add',
4129 help='yaml format dictionary with permission: True/False to access grant/denial')
4130 @click.option('--remove',
4132 help='yaml format list to remove a permission')
4134 def role_update(ctx
, name
, set_name
, add
, remove
):
4139 NAME: Name or ID of the role.
4140 DEFINITION: Definition overwrites the old definition.
4141 ADD: Grant/denial of access to resource to add.
4142 REMOVE: Grant/denial of access to resource to remove.
4146 check_client_version(ctx
.obj
, ctx
.command
.name
)
4147 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
4148 # except ClientException as e:
4153 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
4154 @click.argument('name')
4155 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4157 def role_delete(ctx
, name
):
4162 NAME: Name or ID of the role.
4166 check_client_version(ctx
.obj
, ctx
.command
.name
)
4167 ctx
.obj
.role
.delete(name
)
4168 # except ClientException as e:
4173 @cli_osm.command(name
='role-list', short_help
='list all roles')
4174 @click.option('--filter', default
=None, multiple
=True,
4175 help='restricts the list to the projects matching the filter')
4177 def role_list(ctx
, filter):
4183 check_client_version(ctx
.obj
, ctx
.command
.name
)
4185 filter='&'.join(filter)
4186 resp
= ctx
.obj
.role
.list(filter)
4187 # except ClientException as e:
4190 table
= PrettyTable(['name', 'id'])
4192 table
.add_row([role
['name'], role
['_id']])
4197 @cli_osm.command(name
='role-show', short_help
='show specific role')
4198 @click.argument('name')
4200 def role_show(ctx
, name
):
4202 Shows the details of a role.
4205 NAME: Name or ID of the role.
4209 check_client_version(ctx
.obj
, ctx
.command
.name
)
4210 resp
= ctx
.obj
.role
.get(name
)
4211 # except ClientException as e:
4215 table
= PrettyTable(['key', 'attribute'])
4216 for k
, v
in resp
.items():
4217 table
.add_row([k
, json
.dumps(v
, indent
=2)])
4222 @cli_osm.command(name
='package-create',
4223 short_help
='Create empty NS package structure')
4224 @click.argument('package-type')
4225 @click.argument('package-name')
4226 @click.option('--base-directory',
4228 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4229 @click.option('--image',
4230 default
="image-name",
4231 help='(VNF) Set the name of the vdu image. Default "image-name"')
4232 @click.option('--vdus',
4234 help='(VNF) Set the number of vdus in a VNF. Default 1')
4235 @click.option('--vcpu',
4237 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4238 @click.option('--memory',
4240 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4241 @click.option('--storage',
4243 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4244 @click.option('--interfaces',
4246 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4247 @click.option('--vendor',
4249 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4250 @click.option('--override',
4253 help='(NS/VNF/NST) Flag for overriding the package if exists.')
4254 @click.option('--detailed',
4257 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4258 @click.option('--netslice-subnets',
4260 help='(NST) Number of netslice subnets. Default 1')
4261 @click.option('--netslice-vlds',
4263 help='(NST) Number of netslice vlds. Default 1')
4265 def package_create(ctx
,
4281 Creates an OSM NS, VNF, NST package
4284 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4285 PACKAGE_NAME: Name of the package to create the folder with the content.
4290 check_client_version(ctx
.obj
, ctx
.command
.name
)
4291 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
4292 resp
= ctx
.obj
.package_tool
.create(package_type
,
4301 interfaces
=interfaces
,
4304 netslice_subnets
=netslice_subnets
,
4305 netslice_vlds
=netslice_vlds
)
4307 # except ClientException as inst:
4308 # print("ERROR: {}".format(inst))
4311 @cli_osm.command(name
='package-validate',
4312 short_help
='Validate descriptors given a base directory')
4313 @click.argument('base-directory',
4316 @click.option('--recursive/--no-recursive',
4318 help='The activated recursive option will validate the yaml files'
4319 ' within the indicated directory and in its subdirectories')
4320 @click.option('--old',
4323 help='Validates also the descriptors using the previous OSM format (pre SOL006)')
4325 def package_validate(ctx
,
4330 Validate descriptors given a base directory.
4333 BASE_DIRECTORY: Base folder for NS, VNF or NST package.
4337 check_client_version(ctx
.obj
, ctx
.command
.name
)
4338 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
, old
)
4339 table
= PrettyTable()
4340 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
4341 # Print the dictionary generated by the validation function
4342 for result
in results
:
4343 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
4344 table
.sortby
= "VALID"
4345 table
.align
["PATH"] = "l"
4346 table
.align
["TYPE"] = "l"
4347 table
.align
["ERROR"] = "l"
4349 # except ClientException as inst:
4350 # print("ERROR: {}".format(inst))
4353 @cli_osm.command(name
='package-translate',
4354 short_help
='Translate descriptors given a base directory')
4355 @click.argument('base-directory',
4358 @click.option('--recursive/--no-recursive',
4360 help='The activated recursive option will translate the yaml files'
4361 ' within the indicated directory and in its subdirectories')
4362 @click.option('--dryrun',
4365 help='Do not translate yet, only make a dry-run to test translation')
4367 def package_translate(ctx
,
4372 Translate descriptors given a base directory.
4375 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4378 check_client_version(ctx
.obj
, ctx
.command
.name
)
4379 results
= ctx
.obj
.package_tool
.translate(base_directory
, recursive
, dryrun
)
4380 table
= PrettyTable()
4381 table
.field_names
= ["CURRENT TYPE", "NEW TYPE", "PATH", "VALID", "TRANSLATED", "ERROR"]
4382 # Print the dictionary generated by the validation function
4383 for result
in results
:
4384 table
.add_row([result
["current type"], result
["new type"], result
["path"], result
["valid"], result
["translated"], result
["error"]])
4385 table
.sortby
= "TRANSLATED"
4386 table
.align
["PATH"] = "l"
4387 table
.align
["TYPE"] = "l"
4388 table
.align
["ERROR"] = "l"
4390 # except ClientException as inst:
4391 # print("ERROR: {}".format(inst))
4394 @cli_osm.command(name
='package-build',
4395 short_help
='Build the tar.gz of the package')
4396 @click.argument('package-folder')
4397 @click.option('--skip-validation',
4400 help='skip package validation')
4401 @click.option('--skip-charm-build', default
=False, is_flag
=True,
4402 help='the charm will not be compiled, it is assumed to already exist')
4404 def package_build(ctx
,
4409 Build the package NS, VNF given the package_folder.
4412 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4416 check_client_version(ctx
.obj
, ctx
.command
.name
)
4417 results
= ctx
.obj
.package_tool
.build(package_folder
,
4418 skip_validation
=skip_validation
,
4419 skip_charm_build
=skip_charm_build
)
4421 # except ClientException as inst:
4422 # print("ERROR: {}".format(inst))
4425 @cli_osm.command(name
='descriptor-translate',
4426 short_help
='Translate input descriptor file from Rel EIGHT OSM descriptors to SOL006 and prints in standard output')
4427 @click.argument('descriptor-file',
4430 def descriptor_translate(ctx
,
4433 Translate input descriptor.
4436 DESCRIPTOR_FILE: Descriptor file for NS, VNF or Network Slice.
4439 check_client_version(ctx
.obj
, ctx
.command
.name
)
4440 result
= ctx
.obj
.package_tool
.descriptor_translate(descriptor_file
)
4448 except pycurl
.error
as exc
:
4450 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4451 except ClientException
as exc
:
4452 print("ERROR: {}".format(exc
))
4453 except (FileNotFoundError
, PermissionError
) as exc
:
4454 print("Cannot open file: {}".format(exc
))
4455 except yaml
.YAMLError
as exc
:
4456 print("Invalid YAML format: {}".format(exc
))
4458 # TODO capture other controlled exceptions here
4459 # TODO remove the ClientException captures from all places, unless they do something different
4462 if __name__
== '__main__':