1 # Copyright 2017-2018 Sandvine
2 # Copyright 2018 Telefonica
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
22 from osmclient
import client
23 from osmclient
.common
.exceptions
import ClientException
24 from prettytable
import PrettyTable
33 from datetime
import datetime
38 CONTEXT_SETTINGS
= dict(help_option_names
=['-h', '--help'], max_content_width
=160)
40 def wrap_text(text
, width
):
41 wrapper
= textwrap
.TextWrapper(width
=width
)
42 lines
= text
.splitlines()
43 return "\n".join(map(wrapper
.fill
, lines
))
46 def trunc_text(text
, length
):
47 if len(text
) > length
:
48 return text
[:(length
- 3)] + '...'
53 def check_client_version(obj
, what
, version
='sol005'):
55 Checks the version of the client object and raises error if it not the expected.
57 :param obj: the client object
58 :what: the function or command under evaluation (used when an error is raised)
60 :raises ClientError: if the specified version does not match the client version
63 fullclassname
= obj
.__module
__ + "." + obj
.__class
__.__name
__
64 message
= 'The following commands or options are only supported with the option "--sol005": {}'.format(what
)
66 message
= 'The following commands or options are not supported when using option "--sol005": {}'.format(what
)
67 if fullclassname
!= 'osmclient.{}.client.Client'.format(version
):
68 raise ClientException(message
)
72 @click.group(context_settings
=dict(help_option_names
=['-h', '--help'], max_content_width
=160))
73 @click.option('--hostname',
75 envvar
='OSM_HOSTNAME',
76 help='hostname of server. ' +
77 'Also can set OSM_HOSTNAME in environment')
78 #@click.option('--sol005/--no-sol005',
80 # envvar='OSM_SOL005',
81 # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
82 # 'Also can set OSM_SOL005 in environment')
83 @click.option('--user',
86 help='user (defaults to admin). ' +
87 'Also can set OSM_USER in environment')
88 @click.option('--password',
90 envvar
='OSM_PASSWORD',
91 help='password (defaults to admin). ' +
92 'Also can set OSM_PASSWORD in environment')
93 @click.option('--project',
96 help='project (defaults to admin). ' +
97 'Also can set OSM_PROJECT in environment')
98 @click.option('-v', '--verbose', count
=True,
99 help='increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)')
100 #@click.option('--so-port',
102 # envvar='OSM_SO_PORT',
103 # help='hostname of server. ' +
104 # 'Also can set OSM_SO_PORT in environment')
105 #@click.option('--so-project',
107 # envvar='OSM_SO_PROJECT',
108 # help='Project Name in SO. ' +
109 # 'Also can set OSM_SO_PROJECT in environment')
110 #@click.option('--ro-hostname',
112 # envvar='OSM_RO_HOSTNAME',
113 # help='hostname of RO server. ' +
114 # 'Also can set OSM_RO_HOSTNAME in environment')
115 #@click.option('--ro-port',
117 # envvar='OSM_RO_PORT',
118 # help='hostname of RO server. ' +
119 # 'Also can set OSM_RO_PORT in environment')
121 def cli_osm(ctx
, hostname
, user
, password
, project
, verbose
):
125 "either hostname option or OSM_HOSTNAME " +
126 "environment variable needs to be specified"))
128 kwargs
= {'verbose': verbose
}
129 # if so_port is not None:
130 # kwargs['so_port']=so_port
131 # if so_project is not None:
132 # kwargs['so_project']=so_project
133 # if ro_hostname is not None:
134 # kwargs['ro_host']=ro_hostname
135 # if ro_port is not None:
136 # kwargs['ro_port']=ro_port
137 sol005
= os
.getenv('OSM_SOL005', True)
140 if password
is not None:
141 kwargs
['password']=password
142 if project
is not None:
143 kwargs
['project']=project
144 ctx
.obj
= client
.Client(host
=hostname
, sol005
=sol005
, **kwargs
)
145 logger
= logging
.getLogger('osmclient')
152 @cli_osm.command(name
='ns-list', short_help
='list all NS instances')
153 @click.option('--filter', default
=None,
154 help='restricts the list to the NS instances matching the filter.')
155 @click.option('--long', is_flag
=True,
156 help='get more details of the NS (project, vim, deployment status, configuration status.')
158 def ns_list(ctx
, filter, long):
159 """list all NS instances
163 --filter filterExpr Restricts the list to the NS instances matching the filter
166 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
167 concatenated using the "&" character:
170 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
171 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
172 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
174 value := scalar value
178 * zero or more occurrences
179 ? zero or one occurrence
180 [] grouping of expressions to be used with ? and *
181 "" quotation marks for marking string constants
185 "AttrName" is the name of one attribute in the data type that defines the representation
186 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
187 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
188 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
189 entries, it means that the operator "op" is applied to the attribute addressed by the last
190 <attrName> entry included in the concatenation. All simple filter expressions are combined
191 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
192 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
193 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
194 prefix". If an attribute referenced in an expression is an array, an object that contains a
195 corresponding array shall be considered to match the expression if any of the elements in the
196 array matches all expressions that have the same attribute prefix.
200 --filter admin-status=ENABLED
201 --filter nsd-ref=<NSD_NAME>
202 --filter nsd.vendor=<VENDOR>
203 --filter nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
204 --filter nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
206 def summarize_deployment_status(status_dict
):
211 net_list
= status_dict
['nets']
214 if net
['status'] not in status_nets
:
215 status_nets
[net
['status']] = 1
217 status_nets
[net
['status']] +=1
219 for k
,v
in status_nets
.items():
220 message
+= "{}:{},".format(k
,v
)
221 message
+= "TOTAL:{}".format(n_nets
)
222 summary
+= "{}".format(message
)
227 vnf_list
= status_dict
['vnfs']
229 member_vnf_index
= vnf
['member_vnf_index']
230 if member_vnf_index
not in status_vnfs
:
231 status_vnfs
[member_vnf_index
] = {}
232 for vm
in vnf
['vms']:
234 if vm
['status'] not in status_vms
:
235 status_vms
[vm
['status']] = 1
237 status_vms
[vm
['status']] +=1
238 if vm
['status'] not in status_vnfs
[member_vnf_index
]:
239 status_vnfs
[member_vnf_index
][vm
['status']] = 1
241 status_vnfs
[member_vnf_index
][vm
['status']] += 1
243 for k
,v
in status_vms
.items():
244 message
+= "{}:{},".format(k
,v
)
245 message
+= "TOTAL:{}".format(n_vms
)
246 summary
+= "\n{}".format(message
)
248 for k
,v
in status_vnfs
.items():
250 message
= "\n {} VMs: ".format(k
)
251 for k2
,v2
in v
.items():
252 message
+= "{}:{},".format(k2
,v2
)
254 message
+= "TOTAL:{}".format(total
)
258 def summarize_config_status(ee_list
):
263 if ee
['elementType'] not in status_ee
:
264 status_ee
[ee
['elementType']] = {}
265 status_ee
[ee
['elementType']][ee
['status']] = 1
267 if ee
['status'] in status_ee
[ee
['elementType']]:
268 status_ee
[ee
['elementType']][ee
['status']] += 1
270 status_ee
[ee
['elementType']][ee
['status']] = 1
272 for elementType
in ["KDU", "VDU", "PDU", "VNF", "NS"]:
273 if elementType
in status_ee
:
276 for k
,v
in status_ee
[elementType
].items():
277 message
+= "{}:{},".format(k
,v
)
279 message
+= "TOTAL:{}\n".format(total
)
280 summary
+= "{}: {}".format(elementType
, message
)
281 summary
+= "TOTAL Exec. Env.: {}".format(n_ee
)
285 check_client_version(ctx
.obj
, '--filter')
286 resp
= ctx
.obj
.ns
.list(filter)
288 resp
= ctx
.obj
.ns
.list()
300 'configuration status'])
301 project_list
= ctx
.obj
.project
.list()
302 vim_list
= ctx
.obj
.vim
.list()
312 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
313 if fullclassname
== 'osmclient.sol005.client.Client':
315 nsr_name
= nsr
['name']
317 date
= datetime
.fromtimestamp(nsr
['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
318 ns_state
= nsr
['nsState']
320 deployment_status
= summarize_deployment_status(nsr
['deploymentStatus'])
321 config_status
= summarize_config_status(nsr
['configurationStatus'])
322 project_id
= nsr
.get('_admin').get('projects_read')[0]
324 for p
in project_list
:
325 if p
['_id'] == project_id
:
326 project_name
= p
['name']
328 #project = '{} ({})'.format(project_name, project_id)
329 project
= project_name
330 vim_id
= nsr
.get('datacenter')
333 if v
['uuid'] == vim_id
:
336 #vim = '{} ({})'.format(vim_name, vim_id)
338 current_operation
= "{} ({})".format(nsr
['currentOperation'],nsr
['currentOperationID'])
339 error_details
= "N/A"
340 if ns_state
== "BROKEN" or ns_state
== "DEGRADED":
341 error_details
= "{}\nDetail: {}".format(nsr
['errorDescription'],nsr
['errorDetail'])
343 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
344 nsr
= nsopdata
['nsr:nsr']
345 nsr_name
= nsr
['name-ref']
346 nsr_id
= nsr
['ns-instance-config-ref']
349 deployment_status
= nsr
['operational-status'] if 'operational-status' in nsr
else 'Not found'
350 ns_state
= deployment_status
351 config_status
= nsr
['config-status'] if 'config-status' in nsr
else 'Not found'
352 current_operation
= "Unknown"
353 error_details
= nsr
['detailed-status'] if 'detailed-status' in nsr
else 'Not found'
354 if config_status
== "config_not_needed":
355 config_status
= "configured (no charms)"
364 wrap_text(text
=error_details
,width
=40),
376 wrap_text(text
=error_details
,width
=40)])
379 print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
380 print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
382 def nsd_list(ctx
, filter):
385 check_client_version(ctx
.obj
, '--filter')
386 resp
= ctx
.obj
.nsd
.list(filter)
388 resp
= ctx
.obj
.nsd
.list()
389 # print(yaml.safe_dump(resp))
390 table
= PrettyTable(['nsd name', 'id'])
391 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
392 if fullclassname
== 'osmclient.sol005.client.Client':
394 name
= ns
['name'] if 'name' in ns
else '-'
395 table
.add_row([name
, ns
['_id']])
398 table
.add_row([ns
['name'], ns
['id']])
403 @cli_osm.command(name
='nsd-list', short_help
='list all NS packages')
404 @click.option('--filter', default
=None,
405 help='restricts the list to the NSD/NSpkg matching the filter')
407 def nsd_list1(ctx
, filter):
408 """list all NSD/NS pkg in the system"""
410 nsd_list(ctx
, filter)
413 @cli_osm.command(name
='nspkg-list', short_help
='list all NS packages')
414 @click.option('--filter', default
=None,
415 help='restricts the list to the NSD/NSpkg matching the filter')
417 def nsd_list2(ctx
, filter):
418 """list all NS packages"""
420 nsd_list(ctx
, filter)
423 def vnfd_list(ctx
, nf_type
, filter):
426 check_client_version(ctx
.obj
, '--nf_type')
428 check_client_version(ctx
.obj
, '--filter')
431 nf_filter
= "_admin.type=vnfd"
432 elif nf_type
== "pnf":
433 nf_filter
= "_admin.type=pnfd"
434 elif nf_type
== "hnf":
435 nf_filter
= "_admin.type=hnfd"
437 raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
439 filter = '{}&{}'.format(nf_filter
, filter)
443 resp
= ctx
.obj
.vnfd
.list(filter)
445 resp
= ctx
.obj
.vnfd
.list()
446 # print(yaml.safe_dump(resp))
447 table
= PrettyTable(['nfpkg name', 'id'])
448 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
449 if fullclassname
== 'osmclient.sol005.client.Client':
451 name
= vnfd
['name'] if 'name' in vnfd
else '-'
452 table
.add_row([name
, vnfd
['_id']])
455 table
.add_row([vnfd
['name'], vnfd
['id']])
460 @cli_osm.command(name
='vnfd-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
461 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
462 @click.option('--filter', default
=None,
463 help='restricts the list to the NF pkg matching the filter')
465 def vnfd_list1(ctx
, nf_type
, filter):
466 """list all xNF packages (VNF, HNF, PNF)"""
468 vnfd_list(ctx
, nf_type
, filter)
471 @cli_osm.command(name
='vnfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
472 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
473 @click.option('--filter', default
=None,
474 help='restricts the list to the NFpkg matching the filter')
476 def vnfd_list2(ctx
, nf_type
, filter):
477 """list all xNF packages (VNF, HNF, PNF)"""
479 vnfd_list(ctx
, nf_type
, filter)
482 @cli_osm.command(name
='nfpkg-list', short_help
='list all xNF packages (VNF, HNF, PNF)')
483 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
484 @click.option('--filter', default
=None,
485 help='restricts the list to the NFpkg matching the filter')
487 def nfpkg_list(ctx
, nf_type
, filter):
488 """list all xNF packages (VNF, HNF, PNF)"""
491 check_client_version(ctx
.obj
, ctx
.command
.name
)
492 vnfd_list(ctx
, nf_type
, filter)
493 # except ClientException as e:
498 def vnf_list(ctx
, ns
, filter):
502 check_client_version(ctx
.obj
, '--ns')
504 check_client_version(ctx
.obj
, '--filter')
505 resp
= ctx
.obj
.vnf
.list(ns
, filter)
507 resp
= ctx
.obj
.vnf
.list()
508 # except ClientException as e:
511 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
512 if fullclassname
== 'osmclient.sol005.client.Client':
522 name
= vnfr
['name'] if 'name' in vnfr
else '-'
527 vnfr
['member-vnf-index-ref'],
529 vnfr
['vim-account-id'],
535 'operational status',
538 if 'mgmt-interface' not in vnfr
:
539 vnfr
['mgmt-interface'] = {}
540 vnfr
['mgmt-interface']['ip-address'] = None
544 vnfr
['operational-status'],
545 vnfr
['config-status']])
550 @cli_osm.command(name
='vnf-list', short_help
='list all NF instances')
551 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
552 @click.option('--filter', default
=None,
553 help='restricts the list to the NF instances matching the filter.')
555 def vnf_list1(ctx
, ns
, filter):
556 """list all NF instances"""
558 vnf_list(ctx
, ns
, filter)
561 @cli_osm.command(name
='nf-list', short_help
='list all NF instances')
562 @click.option('--ns', default
=None, help='NS instance id or name to restrict the NF list')
563 @click.option('--filter', default
=None,
564 help='restricts the list to the NF instances matching the filter.')
566 def nf_list(ctx
, ns
, filter):
567 """list all NF instances
571 --ns TEXT NS instance id or name to restrict the VNF list
572 --filter filterExpr Restricts the list to the VNF instances matching the filter
575 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
576 concatenated using the "&" character:
579 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
580 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
581 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
583 value := scalar value
587 * zero or more occurrences
588 ? zero or one occurrence
589 [] grouping of expressions to be used with ? and *
590 "" quotation marks for marking string constants
594 "AttrName" is the name of one attribute in the data type that defines the representation
595 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
596 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
597 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
598 entries, it means that the operator "op" is applied to the attribute addressed by the last
599 <attrName> entry included in the concatenation. All simple filter expressions are combined
600 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
601 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
602 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
603 prefix". If an attribute referenced in an expression is an array, an object that contains a
604 corresponding array shall be considered to match the expression if any of the elements in the
605 array matches all expressions that have the same attribute prefix.
609 --filter vim-account-id=<VIM_ACCOUNT_ID>
610 --filter vnfd-ref=<VNFD_NAME>
611 --filter vdur.ip-address=<IP_ADDRESS>
612 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
615 vnf_list(ctx
, ns
, filter)
618 @cli_osm.command(name
='ns-op-list', short_help
='shows the history of operations over a NS instance')
619 @click.argument('name')
620 @click.option('--long', is_flag
=True,
621 help='get more details of the NS operation (date, ).')
623 def ns_op_list(ctx
, name
, long):
624 """shows the history of operations over a NS instance
626 NAME: name or ID of the NS instance
628 def formatParams(params
):
629 if params
['lcmOperationType']=='instantiate':
630 params
.pop('nsDescription')
634 elif params
['lcmOperationType']=='action':
635 params
.pop('primitive')
636 params
.pop('lcmOperationType')
637 params
.pop('nsInstanceId')
642 check_client_version(ctx
.obj
, ctx
.command
.name
)
643 resp
= ctx
.obj
.ns
.list_op(name
)
644 # except ClientException as e:
649 table
= PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
651 table
= PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
653 #print(yaml.safe_dump(resp))
656 if op
['lcmOperationType']=='action':
657 action_name
= op
['operationParams']['primitive']
659 if op
['operationState']=='PROCESSING':
660 if op
['lcmOperationType']=='instantiate':
664 detail
= "In queue. Current position: {}".format(op
['queuePosition'])
665 elif op
['operationState']=='FAILED' or op
['operationState']=='FAILED_TEMP':
666 detail
= op
['errorMessage']
667 date
= datetime
.fromtimestamp(op
['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
668 last_update
= datetime
.fromtimestamp(op
['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
670 table
.add_row([op
['id'],
671 op
['lcmOperationType'],
673 wrap_text(text
=json
.dumps(formatParams(op
['operationParams']),indent
=2),width
=50),
674 op
['operationState'],
677 wrap_text(text
=detail
,width
=50)])
679 table
.add_row([op
['id'], op
['lcmOperationType'], action_name
,
680 op
['operationState'], date
, wrap_text(text
=detail
,width
=50)])
685 def nsi_list(ctx
, filter):
686 """list all Network Slice Instances"""
689 check_client_version(ctx
.obj
, ctx
.command
.name
)
690 resp
= ctx
.obj
.nsi
.list(filter)
691 # except ClientException as e:
695 ['netslice instance name',
697 'operational status',
701 nsi_name
= nsi
['name']
703 opstatus
= nsi
['operational-status'] if 'operational-status' in nsi
else 'Not found'
704 configstatus
= nsi
['config-status'] if 'config-status' in nsi
else 'Not found'
705 detailed_status
= nsi
['detailed-status'] if 'detailed-status' in nsi
else 'Not found'
706 if configstatus
== "config_not_needed":
707 configstatus
= "configured (no charms)"
718 @cli_osm.command(name
='nsi-list', short_help
='list all Network Slice Instances (NSI)')
719 @click.option('--filter', default
=None,
720 help='restricts the list to the Network Slice Instances matching the filter')
722 def nsi_list1(ctx
, filter):
723 """list all Network Slice Instances (NSI)"""
725 nsi_list(ctx
, filter)
728 @cli_osm.command(name
='netslice-instance-list', short_help
='list all Network Slice Instances (NSI)')
729 @click.option('--filter', default
=None,
730 help='restricts the list to the Network Slice Instances matching the filter')
732 def nsi_list2(ctx
, filter):
733 """list all Network Slice Instances (NSI)"""
735 nsi_list(ctx
, filter)
738 def nst_list(ctx
, filter):
741 check_client_version(ctx
.obj
, ctx
.command
.name
)
742 resp
= ctx
.obj
.nst
.list(filter)
743 # except ClientException as e:
746 # print(yaml.safe_dump(resp))
747 table
= PrettyTable(['nst name', 'id'])
749 name
= nst
['name'] if 'name' in nst
else '-'
750 table
.add_row([name
, nst
['_id']])
755 @cli_osm.command(name
='nst-list', short_help
='list all Network Slice Templates (NST)')
756 @click.option('--filter', default
=None,
757 help='restricts the list to the NST matching the filter')
759 def nst_list1(ctx
, filter):
760 """list all Network Slice Templates (NST) in the system"""
762 nst_list(ctx
, filter)
765 @cli_osm.command(name
='netslice-template-list', short_help
='list all Network Slice Templates (NST)')
766 @click.option('--filter', default
=None,
767 help='restricts the list to the NST matching the filter')
769 def nst_list2(ctx
, filter):
770 """list all Network Slice Templates (NST) in the system"""
772 nst_list(ctx
, filter)
775 def nsi_op_list(ctx
, name
):
778 check_client_version(ctx
.obj
, ctx
.command
.name
)
779 resp
= ctx
.obj
.nsi
.list_op(name
)
780 # except ClientException as e:
783 table
= PrettyTable(['id', 'operation', 'status'])
785 table
.add_row([op
['id'], op
['lcmOperationType'],
786 op
['operationState']])
791 @cli_osm.command(name
='nsi-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
792 @click.argument('name')
794 def nsi_op_list1(ctx
, name
):
795 """shows the history of operations over a Network Slice Instance (NSI)
797 NAME: name or ID of the Network Slice Instance
800 nsi_op_list(ctx
, name
)
803 @cli_osm.command(name
='netslice-instance-op-list', short_help
='shows the history of operations over a Network Slice Instance (NSI)')
804 @click.argument('name')
806 def nsi_op_list2(ctx
, name
):
807 """shows the history of operations over a Network Slice Instance (NSI)
809 NAME: name or ID of the Network Slice Instance
812 nsi_op_list(ctx
, name
)
815 @cli_osm.command(name
='pdu-list', short_help
='list all Physical Deployment Units (PDU)')
816 @click.option('--filter', default
=None,
817 help='restricts the list to the Physical Deployment Units matching the filter')
819 def pdu_list(ctx
, filter):
820 """list all Physical Deployment Units (PDU)"""
823 check_client_version(ctx
.obj
, ctx
.command
.name
)
824 resp
= ctx
.obj
.pdu
.list(filter)
825 # except ClientException as e:
834 pdu_name
= pdu
['name']
836 pdu_type
= pdu
['type']
837 pdu_ipaddress
= "None"
838 for iface
in pdu
['interfaces']:
840 pdu_ipaddress
= iface
['ip-address']
855 def nsd_show(ctx
, name
, literal
):
858 resp
= ctx
.obj
.nsd
.get(name
)
859 # resp = ctx.obj.nsd.get_individual(name)
860 # except ClientException as e:
865 print(yaml
.safe_dump(resp
))
868 table
= PrettyTable(['field', 'value'])
869 for k
, v
in list(resp
.items()):
870 table
.add_row([k
, json
.dumps(v
, indent
=2)])
875 @cli_osm.command(name
='nsd-show', short_help
='shows the content of a NSD')
876 @click.option('--literal', is_flag
=True,
877 help='print literally, no pretty table')
878 @click.argument('name')
880 def nsd_show1(ctx
, name
, literal
):
881 """shows the content of a NSD
883 NAME: name or ID of the NSD/NSpkg
886 nsd_show(ctx
, name
, literal
)
889 @cli_osm.command(name
='nspkg-show', short_help
='shows the content of a NSD')
890 @click.option('--literal', is_flag
=True,
891 help='print literally, no pretty table')
892 @click.argument('name')
894 def nsd_show2(ctx
, name
, literal
):
895 """shows the content of a NSD
897 NAME: name or ID of the NSD/NSpkg
900 nsd_show(ctx
, name
, literal
)
903 def vnfd_show(ctx
, name
, literal
):
906 resp
= ctx
.obj
.vnfd
.get(name
)
907 # resp = ctx.obj.vnfd.get_individual(name)
908 # except ClientException as e:
913 print(yaml
.safe_dump(resp
))
916 table
= PrettyTable(['field', 'value'])
917 for k
, v
in list(resp
.items()):
918 table
.add_row([k
, json
.dumps(v
, indent
=2)])
923 @cli_osm.command(name
='vnfd-show', short_help
='shows the content of a VNFD')
924 @click.option('--literal', is_flag
=True,
925 help='print literally, no pretty table')
926 @click.argument('name')
928 def vnfd_show1(ctx
, name
, literal
):
929 """shows the content of a VNFD
931 NAME: name or ID of the VNFD/VNFpkg
934 vnfd_show(ctx
, name
, literal
)
937 @cli_osm.command(name
='vnfpkg-show', short_help
='shows the content of a VNFD')
938 @click.option('--literal', is_flag
=True,
939 help='print literally, no pretty table')
940 @click.argument('name')
942 def vnfd_show2(ctx
, name
, literal
):
943 """shows the content of a VNFD
945 NAME: name or ID of the VNFD/VNFpkg
948 vnfd_show(ctx
, name
, literal
)
951 @cli_osm.command(name
='nfpkg-show', short_help
='shows the content of a NF Descriptor')
952 @click.option('--literal', is_flag
=True,
953 help='print literally, no pretty table')
954 @click.argument('name')
956 def nfpkg_show(ctx
, name
, literal
):
957 """shows the content of a NF Descriptor
959 NAME: name or ID of the NFpkg
962 vnfd_show(ctx
, name
, literal
)
965 @cli_osm.command(name
='ns-show', short_help
='shows the info of a NS instance')
966 @click.argument('name')
967 @click.option('--literal', is_flag
=True,
968 help='print literally, no pretty table')
969 @click.option('--filter', default
=None)
971 def ns_show(ctx
, name
, literal
, filter):
972 """shows the info of a NS instance
974 NAME: name or ID of the NS instance
978 ns
= ctx
.obj
.ns
.get(name
)
979 # except ClientException as e:
984 print(yaml
.safe_dump(ns
))
987 table
= PrettyTable(['field', 'value'])
989 for k
, v
in list(ns
.items()):
990 if filter is None or filter in k
:
991 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
993 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
994 if fullclassname
!= 'osmclient.sol005.client.Client':
995 nsopdata
= ctx
.obj
.ns
.get_opdata(ns
['id'])
996 nsr_optdata
= nsopdata
['nsr:nsr']
997 for k
, v
in list(nsr_optdata
.items()):
998 if filter is None or filter in k
:
999 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2),width
=100)])
1004 @cli_osm.command(name
='vnf-show', short_help
='shows the info of a VNF instance')
1005 @click.argument('name')
1006 @click.option('--literal', is_flag
=True,
1007 help='print literally, no pretty table')
1008 @click.option('--filter', default
=None, help='restricts the information to the fields in the filter')
1009 @click.option('--kdu', default
=None, help='KDU name (whose status will be shown)')
1011 def vnf_show(ctx
, name
, literal
, filter, kdu
):
1012 """shows the info of a VNF instance
1014 NAME: name or ID of the VNF instance
1016 def print_kdu_status(op_info_status
):
1017 """print KDU status properly formatted
1020 op_status
= yaml
.safe_load(op_info_status
)
1021 if "namespace" in op_status
and "info" in op_status
and \
1022 "last_deployed" in op_status
["info"] and "status" in op_status
["info"] and \
1023 "code" in op_status
["info"]["status"] and "resources" in op_status
["info"]["status"] and \
1024 "notes" in op_status
["info"]["status"] and "seconds" in op_status
["info"]["last_deployed"]:
1025 last_deployed_time
= datetime
.fromtimestamp(op_status
["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1026 print("LAST DEPLOYED: {}".format(last_deployed_time
))
1027 print("NAMESPACE: {}".format(op_status
["namespace"]))
1028 status_code
= "UNKNOWN"
1029 if op_status
["info"]["status"]["code"]==1:
1030 status_code
= "DEPLOYED"
1031 print("STATUS: {}".format(status_code
))
1034 print(op_status
["info"]["status"]["resources"])
1036 print(op_status
["info"]["status"]["notes"])
1038 print(op_info_status
)
1040 print(op_info_status
)
1045 raise ClientException('"--literal" option is incompatible with "--kdu" option')
1047 raise ClientException('"--filter" option is incompatible with "--kdu" option')
1050 check_client_version(ctx
.obj
, ctx
.command
.name
)
1051 resp
= ctx
.obj
.vnf
.get(name
)
1054 ns_id
= resp
['nsr-id-ref']
1056 op_data
['member_vnf_index'] = resp
['member-vnf-index-ref']
1057 op_data
['kdu_name'] = kdu
1058 op_data
['primitive'] = 'status'
1059 op_data
['primitive_params'] = {}
1060 op_id
= ctx
.obj
.ns
.exec_op(ns_id
, op_name
='action', op_data
=op_data
, wait
=False)
1063 op_info
= ctx
.obj
.ns
.get_op(op_id
)
1064 if op_info
['operationState'] == 'COMPLETED':
1065 print_kdu_status(op_info
['detailed-status'])
1069 print ("Could not determine KDU status")
1072 print(yaml
.safe_dump(resp
))
1075 table
= PrettyTable(['field', 'value'])
1077 for k
, v
in list(resp
.items()):
1078 if filter is None or filter in k
:
1079 table
.add_row([k
, wrap_text(text
=json
.dumps(v
,indent
=2),width
=100)])
1082 # except ClientException as e:
1087 #@cli_osm.command(name='vnf-monitoring-show')
1088 #@click.argument('vnf_name')
1089 #@click.pass_context
1090 #def vnf_monitoring_show(ctx, vnf_name):
1092 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1093 # resp = ctx.obj.vnf.get_monitoring(vnf_name)
1094 # except ClientException as e:
1098 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1099 # if resp is not None:
1100 # for monitor in resp:
1104 # monitor['value-integer'],
1105 # monitor['units']])
1110 #@cli_osm.command(name='ns-monitoring-show')
1111 #@click.argument('ns_name')
1112 #@click.pass_context
1113 #def ns_monitoring_show(ctx, ns_name):
1115 # check_client_version(ctx.obj, ctx.command.name, 'v1')
1116 # resp = ctx.obj.ns.get_monitoring(ns_name)
1117 # except ClientException as e:
1121 # table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1122 # for key, val in list(resp.items()):
1123 # for monitor in val:
1127 # monitor['value-integer'],
1128 # monitor['units']])
1133 @cli_osm.command(name
='ns-op-show', short_help
='shows the info of a NS operation')
1134 @click.argument('id')
1135 @click.option('--filter', default
=None)
1136 @click.option('--literal', is_flag
=True,
1137 help='print literally, no pretty table')
1139 def ns_op_show(ctx
, id, filter, literal
):
1140 """shows the detailed info of a NS operation
1142 ID: operation identifier
1146 check_client_version(ctx
.obj
, ctx
.command
.name
)
1147 op_info
= ctx
.obj
.ns
.get_op(id)
1148 # except ClientException as e:
1153 print(yaml
.safe_dump(op_info
))
1156 table
= PrettyTable(['field', 'value'])
1157 for k
, v
in list(op_info
.items()):
1158 if filter is None or filter in k
:
1159 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1164 def nst_show(ctx
, name
, literal
):
1167 check_client_version(ctx
.obj
, ctx
.command
.name
)
1168 resp
= ctx
.obj
.nst
.get(name
)
1169 #resp = ctx.obj.nst.get_individual(name)
1170 # except ClientException as e:
1175 print(yaml
.safe_dump(resp
))
1178 table
= PrettyTable(['field', 'value'])
1179 for k
, v
in list(resp
.items()):
1180 table
.add_row([k
, wrap_text(json
.dumps(v
, indent
=2), 100)])
1185 @cli_osm.command(name
='nst-show', short_help
='shows the content of a Network Slice Template (NST)')
1186 @click.option('--literal', is_flag
=True,
1187 help='print literally, no pretty table')
1188 @click.argument('name')
1190 def nst_show1(ctx
, name
, literal
):
1191 """shows the content of a Network Slice Template (NST)
1193 NAME: name or ID of the NST
1196 nst_show(ctx
, name
, literal
)
1199 @cli_osm.command(name
='netslice-template-show', short_help
='shows the content of a Network Slice Template (NST)')
1200 @click.option('--literal', is_flag
=True,
1201 help='print literally, no pretty table')
1202 @click.argument('name')
1204 def nst_show2(ctx
, name
, literal
):
1205 """shows the content of a Network Slice Template (NST)
1207 NAME: name or ID of the NST
1210 nst_show(ctx
, name
, literal
)
1213 def nsi_show(ctx
, name
, literal
, filter):
1216 check_client_version(ctx
.obj
, ctx
.command
.name
)
1217 nsi
= ctx
.obj
.nsi
.get(name
)
1218 # except ClientException as e:
1223 print(yaml
.safe_dump(nsi
))
1226 table
= PrettyTable(['field', 'value'])
1228 for k
, v
in list(nsi
.items()):
1229 if filter is None or filter in k
:
1230 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1236 @cli_osm.command(name
='nsi-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1237 @click.argument('name')
1238 @click.option('--literal', is_flag
=True,
1239 help='print literally, no pretty table')
1240 @click.option('--filter', default
=None)
1242 def nsi_show1(ctx
, name
, literal
, filter):
1243 """shows the content of a Network Slice Instance (NSI)
1245 NAME: name or ID of the Network Slice Instance
1248 nsi_show(ctx
, name
, literal
, filter)
1251 @cli_osm.command(name
='netslice-instance-show', short_help
='shows the content of a Network Slice Instance (NSI)')
1252 @click.argument('name')
1253 @click.option('--literal', is_flag
=True,
1254 help='print literally, no pretty table')
1255 @click.option('--filter', default
=None)
1257 def nsi_show2(ctx
, name
, literal
, filter):
1258 """shows the content of a Network Slice Instance (NSI)
1260 NAME: name or ID of the Network Slice Instance
1263 nsi_show(ctx
, name
, literal
, filter)
1266 def nsi_op_show(ctx
, id, filter):
1269 check_client_version(ctx
.obj
, ctx
.command
.name
)
1270 op_info
= ctx
.obj
.nsi
.get_op(id)
1271 # except ClientException as e:
1275 table
= PrettyTable(['field', 'value'])
1276 for k
, v
in list(op_info
.items()):
1277 if filter is None or filter in k
:
1278 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1283 @cli_osm.command(name
='nsi-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1284 @click.argument('id')
1285 @click.option('--filter', default
=None)
1287 def nsi_op_show1(ctx
, id, filter):
1288 """shows the info of an operation over a Network Slice Instance(NSI)
1290 ID: operation identifier
1293 nsi_op_show(ctx
, id, filter)
1296 @cli_osm.command(name
='netslice-instance-op-show', short_help
='shows the info of an operation over a Network Slice Instance(NSI)')
1297 @click.argument('id')
1298 @click.option('--filter', default
=None)
1300 def nsi_op_show2(ctx
, id, filter):
1301 """shows the info of an operation over a Network Slice Instance(NSI)
1303 ID: operation identifier
1306 nsi_op_show(ctx
, id, filter)
1309 @cli_osm.command(name
='pdu-show', short_help
='shows the content of a Physical Deployment Unit (PDU)')
1310 @click.argument('name')
1311 @click.option('--literal', is_flag
=True,
1312 help='print literally, no pretty table')
1313 @click.option('--filter', default
=None)
1315 def pdu_show(ctx
, name
, literal
, filter):
1316 """shows the content of a Physical Deployment Unit (PDU)
1318 NAME: name or ID of the PDU
1322 check_client_version(ctx
.obj
, ctx
.command
.name
)
1323 pdu
= ctx
.obj
.pdu
.get(name
)
1324 # except ClientException as e:
1329 print(yaml
.safe_dump(pdu
))
1332 table
= PrettyTable(['field', 'value'])
1334 for k
, v
in list(pdu
.items()):
1335 if filter is None or filter in k
:
1336 table
.add_row([k
, json
.dumps(v
, indent
=2)])
1342 ####################
1344 ####################
1346 def nsd_create(ctx
, filename
, overwrite
):
1349 check_client_version(ctx
.obj
, ctx
.command
.name
)
1350 ctx
.obj
.nsd
.create(filename
, overwrite
)
1351 # except ClientException as e:
1356 @cli_osm.command(name
='nsd-create', short_help
='creates a new NSD/NSpkg')
1357 @click.argument('filename')
1358 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1359 help='Deprecated. Use override')
1360 @click.option('--override', 'overwrite', default
=None,
1361 help='overrides fields in descriptor, format: '
1362 '"key1.key2...=value[;key3...=value;...]"')
1364 def nsd_create1(ctx
, filename
, overwrite
):
1365 """creates a new NSD/NSpkg
1367 FILENAME: NSD yaml file or NSpkg tar.gz file
1370 nsd_create(ctx
, filename
, overwrite
)
1373 @cli_osm.command(name
='nspkg-create', short_help
='creates a new NSD/NSpkg')
1374 @click.argument('filename')
1375 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1376 help='Deprecated. Use override')
1377 @click.option('--override', 'overwrite', default
=None,
1378 help='overrides fields in descriptor, format: '
1379 '"key1.key2...=value[;key3...=value;...]"')
1381 def nsd_create2(ctx
, filename
, overwrite
):
1382 """creates a new NSD/NSpkg
1384 FILENAME: NSD yaml file or NSpkg tar.gz file
1387 nsd_create(ctx
, filename
, overwrite
)
1390 def vnfd_create(ctx
, filename
, overwrite
):
1393 check_client_version(ctx
.obj
, ctx
.command
.name
)
1394 ctx
.obj
.vnfd
.create(filename
, overwrite
)
1395 # except ClientException as e:
1400 @cli_osm.command(name
='vnfd-create', short_help
='creates a new VNFD/VNFpkg')
1401 @click.argument('filename')
1402 @click.option('--overwrite', 'overwrite', default
=None,
1403 help='overwrite deprecated, use override')
1404 @click.option('--override', 'overwrite', default
=None,
1405 help='overrides fields in descriptor, format: '
1406 '"key1.key2...=value[;key3...=value;...]"')
1408 def vnfd_create1(ctx
, filename
, overwrite
):
1409 """creates a new VNFD/VNFpkg
1411 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1414 vnfd_create(ctx
, filename
, overwrite
)
1417 @cli_osm.command(name
='vnfpkg-create', short_help
='creates a new VNFD/VNFpkg')
1418 @click.argument('filename')
1419 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1420 help='Deprecated. Use override')
1421 @click.option('--override', 'overwrite', default
=None,
1422 help='overrides fields in descriptor, format: '
1423 '"key1.key2...=value[;key3...=value;...]"')
1425 def vnfd_create2(ctx
, filename
, overwrite
):
1426 """creates a new VNFD/VNFpkg
1428 FILENAME: VNFD yaml file or VNFpkg tar.gz file
1431 vnfd_create(ctx
, filename
, overwrite
)
1434 @cli_osm.command(name
='nfpkg-create', short_help
='creates a new NFpkg')
1435 @click.argument('filename')
1436 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1437 help='Deprecated. Use override')
1438 @click.option('--override', 'overwrite', default
=None,
1439 help='overrides fields in descriptor, format: '
1440 '"key1.key2...=value[;key3...=value;...]"')
1442 def nfpkg_create(ctx
, filename
, overwrite
):
1443 """creates a new NFpkg
1445 FILENAME: NF Descriptor yaml file or NFpkg tar.gz file
1448 vnfd_create(ctx
, filename
, overwrite
)
1451 @cli_osm.command(name
='ns-create', short_help
='creates a new Network Service instance')
1452 @click.option('--ns_name',
1453 prompt
=True, help='name of the NS instance')
1454 @click.option('--nsd_name',
1455 prompt
=True, help='name of the NS descriptor')
1456 @click.option('--vim_account',
1457 prompt
=True, help='default VIM account id or name for the deployment')
1458 @click.option('--admin_status',
1460 help='administration status')
1461 @click.option('--ssh_keys',
1463 help='comma separated list of public key files to inject to vnfs')
1464 @click.option('--config',
1466 help='ns specific yaml configuration')
1467 @click.option('--config_file',
1469 help='ns specific yaml configuration file')
1470 @click.option('--wait',
1474 help='do not return the control immediately, but keep it '
1475 'until the operation is completed, or timeout')
1486 """creates a new NS instance"""
1490 check_client_version(ctx
.obj
, '--config_file')
1492 raise ClientException('"--config" option is incompatible with "--config_file" option')
1493 with
open(config_file
, 'r') as cf
:
1500 account
=vim_account
,
1502 # except ClientException as e:
1507 def nst_create(ctx
, filename
, overwrite
):
1510 check_client_version(ctx
.obj
, ctx
.command
.name
)
1511 ctx
.obj
.nst
.create(filename
, overwrite
)
1512 # except ClientException as e:
1517 @cli_osm.command(name
='nst-create', short_help
='creates a new Network Slice Template (NST)')
1518 @click.argument('filename')
1519 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1520 help='Deprecated. Use override')
1521 @click.option('--override', 'overwrite', default
=None,
1522 help='overrides fields in descriptor, format: '
1523 '"key1.key2...=value[;key3...=value;...]"')
1525 def nst_create1(ctx
, filename
, overwrite
):
1526 """creates a new Network Slice Template (NST)
1528 FILENAME: NST yaml file or NSTpkg tar.gz file
1531 nst_create(ctx
, filename
, overwrite
)
1534 @cli_osm.command(name
='netslice-template-create', short_help
='creates a new Network Slice Template (NST)')
1535 @click.argument('filename')
1536 @click.option('--overwrite', 'overwrite', default
=None, # hidden=True,
1537 help='Deprecated. Use override')
1538 @click.option('--override', 'overwrite', default
=None,
1539 help='overrides fields in descriptor, format: '
1540 '"key1.key2...=value[;key3...=value;...]"')
1542 def nst_create2(ctx
, filename
, overwrite
):
1543 """creates a new Network Slice Template (NST)
1545 FILENAME: NST yaml file or NSTpkg tar.gz file
1548 nst_create(ctx
, filename
, overwrite
)
1551 def nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1552 """creates a new Network Slice Instance (NSI)"""
1555 check_client_version(ctx
.obj
, ctx
.command
.name
)
1558 raise ClientException('"--config" option is incompatible with "--config_file" option')
1559 with
open(config_file
, 'r') as cf
:
1561 ctx
.obj
.nsi
.create(nst_name
, nsi_name
, config
=config
, ssh_keys
=ssh_keys
,
1562 account
=vim_account
, wait
=wait
)
1563 # except ClientException as e:
1568 @cli_osm.command(name
='nsi-create', short_help
='creates a new Network Slice Instance')
1569 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1570 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1571 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1572 @click.option('--ssh_keys', default
=None,
1573 help='comma separated list of keys to inject to vnfs')
1574 @click.option('--config', default
=None,
1575 help='Netslice specific yaml configuration:\n'
1576 'netslice_subnet: [\n'
1577 'id: TEXT, vim_account: TEXT,\n'
1578 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1579 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1580 'additionalParamsForNsi: {param: value, ...}\n'
1581 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1583 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1585 @click.option('--config_file',
1587 help='nsi specific yaml configuration file')
1588 @click.option('--wait',
1592 help='do not return the control immediately, but keep it '
1593 'until the operation is completed, or timeout')
1595 def nsi_create1(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1596 """creates a new Network Slice Instance (NSI)"""
1598 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1601 @cli_osm.command(name
='netslice-instance-create', short_help
='creates a new Network Slice Instance')
1602 @click.option('--nsi_name', prompt
=True, help='name of the Network Slice Instance')
1603 @click.option('--nst_name', prompt
=True, help='name of the Network Slice Template')
1604 @click.option('--vim_account', prompt
=True, help='default VIM account id or name for the deployment')
1605 @click.option('--ssh_keys', default
=None,
1606 help='comma separated list of keys to inject to vnfs')
1607 @click.option('--config', default
=None,
1608 help='Netslice specific yaml configuration:\n'
1609 'netslice_subnet: [\n'
1610 'id: TEXT, vim_account: TEXT,\n'
1611 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1612 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1614 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1616 @click.option('--config_file',
1618 help='nsi specific yaml configuration file')
1619 @click.option('--wait',
1623 help='do not return the control immediately, but keep it '
1624 'until the operation is completed, or timeout')
1626 def nsi_create2(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
):
1627 """creates a new Network Slice Instance (NSI)"""
1629 nsi_create(ctx
, nst_name
, nsi_name
, vim_account
, ssh_keys
, config
, config_file
, wait
=wait
)
1632 @cli_osm.command(name
='pdu-create', short_help
='adds a new Physical Deployment Unit to the catalog')
1633 @click.option('--name', help='name of the Physical Deployment Unit')
1634 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
1635 @click.option('--interface',
1636 help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
1637 '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
1639 @click.option('--description', help='human readable description')
1640 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple
=True)
1641 @click.option('--descriptor_file', default
=None,
1642 help='PDU descriptor file (as an alternative to using the other arguments')
1644 def pdu_create(ctx
, name
, pdu_type
, interface
, description
, vim_account
, descriptor_file
):
1645 """creates a new Physical Deployment Unit (PDU)"""
1648 check_client_version(ctx
.obj
, ctx
.command
.name
)
1650 if not descriptor_file
:
1652 raise ClientException('in absence of descriptor file, option "--name" is mandatory')
1654 raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
1656 raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
1658 raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
1660 with
open(descriptor_file
, 'r') as df
:
1661 pdu
= yaml
.safe_load(df
.read())
1662 if name
: pdu
["name"] = name
1663 if pdu_type
: pdu
["type"] = pdu_type
1664 if description
: pdu
["description"] = description
1665 if vim_account
: pdu
["vim_accounts"] = vim_account
1668 for iface
in interface
:
1669 new_iface
={k
:v
for k
,v
in [i
.split('=') for i
in iface
.split(',')]}
1670 new_iface
["mgmt"] = (new_iface
.get("mgmt","false").lower() == "true")
1671 ifaces_list
.append(new_iface
)
1672 pdu
["interfaces"] = ifaces_list
1673 ctx
.obj
.pdu
.create(pdu
)
1674 # except ClientException as e:
1679 ####################
1681 ####################
1683 def nsd_update(ctx
, name
, content
):
1686 check_client_version(ctx
.obj
, ctx
.command
.name
)
1687 ctx
.obj
.nsd
.update(name
, content
)
1688 # except ClientException as e:
1693 @cli_osm.command(name
='nsd-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_update1(ctx
, name
, content
):
1699 """updates a NSD/NSpkg
1701 NAME: name or ID of the NSD/NSpkg
1704 nsd_update(ctx
, name
, content
)
1707 @cli_osm.command(name
='nspkg-update', short_help
='updates a NSD/NSpkg')
1708 @click.argument('name')
1709 @click.option('--content', default
=None,
1710 help='filename with the NSD/NSpkg replacing the current one')
1712 def nsd_update2(ctx
, name
, content
):
1713 """updates a NSD/NSpkg
1715 NAME: name or ID of the NSD/NSpkg
1718 nsd_update(ctx
, name
, content
)
1721 def vnfd_update(ctx
, name
, content
):
1724 check_client_version(ctx
.obj
, ctx
.command
.name
)
1725 ctx
.obj
.vnfd
.update(name
, content
)
1726 # except ClientException as e:
1731 @cli_osm.command(name
='vnfd-update', short_help
='updates a new 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_update1(ctx
, name
, content
):
1737 """updates a VNFD/VNFpkg
1739 NAME: name or ID of the VNFD/VNFpkg
1742 vnfd_update(ctx
, name
, content
)
1745 @cli_osm.command(name
='vnfpkg-update', short_help
='updates a VNFD/VNFpkg')
1746 @click.argument('name')
1747 @click.option('--content', default
=None,
1748 help='filename with the VNFD/VNFpkg replacing the current one')
1750 def vnfd_update2(ctx
, name
, content
):
1751 """updates a VNFD/VNFpkg
1753 NAME: VNFD yaml file or VNFpkg tar.gz file
1756 vnfd_update(ctx
, name
, content
)
1759 @cli_osm.command(name
='nfpkg-update', short_help
='updates a NFpkg')
1760 @click.argument('name')
1761 @click.option('--content', default
=None,
1762 help='filename with the NFpkg replacing the current one')
1764 def nfpkg_update(ctx
, name
, content
):
1767 NAME: NF Descriptor yaml file or NFpkg tar.gz file
1770 vnfd_update(ctx
, name
, content
)
1773 def nst_update(ctx
, name
, content
):
1776 check_client_version(ctx
.obj
, ctx
.command
.name
)
1777 ctx
.obj
.nst
.update(name
, content
)
1778 # except ClientException as e:
1783 @cli_osm.command(name
='nst-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_update1(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 @cli_osm.command(name
='netslice-template-update', short_help
='updates a Network Slice Template (NST)')
1798 @click.argument('name')
1799 @click.option('--content', default
=None,
1800 help='filename with the NST/NSTpkg replacing the current one')
1802 def nst_update2(ctx
, name
, content
):
1803 """updates a Network Slice Template (NST)
1805 NAME: name or ID of the NSD/NSpkg
1808 nst_update(ctx
, name
, content
)
1811 ####################
1813 ####################
1815 def nsd_delete(ctx
, name
, force
):
1819 ctx
.obj
.nsd
.delete(name
)
1821 check_client_version(ctx
.obj
, '--force')
1822 ctx
.obj
.nsd
.delete(name
, force
)
1823 # except ClientException as e:
1828 @cli_osm.command(name
='nsd-delete', short_help
='deletes a NSD/NSpkg')
1829 @click.argument('name')
1830 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1832 def nsd_delete1(ctx
, name
, force
):
1833 """deletes a NSD/NSpkg
1835 NAME: name or ID of the NSD/NSpkg to be deleted
1838 nsd_delete(ctx
, name
, force
)
1841 @cli_osm.command(name
='nspkg-delete', short_help
='deletes a NSD/NSpkg')
1842 @click.argument('name')
1843 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1845 def nsd_delete2(ctx
, name
, force
):
1846 """deletes a NSD/NSpkg
1848 NAME: name or ID of the NSD/NSpkg to be deleted
1851 nsd_delete(ctx
, name
, force
)
1854 def vnfd_delete(ctx
, name
, force
):
1858 ctx
.obj
.vnfd
.delete(name
)
1860 check_client_version(ctx
.obj
, '--force')
1861 ctx
.obj
.vnfd
.delete(name
, force
)
1862 # except ClientException as e:
1867 @cli_osm.command(name
='vnfd-delete', short_help
='deletes a VNFD/VNFpkg')
1868 @click.argument('name')
1869 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1871 def vnfd_delete1(ctx
, name
, force
):
1872 """deletes a VNFD/VNFpkg
1874 NAME: name or ID of the VNFD/VNFpkg to be deleted
1877 vnfd_delete(ctx
, name
, force
)
1880 @cli_osm.command(name
='vnfpkg-delete', short_help
='deletes a VNFD/VNFpkg')
1881 @click.argument('name')
1882 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1884 def vnfd_delete2(ctx
, name
, force
):
1885 """deletes a VNFD/VNFpkg
1887 NAME: name or ID of the VNFD/VNFpkg to be deleted
1890 vnfd_delete(ctx
, name
, force
)
1893 @cli_osm.command(name
='nfpkg-delete', short_help
='deletes a NFpkg')
1894 @click.argument('name')
1895 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1897 def nfpkg_delete(ctx
, name
, force
):
1900 NAME: name or ID of the NFpkg to be deleted
1903 vnfd_delete(ctx
, name
, force
)
1906 @cli_osm.command(name
='ns-delete', short_help
='deletes a NS instance')
1907 @click.argument('name')
1908 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1909 @click.option('--wait',
1913 help='do not return the control immediately, but keep it '
1914 'until the operation is completed, or timeout')
1916 def ns_delete(ctx
, name
, force
, wait
):
1917 """deletes a NS instance
1919 NAME: name or ID of the NS instance to be deleted
1924 ctx
.obj
.ns
.delete(name
, wait
=wait
)
1926 check_client_version(ctx
.obj
, '--force')
1927 ctx
.obj
.ns
.delete(name
, force
, wait
=wait
)
1928 # except ClientException as e:
1933 def nst_delete(ctx
, name
, force
):
1936 check_client_version(ctx
.obj
, ctx
.command
.name
)
1937 ctx
.obj
.nst
.delete(name
, force
)
1938 # except ClientException as e:
1943 @cli_osm.command(name
='nst-delete', short_help
='deletes a Network Slice Template (NST)')
1944 @click.argument('name')
1945 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1947 def nst_delete1(ctx
, name
, force
):
1948 """deletes a Network Slice Template (NST)
1950 NAME: name or ID of the NST/NSTpkg to be deleted
1953 nst_delete(ctx
, name
, force
)
1956 @cli_osm.command(name
='netslice-template-delete', short_help
='deletes a Network Slice Template (NST)')
1957 @click.argument('name')
1958 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1960 def nst_delete2(ctx
, name
, force
):
1961 """deletes a Network Slice Template (NST)
1963 NAME: name or ID of the NST/NSTpkg to be deleted
1966 nst_delete(ctx
, name
, force
)
1969 def nsi_delete(ctx
, name
, force
, wait
):
1972 check_client_version(ctx
.obj
, ctx
.command
.name
)
1973 ctx
.obj
.nsi
.delete(name
, force
, wait
=wait
)
1974 # except ClientException as e:
1979 @cli_osm.command(name
='nsi-delete', short_help
='deletes a Network Slice Instance (NSI)')
1980 @click.argument('name')
1981 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
1982 @click.option('--wait',
1986 help='do not return the control immediately, but keep it '
1987 'until the operation is completed, or timeout')
1989 def nsi_delete1(ctx
, name
, force
, wait
):
1990 """deletes a Network Slice Instance (NSI)
1992 NAME: name or ID of the Network Slice instance to be deleted
1995 nsi_delete(ctx
, name
, force
, wait
=wait
)
1998 @cli_osm.command(name
='netslice-instance-delete', short_help
='deletes a Network Slice Instance (NSI)')
1999 @click.argument('name')
2000 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2002 def nsi_delete2(ctx
, name
, force
, wait
):
2003 """deletes a Network Slice Instance (NSI)
2005 NAME: name or ID of the Network Slice instance to be deleted
2008 nsi_delete(ctx
, name
, force
, wait
=wait
)
2011 @cli_osm.command(name
='pdu-delete', short_help
='deletes a Physical Deployment Unit (PDU)')
2012 @click.argument('name')
2013 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2015 def pdu_delete(ctx
, name
, force
):
2016 """deletes a Physical Deployment Unit (PDU)
2018 NAME: name or ID of the PDU to be deleted
2022 check_client_version(ctx
.obj
, ctx
.command
.name
)
2023 ctx
.obj
.pdu
.delete(name
, force
)
2024 # except ClientException as e:
2033 @cli_osm.command(name
='vim-create', short_help
='creates a new VIM account')
2034 @click.option('--name',
2036 help='Name to create datacenter')
2037 @click.option('--user',
2039 help='VIM username')
2040 @click.option('--password',
2043 confirmation_prompt
=True,
2044 help='VIM password')
2045 @click.option('--auth_url',
2048 @click.option('--tenant',
2050 help='VIM tenant name')
2051 @click.option('--config',
2053 help='VIM specific config parameters')
2054 @click.option('--account_type',
2055 default
='openstack',
2057 @click.option('--description',
2058 default
='no description',
2059 help='human readable description')
2060 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2061 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2062 @click.option('--wait',
2066 help='do not return the control immediately, but keep it '
2067 'until the operation is completed, or timeout')
2081 """creates a new VIM account"""
2085 check_client_version(ctx
.obj
, '--sdn_controller')
2086 if sdn_port_mapping
:
2087 check_client_version(ctx
.obj
, '--sdn_port_mapping')
2089 vim
['vim-username'] = user
2090 vim
['vim-password'] = password
2091 vim
['vim-url'] = auth_url
2092 vim
['vim-tenant-name'] = tenant
2093 vim
['vim-type'] = account_type
2094 vim
['description'] = description
2095 vim
['config'] = config
2096 if sdn_controller
or sdn_port_mapping
:
2097 ctx
.obj
.vim
.create(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2099 ctx
.obj
.vim
.create(name
, vim
, wait
=wait
)
2100 # except ClientException as e:
2105 @cli_osm.command(name
='vim-update', short_help
='updates a VIM account')
2106 @click.argument('name')
2107 @click.option('--newname', help='New name for the VIM account')
2108 @click.option('--user', help='VIM username')
2109 @click.option('--password', help='VIM password')
2110 @click.option('--auth_url', help='VIM url')
2111 @click.option('--tenant', help='VIM tenant name')
2112 @click.option('--config', help='VIM specific config parameters')
2113 @click.option('--account_type', help='VIM type')
2114 @click.option('--description', help='human readable description')
2115 @click.option('--sdn_controller', default
=None, help='Name or id of the SDN controller associated to this VIM account')
2116 @click.option('--sdn_port_mapping', default
=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2117 @click.option('--wait',
2121 help='do not return the control immediately, but keep it '
2122 'until the operation is completed, or timeout')
2137 """updates a VIM account
2139 NAME: name or ID of the VIM account
2143 check_client_version(ctx
.obj
, ctx
.command
.name
)
2145 if newname
: vim
['name'] = newname
2146 if user
: vim
['vim_user'] = user
2147 if password
: vim
['vim_password'] = password
2148 if auth_url
: vim
['vim_url'] = auth_url
2149 if tenant
: vim
['vim-tenant-name'] = tenant
2150 if account_type
: vim
['vim_type'] = account_type
2151 if description
: vim
['description'] = description
2152 if config
: vim
['config'] = config
2153 ctx
.obj
.vim
.update(name
, vim
, sdn_controller
, sdn_port_mapping
, wait
=wait
)
2154 # except ClientException as e:
2159 @cli_osm.command(name
='vim-delete', short_help
='deletes a VIM account')
2160 @click.argument('name')
2161 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2162 @click.option('--wait',
2166 help='do not return the control immediately, but keep it '
2167 'until the operation is completed, or timeout')
2169 def vim_delete(ctx
, name
, force
, wait
):
2170 """deletes a VIM account
2172 NAME: name or ID of the VIM account to be deleted
2177 ctx
.obj
.vim
.delete(name
, wait
=wait
)
2179 check_client_version(ctx
.obj
, '--force')
2180 ctx
.obj
.vim
.delete(name
, force
, wait
=wait
)
2181 # except ClientException as e:
2186 @cli_osm.command(name
='vim-list', short_help
='list all VIM accounts')
2187 #@click.option('--ro_update/--no_ro_update',
2189 # help='update list from RO')
2190 @click.option('--filter', default
=None,
2191 help='restricts the list to the VIM accounts matching the filter')
2193 def vim_list(ctx
, filter):
2194 """list all VIM accounts"""
2197 check_client_version(ctx
.obj
, '--filter')
2199 # check_client_version(ctx.obj, '--ro_update', 'v1')
2200 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
2201 if fullclassname
== 'osmclient.sol005.client.Client':
2202 resp
= ctx
.obj
.vim
.list(filter)
2204 # resp = ctx.obj.vim.list(ro_update)
2205 table
= PrettyTable(['vim name', 'uuid'])
2207 table
.add_row([vim
['name'], vim
['uuid']])
2212 @cli_osm.command(name
='vim-show', short_help
='shows the details of a VIM account')
2213 @click.argument('name')
2215 def vim_show(ctx
, name
):
2216 """shows the details of a VIM account
2218 NAME: name or ID of the VIM account
2222 resp
= ctx
.obj
.vim
.get(name
)
2223 if 'vim_password' in resp
:
2224 resp
['vim_password']='********'
2225 # except ClientException as e:
2229 table
= PrettyTable(['key', 'attribute'])
2230 for k
, v
in list(resp
.items()):
2231 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2236 ####################
2238 ####################
2240 @cli_osm.command(name
='wim-create', short_help
='creates a new WIM account')
2241 @click.option('--name',
2243 help='Name for the WIM account')
2244 @click.option('--user',
2245 help='WIM username')
2246 @click.option('--password',
2247 help='WIM password')
2248 @click.option('--url',
2251 # @click.option('--tenant',
2252 # help='wIM tenant name')
2253 @click.option('--config',
2255 help='WIM specific config parameters')
2256 @click.option('--wim_type',
2258 @click.option('--description',
2259 default
='no description',
2260 help='human readable description')
2261 @click.option('--wim_port_mapping', default
=None,
2262 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2263 "(WAN service endpoint id and info)")
2264 @click.option('--wait',
2268 help='do not return the control immediately, but keep it '
2269 'until the operation is completed, or timeout')
2282 """creates a new WIM account"""
2285 check_client_version(ctx
.obj
, ctx
.command
.name
)
2286 # if sdn_controller:
2287 # check_client_version(ctx.obj, '--sdn_controller')
2288 # if sdn_port_mapping:
2289 # check_client_version(ctx.obj, '--sdn_port_mapping')
2291 if user
: wim
['user'] = user
2292 if password
: wim
['password'] = password
2293 if url
: wim
['wim_url'] = url
2294 # if tenant: wim['tenant'] = tenant
2295 wim
['wim_type'] = wim_type
2296 if description
: wim
['description'] = description
2297 if config
: wim
['config'] = config
2298 ctx
.obj
.wim
.create(name
, wim
, wim_port_mapping
, wait
=wait
)
2299 # except ClientException as e:
2304 @cli_osm.command(name
='wim-update', short_help
='updates a WIM account')
2305 @click.argument('name')
2306 @click.option('--newname', help='New name for the WIM account')
2307 @click.option('--user', help='WIM username')
2308 @click.option('--password', help='WIM password')
2309 @click.option('--url', help='WIM url')
2310 @click.option('--config', help='WIM specific config parameters')
2311 @click.option('--wim_type', help='WIM type')
2312 @click.option('--description', help='human readable description')
2313 @click.option('--wim_port_mapping', default
=None,
2314 help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2315 "(WAN service endpoint id and info)")
2316 @click.option('--wait',
2320 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2333 """updates a WIM account
2335 NAME: name or ID of the WIM account
2339 check_client_version(ctx
.obj
, ctx
.command
.name
)
2341 if newname
: wim
['name'] = newname
2342 if user
: wim
['user'] = user
2343 if password
: wim
['password'] = password
2344 if url
: wim
['url'] = url
2345 # if tenant: wim['tenant'] = tenant
2346 if wim_type
: wim
['wim_type'] = wim_type
2347 if description
: wim
['description'] = description
2348 if config
: wim
['config'] = config
2349 ctx
.obj
.wim
.update(name
, wim
, wim_port_mapping
, wait
=wait
)
2350 # except ClientException as e:
2355 @cli_osm.command(name
='wim-delete', short_help
='deletes a WIM account')
2356 @click.argument('name')
2357 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2358 @click.option('--wait',
2362 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2364 def wim_delete(ctx
, name
, force
, wait
):
2365 """deletes a WIM account
2367 NAME: name or ID of the WIM account to be deleted
2371 check_client_version(ctx
.obj
, ctx
.command
.name
)
2372 ctx
.obj
.wim
.delete(name
, force
, wait
=wait
)
2373 # except ClientException as e:
2378 @cli_osm.command(name
='wim-list', short_help
='list all WIM accounts')
2379 @click.option('--filter', default
=None,
2380 help='restricts the list to the WIM accounts matching the filter')
2382 def wim_list(ctx
, filter):
2383 """list all WIM accounts"""
2386 check_client_version(ctx
.obj
, ctx
.command
.name
)
2387 resp
= ctx
.obj
.wim
.list(filter)
2388 table
= PrettyTable(['wim name', 'uuid'])
2390 table
.add_row([wim
['name'], wim
['uuid']])
2393 # except ClientException as e:
2398 @cli_osm.command(name
='wim-show', short_help
='shows the details of a WIM account')
2399 @click.argument('name')
2401 def wim_show(ctx
, name
):
2402 """shows the details of a WIM account
2404 NAME: name or ID of the WIM account
2408 check_client_version(ctx
.obj
, ctx
.command
.name
)
2409 resp
= ctx
.obj
.wim
.get(name
)
2410 if 'password' in resp
:
2411 resp
['wim_password']='********'
2412 # except ClientException as e:
2416 table
= PrettyTable(['key', 'attribute'])
2417 for k
, v
in list(resp
.items()):
2418 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2423 ####################
2424 # SDN controller operations
2425 ####################
2427 @cli_osm.command(name
='sdnc-create', short_help
='creates a new SDN controller')
2428 @click.option('--name',
2430 help='Name to create sdn controller')
2431 @click.option('--type',
2433 help='SDN controller type')
2434 @click.option('--sdn_controller_version', # hidden=True,
2435 help='Deprecated. Use --config {version: sdn_controller_version}')
2436 @click.option('--url',
2437 help='URL in format http[s]://HOST:IP/')
2438 @click.option('--ip_address', # hidden=True,
2439 help='Deprecated. Use --url')
2440 @click.option('--port', # hidden=True,
2441 help='Deprecated. Use --url')
2442 @click.option('--switch_dpid', # hidden=True,
2443 help='Deprecated. Use --config {dpid: DPID}')
2444 @click.option('--config',
2445 help='Extra information for SDN in yaml format, as {dpid: (Openflow Datapath ID), version: version}')
2446 @click.option('--user',
2447 help='SDN controller username')
2448 @click.option('--password',
2450 confirmation_prompt
=True,
2451 help='SDN controller password')
2452 @click.option('--description', default
=None, help='human readable description')
2453 @click.option('--wait',
2457 help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2459 def sdnc_create(ctx
, **kwargs
):
2460 """creates a new SDN controller"""
2462 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2463 x
not in ("wait", "ip_address", "port", "switch_dpid")}
2464 if kwargs
.get("port"):
2465 print("option '--port' is deprecated, use '-url' instead")
2466 sdncontroller
["port"] = int(kwargs
["port"])
2467 if kwargs
.get("ip_address"):
2468 print("option '--ip_address' is deprecated, use '-url' instead")
2469 sdncontroller
["ip"] = kwargs
["ip_address"]
2470 if kwargs
.get("switch_dpid"):
2471 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2472 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2473 if kwargs
.get("sdn_controller_version"):
2474 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2477 check_client_version(ctx
.obj
, ctx
.command
.name
)
2478 ctx
.obj
.sdnc
.create(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2479 # except ClientException as e:
2483 @cli_osm.command(name
='sdnc-update', short_help
='updates an SDN controller')
2484 @click.argument('name')
2485 @click.option('--newname', help='New name for the SDN controller')
2486 @click.option('--description', default
=None, help='human readable description')
2487 @click.option('--type', help='SDN controller type')
2488 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2489 @click.option('--config', help='Extra information for SDN in yaml format, as '
2490 '{dpid: (Openflow Datapath ID), version: version}')
2491 @click.option('--user', help='SDN controller username')
2492 @click.option('--password', help='SDN controller password')
2493 @click.option('--ip_address', help='Deprecated. Use --url') # hidden=True
2494 @click.option('--port', help='Deprecated. Use --url') # hidden=True
2495 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True
2496 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True
2497 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2498 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2500 def sdnc_update(ctx
, **kwargs
):
2501 """updates an SDN controller
2503 NAME: name or ID of the SDN controller
2506 sdncontroller
= {x
: kwargs
[x
] for x
in kwargs
if kwargs
[x
] and
2507 x
not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2508 if kwargs
.get("newname"):
2509 sdncontroller
["name"] = kwargs
["newname"]
2510 if kwargs
.get("port"):
2511 print("option '--port' is deprecated, use '-url' instead")
2512 sdncontroller
["port"] = int(kwargs
["port"])
2513 if kwargs
.get("ip_address"):
2514 print("option '--ip_address' is deprecated, use '-url' instead")
2515 sdncontroller
["ip"] = kwargs
["ip_address"]
2516 if kwargs
.get("switch_dpid"):
2517 print("option '--switch_dpid' is deprecated, use '---config={dpid: DPID}' instead")
2518 sdncontroller
["dpid"] = kwargs
["switch_dpid"]
2519 if kwargs
.get("sdn_controller_version"):
2520 print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2524 check_client_version(ctx
.obj
, ctx
.command
.name
)
2525 ctx
.obj
.sdnc
.update(kwargs
["name"], sdncontroller
, wait
=kwargs
["wait"])
2526 # except ClientException as e:
2531 @cli_osm.command(name
='sdnc-delete', short_help
='deletes an SDN controller')
2532 @click.argument('name')
2533 @click.option('--force', is_flag
=True, help='forces the deletion bypassing pre-conditions')
2534 @click.option('--wait', required
=False, default
=False, is_flag
=True,
2535 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2537 def sdnc_delete(ctx
, name
, force
, wait
):
2538 """deletes an SDN controller
2540 NAME: name or ID of the SDN controller to be deleted
2544 check_client_version(ctx
.obj
, ctx
.command
.name
)
2545 ctx
.obj
.sdnc
.delete(name
, force
, wait
=wait
)
2546 # except ClientException as e:
2551 @cli_osm.command(name
='sdnc-list', short_help
='list all SDN controllers')
2552 @click.option('--filter', default
=None,
2553 help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2555 def sdnc_list(ctx
, filter):
2556 """list all SDN controllers"""
2559 check_client_version(ctx
.obj
, ctx
.command
.name
)
2560 resp
= ctx
.obj
.sdnc
.list(filter)
2561 # except ClientException as e:
2564 table
= PrettyTable(['sdnc name', 'id'])
2566 table
.add_row([sdnc
['name'], sdnc
['_id']])
2571 @cli_osm.command(name
='sdnc-show', short_help
='shows the details of an SDN controller')
2572 @click.argument('name')
2574 def sdnc_show(ctx
, name
):
2575 """shows the details of an SDN controller
2577 NAME: name or ID of the SDN controller
2581 check_client_version(ctx
.obj
, ctx
.command
.name
)
2582 resp
= ctx
.obj
.sdnc
.get(name
)
2583 # except ClientException as e:
2587 table
= PrettyTable(['key', 'attribute'])
2588 for k
, v
in list(resp
.items()):
2589 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2594 ###########################
2595 # K8s cluster operations
2596 ###########################
2598 @cli_osm.command(name
='k8scluster-add', short_help
='adds a K8s cluster to OSM')
2599 @click.argument('name')
2600 @click.option('--creds',
2602 help='credentials file, i.e. a valid `.kube/config` file')
2603 @click.option('--version',
2605 help='Kubernetes version')
2606 @click.option('--vim',
2608 help='VIM target, the VIM where the cluster resides')
2609 @click.option('--k8s-nets',
2611 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) ...]}"')
2612 @click.option('--description',
2614 help='human readable description')
2615 @click.option('--namespace',
2616 default
='kube-system',
2617 help='namespace to be used for its operation, defaults to `kube-system`')
2618 @click.option('--cni',
2620 help='list of CNI plugins, in JSON inline format, used in the cluster')
2621 #@click.option('--skip-init',
2623 # help='If set, K8s cluster is assumed to be ready for its use with OSM')
2624 #@click.option('--wait',
2626 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2628 def k8scluster_add(ctx
,
2637 """adds a K8s cluster to OSM
2639 NAME: name of the K8s cluster
2642 check_client_version(ctx
.obj
, ctx
.command
.name
)
2644 cluster
['name'] = name
2645 with
open(creds
, 'r') as cf
:
2646 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2647 cluster
['k8s_version'] = version
2648 cluster
['vim_account'] = vim
2649 cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2650 cluster
['description'] = description
2651 if namespace
: cluster
['namespace'] = namespace
2652 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2653 ctx
.obj
.k8scluster
.create(name
, cluster
)
2654 # except ClientException as e:
2659 @cli_osm.command(name
='k8scluster-update', short_help
='updates a K8s cluster')
2660 @click.argument('name')
2661 @click.option('--newname', help='New name for the K8s cluster')
2662 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
2663 @click.option('--version', help='Kubernetes version')
2664 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
2665 @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) ...]}"')
2666 @click.option('--description', help='human readable description')
2667 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
2668 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
2670 def k8scluster_update(ctx
,
2680 """updates a K8s cluster
2682 NAME: name or ID of the K8s cluster
2685 check_client_version(ctx
.obj
, ctx
.command
.name
)
2687 if newname
: cluster
['name'] = newname
2689 with
open(creds
, 'r') as cf
:
2690 cluster
['credentials'] = yaml
.safe_load(cf
.read())
2691 if version
: cluster
['k8s_version'] = version
2692 if vim
: cluster
['vim_account'] = vim
2693 if k8s_nets
: cluster
['nets'] = yaml
.safe_load(k8s_nets
)
2694 if description
: cluster
['description'] = description
2695 if namespace
: cluster
['namespace'] = namespace
2696 if cni
: cluster
['cni'] = yaml
.safe_load(cni
)
2697 ctx
.obj
.k8scluster
.update(name
, cluster
)
2698 # except ClientException as e:
2703 @cli_osm.command(name
='k8scluster-delete', short_help
='deletes a K8s cluster')
2704 @click.argument('name')
2705 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2706 #@click.option('--wait',
2708 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2710 def k8scluster_delete(ctx
, name
, force
):
2711 """deletes a K8s cluster
2713 NAME: name or ID of the K8s cluster to be deleted
2716 check_client_version(ctx
.obj
, ctx
.command
.name
)
2717 ctx
.obj
.k8scluster
.delete(name
, force
=force
)
2718 # except ClientException as e:
2723 @cli_osm.command(name
='k8scluster-list')
2724 @click.option('--filter', default
=None,
2725 help='restricts the list to the K8s clusters matching the filter')
2726 @click.option('--literal', is_flag
=True,
2727 help='print literally, no pretty table')
2729 def k8scluster_list(ctx
, filter, literal
):
2730 """list all K8s clusters"""
2732 check_client_version(ctx
.obj
, ctx
.command
.name
)
2733 resp
= ctx
.obj
.k8scluster
.list(filter)
2735 print(yaml
.safe_dump(resp
))
2737 table
= PrettyTable(['Name', 'Id', 'Version', 'VIM', 'K8s-nets', 'Operational State', 'Description'])
2738 for cluster
in resp
:
2739 table
.add_row([cluster
['name'], cluster
['_id'], cluster
['k8s_version'], cluster
['vim_account'],
2740 json
.dumps(cluster
['nets']), cluster
["_admin"]["operationalState"],
2741 trunc_text(cluster
.get('description',''),40)])
2744 # except ClientException as e:
2749 @cli_osm.command(name
='k8scluster-show', short_help
='shows the details of a K8s cluster')
2750 @click.argument('name')
2751 @click.option('--literal', is_flag
=True,
2752 help='print literally, no pretty table')
2754 def k8scluster_show(ctx
, name
, literal
):
2755 """shows the details of a K8s cluster
2757 NAME: name or ID of the K8s cluster
2760 resp
= ctx
.obj
.k8scluster
.get(name
)
2762 print(yaml
.safe_dump(resp
))
2764 table
= PrettyTable(['key', 'attribute'])
2765 for k
, v
in list(resp
.items()):
2766 table
.add_row([k
, wrap_text(text
=json
.dumps(v
, indent
=2),width
=100)])
2769 # except ClientException as e:
2775 ###########################
2777 ###########################
2779 @cli_osm.command(name
='repo-add', short_help
='adds a repo to OSM')
2780 @click.argument('name')
2781 @click.argument('uri')
2782 @click.option('--type',
2783 type=click
.Choice(['helm-chart', 'juju-bundle']),
2785 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2786 @click.option('--description',
2788 help='human readable description')
2789 #@click.option('--wait',
2791 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2798 """adds a repo to OSM
2800 NAME: name of the repo
2801 URI: URI of the repo
2804 check_client_version(ctx
.obj
, ctx
.command
.name
)
2809 repo
['description'] = description
2810 ctx
.obj
.repo
.create(name
, repo
)
2811 # except ClientException as e:
2816 @cli_osm.command(name
='repo-update', short_help
='updates a repo in OSM')
2817 @click.argument('name')
2818 @click.option('--newname', help='New name for the repo')
2819 @click.option('--uri', help='URI of the repo')
2820 @click.option('--type', type=click
.Choice(['helm-chart', 'juju-bundle']),
2821 help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles)')
2822 @click.option('--description', help='human readable description')
2823 #@click.option('--wait',
2825 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2827 def repo_update(ctx
,
2833 """updates a repo in OSM
2835 NAME: name of the repo
2838 check_client_version(ctx
.obj
, ctx
.command
.name
)
2840 if newname
: repo
['name'] = newname
2841 if uri
: repo
['uri'] = uri
2842 if type: repo
['type'] = type
2843 if description
: repo
['description'] = description
2844 ctx
.obj
.repo
.update(name
, repo
)
2845 # except ClientException as e:
2850 @cli_osm.command(name
='repo-delete', short_help
='deletes a repo')
2851 @click.argument('name')
2852 @click.option('--force', is_flag
=True, help='forces the deletion from the DB (not recommended)')
2853 #@click.option('--wait',
2855 # help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2857 def repo_delete(ctx
, name
, force
):
2860 NAME: name or ID of the repo to be deleted
2863 check_client_version(ctx
.obj
, ctx
.command
.name
)
2864 ctx
.obj
.repo
.delete(name
, force
=force
)
2865 # except ClientException as e:
2870 @cli_osm.command(name
='repo-list')
2871 @click.option('--filter', default
=None,
2872 help='restricts the list to the repos matching the filter')
2873 @click.option('--literal', is_flag
=True,
2874 help='print literally, no pretty table')
2876 def repo_list(ctx
, filter, literal
):
2877 """list all repos"""
2879 check_client_version(ctx
.obj
, ctx
.command
.name
)
2880 resp
= ctx
.obj
.repo
.list(filter)
2882 print(yaml
.safe_dump(resp
))
2884 table
= PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
2886 #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
2887 table
.add_row([repo
['name'], repo
['_id'], repo
['type'], repo
['url'], trunc_text(repo
.get('description',''),40)])
2890 # except ClientException as e:
2895 @cli_osm.command(name
='repo-show', short_help
='shows the details of a repo')
2896 @click.argument('name')
2897 @click.option('--literal', is_flag
=True,
2898 help='print literally, no pretty table')
2900 def repo_show(ctx
, name
, literal
):
2901 """shows the details of a repo
2903 NAME: name or ID of the repo
2906 resp
= ctx
.obj
.repo
.get(name
)
2908 print(yaml
.safe_dump(resp
))
2910 table
= PrettyTable(['key', 'attribute'])
2911 for k
, v
in list(resp
.items()):
2912 table
.add_row([k
, json
.dumps(v
, indent
=2)])
2915 # except ClientException as e:
2921 ####################
2922 # Project mgmt operations
2923 ####################
2925 @cli_osm.command(name
='project-create', short_help
='creates a new project')
2926 @click.argument('name')
2927 #@click.option('--description',
2928 # default='no description',
2929 # help='human readable description')
2931 def project_create(ctx
, name
):
2932 """Creates a new project
2934 NAME: name of the project
2938 project
['name'] = name
2940 check_client_version(ctx
.obj
, ctx
.command
.name
)
2941 ctx
.obj
.project
.create(name
, project
)
2942 # except ClientException as e:
2947 @cli_osm.command(name
='project-delete', short_help
='deletes a project')
2948 @click.argument('name')
2949 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2951 def project_delete(ctx
, name
):
2952 """deletes a project
2954 NAME: name or ID of the project to be deleted
2958 check_client_version(ctx
.obj
, ctx
.command
.name
)
2959 ctx
.obj
.project
.delete(name
)
2960 # except ClientException as e:
2965 @cli_osm.command(name
='project-list', short_help
='list all projects')
2966 @click.option('--filter', default
=None,
2967 help='restricts the list to the projects matching the filter')
2969 def project_list(ctx
, filter):
2970 """list all projects"""
2973 check_client_version(ctx
.obj
, ctx
.command
.name
)
2974 resp
= ctx
.obj
.project
.list(filter)
2975 # except ClientException as e:
2978 table
= PrettyTable(['name', 'id'])
2980 table
.add_row([proj
['name'], proj
['_id']])
2985 @cli_osm.command(name
='project-show', short_help
='shows the details of a project')
2986 @click.argument('name')
2988 def project_show(ctx
, name
):
2989 """shows the details of a project
2991 NAME: name or ID of the project
2995 check_client_version(ctx
.obj
, ctx
.command
.name
)
2996 resp
= ctx
.obj
.project
.get(name
)
2997 # except ClientException as e:
3001 table
= PrettyTable(['key', 'attribute'])
3002 for k
, v
in resp
.items():
3003 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3008 @cli_osm.command(name
='project-update', short_help
='updates a project (only the name can be updated)')
3009 @click.argument('project')
3010 @click.option('--name',
3012 help='new name for the project')
3015 def project_update(ctx
, project
, name
):
3017 Update a project name
3020 :param project: id or name of the project to modify
3021 :param name: new name for the project
3025 project_changes
= {}
3026 project_changes
['name'] = name
3029 check_client_version(ctx
.obj
, ctx
.command
.name
)
3030 ctx
.obj
.project
.update(project
, project_changes
)
3031 # except ClientException as e:
3035 ####################
3036 # User mgmt operations
3037 ####################
3039 @cli_osm.command(name
='user-create', short_help
='creates a new user')
3040 @click.argument('username')
3041 @click.option('--password',
3044 confirmation_prompt
=True,
3045 help='user password')
3046 @click.option('--projects',
3047 # prompt="Comma separate list of projects",
3049 callback
=lambda ctx
, param
, value
: ''.join(value
).split(',') if all(len(x
)==1 for x
in value
) else value
,
3050 help='list of project ids that the user belongs to')
3051 @click.option('--project-role-mappings', 'project_role_mappings',
3052 default
=None, multiple
=True,
3053 help='creating user project/role(s) mapping')
3055 def user_create(ctx
, username
, password
, projects
, project_role_mappings
):
3056 """Creates a new user
3059 USERNAME: name of the user
3060 PASSWORD: password of the user
3061 PROJECTS: projects assigned to user (internal only)
3062 PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3066 user
['username'] = username
3067 user
['password'] = password
3068 user
['projects'] = projects
3069 user
['project_role_mappings'] = project_role_mappings
3072 check_client_version(ctx
.obj
, ctx
.command
.name
)
3073 ctx
.obj
.user
.create(username
, user
)
3074 # except ClientException as e:
3079 @cli_osm.command(name
='user-update', short_help
='updates user information')
3080 @click.argument('username')
3081 @click.option('--password',
3084 # confirmation_prompt=True,
3085 help='user password')
3086 @click.option('--set-username', 'set_username',
3088 help='change username')
3089 @click.option('--set-project', 'set_project',
3090 default
=None, multiple
=True,
3091 help='create/replace the project,role(s) mapping for this project: \'project,role1,role2,...\'')
3092 @click.option('--remove-project', 'remove_project',
3093 default
=None, multiple
=True,
3094 help='removes project from user: \'project\'')
3095 @click.option('--add-project-role', 'add_project_role',
3096 default
=None, multiple
=True,
3097 help='adds project,role(s) mapping: \'project,role1,role2,...\'')
3098 @click.option('--remove-project-role', 'remove_project_role',
3099 default
=None, multiple
=True,
3100 help='removes project,role(s) mapping: \'project,role1,role2,...\'')
3102 def user_update(ctx
, username
, password
, set_username
, set_project
, remove_project
,
3103 add_project_role
, remove_project_role
):
3104 """Update a user information
3107 USERNAME: name of the user
3108 PASSWORD: new password
3109 SET_USERNAME: new username
3110 SET_PROJECT: creating mappings for project/role(s)
3111 REMOVE_PROJECT: deleting mappings for project/role(s)
3112 ADD_PROJECT_ROLE: adding mappings for project/role(s)
3113 REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3117 user
['password'] = password
3118 user
['username'] = set_username
3119 user
['set-project'] = set_project
3120 user
['remove-project'] = remove_project
3121 user
['add-project-role'] = add_project_role
3122 user
['remove-project-role'] = remove_project_role
3125 check_client_version(ctx
.obj
, ctx
.command
.name
)
3126 ctx
.obj
.user
.update(username
, user
)
3127 # except ClientException as e:
3132 @cli_osm.command(name
='user-delete', short_help
='deletes a user')
3133 @click.argument('name')
3134 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3136 def user_delete(ctx
, name
):
3140 NAME: name or ID of the user to be deleted
3144 check_client_version(ctx
.obj
, ctx
.command
.name
)
3145 ctx
.obj
.user
.delete(name
)
3146 # except ClientException as e:
3151 @cli_osm.command(name
='user-list', short_help
='list all users')
3152 @click.option('--filter', default
=None,
3153 help='restricts the list to the users matching the filter')
3155 def user_list(ctx
, filter):
3156 """list all users"""
3158 check_client_version(ctx
.obj
, ctx
.command
.name
)
3159 resp
= ctx
.obj
.user
.list(filter)
3160 # except ClientException as e:
3163 table
= PrettyTable(['name', 'id'])
3165 table
.add_row([user
['username'], user
['_id']])
3170 @cli_osm.command(name
='user-show', short_help
='shows the details of a user')
3171 @click.argument('name')
3173 def user_show(ctx
, name
):
3174 """shows the details of a user
3176 NAME: name or ID of the user
3180 check_client_version(ctx
.obj
, ctx
.command
.name
)
3181 resp
= ctx
.obj
.user
.get(name
)
3182 if 'password' in resp
:
3183 resp
['password']='********'
3184 # except ClientException as e:
3188 table
= PrettyTable(['key', 'attribute'])
3189 for k
, v
in resp
.items():
3190 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3195 ####################
3196 # Fault Management operations
3197 ####################
3199 @cli_osm.command(name
='ns-alarm-create')
3200 @click.argument('name')
3201 @click.option('--ns', prompt
=True, help='NS instance id or name')
3202 @click.option('--vnf', prompt
=True,
3203 help='VNF name (VNF member index as declared in the NSD)')
3204 @click.option('--vdu', prompt
=True,
3205 help='VDU name (VDU name as declared in the VNFD)')
3206 @click.option('--metric', prompt
=True,
3207 help='Name of the metric (e.g. cpu_utilization)')
3208 @click.option('--severity', default
='WARNING',
3209 help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3210 @click.option('--threshold_value', prompt
=True,
3211 help='threshold value that, when crossed, an alarm is triggered')
3212 @click.option('--threshold_operator', prompt
=True,
3213 help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3214 @click.option('--statistic', default
='AVERAGE',
3215 help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3217 def ns_alarm_create(ctx
, name
, ns
, vnf
, vdu
, metric
, severity
,
3218 threshold_value
, threshold_operator
, statistic
):
3219 """creates a new alarm for a NS instance"""
3220 # TODO: Check how to validate threshold_value.
3221 # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3224 ns_instance
= ctx
.obj
.ns
.get(ns
)
3226 alarm
['alarm_name'] = name
3227 alarm
['ns_id'] = ns_instance
['_id']
3228 alarm
['correlation_id'] = ns_instance
['_id']
3229 alarm
['vnf_member_index'] = vnf
3230 alarm
['vdu_name'] = vdu
3231 alarm
['metric_name'] = metric
3232 alarm
['severity'] = severity
3233 alarm
['threshold_value'] = int(threshold_value
)
3234 alarm
['operation'] = threshold_operator
3235 alarm
['statistic'] = statistic
3236 check_client_version(ctx
.obj
, ctx
.command
.name
)
3237 ctx
.obj
.ns
.create_alarm(alarm
)
3238 # except ClientException as e:
3243 #@cli_osm.command(name='ns-alarm-delete')
3244 #@click.argument('name')
3245 #@click.pass_context
3246 #def ns_alarm_delete(ctx, name):
3247 # """deletes an alarm
3249 # NAME: name of the alarm to be deleted
3252 # check_client_version(ctx.obj, ctx.command.name)
3253 # ctx.obj.ns.delete_alarm(name)
3254 # except ClientException as e:
3259 ####################
3260 # Performance Management operations
3261 ####################
3263 @cli_osm.command(name
='ns-metric-export', short_help
='exports a metric to the internal OSM bus, which can be read by other apps')
3264 @click.option('--ns', prompt
=True, help='NS instance id or name')
3265 @click.option('--vnf', prompt
=True,
3266 help='VNF name (VNF member index as declared in the NSD)')
3267 @click.option('--vdu', prompt
=True,
3268 help='VDU name (VDU name as declared in the VNFD)')
3269 @click.option('--metric', prompt
=True,
3270 help='name of the metric (e.g. cpu_utilization)')
3271 #@click.option('--period', default='1w',
3272 # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3273 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3275 def ns_metric_export(ctx
, ns
, vnf
, vdu
, metric
, interval
):
3276 """exports a metric to the internal OSM bus, which can be read by other apps"""
3277 # TODO: Check how to validate interval.
3278 # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3281 ns_instance
= ctx
.obj
.ns
.get(ns
)
3283 metric_data
['ns_id'] = ns_instance
['_id']
3284 metric_data
['correlation_id'] = ns_instance
['_id']
3285 metric_data
['vnf_member_index'] = vnf
3286 metric_data
['vdu_name'] = vdu
3287 metric_data
['metric_name'] = metric
3288 metric_data
['collection_unit'] = 'WEEK'
3289 metric_data
['collection_period'] = 1
3290 check_client_version(ctx
.obj
, ctx
.command
.name
)
3292 print('{}'.format(ctx
.obj
.ns
.export_metric(metric_data
)))
3296 print('{} {}'.format(ctx
.obj
.ns
.export_metric(metric_data
),i
))
3297 time
.sleep(int(interval
))
3299 # except ClientException as e:
3304 ####################
3306 ####################
3308 @cli_osm.command(name
='version', short_help
='shows client and server versions')
3310 def get_version(ctx
):
3311 """shows client and server versions"""
3313 check_client_version(ctx
.obj
, "version")
3314 print ("Server version: {}".format(ctx
.obj
.get_version()))
3315 print ("Client version: {}".format(pkg_resources
.get_distribution("osmclient").version
))
3316 # except ClientException as e:
3320 @cli_osm.command(name
='upload-package', short_help
='uploads a VNF package or NS package')
3321 @click.argument('filename')
3323 def upload_package(ctx
, filename
):
3324 """uploads a VNF package or NS package
3326 FILENAME: VNF or NS package file (tar.gz)
3330 ctx
.obj
.package
.upload(filename
)
3331 fullclassname
= ctx
.obj
.__module
__ + "." + ctx
.obj
.__class
__.__name
__
3332 if fullclassname
!= 'osmclient.sol005.client.Client':
3333 ctx
.obj
.package
.wait_for_upload(filename
)
3334 # except ClientException as e:
3339 #@cli_osm.command(name='ns-scaling-show')
3340 #@click.argument('ns_name')
3341 #@click.pass_context
3342 #def show_ns_scaling(ctx, ns_name):
3343 # """shows the status of a NS scaling operation
3345 # NS_NAME: name of the NS instance being scaled
3348 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3349 # resp = ctx.obj.ns.list()
3350 # except ClientException as e:
3354 # table = PrettyTable(
3357 # 'operational status',
3362 # if ns_name == ns['name']:
3363 # nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3364 # scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3365 # for record in scaling_records:
3366 # if 'instance' in record:
3367 # instances = record['instance']
3368 # for inst in instances:
3370 # [record['scaling-group-name-ref'],
3371 # inst['instance-id'],
3372 # inst['op-status'],
3373 # time.strftime('%Y-%m-%d %H:%M:%S',
3375 # inst['create-time'])),
3381 #@cli_osm.command(name='ns-scale')
3382 #@click.argument('ns_name')
3383 #@click.option('--ns_scale_group', prompt=True)
3384 #@click.option('--index', prompt=True)
3385 #@click.option('--wait',
3389 # help='do not return the control immediately, but keep it \
3390 # until the operation is completed, or timeout')
3391 #@click.pass_context
3392 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3395 # NS_NAME: name of the NS instance to be scaled
3398 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3399 # ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3400 # except ClientException as e:
3405 #@cli_osm.command(name='config-agent-list')
3406 #@click.pass_context
3407 #def config_agent_list(ctx):
3408 # """list config agents"""
3410 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3411 # except ClientException as e:
3414 # table = PrettyTable(['name', 'account-type', 'details'])
3415 # for account in ctx.obj.vca.list():
3418 # account['account-type'],
3424 #@cli_osm.command(name='config-agent-delete')
3425 #@click.argument('name')
3426 #@click.pass_context
3427 #def config_agent_delete(ctx, name):
3428 # """deletes a config agent
3430 # NAME: name of the config agent to be deleted
3433 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3434 # ctx.obj.vca.delete(name)
3435 # except ClientException as e:
3440 #@cli_osm.command(name='config-agent-add')
3441 #@click.option('--name',
3443 #@click.option('--account_type',
3445 #@click.option('--server',
3447 #@click.option('--user',
3449 #@click.option('--secret',
3452 # confirmation_prompt=True)
3453 #@click.pass_context
3454 #def config_agent_add(ctx, name, account_type, server, user, secret):
3455 # """adds a config agent"""
3457 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3458 # ctx.obj.vca.create(name, account_type, server, user, secret)
3459 # except ClientException as e:
3464 #@cli_osm.command(name='ro-dump')
3465 #@click.pass_context
3467 # """shows RO agent information"""
3468 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3469 # resp = ctx.obj.vim.get_resource_orchestrator()
3470 # table = PrettyTable(['key', 'attribute'])
3471 # for k, v in list(resp.items()):
3472 # table.add_row([k, json.dumps(v, indent=2)])
3477 #@cli_osm.command(name='vcs-list')
3478 #@click.pass_context
3480 # check_client_version(ctx.obj, ctx.command.name, 'v1')
3481 # resp = ctx.obj.utils.get_vcs_info()
3482 # table = PrettyTable(['component name', 'state'])
3483 # for component in resp:
3484 # table.add_row([component['component_name'], component['state']])
3489 @cli_osm.command(name
='ns-action', short_help
='executes an action/primitive over a NS instance')
3490 @click.argument('ns_name')
3491 @click.option('--vnf_name', default
=None, help='member-vnf-index if the target is a vnf instead of a ns)')
3492 @click.option('--kdu_name', default
=None, help='kdu-name if the target is a kdu)')
3493 @click.option('--vdu_id', default
=None, help='vdu-id if the target is a vdu')
3494 @click.option('--vdu_count', default
=None, help='number of vdu instance of this vdu_id')
3495 @click.option('--action_name', prompt
=True, help='action name')
3496 @click.option('--params', default
=None, help='action params in YAML/JSON inline string')
3497 @click.option('--params_file', default
=None, help='YAML/JSON file with action params')
3498 @click.option('--wait',
3502 help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3514 """executes an action/primitive over a NS instance
3516 NS_NAME: name or ID of the NS instance
3520 check_client_version(ctx
.obj
, ctx
.command
.name
)
3523 op_data
['member_vnf_index'] = vnf_name
3525 op_data
['kdu_name'] = kdu_name
3527 op_data
['vdu_id'] = vdu_id
3529 op_data
['vdu_count_index'] = vdu_count
3530 op_data
['primitive'] = action_name
3532 with
open(params_file
, 'r') as pf
:
3535 op_data
['primitive_params'] = yaml
.safe_load(params
)
3537 op_data
['primitive_params'] = {}
3538 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
='action', op_data
=op_data
, wait
=wait
))
3540 # except ClientException as e:
3545 @cli_osm.command(name
='vnf-scale', short_help
='executes a VNF scale (adding/removing VDUs)')
3546 @click.argument('ns_name')
3547 @click.argument('vnf_name')
3548 @click.option('--scaling-group', prompt
=True, help="scaling-group-descriptor name to use")
3549 @click.option('--scale-in', default
=False, is_flag
=True, help="performs a scale in operation")
3550 @click.option('--scale-out', default
=False, is_flag
=True, help="performs a scale out operation (by default)")
3559 Executes a VNF scale (adding/removing VDUs)
3562 NS_NAME: name or ID of the NS instance.
3563 VNF_NAME: member-vnf-index in the NS to be scaled.
3567 check_client_version(ctx
.obj
, ctx
.command
.name
)
3568 if not scale_in
and not scale_out
:
3570 ctx
.obj
.ns
.scale_vnf(ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
)
3571 # except ClientException as e:
3576 ##############################
3577 # Role Management Operations #
3578 ##############################
3580 @cli_osm.command(name
='role-create', short_help
='creates a new role')
3581 @click.argument('name')
3582 @click.option('--permissions',
3584 help='role permissions using a dictionary')
3586 def role_create(ctx
, name
, permissions
):
3591 NAME: Name or ID of the role.
3592 DEFINITION: Definition of grant/denial of access to resources.
3596 check_client_version(ctx
.obj
, ctx
.command
.name
)
3597 ctx
.obj
.role
.create(name
, permissions
)
3598 # except ClientException as e:
3603 @cli_osm.command(name
='role-update', short_help
='updates a role')
3604 @click.argument('name')
3605 @click.option('--set-name',
3607 help='change name of rle')
3608 # @click.option('--permissions',
3610 # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
3611 @click.option('--add',
3613 help='yaml format dictionary with permission: True/False to access grant/denial')
3614 @click.option('--remove',
3616 help='yaml format list to remove a permission')
3618 def role_update(ctx
, name
, set_name
, add
, remove
):
3623 NAME: Name or ID of the role.
3624 DEFINITION: Definition overwrites the old definition.
3625 ADD: Grant/denial of access to resource to add.
3626 REMOVE: Grant/denial of access to resource to remove.
3630 check_client_version(ctx
.obj
, ctx
.command
.name
)
3631 ctx
.obj
.role
.update(name
, set_name
, None, add
, remove
)
3632 # except ClientException as e:
3637 @cli_osm.command(name
='role-delete', short_help
='deletes a role')
3638 @click.argument('name')
3639 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3641 def role_delete(ctx
, name
):
3646 NAME: Name or ID of the role.
3650 check_client_version(ctx
.obj
, ctx
.command
.name
)
3651 ctx
.obj
.role
.delete(name
)
3652 # except ClientException as e:
3657 @cli_osm.command(name
='role-list', short_help
='list all roles')
3658 @click.option('--filter', default
=None,
3659 help='restricts the list to the projects matching the filter')
3661 def role_list(ctx
, filter):
3667 check_client_version(ctx
.obj
, ctx
.command
.name
)
3668 resp
= ctx
.obj
.role
.list(filter)
3669 # except ClientException as e:
3672 table
= PrettyTable(['name', 'id'])
3674 table
.add_row([role
['name'], role
['_id']])
3679 @cli_osm.command(name
='role-show', short_help
='show specific role')
3680 @click.argument('name')
3682 def role_show(ctx
, name
):
3684 Shows the details of a role.
3687 NAME: Name or ID of the role.
3691 check_client_version(ctx
.obj
, ctx
.command
.name
)
3692 resp
= ctx
.obj
.role
.get(name
)
3693 # except ClientException as e:
3697 table
= PrettyTable(['key', 'attribute'])
3698 for k
, v
in resp
.items():
3699 table
.add_row([k
, json
.dumps(v
, indent
=2)])
3704 @cli_osm.command(name
='package-create',
3705 short_help
='Create a package descriptor')
3706 @click.argument('package-type')
3707 @click.argument('package-name')
3708 @click.option('--base-directory',
3710 help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
3711 @click.option('--image',
3712 default
="image-name",
3713 help='(VNF) Set the name of the vdu image. Default "image-name"')
3714 @click.option('--vdus',
3716 help='(VNF) Set the number of vdus in a VNF. Default 1')
3717 @click.option('--vcpu',
3719 help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
3720 @click.option('--memory',
3722 help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
3723 @click.option('--storage',
3725 help='(VNF) Set the disk size (GB) of the vdu. Default 10')
3726 @click.option('--interfaces',
3728 help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
3729 @click.option('--vendor',
3731 help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
3732 @click.option('--override',
3735 help='(NS/VNF/NST) Flag for overriding the package if exists.')
3736 @click.option('--detailed',
3739 help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
3740 @click.option('--netslice-subnets',
3742 help='(NST) Number of netslice subnets. Default 1')
3743 @click.option('--netslice-vlds',
3745 help='(NST) Number of netslice vlds. Default 1')
3747 def package_create(ctx
,
3763 Creates an OSM NS, VNF, NST package
3766 PACKAGE_TYPE: Package to be created: NS, VNF or NST.
3767 PACKAGE_NAME: Name of the package to create the folder with the content.
3771 check_client_version(ctx
.obj
, ctx
.command
.name
)
3772 print("Creating the {} structure: {}/{}".format(package_type
.upper(), base_directory
, package_name
))
3773 resp
= ctx
.obj
.package_tool
.create(package_type
,
3782 interfaces
=interfaces
,
3785 netslice_subnets
=netslice_subnets
,
3786 netslice_vlds
=netslice_vlds
)
3788 # except ClientException as inst:
3789 # print("ERROR: {}".format(inst))
3792 @cli_osm.command(name
='package-validate',
3793 short_help
='Validate a package descriptor')
3794 @click.argument('base-directory',
3798 def package_validate(ctx
,
3801 Validate descriptors given a base directory.
3804 BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
3807 check_client_version(ctx
.obj
, ctx
.command
.name
)
3808 results
= ctx
.obj
.package_tool
.validate(base_directory
)
3809 table
= PrettyTable()
3810 table
.field_names
= ["TYPE", "PATH", "VALID", "ERROR"]
3811 # Print the dictionary generated by the validation function
3812 for result
in results
:
3813 table
.add_row([result
["type"], result
["path"], result
["valid"], result
["error"]])
3814 table
.sortby
= "VALID"
3815 table
.align
["PATH"] = "l"
3816 table
.align
["TYPE"] = "l"
3817 table
.align
["ERROR"] = "l"
3819 # except ClientException as inst:
3820 # print("ERROR: {}".format(inst))
3823 @cli_osm.command(name
='package-build',
3824 short_help
='Build the tar.gz of the package')
3825 @click.argument('package-folder')
3826 @click.option('--skip-validation',
3829 help='skip package validation')
3831 def package_build(ctx
,
3835 Build the package NS, VNF given the package_folder.
3838 PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
3841 check_client_version(ctx
.obj
, ctx
.command
.name
)
3842 results
= ctx
.obj
.package_tool
.build(package_folder
, skip_validation
)
3844 # except ClientException as inst:
3845 # print("ERROR: {}".format(inst))
3853 except pycurl
.error
as exc
:
3855 print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
3856 except ClientException
as exc
:
3857 print("ERROR: {}".format(exc
))
3858 except (FileNotFoundError
, PermissionError
) as exc
:
3859 print("Cannot open file: {}".format(exc
))
3860 except yaml
.YAMLError
as exc
:
3861 print("Invalid YAML format: {}".format(exc
))
3863 # TODO capture other controlled exceptions here
3864 # TODO remove the ClientException captures from all places, unless they do something different
3867 if __name__
== '__main__':