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 current operation in the NS.')
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')
621 def ns_op_list(ctx
, name
):
622 """shows the history of operations over a NS instance
624 NAME: name or ID of the NS instance
626 def formatParams(params
):
627 if params
['lcmOperationType']=='instantiate':
628 params
.pop('nsDescription')
632 elif params
['lcmOperationType']=='action':
633 params
.pop('primitive')
634 params
.pop('lcmOperationType')
635 params
.pop('nsInstanceId')
640 check_client_version(ctx
.obj
, ctx
.command
.name
)
641 resp
= ctx
.obj
.ns
.list_op(name
)
642 # except ClientException as e:
646 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'detail'])
647 #print(yaml.safe_dump(resp))
650 if op
['lcmOperationType']=='action':
651 action_name
= op
['operationParams']['primitive']
653 if op
['operationState']=='PROCESSING':
654 if op
['lcmOperationType']=='instantiate':
658 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
659 elif op
['operationState']=='FAILED' or op
['operationState']=='FAILED_TEMP':
660 detail
= op
['errorMessage']
661 table
.add_row([op
['id'],
662 op
['lcmOperationType'],
664 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=70),
665 op
['operationState'],
666 wrap_text(text
=detail
,width
=50)])
671 def nsi_list(ctx
, filter):
672 """list all Network Slice Instances"""
675 check_client_version(ctx
.obj
, ctx
.command
.name
)
676 resp
= ctx
.obj
.nsi
.list(filter)
677 # except ClientException as e:
681 ['netslice instance name',
683 'operational status',
687 nsi_name
= nsi
['name']
689 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
690 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
691 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
692 if configstatus
== "config_not_needed":
693 configstatus
= "configured (no charms)"
704 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
705 @click.option('--filter', default
=None,
706 help='restricts the list to the Network Slice Instances matching the filter')
708 def nsi_list1(ctx
, filter):
709 """list all Network Slice Instances (NSI)"""
711 nsi_list(ctx
, filter)
714 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
715 @click.option('--filter', default
=None,
716 help='restricts the list to the Network Slice Instances matching the filter')
718 def nsi_list2(ctx
, filter):
719 """list all Network Slice Instances (NSI)"""
721 nsi_list(ctx
, filter)
724 def nst_list(ctx
, filter):
727 check_client_version(ctx
.obj
, ctx
.command
.name
)
728 resp
= ctx
.obj
.nst
.list(filter)
729 # except ClientException as e:
732 # print(yaml.safe_dump(resp))
733 table
= PrettyTable(['nst name', 'id'])
735 name
= nst
['name'] if 'name' in nst
else '-'
736 table
.add_row([name
, nst
['_id']])
741 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
742 @click.option('--filter', default
=None,
743 help='restricts the list to the NST matching the filter')
745 def nst_list1(ctx
, filter):
746 """list all Network Slice Templates (NST) in the system"""
748 nst_list(ctx
, filter)
751 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
752 @click.option('--filter', default
=None,
753 help='restricts the list to the NST matching the filter')
755 def nst_list2(ctx
, filter):
756 """list all Network Slice Templates (NST) in the system"""
758 nst_list(ctx
, filter)
761 def nsi_op_list(ctx
, name
):
764 check_client_version(ctx
.obj
, ctx
.command
.name
)
765 resp
= ctx
.obj
.nsi
.list_op(name
)
766 # except ClientException as e:
769 table
= PrettyTable(['id', 'operation', 'status'])
771 table
.add_row([op
['id'], op
['lcmOperationType'],
772 op
['operationState']])
777 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
778 @click.argument('name')
780 def nsi_op_list1(ctx
, name
):
781 """shows the history of operations over a Network Slice Instance (NSI)
783 NAME: name or ID of the Network Slice Instance
786 nsi_op_list(ctx
, name
)
789 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
790 @click.argument('name')
792 def nsi_op_list2(ctx
, name
):
793 """shows the history of operations over a Network Slice Instance (NSI)
795 NAME: name or ID of the Network Slice Instance
798 nsi_op_list(ctx
, name
)
801 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
802 @click.option('--filter', default
=None,
803 help='restricts the list to the Physical Deployment Units matching the filter')
805 def pdu_list(ctx
, filter):
806 """list all Physical Deployment Units (PDU)"""
809 check_client_version(ctx
.obj
, ctx
.command
.name
)
810 resp
= ctx
.obj
.pdu
.list(filter)
811 # except ClientException as e:
820 pdu_name
= pdu
['name']
822 pdu_type
= pdu
['type']
823 pdu_ipaddress
= "None"
824 for iface
in pdu
['interfaces']:
826 pdu_ipaddress
= iface
['ip-address']
841 def nsd_show(ctx
, name
, literal
):
844 resp
= ctx
.obj
.nsd
.get(name
)
845 # resp = ctx.obj.nsd.get_individual(name)
846 # except ClientException as e:
851 print(yaml
.safe_dump(resp
))
854 table
= PrettyTable(['field', 'value'])
855 for k
, v
in list(resp
.items()):
856 table
.add_row([k
, json
.dumps(v
, indent
=2)])
861 @cli_osm.command(name
='nsd-show', short_help
='shows the content of a NSD')
862 @click.option('--literal', is_flag
=True,
863 help='print literally, no pretty table')
864 @click.argument('name')
866 def nsd_show1(ctx
, name
, literal
):
867 """shows the content of a NSD
869 NAME: name or ID of the NSD/NSpkg
872 nsd_show(ctx
, name
, literal
)
875 @cli_osm.command(name
='nspkg-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_show2(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 def vnfd_show(ctx
, name
, literal
):
892 resp
= ctx
.obj
.vnfd
.get(name
)
893 # resp = ctx.obj.vnfd.get_individual(name)
894 # except ClientException as e:
899 print(yaml
.safe_dump(resp
))
902 table
= PrettyTable(['field', 'value'])
903 for k
, v
in list(resp
.items()):
904 table
.add_row([k
, json
.dumps(v
, indent
=2)])
909 @cli_osm.command(name
='vnfd-show', short_help
='shows the content of a VNFD')
910 @click.option('--literal', is_flag
=True,
911 help='print literally, no pretty table')
912 @click.argument('name')
914 def vnfd_show1(ctx
, name
, literal
):
915 """shows the content of a VNFD
917 NAME: name or ID of the VNFD/VNFpkg
920 vnfd_show(ctx
, name
, literal
)
923 @cli_osm.command(name
='vnfpkg-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_show2(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
='nfpkg-show', short_help
='shows the content of a NF Descriptor')
938 @click.option('--literal', is_flag
=True,
939 help='print literally, no pretty table')
940 @click.argument('name')
942 def nfpkg_show(ctx
, name
, literal
):
943 """shows the content of a NF Descriptor
945 NAME: name or ID of the NFpkg
948 vnfd_show(ctx
, name
, literal
)
951 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
952 @click.argument('name')
953 @click.option('--literal', is_flag
=True,
954 help='print literally, no pretty table')
955 @click.option('--filter', default
=None)
957 def ns_show(ctx
, name
, literal
, filter):
958 """shows the info of a NS instance
960 NAME: name or ID of the NS instance
964 ns
= ctx
.obj
.ns
.get(name
)
965 # except ClientException as e:
970 print(yaml
.safe_dump(ns
))
973 table
= PrettyTable(['field', 'value'])
975 for k
, v
in list(ns
.items()):
976 if filter is None or filter in k
:
977 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
979 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
980 if fullclassname
!= 'osmclient.sol005.client.Client':
981 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
982 nsr_optdata
= nsopdata
['nsr:nsr']
983 for k
, v
in list(nsr_optdata
.items()):
984 if filter is None or filter in k
:
985 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
990 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
991 @click.argument('name')
992 @click.option('--literal', is_flag
=True,
993 help='print literally, no pretty table')
994 @click.option('--filter', default
=None, help='restricts the information to the fields in the filter')
995 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
997 def vnf_show(ctx
, name
, literal
, filter, kdu
):
998 """shows the info of a VNF instance
1000 NAME: name or ID of the VNF instance
1002 def print_kdu_status(op_info_status
):
1003 """print KDU status properly formatted
1006 op_status
= yaml
.safe_load(op_info_status
)
1007 if "namespace" in op_status
and "info" in op_status
and \
1008 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1009 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1010 "notes" in op_status
["info"]["status"] and "seconds" in op_status
["info"]["last_deployed"]:
1011 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1012 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1013 print("NAMESPACE: {}".format(op_status
["namespace"]))
1014 status_code
= "UNKNOWN"
1015 if op_status
["info"]["status"]["code"]==1:
1016 status_code
= "DEPLOYED"
1017 print("STATUS: {}".format(status_code
))
1020 print(op_status
["info"]["status"]["resources"])
1022 print(op_status
["info"]["status"]["notes"])
1024 print(op_info_status
)
1026 print(op_info_status
)
1031 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1033 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1036 check_client_version(ctx
.obj
, ctx
.command
.name
)
1037 resp
= ctx
.obj
.vnf
.get(name
)
1040 ns_id
= resp
['nsr-id-ref']
1042 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1043 op_data
['kdu_name'] = kdu
1044 op_data
['primitive'] = 'status'
1045 op_data
['primitive_params'] = {}
1046 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1049 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1050 if op_info
['operationState'] == 'COMPLETED':
1051 print_kdu_status(op_info
['detailed-status'])
1055 print ("Could not determine KDU status")
1058 print(yaml
.safe_dump(resp
))
1061 table
= PrettyTable(['field', 'value'])
1063 for k
, v
in list(resp
.items()):
1064 if filter is None or filter in k
:
1065 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1068 # except ClientException as e:
1073 #@cli_osm.command(name='vnf-monitoring-show')
1074 #@click.argument('vnf_name')
1075 #@click.pass_context
1076 #def vnf_monitoring_show(ctx, vnf_name):
1078 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1079 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1080 # except ClientException as e:
1084 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1085 # if resp is not None:
1086 # for monitor in resp:
1090 # monitor['value-integer'],
1091 # monitor['units']])
1096 #@cli_osm.command(name='ns-monitoring-show')
1097 #@click.argument('ns_name')
1098 #@click.pass_context
1099 #def ns_monitoring_show(ctx, ns_name):
1101 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1102 # resp = ctx.obj.ns.get_monitoring(ns_name)
1103 # except ClientException as e:
1107 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1108 # for key, val in list(resp.items()):
1109 # for monitor in val:
1113 # monitor['value-integer'],
1114 # monitor['units']])
1119 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1120 @click.argument('id')
1121 @click.option('--filter', default
=None)
1122 @click.option('--literal', is_flag
=True,
1123 help='print literally, no pretty table')
1125 def ns_op_show(ctx
, id, filter, literal
):
1126 """shows the detailed info of a NS operation
1128 ID: operation identifier
1132 check_client_version(ctx
.obj
, ctx
.command
.name
)
1133 op_info
= ctx
.obj
.ns
.get_op(id)
1134 # except ClientException as e:
1139 print(yaml
.safe_dump(op_info
))
1142 table
= PrettyTable(['field', 'value'])
1143 for k
, v
in list(op_info
.items()):
1144 if filter is None or filter in k
:
1145 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1150 def nst_show(ctx
, name
, literal
):
1153 check_client_version(ctx
.obj
, ctx
.command
.name
)
1154 resp
= ctx
.obj
.nst
.get(name
)
1155 #resp = ctx.obj.nst.get_individual(name)
1156 # except ClientException as e:
1161 print(yaml
.safe_dump(resp
))
1164 table
= PrettyTable(['field', 'value'])
1165 for k
, v
in list(resp
.items()):
1166 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1171 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1172 @click.option('--literal', is_flag
=True,
1173 help='print literally, no pretty table')
1174 @click.argument('name')
1176 def nst_show1(ctx
, name
, literal
):
1177 """shows the content of a Network Slice Template (NST)
1179 NAME: name or ID of the NST
1182 nst_show(ctx
, name
, literal
)
1185 @cli_osm.command(name
='netslice-template-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_show2(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 def nsi_show(ctx
, name
, literal
, filter):
1202 check_client_version(ctx
.obj
, ctx
.command
.name
)
1203 nsi
= ctx
.obj
.nsi
.get(name
)
1204 # except ClientException as e:
1209 print(yaml
.safe_dump(nsi
))
1212 table
= PrettyTable(['field', 'value'])
1214 for k
, v
in list(nsi
.items()):
1215 if filter is None or filter in k
:
1216 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1222 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1223 @click.argument('name')
1224 @click.option('--literal', is_flag
=True,
1225 help='print literally, no pretty table')
1226 @click.option('--filter', default
=None)
1228 def nsi_show1(ctx
, name
, literal
, filter):
1229 """shows the content of a Network Slice Instance (NSI)
1231 NAME: name or ID of the Network Slice Instance
1234 nsi_show(ctx
, name
, literal
, filter)
1237 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1238 @click.argument('name')
1239 @click.option('--literal', is_flag
=True,
1240 help='print literally, no pretty table')
1241 @click.option('--filter', default
=None)
1243 def nsi_show2(ctx
, name
, literal
, filter):
1244 """shows the content of a Network Slice Instance (NSI)
1246 NAME: name or ID of the Network Slice Instance
1249 nsi_show(ctx
, name
, literal
, filter)
1252 def nsi_op_show(ctx
, id, filter):
1255 check_client_version(ctx
.obj
, ctx
.command
.name
)
1256 op_info
= ctx
.obj
.nsi
.get_op(id)
1257 # except ClientException as e:
1261 table
= PrettyTable(['field', 'value'])
1262 for k
, v
in list(op_info
.items()):
1263 if filter is None or filter in k
:
1264 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1269 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1270 @click.argument('id')
1271 @click.option('--filter', default
=None)
1273 def nsi_op_show1(ctx
, id, filter):
1274 """shows the info of an operation over a Network Slice Instance(NSI)
1276 ID: operation identifier
1279 nsi_op_show(ctx
, id, filter)
1282 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1283 @click.argument('id')
1284 @click.option('--filter', default
=None)
1286 def nsi_op_show2(ctx
, id, filter):
1287 """shows the info of an operation over a Network Slice Instance(NSI)
1289 ID: operation identifier
1292 nsi_op_show(ctx
, id, filter)
1295 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1296 @click.argument('name')
1297 @click.option('--literal', is_flag
=True,
1298 help='print literally, no pretty table')
1299 @click.option('--filter', default
=None)
1301 def pdu_show(ctx
, name
, literal
, filter):
1302 """shows the content of a Physical Deployment Unit (PDU)
1304 NAME: name or ID of the PDU
1308 check_client_version(ctx
.obj
, ctx
.command
.name
)
1309 pdu
= ctx
.obj
.pdu
.get(name
)
1310 # except ClientException as e:
1315 print(yaml
.safe_dump(pdu
))
1318 table
= PrettyTable(['field', 'value'])
1320 for k
, v
in list(pdu
.items()):
1321 if filter is None or filter in k
:
1322 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1328 ####################
1330 ####################
1332 def nsd_create(ctx
, filename
, overwrite
):
1335 check_client_version(ctx
.obj
, ctx
.command
.name
)
1336 ctx
.obj
.nsd
.create(filename
, overwrite
)
1337 # except ClientException as e:
1342 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1343 @click.argument('filename')
1344 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1345 help='Deprecated. Use override')
1346 @click.option('--override', 'overwrite', default
=None,
1347 help='overrides fields in descriptor, format: '
1348 '"key1.key2...=value[;key3...=value;...]"')
1350 def nsd_create1(ctx
, filename
, overwrite
):
1351 """creates a new NSD/NSpkg
1353 FILENAME: NSD yaml file or NSpkg tar.gz file
1356 nsd_create(ctx
, filename
, overwrite
)
1359 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1360 @click.argument('filename')
1361 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1362 help='Deprecated. Use override')
1363 @click.option('--override', 'overwrite', default
=None,
1364 help='overrides fields in descriptor, format: '
1365 '"key1.key2...=value[;key3...=value;...]"')
1367 def nsd_create2(ctx
, filename
, overwrite
):
1368 """creates a new NSD/NSpkg
1370 FILENAME: NSD yaml file or NSpkg tar.gz file
1373 nsd_create(ctx
, filename
, overwrite
)
1376 def vnfd_create(ctx
, filename
, overwrite
):
1379 check_client_version(ctx
.obj
, ctx
.command
.name
)
1380 ctx
.obj
.vnfd
.create(filename
, overwrite
)
1381 # except ClientException as e:
1386 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1387 @click.argument('filename')
1388 @click.option('--overwrite', 'overwrite', default
=None,
1389 help='overwrite deprecated, use override')
1390 @click.option('--override', 'overwrite', default
=None,
1391 help='overrides fields in descriptor, format: '
1392 '"key1.key2...=value[;key3...=value;...]"')
1394 def vnfd_create1(ctx
, filename
, overwrite
):
1395 """creates a new VNFD/VNFpkg
1397 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1400 vnfd_create(ctx
, filename
, overwrite
)
1403 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1404 @click.argument('filename')
1405 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1406 help='Deprecated. Use override')
1407 @click.option('--override', 'overwrite', default
=None,
1408 help='overrides fields in descriptor, format: '
1409 '"key1.key2...=value[;key3...=value;...]"')
1411 def vnfd_create2(ctx
, filename
, overwrite
):
1412 """creates a new VNFD/VNFpkg
1414 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1417 vnfd_create(ctx
, filename
, overwrite
)
1420 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1421 @click.argument('filename')
1422 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1423 help='Deprecated. Use override')
1424 @click.option('--override', 'overwrite', default
=None,
1425 help='overrides fields in descriptor, format: '
1426 '"key1.key2...=value[;key3...=value;...]"')
1428 def nfpkg_create(ctx
, filename
, overwrite
):
1429 """creates a new NFpkg
1431 FILENAME: NF Descriptor yaml file or NFpkg tar.gz file
1434 vnfd_create(ctx
, filename
, overwrite
)
1437 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1438 @click.option('--ns_name',
1439 prompt
=True, help='name of the NS instance')
1440 @click.option('--nsd_name',
1441 prompt
=True, help='name of the NS descriptor')
1442 @click.option('--vim_account',
1443 prompt
=True, help='default VIM account id or name for the deployment')
1444 @click.option('--admin_status',
1446 help='administration status')
1447 @click.option('--ssh_keys',
1449 help='comma separated list of public key files to inject to vnfs')
1450 @click.option('--config',
1452 help='ns specific yaml configuration')
1453 @click.option('--config_file',
1455 help='ns specific yaml configuration file')
1456 @click.option('--wait',
1460 help='do not return the control immediately, but keep it '
1461 'until the operation is completed, or timeout')
1472 """creates a new NS instance"""
1476 check_client_version(ctx
.obj
, '--config_file')
1478 raise ClientException('"--config" option is incompatible with "--config_file" option')
1479 with
open(config_file
, 'r') as cf
:
1486 account
=vim_account
,
1488 # except ClientException as e:
1493 def nst_create(ctx
, filename
, overwrite
):
1496 check_client_version(ctx
.obj
, ctx
.command
.name
)
1497 ctx
.obj
.nst
.create(filename
, overwrite
)
1498 # except ClientException as e:
1503 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1504 @click.argument('filename')
1505 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1506 help='Deprecated. Use override')
1507 @click.option('--override', 'overwrite', default
=None,
1508 help='overrides fields in descriptor, format: '
1509 '"key1.key2...=value[;key3...=value;...]"')
1511 def nst_create1(ctx
, filename
, overwrite
):
1512 """creates a new Network Slice Template (NST)
1514 FILENAME: NST yaml file or NSTpkg tar.gz file
1517 nst_create(ctx
, filename
, overwrite
)
1520 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1521 @click.argument('filename')
1522 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1523 help='Deprecated. Use override')
1524 @click.option('--override', 'overwrite', default
=None,
1525 help='overrides fields in descriptor, format: '
1526 '"key1.key2...=value[;key3...=value;...]"')
1528 def nst_create2(ctx
, filename
, overwrite
):
1529 """creates a new Network Slice Template (NST)
1531 FILENAME: NST yaml file or NSTpkg tar.gz file
1534 nst_create(ctx
, filename
, overwrite
)
1537 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1538 """creates a new Network Slice Instance (NSI)"""
1541 check_client_version(ctx
.obj
, ctx
.command
.name
)
1544 raise ClientException('"--config" option is incompatible with "--config_file" option')
1545 with
open(config_file
, 'r') as cf
:
1547 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1548 account
=vim_account
, wait
=wait
)
1549 # except ClientException as e:
1554 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1555 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1556 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1557 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1558 @click.option('--ssh_keys', default
=None,
1559 help='comma separated list of keys to inject to vnfs')
1560 @click.option('--config', default
=None,
1561 help='Netslice specific yaml configuration:\n'
1562 'netslice_subnet: [\n'
1563 'id: TEXT, vim_account: TEXT,\n'
1564 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1565 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1566 'additionalParamsForNsi: {param: value, ...}\n'
1567 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1569 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1571 @click.option('--config_file',
1573 help='nsi specific yaml configuration file')
1574 @click.option('--wait',
1578 help='do not return the control immediately, but keep it '
1579 'until the operation is completed, or timeout')
1581 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1582 """creates a new Network Slice Instance (NSI)"""
1584 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1587 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1588 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1589 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1590 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1591 @click.option('--ssh_keys', default
=None,
1592 help='comma separated list of keys to inject to vnfs')
1593 @click.option('--config', default
=None,
1594 help='Netslice specific yaml configuration:\n'
1595 'netslice_subnet: [\n'
1596 'id: TEXT, vim_account: TEXT,\n'
1597 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1598 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1600 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1602 @click.option('--config_file',
1604 help='nsi specific yaml configuration file')
1605 @click.option('--wait',
1609 help='do not return the control immediately, but keep it '
1610 'until the operation is completed, or timeout')
1612 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1613 """creates a new Network Slice Instance (NSI)"""
1615 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1618 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1619 @click.option('--name', help='name of the Physical Deployment Unit')
1620 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1621 @click.option('--interface',
1622 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1623 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1625 @click.option('--description', help='human readable description')
1626 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
1627 @click.option('--descriptor_file', default
=None,
1628 help='PDU descriptor file (as an alternative to using the other arguments')
1630 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
1631 """creates a new Physical Deployment Unit (PDU)"""
1634 check_client_version(ctx
.obj
, ctx
.command
.name
)
1636 if not descriptor_file
:
1638 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1640 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1642 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1644 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1646 with
open(descriptor_file
, 'r') as df
:
1647 pdu
= yaml
.safe_load(df
.read())
1648 if name
: pdu
["name"] = name
1649 if pdu_type
: pdu
["type"] = pdu_type
1650 if description
: pdu
["description"] = description
1651 if vim_account
: pdu
["vim_accounts"] = vim_account
1654 for iface
in interface
:
1655 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
1656 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
1657 ifaces_list
.append(new_iface
)
1658 pdu
["interfaces"] = ifaces_list
1659 ctx
.obj
.pdu
.create(pdu
)
1660 # except ClientException as e:
1665 ####################
1667 ####################
1669 def nsd_update(ctx
, name
, content
):
1672 check_client_version(ctx
.obj
, ctx
.command
.name
)
1673 ctx
.obj
.nsd
.update(name
, content
)
1674 # except ClientException as e:
1679 @cli_osm.command(name
='nsd-update', short_help
='updates a NSD/NSpkg')
1680 @click.argument('name')
1681 @click.option('--content', default
=None,
1682 help='filename with the NSD/NSpkg replacing the current one')
1684 def nsd_update1(ctx
, name
, content
):
1685 """updates a NSD/NSpkg
1687 NAME: name or ID of the NSD/NSpkg
1690 nsd_update(ctx
, name
, content
)
1693 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
1694 @click.argument('name')
1695 @click.option('--content', default
=None,
1696 help='filename with the NSD/NSpkg replacing the current one')
1698 def nsd_update2(ctx
, name
, content
):
1699 """updates a NSD/NSpkg
1701 NAME: name or ID of the NSD/NSpkg
1704 nsd_update(ctx
, name
, content
)
1707 def vnfd_update(ctx
, name
, content
):
1710 check_client_version(ctx
.obj
, ctx
.command
.name
)
1711 ctx
.obj
.vnfd
.update(name
, content
)
1712 # except ClientException as e:
1717 @cli_osm.command(name
='vnfd-update', short_help
='updates a new VNFD/VNFpkg')
1718 @click.argument('name')
1719 @click.option('--content', default
=None,
1720 help='filename with the VNFD/VNFpkg replacing the current one')
1722 def vnfd_update1(ctx
, name
, content
):
1723 """updates a VNFD/VNFpkg
1725 NAME: name or ID of the VNFD/VNFpkg
1728 vnfd_update(ctx
, name
, content
)
1731 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
1732 @click.argument('name')
1733 @click.option('--content', default
=None,
1734 help='filename with the VNFD/VNFpkg replacing the current one')
1736 def vnfd_update2(ctx
, name
, content
):
1737 """updates a VNFD/VNFpkg
1739 NAME: VNFD yaml file or VNFpkg tar.gz file
1742 vnfd_update(ctx
, name
, content
)
1745 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
1746 @click.argument('name')
1747 @click.option('--content', default
=None,
1748 help='filename with the NFpkg replacing the current one')
1750 def nfpkg_update(ctx
, name
, content
):
1753 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1756 vnfd_update(ctx
, name
, content
)
1759 def nst_update(ctx
, name
, content
):
1762 check_client_version(ctx
.obj
, ctx
.command
.name
)
1763 ctx
.obj
.nst
.update(name
, content
)
1764 # except ClientException as e:
1769 @cli_osm.command(name
='nst-update', short_help
='updates a Network Slice Template (NST)')
1770 @click.argument('name')
1771 @click.option('--content', default
=None,
1772 help='filename with the NST/NSTpkg replacing the current one')
1774 def nst_update1(ctx
, name
, content
):
1775 """updates a Network Slice Template (NST)
1777 NAME: name or ID of the NSD/NSpkg
1780 nst_update(ctx
, name
, content
)
1783 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
1784 @click.argument('name')
1785 @click.option('--content', default
=None,
1786 help='filename with the NST/NSTpkg replacing the current one')
1788 def nst_update2(ctx
, name
, content
):
1789 """updates a Network Slice Template (NST)
1791 NAME: name or ID of the NSD/NSpkg
1794 nst_update(ctx
, name
, content
)
1797 ####################
1799 ####################
1801 def nsd_delete(ctx
, name
, force
):
1805 ctx
.obj
.nsd
.delete(name
)
1807 check_client_version(ctx
.obj
, '--force')
1808 ctx
.obj
.nsd
.delete(name
, force
)
1809 # except ClientException as e:
1814 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
1815 @click.argument('name')
1816 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1818 def nsd_delete1(ctx
, name
, force
):
1819 """deletes a NSD/NSpkg
1821 NAME: name or ID of the NSD/NSpkg to be deleted
1824 nsd_delete(ctx
, name
, force
)
1827 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
1828 @click.argument('name')
1829 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1831 def nsd_delete2(ctx
, name
, force
):
1832 """deletes a NSD/NSpkg
1834 NAME: name or ID of the NSD/NSpkg to be deleted
1837 nsd_delete(ctx
, name
, force
)
1840 def vnfd_delete(ctx
, name
, force
):
1844 ctx
.obj
.vnfd
.delete(name
)
1846 check_client_version(ctx
.obj
, '--force')
1847 ctx
.obj
.vnfd
.delete(name
, force
)
1848 # except ClientException as e:
1853 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
1854 @click.argument('name')
1855 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1857 def vnfd_delete1(ctx
, name
, force
):
1858 """deletes a VNFD/VNFpkg
1860 NAME: name or ID of the VNFD/VNFpkg to be deleted
1863 vnfd_delete(ctx
, name
, force
)
1866 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
1867 @click.argument('name')
1868 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1870 def vnfd_delete2(ctx
, name
, force
):
1871 """deletes a VNFD/VNFpkg
1873 NAME: name or ID of the VNFD/VNFpkg to be deleted
1876 vnfd_delete(ctx
, name
, force
)
1879 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
1880 @click.argument('name')
1881 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1883 def nfpkg_delete(ctx
, name
, force
):
1886 NAME: name or ID of the NFpkg to be deleted
1889 vnfd_delete(ctx
, name
, force
)
1892 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
1893 @click.argument('name')
1894 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1895 @click.option('--wait',
1899 help='do not return the control immediately, but keep it '
1900 'until the operation is completed, or timeout')
1902 def ns_delete(ctx
, name
, force
, wait
):
1903 """deletes a NS instance
1905 NAME: name or ID of the NS instance to be deleted
1910 ctx
.obj
.ns
.delete(name
, wait
=wait
)
1912 check_client_version(ctx
.obj
, '--force')
1913 ctx
.obj
.ns
.delete(name
, force
, wait
=wait
)
1914 # except ClientException as e:
1919 def nst_delete(ctx
, name
, force
):
1922 check_client_version(ctx
.obj
, ctx
.command
.name
)
1923 ctx
.obj
.nst
.delete(name
, force
)
1924 # except ClientException as e:
1929 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
1930 @click.argument('name')
1931 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1933 def nst_delete1(ctx
, name
, force
):
1934 """deletes a Network Slice Template (NST)
1936 NAME: name or ID of the NST/NSTpkg to be deleted
1939 nst_delete(ctx
, name
, force
)
1942 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
1943 @click.argument('name')
1944 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1946 def nst_delete2(ctx
, name
, force
):
1947 """deletes a Network Slice Template (NST)
1949 NAME: name or ID of the NST/NSTpkg to be deleted
1952 nst_delete(ctx
, name
, force
)
1955 def nsi_delete(ctx
, name
, force
, wait
):
1958 check_client_version(ctx
.obj
, ctx
.command
.name
)
1959 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
1960 # except ClientException as e:
1965 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
1966 @click.argument('name')
1967 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1968 @click.option('--wait',
1972 help='do not return the control immediately, but keep it '
1973 'until the operation is completed, or timeout')
1975 def nsi_delete1(ctx
, name
, force
, wait
):
1976 """deletes a Network Slice Instance (NSI)
1978 NAME: name or ID of the Network Slice instance to be deleted
1981 nsi_delete(ctx
, name
, force
, wait
=wait
)
1984 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
1985 @click.argument('name')
1986 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1988 def nsi_delete2(ctx
, name
, force
, wait
):
1989 """deletes a Network Slice Instance (NSI)
1991 NAME: name or ID of the Network Slice instance to be deleted
1994 nsi_delete(ctx
, name
, force
, wait
=wait
)
1997 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
1998 @click.argument('name')
1999 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2001 def pdu_delete(ctx
, name
, force
):
2002 """deletes a Physical Deployment Unit (PDU)
2004 NAME: name or ID of the PDU to be deleted
2008 check_client_version(ctx
.obj
, ctx
.command
.name
)
2009 ctx
.obj
.pdu
.delete(name
, force
)
2010 # except ClientException as e:
2019 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2020 @click.option('--name',
2022 help='Name to create datacenter')
2023 @click.option('--user',
2025 help='VIM username')
2026 @click.option('--password',
2029 confirmation_prompt
=True,
2030 help='VIM password')
2031 @click.option('--auth_url',
2034 @click.option('--tenant',
2036 help='VIM tenant name')
2037 @click.option('--config',
2039 help='VIM specific config parameters')
2040 @click.option('--account_type',
2041 default
='openstack',
2043 @click.option('--description',
2044 default
='no description',
2045 help='human readable description')
2046 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2047 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2048 @click.option('--wait',
2052 help='do not return the control immediately, but keep it '
2053 'until the operation is completed, or timeout')
2067 """creates a new VIM account"""
2071 check_client_version(ctx
.obj
, '--sdn_controller')
2072 if sdn_port_mapping
:
2073 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2075 vim
['vim-username'] = user
2076 vim
['vim-password'] = password
2077 vim
['vim-url'] = auth_url
2078 vim
['vim-tenant-name'] = tenant
2079 vim
['vim-type'] = account_type
2080 vim
['description'] = description
2081 vim
['config'] = config
2082 if sdn_controller
or sdn_port_mapping
:
2083 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2085 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2086 # except ClientException as e:
2091 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2092 @click.argument('name')
2093 @click.option('--newname', help='New name for the VIM account')
2094 @click.option('--user', help='VIM username')
2095 @click.option('--password', help='VIM password')
2096 @click.option('--auth_url', help='VIM url')
2097 @click.option('--tenant', help='VIM tenant name')
2098 @click.option('--config', help='VIM specific config parameters')
2099 @click.option('--account_type', help='VIM type')
2100 @click.option('--description', help='human readable description')
2101 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2102 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2103 @click.option('--wait',
2107 help='do not return the control immediately, but keep it '
2108 'until the operation is completed, or timeout')
2123 """updates a VIM account
2125 NAME: name or ID of the VIM account
2129 check_client_version(ctx
.obj
, ctx
.command
.name
)
2131 if newname
: vim
['name'] = newname
2132 if user
: vim
['vim_user'] = user
2133 if password
: vim
['vim_password'] = password
2134 if auth_url
: vim
['vim_url'] = auth_url
2135 if tenant
: vim
['vim-tenant-name'] = tenant
2136 if account_type
: vim
['vim_type'] = account_type
2137 if description
: vim
['description'] = description
2138 if config
: vim
['config'] = config
2139 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2140 # except ClientException as e:
2145 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2146 @click.argument('name')
2147 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2148 @click.option('--wait',
2152 help='do not return the control immediately, but keep it '
2153 'until the operation is completed, or timeout')
2155 def vim_delete(ctx
, name
, force
, wait
):
2156 """deletes a VIM account
2158 NAME: name or ID of the VIM account to be deleted
2163 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2165 check_client_version(ctx
.obj
, '--force')
2166 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2167 # except ClientException as e:
2172 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2173 #@click.option('--ro_update/--no_ro_update',
2175 # help='update list from RO')
2176 @click.option('--filter', default
=None,
2177 help='restricts the list to the VIM accounts matching the filter')
2179 def vim_list(ctx
, filter):
2180 """list all VIM accounts"""
2183 check_client_version(ctx
.obj
, '--filter')
2185 # check_client_version(ctx.obj, '--ro_update', 'v1')
2186 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2187 if fullclassname
== 'osmclient.sol005.client.Client':
2188 resp
= ctx
.obj
.vim
.list(filter)
2190 # resp = ctx.obj.vim.list(ro_update)
2191 table
= PrettyTable(['vim name', 'uuid'])
2193 table
.add_row([vim
['name'], vim
['uuid']])
2198 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2199 @click.argument('name')
2201 def vim_show(ctx
, name
):
2202 """shows the details of a VIM account
2204 NAME: name or ID of the VIM account
2208 resp
= ctx
.obj
.vim
.get(name
)
2209 if 'vim_password' in resp
:
2210 resp
['vim_password']='********'
2211 # except ClientException as e:
2215 table
= PrettyTable(['key', 'attribute'])
2216 for k
, v
in list(resp
.items()):
2217 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2222 ####################
2224 ####################
2226 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2227 @click.option('--name',
2229 help='Name for the WIM account')
2230 @click.option('--user',
2231 help='WIM username')
2232 @click.option('--password',
2233 help='WIM password')
2234 @click.option('--url',
2237 # @click.option('--tenant',
2238 # help='wIM tenant name')
2239 @click.option('--config',
2241 help='WIM specific config parameters')
2242 @click.option('--wim_type',
2244 @click.option('--description',
2245 default
='no description',
2246 help='human readable description')
2247 @click.option('--wim_port_mapping', default
=None,
2248 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2249 "(WAN service endpoint id and info)")
2250 @click.option('--wait',
2254 help='do not return the control immediately, but keep it '
2255 'until the operation is completed, or timeout')
2268 """creates a new WIM account"""
2271 check_client_version(ctx
.obj
, ctx
.command
.name
)
2272 # if sdn_controller:
2273 # check_client_version(ctx.obj, '--sdn_controller')
2274 # if sdn_port_mapping:
2275 # check_client_version(ctx.obj, '--sdn_port_mapping')
2277 if user
: wim
['user'] = user
2278 if password
: wim
['password'] = password
2279 if url
: wim
['wim_url'] = url
2280 # if tenant: wim['tenant'] = tenant
2281 wim
['wim_type'] = wim_type
2282 if description
: wim
['description'] = description
2283 if config
: wim
['config'] = config
2284 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2285 # except ClientException as e:
2290 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2291 @click.argument('name')
2292 @click.option('--newname', help='New name for the WIM account')
2293 @click.option('--user', help='WIM username')
2294 @click.option('--password', help='WIM password')
2295 @click.option('--url', help='WIM url')
2296 @click.option('--config', help='WIM specific config parameters')
2297 @click.option('--wim_type', help='WIM type')
2298 @click.option('--description', help='human readable description')
2299 @click.option('--wim_port_mapping', default
=None,
2300 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2301 "(WAN service endpoint id and info)")
2302 @click.option('--wait',
2306 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2319 """updates a WIM account
2321 NAME: name or ID of the WIM account
2325 check_client_version(ctx
.obj
, ctx
.command
.name
)
2327 if newname
: wim
['name'] = newname
2328 if user
: wim
['user'] = user
2329 if password
: wim
['password'] = password
2330 if url
: wim
['url'] = url
2331 # if tenant: wim['tenant'] = tenant
2332 if wim_type
: wim
['wim_type'] = wim_type
2333 if description
: wim
['description'] = description
2334 if config
: wim
['config'] = config
2335 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2336 # except ClientException as e:
2341 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2342 @click.argument('name')
2343 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2344 @click.option('--wait',
2348 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2350 def wim_delete(ctx
, name
, force
, wait
):
2351 """deletes a WIM account
2353 NAME: name or ID of the WIM account to be deleted
2357 check_client_version(ctx
.obj
, ctx
.command
.name
)
2358 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2359 # except ClientException as e:
2364 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2365 @click.option('--filter', default
=None,
2366 help='restricts the list to the WIM accounts matching the filter')
2368 def wim_list(ctx
, filter):
2369 """list all WIM accounts"""
2372 check_client_version(ctx
.obj
, ctx
.command
.name
)
2373 resp
= ctx
.obj
.wim
.list(filter)
2374 table
= PrettyTable(['wim name', 'uuid'])
2376 table
.add_row([wim
['name'], wim
['uuid']])
2379 # except ClientException as e:
2384 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2385 @click.argument('name')
2387 def wim_show(ctx
, name
):
2388 """shows the details of a WIM account
2390 NAME: name or ID of the WIM account
2394 check_client_version(ctx
.obj
, ctx
.command
.name
)
2395 resp
= ctx
.obj
.wim
.get(name
)
2396 if 'password' in resp
:
2397 resp
['wim_password']='********'
2398 # except ClientException as e:
2402 table
= PrettyTable(['key', 'attribute'])
2403 for k
, v
in list(resp
.items()):
2404 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2409 ####################
2410 # SDN controller operations
2411 ####################
2413 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2414 @click.option('--name',
2416 help='Name to create sdn controller')
2417 @click.option('--type',
2419 help='SDN controller type')
2420 @click.option('--sdn_controller_version', # hidden=True,
2421 help='Deprecated. Use --config {version: sdn_controller_version}')
2422 @click.option('--url',
2423 help='URL in format http[s]://HOST:IP/')
2424 @click.option('--ip_address', # hidden=True,
2425 help='Deprecated. Use --url')
2426 @click.option('--port', # hidden=True,
2427 help='Deprecated. Use --url')
2428 @click.option('--switch_dpid', # hidden=True,
2429 help='Deprecated. Use --config {dpid: DPID}')
2430 @click.option('--config',
2431 help='Extra information for SDN in yaml format, as {dpid: (Openflow Datapath ID), version: version}')
2432 @click.option('--user',
2433 help='SDN controller username')
2434 @click.option('--password',
2436 confirmation_prompt
=True,
2437 help='SDN controller password')
2438 @click.option('--description', default
=None, help='human readable description')
2439 @click.option('--wait',
2443 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2445 def sdnc_create(ctx
, **kwargs
):
2446 """creates a new SDN controller"""
2448 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2449 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2450 if kwargs
.get("port"):
2451 print("option '--port' is deprecated, use '-url' instead")
2452 sdncontroller
["port"] = int(kwargs
["port"])
2453 if kwargs
.get("ip_address"):
2454 print("option '--ip_address' is deprecated, use '-url' instead")
2455 sdncontroller
["ip"] = kwargs
["ip_address"]
2456 if kwargs
.get("switch_dpid"):
2457 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2458 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2459 if kwargs
.get("sdn_controller_version"):
2460 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2463 check_client_version(ctx
.obj
, ctx
.command
.name
)
2464 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2465 # except ClientException as e:
2469 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2470 @click.argument('name')
2471 @click.option('--newname', help='New name for the SDN controller')
2472 @click.option('--description', default
=None, help='human readable description')
2473 @click.option('--type', help='SDN controller type')
2474 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2475 @click.option('--config', help='Extra information for SDN in yaml format, as '
2476 '{dpid: (Openflow Datapath ID), version: version}')
2477 @click.option('--user', help='SDN controller username')
2478 @click.option('--password', help='SDN controller password')
2479 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2480 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2481 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2482 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2483 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2484 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2486 def sdnc_update(ctx
, **kwargs
):
2487 """updates an SDN controller
2489 NAME: name or ID of the SDN controller
2492 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2493 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2494 if kwargs
.get("newname"):
2495 sdncontroller
["name"] = kwargs
["newname"]
2496 if kwargs
.get("port"):
2497 print("option '--port' is deprecated, use '-url' instead")
2498 sdncontroller
["port"] = int(kwargs
["port"])
2499 if kwargs
.get("ip_address"):
2500 print("option '--ip_address' is deprecated, use '-url' instead")
2501 sdncontroller
["ip"] = kwargs
["ip_address"]
2502 if kwargs
.get("switch_dpid"):
2503 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2504 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2505 if kwargs
.get("sdn_controller_version"):
2506 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2510 check_client_version(ctx
.obj
, ctx
.command
.name
)
2511 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2512 # except ClientException as e:
2517 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2518 @click.argument('name')
2519 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2520 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2521 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2523 def sdnc_delete(ctx
, name
, force
, wait
):
2524 """deletes an SDN controller
2526 NAME: name or ID of the SDN controller to be deleted
2530 check_client_version(ctx
.obj
, ctx
.command
.name
)
2531 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2532 # except ClientException as e:
2537 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2538 @click.option('--filter', default
=None,
2539 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2541 def sdnc_list(ctx
, filter):
2542 """list all SDN controllers"""
2545 check_client_version(ctx
.obj
, ctx
.command
.name
)
2546 resp
= ctx
.obj
.sdnc
.list(filter)
2547 # except ClientException as e:
2550 table
= PrettyTable(['sdnc name', 'id'])
2552 table
.add_row([sdnc
['name'], sdnc
['_id']])
2557 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2558 @click.argument('name')
2560 def sdnc_show(ctx
, name
):
2561 """shows the details of an SDN controller
2563 NAME: name or ID of the SDN controller
2567 check_client_version(ctx
.obj
, ctx
.command
.name
)
2568 resp
= ctx
.obj
.sdnc
.get(name
)
2569 # except ClientException as e:
2573 table
= PrettyTable(['key', 'attribute'])
2574 for k
, v
in list(resp
.items()):
2575 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2580 ###########################
2581 # K8s cluster operations
2582 ###########################
2584 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2585 @click.argument('name')
2586 @click.option('--creds',
2588 help='credentials file, i.e. a valid `.kube/config` file')
2589 @click.option('--version',
2591 help='Kubernetes version')
2592 @click.option('--vim',
2594 help='VIM target, the VIM where the cluster resides')
2595 @click.option('--k8s-nets',
2597 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) ...]}"')
2598 @click.option('--description',
2600 help='human readable description')
2601 @click.option('--namespace',
2602 default
='kube-system',
2603 help='namespace to be used for its operation, defaults to `kube-system`')
2604 @click.option('--cni',
2606 help='list of CNI plugins, in JSON inline format, used in the cluster')
2607 #@click.option('--skip-init',
2609 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2610 #@click.option('--wait',
2612 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2614 def k8scluster_add(ctx
,
2623 """adds a K8s cluster to OSM
2625 NAME: name of the K8s cluster
2628 check_client_version(ctx
.obj
, ctx
.command
.name
)
2630 cluster
['name'] = name
2631 with
open(creds
, 'r') as cf
:
2632 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2633 cluster
['k8s_version'] = version
2634 cluster
['vim_account'] = vim
2635 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2636 cluster
['description'] = description
2637 if namespace
: cluster
['namespace'] = namespace
2638 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2639 ctx
.obj
.k8scluster
.create(name
, cluster
)
2640 # except ClientException as e:
2645 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
2646 @click.argument('name')
2647 @click.option('--newname', help='New name for the K8s cluster')
2648 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
2649 @click.option('--version', help='Kubernetes version')
2650 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
2651 @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) ...]}"')
2652 @click.option('--description', help='human readable description')
2653 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
2654 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
2656 def k8scluster_update(ctx
,
2666 """updates a K8s cluster
2668 NAME: name or ID of the K8s cluster
2671 check_client_version(ctx
.obj
, ctx
.command
.name
)
2673 if newname
: cluster
['name'] = newname
2675 with
open(creds
, 'r') as cf
:
2676 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2677 if version
: cluster
['k8s_version'] = version
2678 if vim
: cluster
['vim_account'] = vim
2679 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2680 if description
: cluster
['description'] = description
2681 if namespace
: cluster
['namespace'] = namespace
2682 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2683 ctx
.obj
.k8scluster
.update(name
, cluster
)
2684 # except ClientException as e:
2689 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
2690 @click.argument('name')
2691 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2692 #@click.option('--wait',
2694 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2696 def k8scluster_delete(ctx
, name
, force
):
2697 """deletes a K8s cluster
2699 NAME: name or ID of the K8s cluster to be deleted
2702 check_client_version(ctx
.obj
, ctx
.command
.name
)
2703 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
2704 # except ClientException as e:
2709 @cli_osm.command(name
='k8scluster-list')
2710 @click.option('--filter', default
=None,
2711 help='restricts the list to the K8s clusters matching the filter')
2712 @click.option('--literal', is_flag
=True,
2713 help='print literally, no pretty table')
2715 def k8scluster_list(ctx
, filter, literal
):
2716 """list all K8s clusters"""
2718 check_client_version(ctx
.obj
, ctx
.command
.name
)
2719 resp
= ctx
.obj
.k8scluster
.list(filter)
2721 print(yaml
.safe_dump(resp
))
2723 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
2724 for cluster
in resp
:
2725 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
2726 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
2727 trunc_text(cluster
.get('description',''),40)])
2730 # except ClientException as e:
2735 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
2736 @click.argument('name')
2737 @click.option('--literal', is_flag
=True,
2738 help='print literally, no pretty table')
2740 def k8scluster_show(ctx
, name
, literal
):
2741 """shows the details of a K8s cluster
2743 NAME: name or ID of the K8s cluster
2746 resp
= ctx
.obj
.k8scluster
.get(name
)
2748 print(yaml
.safe_dump(resp
))
2750 table
= PrettyTable(['key', 'attribute'])
2751 for k
, v
in list(resp
.items()):
2752 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2755 # except ClientException as e:
2761 ###########################
2763 ###########################
2765 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
2766 @click.argument('name')
2767 @click.argument('uri')
2768 @click.option('--type',
2769 type=click
.Choice(['helm-chart', 'juju-bundle']),
2771 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2772 @click.option('--description',
2774 help='human readable description')
2775 #@click.option('--wait',
2777 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2784 """adds a repo to OSM
2786 NAME: name of the repo
2787 URI: URI of the repo
2790 check_client_version(ctx
.obj
, ctx
.command
.name
)
2795 repo
['description'] = description
2796 ctx
.obj
.repo
.create(name
, repo
)
2797 # except ClientException as e:
2802 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
2803 @click.argument('name')
2804 @click.option('--newname', help='New name for the repo')
2805 @click.option('--uri', help='URI of the repo')
2806 @click.option('--type', type=click
.Choice(['helm-chart', 'juju-bundle']),
2807 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2808 @click.option('--description', help='human readable description')
2809 #@click.option('--wait',
2811 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2813 def repo_update(ctx
,
2819 """updates a repo in OSM
2821 NAME: name of the repo
2824 check_client_version(ctx
.obj
, ctx
.command
.name
)
2826 if newname
: repo
['name'] = newname
2827 if uri
: repo
['uri'] = uri
2828 if type: repo
['type'] = type
2829 if description
: repo
['description'] = description
2830 ctx
.obj
.repo
.update(name
, repo
)
2831 # except ClientException as e:
2836 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
2837 @click.argument('name')
2838 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2839 #@click.option('--wait',
2841 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2843 def repo_delete(ctx
, name
, force
):
2846 NAME: name or ID of the repo to be deleted
2849 check_client_version(ctx
.obj
, ctx
.command
.name
)
2850 ctx
.obj
.repo
.delete(name
, force
=force
)
2851 # except ClientException as e:
2856 @cli_osm.command(name
='repo-list')
2857 @click.option('--filter', default
=None,
2858 help='restricts the list to the repos matching the filter')
2859 @click.option('--literal', is_flag
=True,
2860 help='print literally, no pretty table')
2862 def repo_list(ctx
, filter, literal
):
2863 """list all repos"""
2865 check_client_version(ctx
.obj
, ctx
.command
.name
)
2866 resp
= ctx
.obj
.repo
.list(filter)
2868 print(yaml
.safe_dump(resp
))
2870 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
2872 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
2873 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description',''),40)])
2876 # except ClientException as e:
2881 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
2882 @click.argument('name')
2883 @click.option('--literal', is_flag
=True,
2884 help='print literally, no pretty table')
2886 def repo_show(ctx
, name
, literal
):
2887 """shows the details of a repo
2889 NAME: name or ID of the repo
2892 resp
= ctx
.obj
.repo
.get(name
)
2894 print(yaml
.safe_dump(resp
))
2896 table
= PrettyTable(['key', 'attribute'])
2897 for k
, v
in list(resp
.items()):
2898 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2901 # except ClientException as e:
2907 ####################
2908 # Project mgmt operations
2909 ####################
2911 @cli_osm.command(name
='project-create', short_help
='creates a new project')
2912 @click.argument('name')
2913 #@click.option('--description',
2914 # default='no description',
2915 # help='human readable description')
2917 def project_create(ctx
, name
):
2918 """Creates a new project
2920 NAME: name of the project
2924 project
['name'] = name
2926 check_client_version(ctx
.obj
, ctx
.command
.name
)
2927 ctx
.obj
.project
.create(name
, project
)
2928 # except ClientException as e:
2933 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
2934 @click.argument('name')
2935 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2937 def project_delete(ctx
, name
):
2938 """deletes a project
2940 NAME: name or ID of the project to be deleted
2944 check_client_version(ctx
.obj
, ctx
.command
.name
)
2945 ctx
.obj
.project
.delete(name
)
2946 # except ClientException as e:
2951 @cli_osm.command(name
='project-list', short_help
='list all projects')
2952 @click.option('--filter', default
=None,
2953 help='restricts the list to the projects matching the filter')
2955 def project_list(ctx
, filter):
2956 """list all projects"""
2959 check_client_version(ctx
.obj
, ctx
.command
.name
)
2960 resp
= ctx
.obj
.project
.list(filter)
2961 # except ClientException as e:
2964 table
= PrettyTable(['name', 'id'])
2966 table
.add_row([proj
['name'], proj
['_id']])
2971 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
2972 @click.argument('name')
2974 def project_show(ctx
, name
):
2975 """shows the details of a project
2977 NAME: name or ID of the project
2981 check_client_version(ctx
.obj
, ctx
.command
.name
)
2982 resp
= ctx
.obj
.project
.get(name
)
2983 # except ClientException as e:
2987 table
= PrettyTable(['key', 'attribute'])
2988 for k
, v
in resp
.items():
2989 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2994 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
2995 @click.argument('project')
2996 @click.option('--name',
2998 help='new name for the project')
3001 def project_update(ctx
, project
, name
):
3003 Update a project name
3006 :param project: id or name of the project to modify
3007 :param name: new name for the project
3011 project_changes
= {}
3012 project_changes
['name'] = name
3015 check_client_version(ctx
.obj
, ctx
.command
.name
)
3016 ctx
.obj
.project
.update(project
, project_changes
)
3017 # except ClientException as e:
3021 ####################
3022 # User mgmt operations
3023 ####################
3025 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3026 @click.argument('username')
3027 @click.option('--password',
3030 confirmation_prompt
=True,
3031 help='user password')
3032 @click.option('--projects',
3033 # prompt="Comma separate list of projects",
3035 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3036 help='list of project ids that the user belongs to')
3037 @click.option('--project-role-mappings', 'project_role_mappings',
3038 default
=None, multiple
=True,
3039 help='creating user project/role(s) mapping')
3041 def user_create(ctx
, username
, password
, projects
, project_role_mappings
):
3042 """Creates a new user
3045 USERNAME: name of the user
3046 PASSWORD: password of the user
3047 PROJECTS: projects assigned to user (internal only)
3048 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3052 user
['username'] = username
3053 user
['password'] = password
3054 user
['projects'] = projects
3055 user
['project_role_mappings'] = project_role_mappings
3058 check_client_version(ctx
.obj
, ctx
.command
.name
)
3059 ctx
.obj
.user
.create(username
, user
)
3060 # except ClientException as e:
3065 @cli_osm.command(name
='user-update', short_help
='updates user information')
3066 @click.argument('username')
3067 @click.option('--password',
3070 # confirmation_prompt=True,
3071 help='user password')
3072 @click.option('--set-username', 'set_username',
3074 help='change username')
3075 @click.option('--set-project', 'set_project',
3076 default
=None, multiple
=True,
3077 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
3078 @click.option('--remove-project', 'remove_project',
3079 default
=None, multiple
=True,
3080 help='removes project from user: \'project\'')
3081 @click.option('--add-project-role', 'add_project_role',
3082 default
=None, multiple
=True,
3083 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
3084 @click.option('--remove-project-role', 'remove_project_role',
3085 default
=None, multiple
=True,
3086 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
3088 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3089 add_project_role
, remove_project_role
):
3090 """Update a user information
3093 USERNAME: name of the user
3094 PASSWORD: new password
3095 SET_USERNAME: new username
3096 SET_PROJECT: creating mappings for project/role(s)
3097 REMOVE_PROJECT: deleting mappings for project/role(s)
3098 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3099 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3103 user
['password'] = password
3104 user
['username'] = set_username
3105 user
['set-project'] = set_project
3106 user
['remove-project'] = remove_project
3107 user
['add-project-role'] = add_project_role
3108 user
['remove-project-role'] = remove_project_role
3111 check_client_version(ctx
.obj
, ctx
.command
.name
)
3112 ctx
.obj
.user
.update(username
, user
)
3113 # except ClientException as e:
3118 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3119 @click.argument('name')
3120 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3122 def user_delete(ctx
, name
):
3126 NAME: name or ID of the user to be deleted
3130 check_client_version(ctx
.obj
, ctx
.command
.name
)
3131 ctx
.obj
.user
.delete(name
)
3132 # except ClientException as e:
3137 @cli_osm.command(name
='user-list', short_help
='list all users')
3138 @click.option('--filter', default
=None,
3139 help='restricts the list to the users matching the filter')
3141 def user_list(ctx
, filter):
3142 """list all users"""
3144 check_client_version(ctx
.obj
, ctx
.command
.name
)
3145 resp
= ctx
.obj
.user
.list(filter)
3146 # except ClientException as e:
3149 table
= PrettyTable(['name', 'id'])
3151 table
.add_row([user
['username'], user
['_id']])
3156 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3157 @click.argument('name')
3159 def user_show(ctx
, name
):
3160 """shows the details of a user
3162 NAME: name or ID of the user
3166 check_client_version(ctx
.obj
, ctx
.command
.name
)
3167 resp
= ctx
.obj
.user
.get(name
)
3168 if 'password' in resp
:
3169 resp
['password']='********'
3170 # except ClientException as e:
3174 table
= PrettyTable(['key', 'attribute'])
3175 for k
, v
in resp
.items():
3176 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3181 ####################
3182 # Fault Management operations
3183 ####################
3185 @cli_osm.command(name
='ns-alarm-create')
3186 @click.argument('name')
3187 @click.option('--ns', prompt
=True, help='NS instance id or name')
3188 @click.option('--vnf', prompt
=True,
3189 help='VNF name (VNF member index as declared in the NSD)')
3190 @click.option('--vdu', prompt
=True,
3191 help='VDU name (VDU name as declared in the VNFD)')
3192 @click.option('--metric', prompt
=True,
3193 help='Name of the metric (e.g. cpu_utilization)')
3194 @click.option('--severity', default
='WARNING',
3195 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3196 @click.option('--threshold_value', prompt
=True,
3197 help='threshold value that, when crossed, an alarm is triggered')
3198 @click.option('--threshold_operator', prompt
=True,
3199 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3200 @click.option('--statistic', default
='AVERAGE',
3201 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3203 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3204 threshold_value
, threshold_operator
, statistic
):
3205 """creates a new alarm for a NS instance"""
3206 # TODO: Check how to validate threshold_value.
3207 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3210 ns_instance
= ctx
.obj
.ns
.get(ns
)
3212 alarm
['alarm_name'] = name
3213 alarm
['ns_id'] = ns_instance
['_id']
3214 alarm
['correlation_id'] = ns_instance
['_id']
3215 alarm
['vnf_member_index'] = vnf
3216 alarm
['vdu_name'] = vdu
3217 alarm
['metric_name'] = metric
3218 alarm
['severity'] = severity
3219 alarm
['threshold_value'] = int(threshold_value
)
3220 alarm
['operation'] = threshold_operator
3221 alarm
['statistic'] = statistic
3222 check_client_version(ctx
.obj
, ctx
.command
.name
)
3223 ctx
.obj
.ns
.create_alarm(alarm
)
3224 # except ClientException as e:
3229 #@cli_osm.command(name='ns-alarm-delete')
3230 #@click.argument('name')
3231 #@click.pass_context
3232 #def ns_alarm_delete(ctx, name):
3233 # """deletes an alarm
3235 # NAME: name of the alarm to be deleted
3238 # check_client_version(ctx.obj, ctx.command.name)
3239 # ctx.obj.ns.delete_alarm(name)
3240 # except ClientException as e:
3245 ####################
3246 # Performance Management operations
3247 ####################
3249 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3250 @click.option('--ns', prompt
=True, help='NS instance id or name')
3251 @click.option('--vnf', prompt
=True,
3252 help='VNF name (VNF member index as declared in the NSD)')
3253 @click.option('--vdu', prompt
=True,
3254 help='VDU name (VDU name as declared in the VNFD)')
3255 @click.option('--metric', prompt
=True,
3256 help='name of the metric (e.g. cpu_utilization)')
3257 #@click.option('--period', default='1w',
3258 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3259 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3261 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3262 """exports a metric to the internal OSM bus, which can be read by other apps"""
3263 # TODO: Check how to validate interval.
3264 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3267 ns_instance
= ctx
.obj
.ns
.get(ns
)
3269 metric_data
['ns_id'] = ns_instance
['_id']
3270 metric_data
['correlation_id'] = ns_instance
['_id']
3271 metric_data
['vnf_member_index'] = vnf
3272 metric_data
['vdu_name'] = vdu
3273 metric_data
['metric_name'] = metric
3274 metric_data
['collection_unit'] = 'WEEK'
3275 metric_data
['collection_period'] = 1
3276 check_client_version(ctx
.obj
, ctx
.command
.name
)
3278 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3282 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3283 time
.sleep(int(interval
))
3285 # except ClientException as e:
3290 ####################
3292 ####################
3294 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3296 def get_version(ctx
):
3297 """shows client and server versions"""
3299 check_client_version(ctx
.obj
, "version")
3300 print ("Server version: {}".format(ctx
.obj
.get_version()))
3301 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3302 # except ClientException as e:
3306 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3307 @click.argument('filename')
3309 def upload_package(ctx
, filename
):
3310 """uploads a VNF package or NS package
3312 FILENAME: VNF or NS package file (tar.gz)
3316 ctx
.obj
.package
.upload(filename
)
3317 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3318 if fullclassname
!= 'osmclient.sol005.client.Client':
3319 ctx
.obj
.package
.wait_for_upload(filename
)
3320 # except ClientException as e:
3325 #@cli_osm.command(name='ns-scaling-show')
3326 #@click.argument('ns_name')
3327 #@click.pass_context
3328 #def show_ns_scaling(ctx, ns_name):
3329 # """shows the status of a NS scaling operation
3331 # NS_NAME: name of the NS instance being scaled
3334 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3335 # resp = ctx.obj.ns.list()
3336 # except ClientException as e:
3340 # table = PrettyTable(
3343 # 'operational status',
3348 # if ns_name == ns['name']:
3349 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3350 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3351 # for record in scaling_records:
3352 # if 'instance' in record:
3353 # instances = record['instance']
3354 # for inst in instances:
3356 # [record['scaling-group-name-ref'],
3357 # inst['instance-id'],
3358 # inst['op-status'],
3359 # time.strftime('%Y-%m-%d %H:%M:%S',
3361 # inst['create-time'])),
3367 #@cli_osm.command(name='ns-scale')
3368 #@click.argument('ns_name')
3369 #@click.option('--ns_scale_group', prompt=True)
3370 #@click.option('--index', prompt=True)
3371 #@click.option('--wait',
3375 # help='do not return the control immediately, but keep it \
3376 # until the operation is completed, or timeout')
3377 #@click.pass_context
3378 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3381 # NS_NAME: name of the NS instance to be scaled
3384 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3385 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3386 # except ClientException as e:
3391 #@cli_osm.command(name='config-agent-list')
3392 #@click.pass_context
3393 #def config_agent_list(ctx):
3394 # """list config agents"""
3396 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3397 # except ClientException as e:
3400 # table = PrettyTable(['name', 'account-type', 'details'])
3401 # for account in ctx.obj.vca.list():
3404 # account['account-type'],
3410 #@cli_osm.command(name='config-agent-delete')
3411 #@click.argument('name')
3412 #@click.pass_context
3413 #def config_agent_delete(ctx, name):
3414 # """deletes a config agent
3416 # NAME: name of the config agent to be deleted
3419 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3420 # ctx.obj.vca.delete(name)
3421 # except ClientException as e:
3426 #@cli_osm.command(name='config-agent-add')
3427 #@click.option('--name',
3429 #@click.option('--account_type',
3431 #@click.option('--server',
3433 #@click.option('--user',
3435 #@click.option('--secret',
3438 # confirmation_prompt=True)
3439 #@click.pass_context
3440 #def config_agent_add(ctx, name, account_type, server, user, secret):
3441 # """adds a config agent"""
3443 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3444 # ctx.obj.vca.create(name, account_type, server, user, secret)
3445 # except ClientException as e:
3450 #@cli_osm.command(name='ro-dump')
3451 #@click.pass_context
3453 # """shows RO agent information"""
3454 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3455 # resp = ctx.obj.vim.get_resource_orchestrator()
3456 # table = PrettyTable(['key', 'attribute'])
3457 # for k, v in list(resp.items()):
3458 # table.add_row([k, json.dumps(v, indent=2)])
3463 #@cli_osm.command(name='vcs-list')
3464 #@click.pass_context
3466 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3467 # resp = ctx.obj.utils.get_vcs_info()
3468 # table = PrettyTable(['component name', 'state'])
3469 # for component in resp:
3470 # table.add_row([component['component_name'], component['state']])
3475 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3476 @click.argument('ns_name')
3477 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3478 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3479 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3480 @click.option('--vdu_count', default
=None, help='number of vdu instance of this vdu_id')
3481 @click.option('--action_name', prompt
=True, help='action name')
3482 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3483 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3484 @click.option('--wait',
3488 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3500 """executes an action/primitive over a NS instance
3502 NS_NAME: name or ID of the NS instance
3506 check_client_version(ctx
.obj
, ctx
.command
.name
)
3509 op_data
['member_vnf_index'] = vnf_name
3511 op_data
['kdu_name'] = kdu_name
3513 op_data
['vdu_id'] = vdu_id
3515 op_data
['vdu_count_index'] = vdu_count
3516 op_data
['primitive'] = action_name
3518 with
open(params_file
, 'r') as pf
:
3521 op_data
['primitive_params'] = yaml
.safe_load(params
)
3523 op_data
['primitive_params'] = {}
3524 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
3526 # except ClientException as e:
3531 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
3532 @click.argument('ns_name')
3533 @click.argument('vnf_name')
3534 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
3535 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
3536 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
3545 Executes a VNF scale (adding/removing VDUs)
3548 NS_NAME: name or ID of the NS instance.
3549 VNF_NAME: member-vnf-index in the NS to be scaled.
3553 check_client_version(ctx
.obj
, ctx
.command
.name
)
3554 if not scale_in
and not scale_out
:
3556 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
)
3557 # except ClientException as e:
3562 ##############################
3563 # Role Management Operations #
3564 ##############################
3566 @cli_osm.command(name
='role-create', short_help
='creates a new role')
3567 @click.argument('name')
3568 @click.option('--permissions',
3570 help='role permissions using a dictionary')
3572 def role_create(ctx
, name
, permissions
):
3577 NAME: Name or ID of the role.
3578 DEFINITION: Definition of grant/denial of access to resources.
3582 check_client_version(ctx
.obj
, ctx
.command
.name
)
3583 ctx
.obj
.role
.create(name
, permissions
)
3584 # except ClientException as e:
3589 @cli_osm.command(name
='role-update', short_help
='updates a role')
3590 @click.argument('name')
3591 @click.option('--set-name',
3593 help='change name of rle')
3594 # @click.option('--permissions',
3596 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
3597 @click.option('--add',
3599 help='yaml format dictionary with permission: True/False to access grant/denial')
3600 @click.option('--remove',
3602 help='yaml format list to remove a permission')
3604 def role_update(ctx
, name
, set_name
, add
, remove
):
3609 NAME: Name or ID of the role.
3610 DEFINITION: Definition overwrites the old definition.
3611 ADD: Grant/denial of access to resource to add.
3612 REMOVE: Grant/denial of access to resource to remove.
3616 check_client_version(ctx
.obj
, ctx
.command
.name
)
3617 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
3618 # except ClientException as e:
3623 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
3624 @click.argument('name')
3625 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3627 def role_delete(ctx
, name
):
3632 NAME: Name or ID of the role.
3636 check_client_version(ctx
.obj
, ctx
.command
.name
)
3637 ctx
.obj
.role
.delete(name
)
3638 # except ClientException as e:
3643 @cli_osm.command(name
='role-list', short_help
='list all roles')
3644 @click.option('--filter', default
=None,
3645 help='restricts the list to the projects matching the filter')
3647 def role_list(ctx
, filter):
3653 check_client_version(ctx
.obj
, ctx
.command
.name
)
3654 resp
= ctx
.obj
.role
.list(filter)
3655 # except ClientException as e:
3658 table
= PrettyTable(['name', 'id'])
3660 table
.add_row([role
['name'], role
['_id']])
3665 @cli_osm.command(name
='role-show', short_help
='show specific role')
3666 @click.argument('name')
3668 def role_show(ctx
, name
):
3670 Shows the details of a role.
3673 NAME: Name or ID of the role.
3677 check_client_version(ctx
.obj
, ctx
.command
.name
)
3678 resp
= ctx
.obj
.role
.get(name
)
3679 # except ClientException as e:
3683 table
= PrettyTable(['key', 'attribute'])
3684 for k
, v
in resp
.items():
3685 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3690 @cli_osm.command(name
='package-create',
3691 short_help
='Create a package descriptor')
3692 @click.argument('package-type')
3693 @click.argument('package-name')
3694 @click.option('--base-directory',
3696 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
3697 @click.option('--image',
3698 default
="image-name",
3699 help='(VNF) Set the name of the vdu image. Default "image-name"')
3700 @click.option('--vdus',
3702 help='(VNF) Set the number of vdus in a VNF. Default 1')
3703 @click.option('--vcpu',
3705 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
3706 @click.option('--memory',
3708 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
3709 @click.option('--storage',
3711 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
3712 @click.option('--interfaces',
3714 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
3715 @click.option('--vendor',
3717 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
3718 @click.option('--override',
3721 help='(NS/VNF/NST) Flag for overriding the package if exists.')
3722 @click.option('--detailed',
3725 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
3726 @click.option('--netslice-subnets',
3728 help='(NST) Number of netslice subnets. Default 1')
3729 @click.option('--netslice-vlds',
3731 help='(NST) Number of netslice vlds. Default 1')
3733 def package_create(ctx
,
3749 Creates an OSM NS, VNF, NST package
3752 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
3753 PACKAGE_NAME: Name of the package to create the folder with the content.
3757 check_client_version(ctx
.obj
, ctx
.command
.name
)
3758 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
3759 resp
= ctx
.obj
.package_tool
.create(package_type
,
3768 interfaces
=interfaces
,
3771 netslice_subnets
=netslice_subnets
,
3772 netslice_vlds
=netslice_vlds
)
3774 # except ClientException as inst:
3775 # print("ERROR: {}".format(inst))
3778 @cli_osm.command(name
='package-validate',
3779 short_help
='Validate a package descriptor')
3780 @click.argument('base-directory',
3784 def package_validate(ctx
,
3787 Validate descriptors given a base directory.
3790 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
3793 check_client_version(ctx
.obj
, ctx
.command
.name
)
3794 results
= ctx
.obj
.package_tool
.validate(base_directory
)
3795 table
= PrettyTable()
3796 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
3797 # Print the dictionary generated by the validation function
3798 for result
in results
:
3799 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
3800 table
.sortby
= "VALID"
3801 table
.align
["PATH"] = "l"
3802 table
.align
["TYPE"] = "l"
3803 table
.align
["ERROR"] = "l"
3805 # except ClientException as inst:
3806 # print("ERROR: {}".format(inst))
3809 @cli_osm.command(name
='package-build',
3810 short_help
='Build the tar.gz of the package')
3811 @click.argument('package-folder')
3812 @click.option('--skip-validation',
3815 help='skip package validation')
3817 def package_build(ctx
,
3821 Build the package NS, VNF given the package_folder.
3824 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
3827 check_client_version(ctx
.obj
, ctx
.command
.name
)
3828 results
= ctx
.obj
.package_tool
.build(package_folder
, skip_validation
)
3830 # except ClientException as inst:
3831 # print("ERROR: {}".format(inst))
3839 except pycurl
.error
as exc
:
3841 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
3842 except ClientException
as exc
:
3843 print("ERROR: {}".format(exc
))
3844 except (FileNotFoundError
, PermissionError
) as exc
:
3845 print("Cannot open file: {}".format(exc
))
3846 except yaml
.YAMLError
as exc
:
3847 print("Invalid YAML format: {}".format(exc
))
3849 # TODO capture other controlled exceptions here
3850 # TODO remove the ClientException captures from all places, unless they do something different
3853 if __name__
== '__main__':