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
24 from prettytable
import PrettyTable
33 from datetime
import datetime
38 CONTEXT_SETTINGS
= dict(help_option_names
=['-h', '--help'], max_content_width
=160)
40 def wrap_text(text
, width
):
41 wrapper
= textwrap
.TextWrapper(width
=width
)
42 lines
= text
.splitlines()
43 return "\n".join(map(wrapper
.fill
, lines
))
46 def trunc_text(text
, length
):
47 if len(text
) > length
:
48 return text
[:(length
- 3)] + '...'
53 def check_client_version(obj
, what
, version
='sol005'):
55 Checks the version of the client object and raises error if it not the expected.
57 :param obj: the client object
58 :what: the function or command under evaluation (used when an error is raised)
60 :raises ClientError: if the specified version does not match the client version
63 fullclassname
= obj
.__module
__ + "." + obj
.__class
__.__name
__
64 message
= 'The following commands or options are only supported with the option "--sol005": {}'.format(what
)
66 message
= 'The following commands or options are not supported when using option "--sol005": {}'.format(what
)
67 if fullclassname
!= 'osmclient.{}.client.Client'.format(version
):
68 raise ClientException(message
)
72 @click.group(context_settings
=dict(help_option_names
=['-h', '--help'], max_content_width
=160))
73 @click.option('--hostname',
75 envvar
='OSM_HOSTNAME',
76 help='hostname of server. ' +
77 'Also can set OSM_HOSTNAME in environment')
78 #@click.option('--sol005/--no-sol005',
80 # envvar='OSM_SOL005',
81 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
82 # 'Also can set OSM_SOL005 in environment')
83 @click.option('--user',
86 help='user (defaults to admin). ' +
87 'Also can set OSM_USER in environment')
88 @click.option('--password',
90 envvar
='OSM_PASSWORD',
91 help='password (defaults to admin). ' +
92 'Also can set OSM_PASSWORD in environment')
93 @click.option('--project',
96 help='project (defaults to admin). ' +
97 'Also can set OSM_PROJECT in environment')
98 @click.option('-v', '--verbose', count
=True,
99 help='increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)')
100 #@click.option('--so-port',
102 # envvar='OSM_SO_PORT',
103 # help='hostname of server. ' +
104 # 'Also can set OSM_SO_PORT in environment')
105 #@click.option('--so-project',
107 # envvar='OSM_SO_PROJECT',
108 # help='Project Name in SO. ' +
109 # 'Also can set OSM_SO_PROJECT in environment')
110 #@click.option('--ro-hostname',
112 # envvar='OSM_RO_HOSTNAME',
113 # help='hostname of RO server. ' +
114 # 'Also can set OSM_RO_HOSTNAME in environment')
115 #@click.option('--ro-port',
117 # envvar='OSM_RO_PORT',
118 # help='hostname of RO server. ' +
119 # 'Also can set OSM_RO_PORT in environment')
121 def cli_osm(ctx
, hostname
, user
, password
, project
, verbose
):
125 "either hostname option or OSM_HOSTNAME " +
126 "environment variable needs to be specified"))
128 kwargs
= {'verbose': verbose
}
129 # if so_port is not None:
130 # kwargs['so_port']=so_port
131 # if so_project is not None:
132 # kwargs['so_project']=so_project
133 # if ro_hostname is not None:
134 # kwargs['ro_host']=ro_hostname
135 # if ro_port is not None:
136 # kwargs['ro_port']=ro_port
137 sol005
= os
.getenv('OSM_SOL005', True)
140 if password
is not None:
141 kwargs
['password']=password
142 if project
is not None:
143 kwargs
['project']=project
144 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
145 logger
= logging
.getLogger('osmclient')
152 @cli_osm.command(name
='ns-list', short_help
='list all NS instances')
153 @click.option('--filter', default
=None,
154 help='restricts the list to the NS instances matching the filter.')
155 @click.option('--long', is_flag
=True,
156 help='get more details of the NS (project, vim, deployment status, configuration status.')
158 def ns_list(ctx
, filter, long):
159 """list all NS instances
163 --filter filterExpr Restricts the list to the NS instances matching the filter
166 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
167 concatenated using the "&" character:
170 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
171 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
172 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
174 value := scalar value
178 * zero or more occurrences
179 ? zero or one occurrence
180 [] grouping of expressions to be used with ? and *
181 "" quotation marks for marking string constants
185 "AttrName" is the name of one attribute in the data type that defines the representation
186 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
187 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
188 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
189 entries, it means that the operator "op" is applied to the attribute addressed by the last
190 <attrName> entry included in the concatenation. All simple filter expressions are combined
191 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
192 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
193 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
194 prefix". If an attribute referenced in an expression is an array, an object that contains a
195 corresponding array shall be considered to match the expression if any of the elements in the
196 array matches all expressions that have the same attribute prefix.
200 --filter admin-status=ENABLED
201 --filter nsd-ref=<NSD_NAME>
202 --filter nsd.vendor=<VENDOR>
203 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
204 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
206 def summarize_deployment_status(status_dict
):
211 net_list
= status_dict
['nets']
214 if net
['status'] not in status_nets
:
215 status_nets
[net
['status']] = 1
217 status_nets
[net
['status']] +=1
219 for k
,v
in status_nets
.items():
220 message
+= "{}:{},".format(k
,v
)
221 message
+= "TOTAL:{}".format(n_nets
)
222 summary
+= "{}".format(message
)
227 vnf_list
= status_dict
['vnfs']
229 member_vnf_index
= vnf
['member_vnf_index']
230 if member_vnf_index
not in status_vnfs
:
231 status_vnfs
[member_vnf_index
] = {}
232 for vm
in vnf
['vms']:
234 if vm
['status'] not in status_vms
:
235 status_vms
[vm
['status']] = 1
237 status_vms
[vm
['status']] +=1
238 if vm
['status'] not in status_vnfs
[member_vnf_index
]:
239 status_vnfs
[member_vnf_index
][vm
['status']] = 1
241 status_vnfs
[member_vnf_index
][vm
['status']] += 1
243 for k
,v
in status_vms
.items():
244 message
+= "{}:{},".format(k
,v
)
245 message
+= "TOTAL:{}".format(n_vms
)
246 summary
+= "\n{}".format(message
)
248 for k
,v
in status_vnfs
.items():
250 message
= "\n {} VMs: ".format(k
)
251 for k2
,v2
in v
.items():
252 message
+= "{}:{},".format(k2
,v2
)
254 message
+= "TOTAL:{}".format(total
)
258 def summarize_config_status(ee_list
):
263 if ee
['elementType'] not in status_ee
:
264 status_ee
[ee
['elementType']] = {}
265 status_ee
[ee
['elementType']][ee
['status']] = 1
267 if ee
['status'] in status_ee
[ee
['elementType']]:
268 status_ee
[ee
['elementType']][ee
['status']] += 1
270 status_ee
[ee
['elementType']][ee
['status']] = 1
272 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
273 if elementType
in status_ee
:
276 for k
,v
in status_ee
[elementType
].items():
277 message
+= "{}:{},".format(k
,v
)
279 message
+= "TOTAL:{}\n".format(total
)
280 summary
+= "{}: {}".format(elementType
, message
)
281 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
285 check_client_version(ctx
.obj
, '--filter')
286 resp
= ctx
.obj
.ns
.list(filter)
288 resp
= ctx
.obj
.ns
.list()
300 'configuration status'])
301 project_list
= ctx
.obj
.project
.list()
302 vim_list
= ctx
.obj
.vim
.list()
312 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
313 if fullclassname
== 'osmclient.sol005.client.Client':
315 nsr_name
= nsr
['name']
317 date
= datetime
.fromtimestamp(nsr
['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
318 ns_state
= nsr
['nsState']
320 deployment_status
= summarize_deployment_status(nsr
['deploymentStatus'])
321 config_status
= summarize_config_status(nsr
['configurationStatus'])
322 project_id
= nsr
.get('_admin').get('projects_read')[0]
324 for p
in project_list
:
325 if p
['_id'] == project_id
:
326 project_name
= p
['name']
328 #project = '{} ({})'.format(project_name, project_id)
329 project
= project_name
330 vim_id
= nsr
.get('datacenter')
333 if v
['uuid'] == vim_id
:
336 #vim = '{} ({})'.format(vim_name, vim_id)
338 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
339 error_details
= "N/A"
340 if ns_state
== "BROKEN" or ns_state
== "DEGRADED":
341 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'],nsr
['errorDetail'])
343 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
344 nsr
= nsopdata
['nsr:nsr']
345 nsr_name
= nsr
['name-ref']
346 nsr_id
= nsr
['ns-instance-config-ref']
349 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
350 ns_state
= deployment_status
351 config_status
= nsr
['config-status'] if 'config-status' in nsr
else 'Not found'
352 current_operation
= "Unknown"
353 error_details
= nsr
['detailed-status'] if 'detailed-status' in nsr
else 'Not found'
354 if config_status
== "config_not_needed":
355 config_status
= "configured (no charms)"
364 wrap_text(text
=error_details
,width
=40),
376 wrap_text(text
=error_details
,width
=40)])
379 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
380 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
382 def nsd_list(ctx
, filter):
385 check_client_version(ctx
.obj
, '--filter')
386 resp
= ctx
.obj
.nsd
.list(filter)
388 resp
= ctx
.obj
.nsd
.list()
389 # print(yaml.safe_dump(resp))
390 table
= PrettyTable(['nsd name', 'id'])
391 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
392 if fullclassname
== 'osmclient.sol005.client.Client':
394 name
= ns
['name'] if 'name' in ns
else '-'
395 table
.add_row([name
, ns
['_id']])
398 table
.add_row([ns
['name'], ns
['id']])
403 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
404 @click.option('--filter', default
=None,
405 help='restricts the list to the NSD/NSpkg matching the filter')
407 def nsd_list1(ctx
, filter):
408 """list all NSD/NS pkg in the system"""
410 nsd_list(ctx
, filter)
413 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
414 @click.option('--filter', default
=None,
415 help='restricts the list to the NSD/NSpkg matching the filter')
417 def nsd_list2(ctx
, filter):
418 """list all NS packages"""
420 nsd_list(ctx
, filter)
423 def vnfd_list(ctx
, nf_type
, filter):
426 check_client_version(ctx
.obj
, '--nf_type')
428 check_client_version(ctx
.obj
, '--filter')
431 nf_filter
= "_admin.type=vnfd"
432 elif nf_type
== "pnf":
433 nf_filter
= "_admin.type=pnfd"
434 elif nf_type
== "hnf":
435 nf_filter
= "_admin.type=hnfd"
437 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
439 filter = '{}&{}'.format(nf_filter
, filter)
443 resp
= ctx
.obj
.vnfd
.list(filter)
445 resp
= ctx
.obj
.vnfd
.list()
446 # print(yaml.safe_dump(resp))
447 table
= PrettyTable(['nfpkg name', 'id'])
448 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
449 if fullclassname
== 'osmclient.sol005.client.Client':
451 name
= vnfd
['name'] if 'name' in vnfd
else '-'
452 table
.add_row([name
, vnfd
['_id']])
455 table
.add_row([vnfd
['name'], vnfd
['id']])
460 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
461 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
462 @click.option('--filter', default
=None,
463 help='restricts the list to the NF pkg matching the filter')
465 def vnfd_list1(ctx
, nf_type
, filter):
466 """list all xNF packages (VNF, HNF, PNF)"""
468 vnfd_list(ctx
, nf_type
, filter)
471 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
472 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
473 @click.option('--filter', default
=None,
474 help='restricts the list to the NFpkg matching the filter')
476 def vnfd_list2(ctx
, nf_type
, filter):
477 """list all xNF packages (VNF, HNF, PNF)"""
479 vnfd_list(ctx
, nf_type
, filter)
482 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
483 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
484 @click.option('--filter', default
=None,
485 help='restricts the list to the NFpkg matching the filter')
487 def nfpkg_list(ctx
, nf_type
, filter):
488 """list all xNF packages (VNF, HNF, PNF)"""
491 check_client_version(ctx
.obj
, ctx
.command
.name
)
492 vnfd_list(ctx
, nf_type
, filter)
493 # except ClientException as e:
498 def vnf_list(ctx
, ns
, filter):
502 check_client_version(ctx
.obj
, '--ns')
504 check_client_version(ctx
.obj
, '--filter')
505 resp
= ctx
.obj
.vnf
.list(ns
, filter)
507 resp
= ctx
.obj
.vnf
.list()
508 # except ClientException as e:
511 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
512 if fullclassname
== 'osmclient.sol005.client.Client':
522 name
= vnfr
['name'] if 'name' in vnfr
else '-'
527 vnfr
['member-vnf-index-ref'],
529 vnfr
['vim-account-id'],
535 'operational status',
538 if 'mgmt-interface' not in vnfr
:
539 vnfr
['mgmt-interface'] = {}
540 vnfr
['mgmt-interface']['ip-address'] = None
544 vnfr
['operational-status'],
545 vnfr
['config-status']])
550 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
551 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
552 @click.option('--filter', default
=None,
553 help='restricts the list to the NF instances matching the filter.')
555 def vnf_list1(ctx
, ns
, filter):
556 """list all NF instances"""
558 vnf_list(ctx
, ns
, filter)
561 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
562 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
563 @click.option('--filter', default
=None,
564 help='restricts the list to the NF instances matching the filter.')
566 def nf_list(ctx
, ns
, filter):
567 """list all NF instances
571 --ns TEXT NS instance id or name to restrict the VNF list
572 --filter filterExpr Restricts the list to the VNF instances matching the filter
575 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
576 concatenated using the "&" character:
579 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
580 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
581 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
583 value := scalar value
587 * zero or more occurrences
588 ? zero or one occurrence
589 [] grouping of expressions to be used with ? and *
590 "" quotation marks for marking string constants
594 "AttrName" is the name of one attribute in the data type that defines the representation
595 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
596 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
597 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
598 entries, it means that the operator "op" is applied to the attribute addressed by the last
599 <attrName> entry included in the concatenation. All simple filter expressions are combined
600 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
601 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
602 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
603 prefix". If an attribute referenced in an expression is an array, an object that contains a
604 corresponding array shall be considered to match the expression if any of the elements in the
605 array matches all expressions that have the same attribute prefix.
609 --filter vim-account-id=<VIM_ACCOUNT_ID>
610 --filter vnfd-ref=<VNFD_NAME>
611 --filter vdur.ip-address=<IP_ADDRESS>
612 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
615 vnf_list(ctx
, ns
, filter)
618 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
619 @click.argument('name')
620 @click.option('--long', is_flag
=True,
621 help='get more details of the NS operation (date, ).')
623 def ns_op_list(ctx
, name
, long):
624 """shows the history of operations over a NS instance
626 NAME: name or ID of the NS instance
628 def formatParams(params
):
629 if params
['lcmOperationType']=='instantiate':
630 params
.pop('nsDescription')
634 elif params
['lcmOperationType']=='action':
635 params
.pop('primitive')
636 params
.pop('lcmOperationType')
637 params
.pop('nsInstanceId')
642 check_client_version(ctx
.obj
, ctx
.command
.name
)
643 resp
= ctx
.obj
.ns
.list_op(name
)
644 # except ClientException as e:
649 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
651 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
653 #print(yaml.safe_dump(resp))
656 if op
['lcmOperationType']=='action':
657 action_name
= op
['operationParams']['primitive']
659 if op
['operationState']=='PROCESSING':
660 if op
['lcmOperationType']=='instantiate':
664 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
665 elif op
['operationState']=='FAILED' or op
['operationState']=='FAILED_TEMP':
666 detail
= op
['errorMessage']
667 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
668 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
670 table
.add_row([op
['id'],
671 op
['lcmOperationType'],
673 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
674 op
['operationState'],
677 wrap_text(text
=detail
,width
=50)])
679 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
680 op
['operationState'], date
, wrap_text(text
=detail
,width
=50)])
685 def nsi_list(ctx
, filter):
686 """list all Network Slice Instances"""
689 check_client_version(ctx
.obj
, ctx
.command
.name
)
690 resp
= ctx
.obj
.nsi
.list(filter)
691 # except ClientException as e:
695 ['netslice instance name',
697 'operational status',
701 nsi_name
= nsi
['name']
703 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
704 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
705 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
706 if configstatus
== "config_not_needed":
707 configstatus
= "configured (no charms)"
718 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
719 @click.option('--filter', default
=None,
720 help='restricts the list to the Network Slice Instances matching the filter')
722 def nsi_list1(ctx
, filter):
723 """list all Network Slice Instances (NSI)"""
725 nsi_list(ctx
, filter)
728 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
729 @click.option('--filter', default
=None,
730 help='restricts the list to the Network Slice Instances matching the filter')
732 def nsi_list2(ctx
, filter):
733 """list all Network Slice Instances (NSI)"""
735 nsi_list(ctx
, filter)
738 def nst_list(ctx
, filter):
741 check_client_version(ctx
.obj
, ctx
.command
.name
)
742 resp
= ctx
.obj
.nst
.list(filter)
743 # except ClientException as e:
746 # print(yaml.safe_dump(resp))
747 table
= PrettyTable(['nst name', 'id'])
749 name
= nst
['name'] if 'name' in nst
else '-'
750 table
.add_row([name
, nst
['_id']])
755 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
756 @click.option('--filter', default
=None,
757 help='restricts the list to the NST matching the filter')
759 def nst_list1(ctx
, filter):
760 """list all Network Slice Templates (NST) in the system"""
762 nst_list(ctx
, filter)
765 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
766 @click.option('--filter', default
=None,
767 help='restricts the list to the NST matching the filter')
769 def nst_list2(ctx
, filter):
770 """list all Network Slice Templates (NST) in the system"""
772 nst_list(ctx
, filter)
775 def nsi_op_list(ctx
, name
):
778 check_client_version(ctx
.obj
, ctx
.command
.name
)
779 resp
= ctx
.obj
.nsi
.list_op(name
)
780 # except ClientException as e:
783 table
= PrettyTable(['id', 'operation', 'status'])
785 table
.add_row([op
['id'], op
['lcmOperationType'],
786 op
['operationState']])
791 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
792 @click.argument('name')
794 def nsi_op_list1(ctx
, name
):
795 """shows the history of operations over a Network Slice Instance (NSI)
797 NAME: name or ID of the Network Slice Instance
800 nsi_op_list(ctx
, name
)
803 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
804 @click.argument('name')
806 def nsi_op_list2(ctx
, name
):
807 """shows the history of operations over a Network Slice Instance (NSI)
809 NAME: name or ID of the Network Slice Instance
812 nsi_op_list(ctx
, name
)
815 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
816 @click.option('--filter', default
=None,
817 help='restricts the list to the Physical Deployment Units matching the filter')
819 def pdu_list(ctx
, filter):
820 """list all Physical Deployment Units (PDU)"""
823 check_client_version(ctx
.obj
, ctx
.command
.name
)
824 resp
= ctx
.obj
.pdu
.list(filter)
825 # except ClientException as e:
834 pdu_name
= pdu
['name']
836 pdu_type
= pdu
['type']
837 pdu_ipaddress
= "None"
838 for iface
in pdu
['interfaces']:
840 pdu_ipaddress
= iface
['ip-address']
855 def nsd_show(ctx
, name
, literal
):
858 resp
= ctx
.obj
.nsd
.get(name
)
859 # resp = ctx.obj.nsd.get_individual(name)
860 # except ClientException as e:
865 print(yaml
.safe_dump(resp
))
868 table
= PrettyTable(['field', 'value'])
869 for k
, v
in list(resp
.items()):
870 table
.add_row([k
, json
.dumps(v
, indent
=2)])
875 @cli_osm.command(name
='nsd-show', short_help
='shows the content of a NSD')
876 @click.option('--literal', is_flag
=True,
877 help='print literally, no pretty table')
878 @click.argument('name')
880 def nsd_show1(ctx
, name
, literal
):
881 """shows the content of a NSD
883 NAME: name or ID of the NSD/NSpkg
886 nsd_show(ctx
, name
, literal
)
889 @cli_osm.command(name
='nspkg-show', short_help
='shows the content of a NSD')
890 @click.option('--literal', is_flag
=True,
891 help='print literally, no pretty table')
892 @click.argument('name')
894 def nsd_show2(ctx
, name
, literal
):
895 """shows the content of a NSD
897 NAME: name or ID of the NSD/NSpkg
900 nsd_show(ctx
, name
, literal
)
903 def vnfd_show(ctx
, name
, literal
):
906 resp
= ctx
.obj
.vnfd
.get(name
)
907 # resp = ctx.obj.vnfd.get_individual(name)
908 # except ClientException as e:
913 print(yaml
.safe_dump(resp
))
916 table
= PrettyTable(['field', 'value'])
917 for k
, v
in list(resp
.items()):
918 table
.add_row([k
, json
.dumps(v
, indent
=2)])
923 @cli_osm.command(name
='vnfd-show', short_help
='shows the content of a VNFD')
924 @click.option('--literal', is_flag
=True,
925 help='print literally, no pretty table')
926 @click.argument('name')
928 def vnfd_show1(ctx
, name
, literal
):
929 """shows the content of a VNFD
931 NAME: name or ID of the VNFD/VNFpkg
934 vnfd_show(ctx
, name
, literal
)
937 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the content of a VNFD')
938 @click.option('--literal', is_flag
=True,
939 help='print literally, no pretty table')
940 @click.argument('name')
942 def vnfd_show2(ctx
, name
, literal
):
943 """shows the content of a VNFD
945 NAME: name or ID of the VNFD/VNFpkg
948 vnfd_show(ctx
, name
, literal
)
951 @cli_osm.command(name
='nfpkg-show', short_help
='shows the content of a NF Descriptor')
952 @click.option('--literal', is_flag
=True,
953 help='print literally, no pretty table')
954 @click.argument('name')
956 def nfpkg_show(ctx
, name
, literal
):
957 """shows the content of a NF Descriptor
959 NAME: name or ID of the NFpkg
962 vnfd_show(ctx
, name
, literal
)
965 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
966 @click.argument('name')
967 @click.option('--literal', is_flag
=True,
968 help='print literally, no pretty table')
969 @click.option('--filter', default
=None)
971 def ns_show(ctx
, name
, literal
, filter):
972 """shows the info of a NS instance
974 NAME: name or ID of the NS instance
978 ns
= ctx
.obj
.ns
.get(name
)
979 # except ClientException as e:
984 print(yaml
.safe_dump(ns
))
987 table
= PrettyTable(['field', 'value'])
989 for k
, v
in list(ns
.items()):
990 if filter is None or filter in k
:
991 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
993 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
994 if fullclassname
!= 'osmclient.sol005.client.Client':
995 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
996 nsr_optdata
= nsopdata
['nsr:nsr']
997 for k
, v
in list(nsr_optdata
.items()):
998 if filter is None or filter in k
:
999 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1004 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1005 @click.argument('name')
1006 @click.option('--literal', is_flag
=True,
1007 help='print literally, no pretty table')
1008 @click.option('--filter', default
=None, help='restricts the information to the fields in the filter')
1009 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1011 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1012 """shows the info of a VNF instance
1014 NAME: name or ID of the VNF instance
1016 def print_kdu_status(op_info_status
):
1017 """print KDU status properly formatted
1020 op_status
= yaml
.safe_load(op_info_status
)
1021 if "namespace" in op_status
and "info" in op_status
and \
1022 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1023 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1024 "notes" in op_status
["info"]["status"] and "seconds" in op_status
["info"]["last_deployed"]:
1025 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1026 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1027 print("NAMESPACE: {}".format(op_status
["namespace"]))
1028 status_code
= "UNKNOWN"
1029 if op_status
["info"]["status"]["code"]==1:
1030 status_code
= "DEPLOYED"
1031 print("STATUS: {}".format(status_code
))
1034 print(op_status
["info"]["status"]["resources"])
1036 print(op_status
["info"]["status"]["notes"])
1038 print(op_info_status
)
1040 print(op_info_status
)
1045 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1047 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1050 check_client_version(ctx
.obj
, ctx
.command
.name
)
1051 resp
= ctx
.obj
.vnf
.get(name
)
1054 ns_id
= resp
['nsr-id-ref']
1056 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1057 op_data
['kdu_name'] = kdu
1058 op_data
['primitive'] = 'status'
1059 op_data
['primitive_params'] = {}
1060 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1063 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1064 if op_info
['operationState'] == 'COMPLETED':
1065 print_kdu_status(op_info
['detailed-status'])
1069 print ("Could not determine KDU status")
1072 print(yaml
.safe_dump(resp
))
1075 table
= PrettyTable(['field', 'value'])
1077 for k
, v
in list(resp
.items()):
1078 if filter is None or filter in k
:
1079 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1082 # except ClientException as e:
1087 #@cli_osm.command(name='vnf-monitoring-show')
1088 #@click.argument('vnf_name')
1089 #@click.pass_context
1090 #def vnf_monitoring_show(ctx, vnf_name):
1092 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1093 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1094 # except ClientException as e:
1098 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1099 # if resp is not None:
1100 # for monitor in resp:
1104 # monitor['value-integer'],
1105 # monitor['units']])
1110 #@cli_osm.command(name='ns-monitoring-show')
1111 #@click.argument('ns_name')
1112 #@click.pass_context
1113 #def ns_monitoring_show(ctx, ns_name):
1115 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1116 # resp = ctx.obj.ns.get_monitoring(ns_name)
1117 # except ClientException as e:
1121 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1122 # for key, val in list(resp.items()):
1123 # for monitor in val:
1127 # monitor['value-integer'],
1128 # monitor['units']])
1133 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1134 @click.argument('id')
1135 @click.option('--filter', default
=None)
1136 @click.option('--literal', is_flag
=True,
1137 help='print literally, no pretty table')
1139 def ns_op_show(ctx
, id, filter, literal
):
1140 """shows the detailed info of a NS operation
1142 ID: operation identifier
1146 check_client_version(ctx
.obj
, ctx
.command
.name
)
1147 op_info
= ctx
.obj
.ns
.get_op(id)
1148 # except ClientException as e:
1153 print(yaml
.safe_dump(op_info
))
1156 table
= PrettyTable(['field', 'value'])
1157 for k
, v
in list(op_info
.items()):
1158 if filter is None or filter in k
:
1159 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1164 def nst_show(ctx
, name
, literal
):
1167 check_client_version(ctx
.obj
, ctx
.command
.name
)
1168 resp
= ctx
.obj
.nst
.get(name
)
1169 #resp = ctx.obj.nst.get_individual(name)
1170 # except ClientException as e:
1175 print(yaml
.safe_dump(resp
))
1178 table
= PrettyTable(['field', 'value'])
1179 for k
, v
in list(resp
.items()):
1180 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1185 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1186 @click.option('--literal', is_flag
=True,
1187 help='print literally, no pretty table')
1188 @click.argument('name')
1190 def nst_show1(ctx
, name
, literal
):
1191 """shows the content of a Network Slice Template (NST)
1193 NAME: name or ID of the NST
1196 nst_show(ctx
, name
, literal
)
1199 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1200 @click.option('--literal', is_flag
=True,
1201 help='print literally, no pretty table')
1202 @click.argument('name')
1204 def nst_show2(ctx
, name
, literal
):
1205 """shows the content of a Network Slice Template (NST)
1207 NAME: name or ID of the NST
1210 nst_show(ctx
, name
, literal
)
1213 def nsi_show(ctx
, name
, literal
, filter):
1216 check_client_version(ctx
.obj
, ctx
.command
.name
)
1217 nsi
= ctx
.obj
.nsi
.get(name
)
1218 # except ClientException as e:
1223 print(yaml
.safe_dump(nsi
))
1226 table
= PrettyTable(['field', 'value'])
1228 for k
, v
in list(nsi
.items()):
1229 if filter is None or filter in k
:
1230 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1236 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1237 @click.argument('name')
1238 @click.option('--literal', is_flag
=True,
1239 help='print literally, no pretty table')
1240 @click.option('--filter', default
=None)
1242 def nsi_show1(ctx
, name
, literal
, filter):
1243 """shows the content of a Network Slice Instance (NSI)
1245 NAME: name or ID of the Network Slice Instance
1248 nsi_show(ctx
, name
, literal
, filter)
1251 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1252 @click.argument('name')
1253 @click.option('--literal', is_flag
=True,
1254 help='print literally, no pretty table')
1255 @click.option('--filter', default
=None)
1257 def nsi_show2(ctx
, name
, literal
, filter):
1258 """shows the content of a Network Slice Instance (NSI)
1260 NAME: name or ID of the Network Slice Instance
1263 nsi_show(ctx
, name
, literal
, filter)
1266 def nsi_op_show(ctx
, id, filter):
1269 check_client_version(ctx
.obj
, ctx
.command
.name
)
1270 op_info
= ctx
.obj
.nsi
.get_op(id)
1271 # except ClientException as e:
1275 table
= PrettyTable(['field', 'value'])
1276 for k
, v
in list(op_info
.items()):
1277 if filter is None or filter in k
:
1278 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1283 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1284 @click.argument('id')
1285 @click.option('--filter', default
=None)
1287 def nsi_op_show1(ctx
, id, filter):
1288 """shows the info of an operation over a Network Slice Instance(NSI)
1290 ID: operation identifier
1293 nsi_op_show(ctx
, id, filter)
1296 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1297 @click.argument('id')
1298 @click.option('--filter', default
=None)
1300 def nsi_op_show2(ctx
, id, filter):
1301 """shows the info of an operation over a Network Slice Instance(NSI)
1303 ID: operation identifier
1306 nsi_op_show(ctx
, id, filter)
1309 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1310 @click.argument('name')
1311 @click.option('--literal', is_flag
=True,
1312 help='print literally, no pretty table')
1313 @click.option('--filter', default
=None)
1315 def pdu_show(ctx
, name
, literal
, filter):
1316 """shows the content of a Physical Deployment Unit (PDU)
1318 NAME: name or ID of the PDU
1322 check_client_version(ctx
.obj
, ctx
.command
.name
)
1323 pdu
= ctx
.obj
.pdu
.get(name
)
1324 # except ClientException as e:
1329 print(yaml
.safe_dump(pdu
))
1332 table
= PrettyTable(['field', 'value'])
1334 for k
, v
in list(pdu
.items()):
1335 if filter is None or filter in k
:
1336 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1342 ####################
1344 ####################
1346 def nsd_create(ctx
, filename
, overwrite
, skip_charm_build
):
1349 check_client_version(ctx
.obj
, ctx
.command
.name
)
1350 ctx
.obj
.nsd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1351 # except ClientException as e:
1356 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1357 @click.argument('filename')
1358 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1359 help='Deprecated. Use override')
1360 @click.option('--override', 'overwrite', default
=None,
1361 help='overrides fields in descriptor, format: '
1362 '"key1.key2...=value[;key3...=value;...]"')
1363 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1364 help='The charm will not be compiled, it is assumed to already exist')
1366 def nsd_create1(ctx
, filename
, overwrite
, skip_charm_build
):
1367 """creates a new NSD/NSpkg
1369 FILENAME: NSD yaml file or NSpkg tar.gz file
1372 nsd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1375 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1376 @click.argument('filename')
1377 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1378 help='Deprecated. Use override')
1379 @click.option('--override', 'overwrite', default
=None,
1380 help='overrides fields in descriptor, format: '
1381 '"key1.key2...=value[;key3...=value;...]"')
1382 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1383 help='The charm will not be compiled, it is assumed to already exist')
1385 def nsd_create2(ctx
, charm_folder
, overwrite
, skip_charm_build
):
1386 """creates a new NSD/NSpkg
1388 FILENAME: NSD folder, NSD yaml file or NSpkg tar.gz file
1391 nsd_create(ctx
, charm_folder
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1394 def vnfd_create(ctx
, filename
, overwrite
, skip_charm_build
):
1397 check_client_version(ctx
.obj
, ctx
.command
.name
)
1398 ctx
.obj
.vnfd
.create(filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1399 # except ClientException as e:
1404 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1405 @click.argument('filename')
1406 @click.option('--overwrite', 'overwrite', default
=None,
1407 help='overwrite deprecated, use override')
1408 @click.option('--override', 'overwrite', default
=None,
1409 help='overrides fields in descriptor, format: '
1410 '"key1.key2...=value[;key3...=value;...]"')
1411 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1412 help='The charm will not be compiled, it is assumed to already exist')
1414 def vnfd_create1(ctx
, filename
, overwrite
, skip_charm_build
):
1415 """creates a new VNFD/VNFpkg
1417 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1420 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1423 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1424 @click.argument('filename')
1425 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1426 help='Deprecated. Use override')
1427 @click.option('--override', 'overwrite', default
=None,
1428 help='overrides fields in descriptor, format: '
1429 '"key1.key2...=value[;key3...=value;...]"')
1430 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1431 help='The charm will not be compiled, it is assumed to already exist')
1433 def vnfd_create2(ctx
, filename
, overwrite
, skip_charm_build
):
1434 """creates a new VNFD/VNFpkg
1436 FILENAME: NF Package Folder, NF Descriptor yaml file or NFpkg tar.gz file
1439 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1442 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1443 @click.argument('filename')
1444 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1445 help='Deprecated. Use override')
1446 @click.option('--override', 'overwrite', default
=None,
1447 help='overrides fields in descriptor, format: '
1448 '"key1.key2...=value[;key3...=value;...]"')
1449 @click.option('--skip-charm-build', default
=False, is_flag
=True,
1450 help='The charm will not be compiled, it is assumed to already exist')
1452 def nfpkg_create(ctx
, filename
, overwrite
, skip_charm_build
):
1453 """creates a new NFpkg
1455 FILENAME: NF Package Folder, NF Descriptor yaml file or NFpkg tar.gz filems to build
1458 vnfd_create(ctx
, filename
, overwrite
=overwrite
, skip_charm_build
=skip_charm_build
)
1461 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1462 @click.option('--ns_name',
1463 prompt
=True, help='name of the NS instance')
1464 @click.option('--nsd_name',
1465 prompt
=True, help='name of the NS descriptor')
1466 @click.option('--vim_account',
1467 prompt
=True, help='default VIM account id or name for the deployment')
1468 @click.option('--admin_status',
1470 help='administration status')
1471 @click.option('--ssh_keys',
1473 help='comma separated list of public key files to inject to vnfs')
1474 @click.option('--config',
1476 help='ns specific yaml configuration')
1477 @click.option('--config_file',
1479 help='ns specific yaml configuration file')
1480 @click.option('--wait',
1484 help='do not return the control immediately, but keep it '
1485 'until the operation is completed, or timeout')
1496 """creates a new NS instance"""
1500 check_client_version(ctx
.obj
, '--config_file')
1502 raise ClientException('"--config" option is incompatible with "--config_file" option')
1503 with
open(config_file
, 'r') as cf
:
1510 account
=vim_account
,
1512 # except ClientException as e:
1517 def nst_create(ctx
, filename
, overwrite
):
1520 check_client_version(ctx
.obj
, ctx
.command
.name
)
1521 ctx
.obj
.nst
.create(filename
, overwrite
)
1522 # except ClientException as e:
1527 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1528 @click.argument('filename')
1529 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1530 help='Deprecated. Use override')
1531 @click.option('--override', 'overwrite', default
=None,
1532 help='overrides fields in descriptor, format: '
1533 '"key1.key2...=value[;key3...=value;...]"')
1535 def nst_create1(ctx
, charm_folder
, overwrite
):
1536 """creates a new Network Slice Template (NST)
1538 FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1541 nst_create(ctx
, charm_folder
, overwrite
)
1544 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1545 @click.argument('filename')
1546 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1547 help='Deprecated. Use override')
1548 @click.option('--override', 'overwrite', default
=None,
1549 help='overrides fields in descriptor, format: '
1550 '"key1.key2...=value[;key3...=value;...]"')
1552 def nst_create2(ctx
, filename
, overwrite
):
1553 """creates a new Network Slice Template (NST)
1555 FILENAME: NST yaml file or NSTpkg tar.gz file
1558 nst_create(ctx
, filename
, overwrite
)
1561 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1562 """creates a new Network Slice Instance (NSI)"""
1565 check_client_version(ctx
.obj
, ctx
.command
.name
)
1568 raise ClientException('"--config" option is incompatible with "--config_file" option')
1569 with
open(config_file
, 'r') as cf
:
1571 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1572 account
=vim_account
, wait
=wait
)
1573 # except ClientException as e:
1578 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1579 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1580 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1581 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1582 @click.option('--ssh_keys', default
=None,
1583 help='comma separated list of keys to inject to vnfs')
1584 @click.option('--config', default
=None,
1585 help='Netslice specific yaml configuration:\n'
1586 'netslice_subnet: [\n'
1587 'id: TEXT, vim_account: TEXT,\n'
1588 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1589 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1590 'additionalParamsForNsi: {param: value, ...}\n'
1591 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1593 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1595 @click.option('--config_file',
1597 help='nsi specific yaml configuration file')
1598 @click.option('--wait',
1602 help='do not return the control immediately, but keep it '
1603 'until the operation is completed, or timeout')
1605 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1606 """creates a new Network Slice Instance (NSI)"""
1608 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1611 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1612 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1613 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1614 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1615 @click.option('--ssh_keys', default
=None,
1616 help='comma separated list of keys to inject to vnfs')
1617 @click.option('--config', default
=None,
1618 help='Netslice specific yaml configuration:\n'
1619 'netslice_subnet: [\n'
1620 'id: TEXT, vim_account: TEXT,\n'
1621 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1622 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1624 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1626 @click.option('--config_file',
1628 help='nsi specific yaml configuration file')
1629 @click.option('--wait',
1633 help='do not return the control immediately, but keep it '
1634 'until the operation is completed, or timeout')
1636 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1637 """creates a new Network Slice Instance (NSI)"""
1639 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1642 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1643 @click.option('--name', help='name of the Physical Deployment Unit')
1644 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1645 @click.option('--interface',
1646 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1647 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1649 @click.option('--description', help='human readable description')
1650 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
1651 @click.option('--descriptor_file', default
=None,
1652 help='PDU descriptor file (as an alternative to using the other arguments')
1654 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
1655 """creates a new Physical Deployment Unit (PDU)"""
1658 check_client_version(ctx
.obj
, ctx
.command
.name
)
1660 if not descriptor_file
:
1662 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1664 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1666 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1668 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1670 with
open(descriptor_file
, 'r') as df
:
1671 pdu
= yaml
.safe_load(df
.read())
1672 if name
: pdu
["name"] = name
1673 if pdu_type
: pdu
["type"] = pdu_type
1674 if description
: pdu
["description"] = description
1675 if vim_account
: pdu
["vim_accounts"] = vim_account
1678 for iface
in interface
:
1679 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
1680 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
1681 ifaces_list
.append(new_iface
)
1682 pdu
["interfaces"] = ifaces_list
1683 ctx
.obj
.pdu
.create(pdu
)
1684 # except ClientException as e:
1689 ####################
1691 ####################
1693 def nsd_update(ctx
, name
, content
):
1696 check_client_version(ctx
.obj
, ctx
.command
.name
)
1697 ctx
.obj
.nsd
.update(name
, content
)
1698 # except ClientException as e:
1703 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
1704 @click.argument('name')
1705 @click.option('--content', default
=None,
1706 help='filename with the NSD/NSpkg replacing the current one')
1708 def nsd_update1(ctx
, name
, content
):
1709 """updates a NSD/NSpkg
1711 NAME: name or ID of the NSD/NSpkg
1714 nsd_update(ctx
, name
, content
)
1717 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
1718 @click.argument('name')
1719 @click.option('--content', default
=None,
1720 help='filename with the NSD/NSpkg replacing the current one')
1722 def nsd_update2(ctx
, name
, content
):
1723 """updates a NSD/NSpkg
1725 NAME: name or ID of the NSD/NSpkg
1728 nsd_update(ctx
, name
, content
)
1731 def vnfd_update(ctx
, name
, content
):
1734 check_client_version(ctx
.obj
, ctx
.command
.name
)
1735 ctx
.obj
.vnfd
.update(name
, content
)
1736 # except ClientException as e:
1741 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
1742 @click.argument('name')
1743 @click.option('--content', default
=None,
1744 help='filename with the VNFD/VNFpkg replacing the current one')
1746 def vnfd_update1(ctx
, name
, content
):
1747 """updates a VNFD/VNFpkg
1749 NAME: name or ID of the VNFD/VNFpkg
1752 vnfd_update(ctx
, name
, content
)
1755 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
1756 @click.argument('name')
1757 @click.option('--content', default
=None,
1758 help='filename with the VNFD/VNFpkg replacing the current one')
1760 def vnfd_update2(ctx
, name
, content
):
1761 """updates a VNFD/VNFpkg
1763 NAME: VNFD yaml file or VNFpkg tar.gz file
1766 vnfd_update(ctx
, name
, content
)
1769 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
1770 @click.argument('name')
1771 @click.option('--content', default
=None,
1772 help='filename with the NFpkg replacing the current one')
1774 def nfpkg_update(ctx
, name
, content
):
1777 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1780 vnfd_update(ctx
, name
, content
)
1783 def nst_update(ctx
, name
, content
):
1786 check_client_version(ctx
.obj
, ctx
.command
.name
)
1787 ctx
.obj
.nst
.update(name
, content
)
1788 # except ClientException as e:
1793 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
1794 @click.argument('name')
1795 @click.option('--content', default
=None,
1796 help='filename with the NST/NSTpkg replacing the current one')
1798 def nst_update1(ctx
, name
, content
):
1799 """updates a Network Slice Template (NST)
1801 NAME: name or ID of the NSD/NSpkg
1804 nst_update(ctx
, name
, content
)
1807 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
1808 @click.argument('name')
1809 @click.option('--content', default
=None,
1810 help='filename with the NST/NSTpkg replacing the current one')
1812 def nst_update2(ctx
, name
, content
):
1813 """updates a Network Slice Template (NST)
1815 NAME: name or ID of the NSD/NSpkg
1818 nst_update(ctx
, name
, content
)
1821 ####################
1823 ####################
1825 def nsd_delete(ctx
, name
, force
):
1829 ctx
.obj
.nsd
.delete(name
)
1831 check_client_version(ctx
.obj
, '--force')
1832 ctx
.obj
.nsd
.delete(name
, force
)
1833 # except ClientException as e:
1838 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
1839 @click.argument('name')
1840 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1842 def nsd_delete1(ctx
, name
, force
):
1843 """deletes a NSD/NSpkg
1845 NAME: name or ID of the NSD/NSpkg to be deleted
1848 nsd_delete(ctx
, name
, force
)
1851 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
1852 @click.argument('name')
1853 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1855 def nsd_delete2(ctx
, name
, force
):
1856 """deletes a NSD/NSpkg
1858 NAME: name or ID of the NSD/NSpkg to be deleted
1861 nsd_delete(ctx
, name
, force
)
1864 def vnfd_delete(ctx
, name
, force
):
1868 ctx
.obj
.vnfd
.delete(name
)
1870 check_client_version(ctx
.obj
, '--force')
1871 ctx
.obj
.vnfd
.delete(name
, force
)
1872 # except ClientException as e:
1877 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
1878 @click.argument('name')
1879 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1881 def vnfd_delete1(ctx
, name
, force
):
1882 """deletes a VNFD/VNFpkg
1884 NAME: name or ID of the VNFD/VNFpkg to be deleted
1887 vnfd_delete(ctx
, name
, force
)
1890 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
1891 @click.argument('name')
1892 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1894 def vnfd_delete2(ctx
, name
, force
):
1895 """deletes a VNFD/VNFpkg
1897 NAME: name or ID of the VNFD/VNFpkg to be deleted
1900 vnfd_delete(ctx
, name
, force
)
1903 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
1904 @click.argument('name')
1905 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1907 def nfpkg_delete(ctx
, name
, force
):
1910 NAME: name or ID of the NFpkg to be deleted
1913 vnfd_delete(ctx
, name
, force
)
1916 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
1917 @click.argument('name')
1918 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1919 @click.option('--wait',
1923 help='do not return the control immediately, but keep it '
1924 'until the operation is completed, or timeout')
1926 def ns_delete(ctx
, name
, force
, wait
):
1927 """deletes a NS instance
1929 NAME: name or ID of the NS instance to be deleted
1934 ctx
.obj
.ns
.delete(name
, wait
=wait
)
1936 check_client_version(ctx
.obj
, '--force')
1937 ctx
.obj
.ns
.delete(name
, force
, wait
=wait
)
1938 # except ClientException as e:
1943 def nst_delete(ctx
, name
, force
):
1946 check_client_version(ctx
.obj
, ctx
.command
.name
)
1947 ctx
.obj
.nst
.delete(name
, force
)
1948 # except ClientException as e:
1953 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
1954 @click.argument('name')
1955 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1957 def nst_delete1(ctx
, name
, force
):
1958 """deletes a Network Slice Template (NST)
1960 NAME: name or ID of the NST/NSTpkg to be deleted
1963 nst_delete(ctx
, name
, force
)
1966 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
1967 @click.argument('name')
1968 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1970 def nst_delete2(ctx
, name
, force
):
1971 """deletes a Network Slice Template (NST)
1973 NAME: name or ID of the NST/NSTpkg to be deleted
1976 nst_delete(ctx
, name
, force
)
1979 def nsi_delete(ctx
, name
, force
, wait
):
1982 check_client_version(ctx
.obj
, ctx
.command
.name
)
1983 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
1984 # except ClientException as e:
1989 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
1990 @click.argument('name')
1991 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1992 @click.option('--wait',
1996 help='do not return the control immediately, but keep it '
1997 'until the operation is completed, or timeout')
1999 def nsi_delete1(ctx
, name
, force
, wait
):
2000 """deletes a Network Slice Instance (NSI)
2002 NAME: name or ID of the Network Slice instance to be deleted
2005 nsi_delete(ctx
, name
, force
, wait
=wait
)
2008 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
2009 @click.argument('name')
2010 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2012 def nsi_delete2(ctx
, name
, force
, wait
):
2013 """deletes a Network Slice Instance (NSI)
2015 NAME: name or ID of the Network Slice instance to be deleted
2018 nsi_delete(ctx
, name
, force
, wait
=wait
)
2021 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2022 @click.argument('name')
2023 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2025 def pdu_delete(ctx
, name
, force
):
2026 """deletes a Physical Deployment Unit (PDU)
2028 NAME: name or ID of the PDU to be deleted
2032 check_client_version(ctx
.obj
, ctx
.command
.name
)
2033 ctx
.obj
.pdu
.delete(name
, force
)
2034 # except ClientException as e:
2043 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2044 @click.option('--name',
2046 help='Name to create datacenter')
2047 @click.option('--user',
2049 help='VIM username')
2050 @click.option('--password',
2053 confirmation_prompt
=True,
2054 help='VIM password')
2055 @click.option('--auth_url',
2058 @click.option('--tenant',
2060 help='VIM tenant name')
2061 @click.option('--config',
2063 help='VIM specific config parameters')
2064 @click.option('--account_type',
2065 default
='openstack',
2067 @click.option('--description',
2068 default
='no description',
2069 help='human readable description')
2070 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2071 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2072 @click.option('--wait',
2076 help='do not return the control immediately, but keep it '
2077 'until the operation is completed, or timeout')
2091 """creates a new VIM account"""
2095 check_client_version(ctx
.obj
, '--sdn_controller')
2096 if sdn_port_mapping
:
2097 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2099 vim
['vim-username'] = user
2100 vim
['vim-password'] = password
2101 vim
['vim-url'] = auth_url
2102 vim
['vim-tenant-name'] = tenant
2103 vim
['vim-type'] = account_type
2104 vim
['description'] = description
2105 vim
['config'] = config
2106 if sdn_controller
or sdn_port_mapping
:
2107 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2109 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2110 # except ClientException as e:
2115 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2116 @click.argument('name')
2117 @click.option('--newname', help='New name for the VIM account')
2118 @click.option('--user', help='VIM username')
2119 @click.option('--password', help='VIM password')
2120 @click.option('--auth_url', help='VIM url')
2121 @click.option('--tenant', help='VIM tenant name')
2122 @click.option('--config', help='VIM specific config parameters')
2123 @click.option('--account_type', help='VIM type')
2124 @click.option('--description', help='human readable description')
2125 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2126 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2127 @click.option('--wait',
2131 help='do not return the control immediately, but keep it '
2132 'until the operation is completed, or timeout')
2147 """updates a VIM account
2149 NAME: name or ID of the VIM account
2153 check_client_version(ctx
.obj
, ctx
.command
.name
)
2155 if newname
: vim
['name'] = newname
2156 if user
: vim
['vim_user'] = user
2157 if password
: vim
['vim_password'] = password
2158 if auth_url
: vim
['vim_url'] = auth_url
2159 if tenant
: vim
['vim-tenant-name'] = tenant
2160 if account_type
: vim
['vim_type'] = account_type
2161 if description
: vim
['description'] = description
2162 if config
: vim
['config'] = config
2163 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2164 # except ClientException as e:
2169 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2170 @click.argument('name')
2171 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2172 @click.option('--wait',
2176 help='do not return the control immediately, but keep it '
2177 'until the operation is completed, or timeout')
2179 def vim_delete(ctx
, name
, force
, wait
):
2180 """deletes a VIM account
2182 NAME: name or ID of the VIM account to be deleted
2187 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2189 check_client_version(ctx
.obj
, '--force')
2190 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2191 # except ClientException as e:
2196 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2197 #@click.option('--ro_update/--no_ro_update',
2199 # help='update list from RO')
2200 @click.option('--filter', default
=None,
2201 help='restricts the list to the VIM accounts matching the filter')
2203 def vim_list(ctx
, filter):
2204 """list all VIM accounts"""
2207 check_client_version(ctx
.obj
, '--filter')
2209 # check_client_version(ctx.obj, '--ro_update', 'v1')
2210 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2211 if fullclassname
== 'osmclient.sol005.client.Client':
2212 resp
= ctx
.obj
.vim
.list(filter)
2214 # resp = ctx.obj.vim.list(ro_update)
2215 table
= PrettyTable(['vim name', 'uuid'])
2217 table
.add_row([vim
['name'], vim
['uuid']])
2222 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2223 @click.argument('name')
2225 def vim_show(ctx
, name
):
2226 """shows the details of a VIM account
2228 NAME: name or ID of the VIM account
2232 resp
= ctx
.obj
.vim
.get(name
)
2233 if 'vim_password' in resp
:
2234 resp
['vim_password']='********'
2235 # except ClientException as e:
2239 table
= PrettyTable(['key', 'attribute'])
2240 for k
, v
in list(resp
.items()):
2241 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2246 ####################
2248 ####################
2250 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2251 @click.option('--name',
2253 help='Name for the WIM account')
2254 @click.option('--user',
2255 help='WIM username')
2256 @click.option('--password',
2257 help='WIM password')
2258 @click.option('--url',
2261 # @click.option('--tenant',
2262 # help='wIM tenant name')
2263 @click.option('--config',
2265 help='WIM specific config parameters')
2266 @click.option('--wim_type',
2268 @click.option('--description',
2269 default
='no description',
2270 help='human readable description')
2271 @click.option('--wim_port_mapping', default
=None,
2272 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2273 "(WAN service endpoint id and info)")
2274 @click.option('--wait',
2278 help='do not return the control immediately, but keep it '
2279 'until the operation is completed, or timeout')
2292 """creates a new WIM account"""
2295 check_client_version(ctx
.obj
, ctx
.command
.name
)
2296 # if sdn_controller:
2297 # check_client_version(ctx.obj, '--sdn_controller')
2298 # if sdn_port_mapping:
2299 # check_client_version(ctx.obj, '--sdn_port_mapping')
2301 if user
: wim
['user'] = user
2302 if password
: wim
['password'] = password
2303 if url
: wim
['wim_url'] = url
2304 # if tenant: wim['tenant'] = tenant
2305 wim
['wim_type'] = wim_type
2306 if description
: wim
['description'] = description
2307 if config
: wim
['config'] = config
2308 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2309 # except ClientException as e:
2314 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2315 @click.argument('name')
2316 @click.option('--newname', help='New name for the WIM account')
2317 @click.option('--user', help='WIM username')
2318 @click.option('--password', help='WIM password')
2319 @click.option('--url', help='WIM url')
2320 @click.option('--config', help='WIM specific config parameters')
2321 @click.option('--wim_type', help='WIM type')
2322 @click.option('--description', help='human readable description')
2323 @click.option('--wim_port_mapping', default
=None,
2324 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2325 "(WAN service endpoint id and info)")
2326 @click.option('--wait',
2330 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2343 """updates a WIM account
2345 NAME: name or ID of the WIM account
2349 check_client_version(ctx
.obj
, ctx
.command
.name
)
2351 if newname
: wim
['name'] = newname
2352 if user
: wim
['user'] = user
2353 if password
: wim
['password'] = password
2354 if url
: wim
['url'] = url
2355 # if tenant: wim['tenant'] = tenant
2356 if wim_type
: wim
['wim_type'] = wim_type
2357 if description
: wim
['description'] = description
2358 if config
: wim
['config'] = config
2359 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2360 # except ClientException as e:
2365 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2366 @click.argument('name')
2367 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2368 @click.option('--wait',
2372 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2374 def wim_delete(ctx
, name
, force
, wait
):
2375 """deletes a WIM account
2377 NAME: name or ID of the WIM account to be deleted
2381 check_client_version(ctx
.obj
, ctx
.command
.name
)
2382 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2383 # except ClientException as e:
2388 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2389 @click.option('--filter', default
=None,
2390 help='restricts the list to the WIM accounts matching the filter')
2392 def wim_list(ctx
, filter):
2393 """list all WIM accounts"""
2396 check_client_version(ctx
.obj
, ctx
.command
.name
)
2397 resp
= ctx
.obj
.wim
.list(filter)
2398 table
= PrettyTable(['wim name', 'uuid'])
2400 table
.add_row([wim
['name'], wim
['uuid']])
2403 # except ClientException as e:
2408 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2409 @click.argument('name')
2411 def wim_show(ctx
, name
):
2412 """shows the details of a WIM account
2414 NAME: name or ID of the WIM account
2418 check_client_version(ctx
.obj
, ctx
.command
.name
)
2419 resp
= ctx
.obj
.wim
.get(name
)
2420 if 'password' in resp
:
2421 resp
['wim_password']='********'
2422 # except ClientException as e:
2426 table
= PrettyTable(['key', 'attribute'])
2427 for k
, v
in list(resp
.items()):
2428 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2433 ####################
2434 # SDN controller operations
2435 ####################
2437 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2438 @click.option('--name',
2440 help='Name to create sdn controller')
2441 @click.option('--type',
2443 help='SDN controller type')
2444 @click.option('--sdn_controller_version', # hidden=True,
2445 help='Deprecated. Use --config {version: sdn_controller_version}')
2446 @click.option('--url',
2447 help='URL in format http[s]://HOST:IP/')
2448 @click.option('--ip_address', # hidden=True,
2449 help='Deprecated. Use --url')
2450 @click.option('--port', # hidden=True,
2451 help='Deprecated. Use --url')
2452 @click.option('--switch_dpid', # hidden=True,
2453 help='Deprecated. Use --config {dpid: DPID}')
2454 @click.option('--config',
2455 help='Extra information for SDN in yaml format, as {dpid: (Openflow Datapath ID), version: version}')
2456 @click.option('--user',
2457 help='SDN controller username')
2458 @click.option('--password',
2460 confirmation_prompt
=True,
2461 help='SDN controller password')
2462 @click.option('--description', default
=None, help='human readable description')
2463 @click.option('--wait',
2467 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2469 def sdnc_create(ctx
, **kwargs
):
2470 """creates a new SDN controller"""
2472 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2473 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2474 if kwargs
.get("port"):
2475 print("option '--port' is deprecated, use '-url' instead")
2476 sdncontroller
["port"] = int(kwargs
["port"])
2477 if kwargs
.get("ip_address"):
2478 print("option '--ip_address' is deprecated, use '-url' instead")
2479 sdncontroller
["ip"] = kwargs
["ip_address"]
2480 if kwargs
.get("switch_dpid"):
2481 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2482 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2483 if kwargs
.get("sdn_controller_version"):
2484 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2487 check_client_version(ctx
.obj
, ctx
.command
.name
)
2488 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2489 # except ClientException as e:
2493 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2494 @click.argument('name')
2495 @click.option('--newname', help='New name for the SDN controller')
2496 @click.option('--description', default
=None, help='human readable description')
2497 @click.option('--type', help='SDN controller type')
2498 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2499 @click.option('--config', help='Extra information for SDN in yaml format, as '
2500 '{dpid: (Openflow Datapath ID), version: version}')
2501 @click.option('--user', help='SDN controller username')
2502 @click.option('--password', help='SDN controller password')
2503 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2504 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2505 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2506 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2507 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2508 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2510 def sdnc_update(ctx
, **kwargs
):
2511 """updates an SDN controller
2513 NAME: name or ID of the SDN controller
2516 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2517 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2518 if kwargs
.get("newname"):
2519 sdncontroller
["name"] = kwargs
["newname"]
2520 if kwargs
.get("port"):
2521 print("option '--port' is deprecated, use '-url' instead")
2522 sdncontroller
["port"] = int(kwargs
["port"])
2523 if kwargs
.get("ip_address"):
2524 print("option '--ip_address' is deprecated, use '-url' instead")
2525 sdncontroller
["ip"] = kwargs
["ip_address"]
2526 if kwargs
.get("switch_dpid"):
2527 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2528 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2529 if kwargs
.get("sdn_controller_version"):
2530 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2534 check_client_version(ctx
.obj
, ctx
.command
.name
)
2535 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2536 # except ClientException as e:
2541 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2542 @click.argument('name')
2543 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2544 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2545 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2547 def sdnc_delete(ctx
, name
, force
, wait
):
2548 """deletes an SDN controller
2550 NAME: name or ID of the SDN controller to be deleted
2554 check_client_version(ctx
.obj
, ctx
.command
.name
)
2555 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2556 # except ClientException as e:
2561 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2562 @click.option('--filter', default
=None,
2563 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2565 def sdnc_list(ctx
, filter):
2566 """list all SDN controllers"""
2569 check_client_version(ctx
.obj
, ctx
.command
.name
)
2570 resp
= ctx
.obj
.sdnc
.list(filter)
2571 # except ClientException as e:
2574 table
= PrettyTable(['sdnc name', 'id'])
2576 table
.add_row([sdnc
['name'], sdnc
['_id']])
2581 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2582 @click.argument('name')
2584 def sdnc_show(ctx
, name
):
2585 """shows the details of an SDN controller
2587 NAME: name or ID of the SDN controller
2591 check_client_version(ctx
.obj
, ctx
.command
.name
)
2592 resp
= ctx
.obj
.sdnc
.get(name
)
2593 # except ClientException as e:
2597 table
= PrettyTable(['key', 'attribute'])
2598 for k
, v
in list(resp
.items()):
2599 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2604 ###########################
2605 # K8s cluster operations
2606 ###########################
2608 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2609 @click.argument('name')
2610 @click.option('--creds',
2612 help='credentials file, i.e. a valid `.kube/config` file')
2613 @click.option('--version',
2615 help='Kubernetes version')
2616 @click.option('--vim',
2618 help='VIM target, the VIM where the cluster resides')
2619 @click.option('--k8s-nets',
2621 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) ...]}"')
2622 @click.option('--description',
2624 help='human readable description')
2625 @click.option('--namespace',
2626 default
='kube-system',
2627 help='namespace to be used for its operation, defaults to `kube-system`')
2628 @click.option('--cni',
2630 help='list of CNI plugins, in JSON inline format, used in the cluster')
2631 #@click.option('--skip-init',
2633 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2634 #@click.option('--wait',
2636 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2638 def k8scluster_add(ctx
,
2647 """adds a K8s cluster to OSM
2649 NAME: name of the K8s cluster
2652 check_client_version(ctx
.obj
, ctx
.command
.name
)
2654 cluster
['name'] = name
2655 with
open(creds
, 'r') as cf
:
2656 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2657 cluster
['k8s_version'] = version
2658 cluster
['vim_account'] = vim
2659 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2660 cluster
['description'] = description
2661 if namespace
: cluster
['namespace'] = namespace
2662 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2663 ctx
.obj
.k8scluster
.create(name
, cluster
)
2664 # except ClientException as e:
2669 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
2670 @click.argument('name')
2671 @click.option('--newname', help='New name for the K8s cluster')
2672 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
2673 @click.option('--version', help='Kubernetes version')
2674 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
2675 @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) ...]}"')
2676 @click.option('--description', help='human readable description')
2677 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
2678 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
2680 def k8scluster_update(ctx
,
2690 """updates a K8s cluster
2692 NAME: name or ID of the K8s cluster
2695 check_client_version(ctx
.obj
, ctx
.command
.name
)
2697 if newname
: cluster
['name'] = newname
2699 with
open(creds
, 'r') as cf
:
2700 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2701 if version
: cluster
['k8s_version'] = version
2702 if vim
: cluster
['vim_account'] = vim
2703 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2704 if description
: cluster
['description'] = description
2705 if namespace
: cluster
['namespace'] = namespace
2706 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2707 ctx
.obj
.k8scluster
.update(name
, cluster
)
2708 # except ClientException as e:
2713 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
2714 @click.argument('name')
2715 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2716 #@click.option('--wait',
2718 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2720 def k8scluster_delete(ctx
, name
, force
):
2721 """deletes a K8s cluster
2723 NAME: name or ID of the K8s cluster to be deleted
2726 check_client_version(ctx
.obj
, ctx
.command
.name
)
2727 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
2728 # except ClientException as e:
2733 @cli_osm.command(name
='k8scluster-list')
2734 @click.option('--filter', default
=None,
2735 help='restricts the list to the K8s clusters matching the filter')
2736 @click.option('--literal', is_flag
=True,
2737 help='print literally, no pretty table')
2739 def k8scluster_list(ctx
, filter, literal
):
2740 """list all K8s clusters"""
2742 check_client_version(ctx
.obj
, ctx
.command
.name
)
2743 resp
= ctx
.obj
.k8scluster
.list(filter)
2745 print(yaml
.safe_dump(resp
))
2747 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
2748 for cluster
in resp
:
2749 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
2750 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
2751 trunc_text(cluster
.get('description',''),40)])
2754 # except ClientException as e:
2759 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
2760 @click.argument('name')
2761 @click.option('--literal', is_flag
=True,
2762 help='print literally, no pretty table')
2764 def k8scluster_show(ctx
, name
, literal
):
2765 """shows the details of a K8s cluster
2767 NAME: name or ID of the K8s cluster
2770 resp
= ctx
.obj
.k8scluster
.get(name
)
2772 print(yaml
.safe_dump(resp
))
2774 table
= PrettyTable(['key', 'attribute'])
2775 for k
, v
in list(resp
.items()):
2776 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2779 # except ClientException as e:
2785 ###########################
2787 ###########################
2789 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
2790 @click.argument('name')
2791 @click.argument('uri')
2792 @click.option('--type',
2793 type=click
.Choice(['helm-chart', 'juju-bundle']),
2795 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2796 @click.option('--description',
2798 help='human readable description')
2799 #@click.option('--wait',
2801 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2808 """adds a repo to OSM
2810 NAME: name of the repo
2811 URI: URI of the repo
2814 check_client_version(ctx
.obj
, ctx
.command
.name
)
2819 repo
['description'] = description
2820 ctx
.obj
.repo
.create(name
, repo
)
2821 # except ClientException as e:
2826 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
2827 @click.argument('name')
2828 @click.option('--newname', help='New name for the repo')
2829 @click.option('--uri', help='URI of the repo')
2830 @click.option('--type', type=click
.Choice(['helm-chart', 'juju-bundle']),
2831 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2832 @click.option('--description', help='human readable description')
2833 #@click.option('--wait',
2835 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2837 def repo_update(ctx
,
2843 """updates a repo in OSM
2845 NAME: name of the repo
2848 check_client_version(ctx
.obj
, ctx
.command
.name
)
2850 if newname
: repo
['name'] = newname
2851 if uri
: repo
['uri'] = uri
2852 if type: repo
['type'] = type
2853 if description
: repo
['description'] = description
2854 ctx
.obj
.repo
.update(name
, repo
)
2855 # except ClientException as e:
2860 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
2861 @click.argument('name')
2862 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2863 #@click.option('--wait',
2865 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2867 def repo_delete(ctx
, name
, force
):
2870 NAME: name or ID of the repo to be deleted
2873 check_client_version(ctx
.obj
, ctx
.command
.name
)
2874 ctx
.obj
.repo
.delete(name
, force
=force
)
2875 # except ClientException as e:
2880 @cli_osm.command(name
='repo-list')
2881 @click.option('--filter', default
=None,
2882 help='restricts the list to the repos matching the filter')
2883 @click.option('--literal', is_flag
=True,
2884 help='print literally, no pretty table')
2886 def repo_list(ctx
, filter, literal
):
2887 """list all repos"""
2889 check_client_version(ctx
.obj
, ctx
.command
.name
)
2890 resp
= ctx
.obj
.repo
.list(filter)
2892 print(yaml
.safe_dump(resp
))
2894 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
2896 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
2897 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description',''),40)])
2900 # except ClientException as e:
2905 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
2906 @click.argument('name')
2907 @click.option('--literal', is_flag
=True,
2908 help='print literally, no pretty table')
2910 def repo_show(ctx
, name
, literal
):
2911 """shows the details of a repo
2913 NAME: name or ID of the repo
2916 resp
= ctx
.obj
.repo
.get(name
)
2918 print(yaml
.safe_dump(resp
))
2920 table
= PrettyTable(['key', 'attribute'])
2921 for k
, v
in list(resp
.items()):
2922 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2925 # except ClientException as e:
2931 ####################
2932 # Project mgmt operations
2933 ####################
2935 @cli_osm.command(name
='project-create', short_help
='creates a new project')
2936 @click.argument('name')
2937 #@click.option('--description',
2938 # default='no description',
2939 # help='human readable description')
2941 def project_create(ctx
, name
):
2942 """Creates a new project
2944 NAME: name of the project
2948 project
['name'] = name
2950 check_client_version(ctx
.obj
, ctx
.command
.name
)
2951 ctx
.obj
.project
.create(name
, project
)
2952 # except ClientException as e:
2957 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
2958 @click.argument('name')
2959 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2961 def project_delete(ctx
, name
):
2962 """deletes a project
2964 NAME: name or ID of the project to be deleted
2968 check_client_version(ctx
.obj
, ctx
.command
.name
)
2969 ctx
.obj
.project
.delete(name
)
2970 # except ClientException as e:
2975 @cli_osm.command(name
='project-list', short_help
='list all projects')
2976 @click.option('--filter', default
=None,
2977 help='restricts the list to the projects matching the filter')
2979 def project_list(ctx
, filter):
2980 """list all projects"""
2983 check_client_version(ctx
.obj
, ctx
.command
.name
)
2984 resp
= ctx
.obj
.project
.list(filter)
2985 # except ClientException as e:
2988 table
= PrettyTable(['name', 'id'])
2990 table
.add_row([proj
['name'], proj
['_id']])
2995 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
2996 @click.argument('name')
2998 def project_show(ctx
, name
):
2999 """shows the details of a project
3001 NAME: name or ID of the project
3005 check_client_version(ctx
.obj
, ctx
.command
.name
)
3006 resp
= ctx
.obj
.project
.get(name
)
3007 # except ClientException as e:
3011 table
= PrettyTable(['key', 'attribute'])
3012 for k
, v
in resp
.items():
3013 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3018 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3019 @click.argument('project')
3020 @click.option('--name',
3022 help='new name for the project')
3025 def project_update(ctx
, project
, name
):
3027 Update a project name
3030 :param project: id or name of the project to modify
3031 :param name: new name for the project
3035 project_changes
= {}
3036 project_changes
['name'] = name
3039 check_client_version(ctx
.obj
, ctx
.command
.name
)
3040 ctx
.obj
.project
.update(project
, project_changes
)
3041 # except ClientException as e:
3045 ####################
3046 # User mgmt operations
3047 ####################
3049 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3050 @click.argument('username')
3051 @click.option('--password',
3054 confirmation_prompt
=True,
3055 help='user password')
3056 @click.option('--projects',
3057 # prompt="Comma separate list of projects",
3059 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3060 help='list of project ids that the user belongs to')
3061 @click.option('--project-role-mappings', 'project_role_mappings',
3062 default
=None, multiple
=True,
3063 help='creating user project/role(s) mapping')
3065 def user_create(ctx
, username
, password
, projects
, project_role_mappings
):
3066 """Creates a new user
3069 USERNAME: name of the user
3070 PASSWORD: password of the user
3071 PROJECTS: projects assigned to user (internal only)
3072 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3076 user
['username'] = username
3077 user
['password'] = password
3078 user
['projects'] = projects
3079 user
['project_role_mappings'] = project_role_mappings
3082 check_client_version(ctx
.obj
, ctx
.command
.name
)
3083 ctx
.obj
.user
.create(username
, user
)
3084 # except ClientException as e:
3089 @cli_osm.command(name
='user-update', short_help
='updates user information')
3090 @click.argument('username')
3091 @click.option('--password',
3094 # confirmation_prompt=True,
3095 help='user password')
3096 @click.option('--set-username', 'set_username',
3098 help='change username')
3099 @click.option('--set-project', 'set_project',
3100 default
=None, multiple
=True,
3101 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
3102 @click.option('--remove-project', 'remove_project',
3103 default
=None, multiple
=True,
3104 help='removes project from user: \'project\'')
3105 @click.option('--add-project-role', 'add_project_role',
3106 default
=None, multiple
=True,
3107 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
3108 @click.option('--remove-project-role', 'remove_project_role',
3109 default
=None, multiple
=True,
3110 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
3112 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3113 add_project_role
, remove_project_role
):
3114 """Update a user information
3117 USERNAME: name of the user
3118 PASSWORD: new password
3119 SET_USERNAME: new username
3120 SET_PROJECT: creating mappings for project/role(s)
3121 REMOVE_PROJECT: deleting mappings for project/role(s)
3122 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3123 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3127 user
['password'] = password
3128 user
['username'] = set_username
3129 user
['set-project'] = set_project
3130 user
['remove-project'] = remove_project
3131 user
['add-project-role'] = add_project_role
3132 user
['remove-project-role'] = remove_project_role
3135 check_client_version(ctx
.obj
, ctx
.command
.name
)
3136 ctx
.obj
.user
.update(username
, user
)
3137 # except ClientException as e:
3142 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3143 @click.argument('name')
3144 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3146 def user_delete(ctx
, name
):
3150 NAME: name or ID of the user to be deleted
3154 check_client_version(ctx
.obj
, ctx
.command
.name
)
3155 ctx
.obj
.user
.delete(name
)
3156 # except ClientException as e:
3161 @cli_osm.command(name
='user-list', short_help
='list all users')
3162 @click.option('--filter', default
=None,
3163 help='restricts the list to the users matching the filter')
3165 def user_list(ctx
, filter):
3166 """list all users"""
3168 check_client_version(ctx
.obj
, ctx
.command
.name
)
3169 resp
= ctx
.obj
.user
.list(filter)
3170 # except ClientException as e:
3173 table
= PrettyTable(['name', 'id'])
3175 table
.add_row([user
['username'], user
['_id']])
3180 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3181 @click.argument('name')
3183 def user_show(ctx
, name
):
3184 """shows the details of a user
3186 NAME: name or ID of the user
3190 check_client_version(ctx
.obj
, ctx
.command
.name
)
3191 resp
= ctx
.obj
.user
.get(name
)
3192 if 'password' in resp
:
3193 resp
['password']='********'
3194 # except ClientException as e:
3198 table
= PrettyTable(['key', 'attribute'])
3199 for k
, v
in resp
.items():
3200 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3205 ####################
3206 # Fault Management operations
3207 ####################
3209 @cli_osm.command(name
='ns-alarm-create')
3210 @click.argument('name')
3211 @click.option('--ns', prompt
=True, help='NS instance id or name')
3212 @click.option('--vnf', prompt
=True,
3213 help='VNF name (VNF member index as declared in the NSD)')
3214 @click.option('--vdu', prompt
=True,
3215 help='VDU name (VDU name as declared in the VNFD)')
3216 @click.option('--metric', prompt
=True,
3217 help='Name of the metric (e.g. cpu_utilization)')
3218 @click.option('--severity', default
='WARNING',
3219 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3220 @click.option('--threshold_value', prompt
=True,
3221 help='threshold value that, when crossed, an alarm is triggered')
3222 @click.option('--threshold_operator', prompt
=True,
3223 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3224 @click.option('--statistic', default
='AVERAGE',
3225 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3227 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3228 threshold_value
, threshold_operator
, statistic
):
3229 """creates a new alarm for a NS instance"""
3230 # TODO: Check how to validate threshold_value.
3231 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3234 ns_instance
= ctx
.obj
.ns
.get(ns
)
3236 alarm
['alarm_name'] = name
3237 alarm
['ns_id'] = ns_instance
['_id']
3238 alarm
['correlation_id'] = ns_instance
['_id']
3239 alarm
['vnf_member_index'] = vnf
3240 alarm
['vdu_name'] = vdu
3241 alarm
['metric_name'] = metric
3242 alarm
['severity'] = severity
3243 alarm
['threshold_value'] = int(threshold_value
)
3244 alarm
['operation'] = threshold_operator
3245 alarm
['statistic'] = statistic
3246 check_client_version(ctx
.obj
, ctx
.command
.name
)
3247 ctx
.obj
.ns
.create_alarm(alarm
)
3248 # except ClientException as e:
3253 #@cli_osm.command(name='ns-alarm-delete')
3254 #@click.argument('name')
3255 #@click.pass_context
3256 #def ns_alarm_delete(ctx, name):
3257 # """deletes an alarm
3259 # NAME: name of the alarm to be deleted
3262 # check_client_version(ctx.obj, ctx.command.name)
3263 # ctx.obj.ns.delete_alarm(name)
3264 # except ClientException as e:
3269 ####################
3270 # Performance Management operations
3271 ####################
3273 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3274 @click.option('--ns', prompt
=True, help='NS instance id or name')
3275 @click.option('--vnf', prompt
=True,
3276 help='VNF name (VNF member index as declared in the NSD)')
3277 @click.option('--vdu', prompt
=True,
3278 help='VDU name (VDU name as declared in the VNFD)')
3279 @click.option('--metric', prompt
=True,
3280 help='name of the metric (e.g. cpu_utilization)')
3281 #@click.option('--period', default='1w',
3282 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3283 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3285 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3286 """exports a metric to the internal OSM bus, which can be read by other apps"""
3287 # TODO: Check how to validate interval.
3288 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3291 ns_instance
= ctx
.obj
.ns
.get(ns
)
3293 metric_data
['ns_id'] = ns_instance
['_id']
3294 metric_data
['correlation_id'] = ns_instance
['_id']
3295 metric_data
['vnf_member_index'] = vnf
3296 metric_data
['vdu_name'] = vdu
3297 metric_data
['metric_name'] = metric
3298 metric_data
['collection_unit'] = 'WEEK'
3299 metric_data
['collection_period'] = 1
3300 check_client_version(ctx
.obj
, ctx
.command
.name
)
3302 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3306 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3307 time
.sleep(int(interval
))
3309 # except ClientException as e:
3314 ####################
3316 ####################
3318 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3320 def get_version(ctx
):
3321 """shows client and server versions"""
3323 check_client_version(ctx
.obj
, "version")
3324 print ("Server version: {}".format(ctx
.obj
.get_version()))
3325 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3326 # except ClientException as e:
3330 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3331 @click.argument('filename')
3332 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3333 help='the charm will not be compiled, it is assumed to already exist')
3335 def upload_package(ctx
, filename
, skip_charm_build
):
3336 """uploads a vnf package or ns package
3338 filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3342 ctx
.obj
.package
.upload(filename
, skip_charm_build
=skip_charm_build
)
3343 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3344 if fullclassname
!= 'osmclient.sol005.client.Client':
3345 ctx
.obj
.package
.wait_for_upload(filename
)
3346 # except ClientException as e:
3351 #@cli_osm.command(name='ns-scaling-show')
3352 #@click.argument('ns_name')
3353 #@click.pass_context
3354 #def show_ns_scaling(ctx, ns_name):
3355 # """shows the status of a NS scaling operation
3357 # NS_NAME: name of the NS instance being scaled
3360 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3361 # resp = ctx.obj.ns.list()
3362 # except ClientException as e:
3366 # table = PrettyTable(
3369 # 'operational status',
3374 # if ns_name == ns['name']:
3375 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3376 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3377 # for record in scaling_records:
3378 # if 'instance' in record:
3379 # instances = record['instance']
3380 # for inst in instances:
3382 # [record['scaling-group-name-ref'],
3383 # inst['instance-id'],
3384 # inst['op-status'],
3385 # time.strftime('%Y-%m-%d %H:%M:%S',
3387 # inst['create-time'])),
3393 #@cli_osm.command(name='ns-scale')
3394 #@click.argument('ns_name')
3395 #@click.option('--ns_scale_group', prompt=True)
3396 #@click.option('--index', prompt=True)
3397 #@click.option('--wait',
3401 # help='do not return the control immediately, but keep it \
3402 # until the operation is completed, or timeout')
3403 #@click.pass_context
3404 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3407 # NS_NAME: name of the NS instance to be scaled
3410 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3411 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3412 # except ClientException as e:
3417 #@cli_osm.command(name='config-agent-list')
3418 #@click.pass_context
3419 #def config_agent_list(ctx):
3420 # """list config agents"""
3422 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3423 # except ClientException as e:
3426 # table = PrettyTable(['name', 'account-type', 'details'])
3427 # for account in ctx.obj.vca.list():
3430 # account['account-type'],
3436 #@cli_osm.command(name='config-agent-delete')
3437 #@click.argument('name')
3438 #@click.pass_context
3439 #def config_agent_delete(ctx, name):
3440 # """deletes a config agent
3442 # NAME: name of the config agent to be deleted
3445 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3446 # ctx.obj.vca.delete(name)
3447 # except ClientException as e:
3452 #@cli_osm.command(name='config-agent-add')
3453 #@click.option('--name',
3455 #@click.option('--account_type',
3457 #@click.option('--server',
3459 #@click.option('--user',
3461 #@click.option('--secret',
3464 # confirmation_prompt=True)
3465 #@click.pass_context
3466 #def config_agent_add(ctx, name, account_type, server, user, secret):
3467 # """adds a config agent"""
3469 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3470 # ctx.obj.vca.create(name, account_type, server, user, secret)
3471 # except ClientException as e:
3476 #@cli_osm.command(name='ro-dump')
3477 #@click.pass_context
3479 # """shows RO agent information"""
3480 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3481 # resp = ctx.obj.vim.get_resource_orchestrator()
3482 # table = PrettyTable(['key', 'attribute'])
3483 # for k, v in list(resp.items()):
3484 # table.add_row([k, json.dumps(v, indent=2)])
3489 #@cli_osm.command(name='vcs-list')
3490 #@click.pass_context
3492 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3493 # resp = ctx.obj.utils.get_vcs_info()
3494 # table = PrettyTable(['component name', 'state'])
3495 # for component in resp:
3496 # table.add_row([component['component_name'], component['state']])
3501 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3502 @click.argument('ns_name')
3503 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3504 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3505 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3506 @click.option('--vdu_count', default
=None, help='number of vdu instance of this vdu_id')
3507 @click.option('--action_name', prompt
=True, help='action name')
3508 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3509 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3510 @click.option('--wait',
3514 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3526 """executes an action/primitive over a NS instance
3528 NS_NAME: name or ID of the NS instance
3532 check_client_version(ctx
.obj
, ctx
.command
.name
)
3535 op_data
['member_vnf_index'] = vnf_name
3537 op_data
['kdu_name'] = kdu_name
3539 op_data
['vdu_id'] = vdu_id
3541 op_data
['vdu_count_index'] = vdu_count
3542 op_data
['primitive'] = action_name
3544 with
open(params_file
, 'r') as pf
:
3547 op_data
['primitive_params'] = yaml
.safe_load(params
)
3549 op_data
['primitive_params'] = {}
3550 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
3552 # except ClientException as e:
3557 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
3558 @click.argument('ns_name')
3559 @click.argument('vnf_name')
3560 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
3561 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
3562 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
3571 Executes a VNF scale (adding/removing VDUs)
3574 NS_NAME: name or ID of the NS instance.
3575 VNF_NAME: member-vnf-index in the NS to be scaled.
3579 check_client_version(ctx
.obj
, ctx
.command
.name
)
3580 if not scale_in
and not scale_out
:
3582 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
)
3583 # except ClientException as e:
3588 ##############################
3589 # Role Management Operations #
3590 ##############################
3592 @cli_osm.command(name
='role-create', short_help
='creates a new role')
3593 @click.argument('name')
3594 @click.option('--permissions',
3596 help='role permissions using a dictionary')
3598 def role_create(ctx
, name
, permissions
):
3603 NAME: Name or ID of the role.
3604 DEFINITION: Definition of grant/denial of access to resources.
3608 check_client_version(ctx
.obj
, ctx
.command
.name
)
3609 ctx
.obj
.role
.create(name
, permissions
)
3610 # except ClientException as e:
3615 @cli_osm.command(name
='role-update', short_help
='updates a role')
3616 @click.argument('name')
3617 @click.option('--set-name',
3619 help='change name of rle')
3620 # @click.option('--permissions',
3622 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
3623 @click.option('--add',
3625 help='yaml format dictionary with permission: True/False to access grant/denial')
3626 @click.option('--remove',
3628 help='yaml format list to remove a permission')
3630 def role_update(ctx
, name
, set_name
, add
, remove
):
3635 NAME: Name or ID of the role.
3636 DEFINITION: Definition overwrites the old definition.
3637 ADD: Grant/denial of access to resource to add.
3638 REMOVE: Grant/denial of access to resource to remove.
3642 check_client_version(ctx
.obj
, ctx
.command
.name
)
3643 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
3644 # except ClientException as e:
3649 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
3650 @click.argument('name')
3651 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3653 def role_delete(ctx
, name
):
3658 NAME: Name or ID of the role.
3662 check_client_version(ctx
.obj
, ctx
.command
.name
)
3663 ctx
.obj
.role
.delete(name
)
3664 # except ClientException as e:
3669 @cli_osm.command(name
='role-list', short_help
='list all roles')
3670 @click.option('--filter', default
=None,
3671 help='restricts the list to the projects matching the filter')
3673 def role_list(ctx
, filter):
3679 check_client_version(ctx
.obj
, ctx
.command
.name
)
3680 resp
= ctx
.obj
.role
.list(filter)
3681 # except ClientException as e:
3684 table
= PrettyTable(['name', 'id'])
3686 table
.add_row([role
['name'], role
['_id']])
3691 @cli_osm.command(name
='role-show', short_help
='show specific role')
3692 @click.argument('name')
3694 def role_show(ctx
, name
):
3696 Shows the details of a role.
3699 NAME: Name or ID of the role.
3703 check_client_version(ctx
.obj
, ctx
.command
.name
)
3704 resp
= ctx
.obj
.role
.get(name
)
3705 # except ClientException as e:
3709 table
= PrettyTable(['key', 'attribute'])
3710 for k
, v
in resp
.items():
3711 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3716 @cli_osm.command(name
='package-create',
3717 short_help
='Create a package descriptor')
3718 @click.argument('package-type')
3719 @click.argument('package-name')
3720 @click.option('--base-directory',
3722 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
3723 @click.option('--image',
3724 default
="image-name",
3725 help='(VNF) Set the name of the vdu image. Default "image-name"')
3726 @click.option('--vdus',
3728 help='(VNF) Set the number of vdus in a VNF. Default 1')
3729 @click.option('--vcpu',
3731 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
3732 @click.option('--memory',
3734 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
3735 @click.option('--storage',
3737 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
3738 @click.option('--interfaces',
3740 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
3741 @click.option('--vendor',
3743 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
3744 @click.option('--override',
3747 help='(NS/VNF/NST) Flag for overriding the package if exists.')
3748 @click.option('--detailed',
3751 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
3752 @click.option('--netslice-subnets',
3754 help='(NST) Number of netslice subnets. Default 1')
3755 @click.option('--netslice-vlds',
3757 help='(NST) Number of netslice vlds. Default 1')
3759 def package_create(ctx
,
3775 Creates an OSM NS, VNF, NST package
3778 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
3779 PACKAGE_NAME: Name of the package to create the folder with the content.
3783 check_client_version(ctx
.obj
, ctx
.command
.name
)
3784 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
3785 resp
= ctx
.obj
.package_tool
.create(package_type
,
3794 interfaces
=interfaces
,
3797 netslice_subnets
=netslice_subnets
,
3798 netslice_vlds
=netslice_vlds
)
3800 # except ClientException as inst:
3801 # print("ERROR: {}".format(inst))
3804 @cli_osm.command(name
='package-validate',
3805 short_help
='Validate a package descriptor')
3806 @click.argument('base-directory',
3809 @click.option('--recursive/--no-recursive',
3811 help='The activated recursive option will validate the yaml files'
3812 ' within the indicated directory and in its subdirectories')
3814 def package_validate(ctx
,
3818 Validate descriptors given a base directory.
3821 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
3824 check_client_version(ctx
.obj
, ctx
.command
.name
)
3825 results
= ctx
.obj
.package_tool
.validate(base_directory
, recursive
)
3826 table
= PrettyTable()
3827 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
3828 # Print the dictionary generated by the validation function
3829 for result
in results
:
3830 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
3831 table
.sortby
= "VALID"
3832 table
.align
["PATH"] = "l"
3833 table
.align
["TYPE"] = "l"
3834 table
.align
["ERROR"] = "l"
3836 # except ClientException as inst:
3837 # print("ERROR: {}".format(inst))
3840 @cli_osm.command(name
='package-build',
3841 short_help
='Build the tar.gz of the package')
3842 @click.argument('package-folder')
3843 @click.option('--skip-validation',
3846 help='skip package validation')
3847 @click.option('--skip-charm-build', default
=False, is_flag
=True,
3848 help='the charm will not be compiled, it is assumed to already exist')
3850 def package_build(ctx
,
3855 Build the package NS, VNF given the package_folder.
3858 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
3861 check_client_version(ctx
.obj
, ctx
.command
.name
)
3862 results
= ctx
.obj
.package_tool
.build(package_folder
,
3863 skip_validation
=skip_validation
,
3864 skip_charm_build
=skip_charm_build
)
3866 # except ClientException as inst:
3867 # print("ERROR: {}".format(inst))
3875 except pycurl
.error
as exc
:
3877 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
3878 except ClientException
as exc
:
3879 print("ERROR: {}".format(exc
))
3880 except (FileNotFoundError
, PermissionError
) as exc
:
3881 print("Cannot open file: {}".format(exc
))
3882 except yaml
.YAMLError
as exc
:
3883 print("Invalid YAML format: {}".format(exc
))
3885 # TODO capture other controlled exceptions here
3886 # TODO remove the ClientException captures from all places, unless they do something different
3889 if __name__
== '__main__':