1 # Copyright ETSI Contributors and Others.
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
17 from osmclient
.common
.exceptions
import ClientException
18 from osmclient
.common
.utils
import validate_uuid4
19 from osmclient
.cli_commands
import utils
23 logger
= logging
.getLogger("osmclient")
27 name
="ns-action", short_help
="executes an action/primitive over a NS instance"
29 @click.argument("ns_name")
33 help="member-vnf-index if the target is a vnf instead of a ns)",
35 @click.option("--kdu_name", default
=None, help="kdu-name if the target is a kdu)")
36 @click.option("--vdu_id", default
=None, help="vdu-id if the target is a vdu")
38 "--vdu_count", default
=None, type=int, help="number of vdu instance of this vdu_id"
40 @click.option("--action_name", prompt
=True, help="action name")
41 @click.option("--params", default
=None, help="action params in YAML/JSON inline string")
42 @click.option("--params_file", default
=None, help="YAML/JSON file with action params")
44 "--timeout", required
=False, default
=None, type=int, help="timeout in seconds"
51 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
67 """executes an action/primitive over a NS instance
69 NS_NAME: name or ID of the NS instance
72 utils
.check_client_version(ctx
.obj
, ctx
.command
.name
)
75 op_data
["member_vnf_index"] = vnf_name
77 op_data
["kdu_name"] = kdu_name
79 op_data
["vdu_id"] = vdu_id
80 if vdu_count
is not None:
81 op_data
["vdu_count_index"] = vdu_count
83 op_data
["timeout_ns_action"] = timeout
84 op_data
["primitive"] = action_name
86 with
open(params_file
, "r") as pf
:
89 op_data
["primitive_params"] = yaml
.safe_load(params
)
91 op_data
["primitive_params"] = {}
92 print(ctx
.obj
.ns
.exec_op(ns_name
, op_name
="action", op_data
=op_data
, wait
=wait
))
96 name
="vnf-scale", short_help
="executes a VNF scale (adding/removing VDUs)"
98 @click.argument("ns_name")
99 @click.argument("vnf_name")
101 "--scaling-group", prompt
=True, help="scaling-group-descriptor name to use"
104 "--scale-in", default
=False, is_flag
=True, help="performs a scale in operation"
110 help="performs a scale out operation (by default)",
113 "--timeout", required
=False, default
=None, type=int, help="timeout in seconds"
120 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
124 ctx
, ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, timeout
, wait
127 Executes a VNF scale (adding/removing VDUs)
130 NS_NAME: name or ID of the NS instance.
131 VNF_NAME: member-vnf-index in the NS to be scaled.
134 utils
.check_client_version(ctx
.obj
, ctx
.command
.name
)
135 if not scale_in
and not scale_out
:
137 ctx
.obj
.ns
.scale_vnf(
138 ns_name
, vnf_name
, scaling_group
, scale_in
, scale_out
, wait
, timeout
142 @click.command(name
="ns-update", short_help
="executes an update of a Network Service.")
143 @click.argument("ns_name")
145 "--updatetype", required
=True, type=str, help="available types: CHANGE_VNFPKG"
151 help="extra information for update operation as YAML/JSON inline string as --config"
152 " '{changeVnfPackageData:[{vnfInstanceId: xxx, vnfdId: yyy}]}'",
155 "--timeout", required
=False, default
=None, type=int, help="timeout in seconds"
162 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
165 def ns_update(ctx
, ns_name
, updatetype
, config
, timeout
, wait
):
166 """Executes an update of a Network Service.
168 The update will check new revisions of the Network Functions that are part of the
169 Network Service, and it will update them if needed.
170 Sample update command: osm ns-update ns_instance_id --updatetype CHANGE_VNFPKG
171 --config '{changeVnfPackageData: [{vnfInstanceId: id_x,vnfdId: id_y}]}' --timeout 300 --wait
173 NS_NAME: Network service instance name or ID.
178 "updateType": updatetype
,
181 op_data
["config"] = yaml
.safe_load(config
)
183 utils
.check_client_version(ctx
.obj
, ctx
.command
.name
)
184 ctx
.obj
.ns
.update(ns_name
, op_data
, wait
=wait
)
187 def iterator_split(iterator
, separators
):
189 Splits a tuple or list into several lists whenever a separator is found
190 For instance, the following tuple will be separated with the separator "--vnf" as follows.
192 ("--vnf", "A", "--cause", "cause_A", "--vdu", "vdu_A1", "--vnf", "B", "--cause", "cause_B", ...
193 "--vdu", "vdu_B1", "--count_index", "1", "--run-day1", "--vdu", "vdu_B1", "--count_index", "2")
196 ("--vnf", "A", "--cause", "cause_A", "--vdu", "vdu_A1"),
197 ("--vnf", "B", "--cause", "cause_B", "--vdu", "vdu_B1", "--count_index", "1", "--run-day1", ...
198 "--vdu", "vdu_B1", "--count_index", "2")
201 Returns as many lists as separators are found
204 if iterator
[0] not in separators
:
205 raise ClientException(f
"Expected one of {separators}. Received: {iterator[0]}.")
208 for i
in range(len(iterator
)):
209 if iterator
[i
] in separators
:
213 raise ClientException(
214 f
"Expected at least one argument after separator (possible separators: {separators})."
216 list_of_lists
.append(list(iterator
[first
:i
]))
218 if (len(iterator
) - first
) < 2:
219 raise ClientException(
220 f
"Expected at least one argument after separator (possible separators: {separators})."
223 list_of_lists
.append(list(iterator
[first
: len(iterator
)]))
224 # logger.debug(f"List of lists: {list_of_lists}")
228 def process_common_heal_params(heal_vnf_dict
, args
):
233 if args
[i
] == "--cause":
234 if (i
+ 1 >= len(args
)) or args
[i
+ 1].startswith("--"):
235 raise ClientException("No cause was provided after --cause")
236 heal_vnf_dict
["cause"] = args
[i
+ 1]
239 if args
[i
] == "--run-day1":
240 if current_item
== "vnf":
241 if "additionalParams" not in heal_vnf_dict
:
242 heal_vnf_dict
["additionalParams"] = {}
243 heal_vnf_dict
["additionalParams"]["run-day1"] = True
245 # if current_item == "vdu"
246 heal_vnf_dict
["additionalParams"]["vdu"][-1]["run-day1"] = True
249 if args
[i
] == "--vdu":
250 if "additionalParams" not in heal_vnf_dict
:
251 heal_vnf_dict
["additionalParams"] = {}
252 heal_vnf_dict
["additionalParams"]["vdu"] = []
253 if (i
+ 1 >= len(args
)) or args
[i
+ 1].startswith("--"):
254 raise ClientException("No VDU ID was provided after --vdu")
255 heal_vnf_dict
["additionalParams"]["vdu"].append({"vdu-id": args
[i
+ 1]})
259 if args
[i
] == "--count-index":
260 if current_item
== "vnf":
261 raise ClientException(
262 "Option --count-index only applies to VDU, not to VNF"
264 if (i
+ 1 >= len(args
)) or args
[i
+ 1].startswith("--"):
265 raise ClientException("No count index was provided after --count-index")
266 heal_vnf_dict
["additionalParams"]["vdu"][-1]["count-index"] = int(
275 def process_ns_heal_params(ctx
, param
, value
):
277 Processes the params in the command ns-heal
278 Click does not allow advanced patterns for positional options like this:
279 --vnf volumes_vnf --cause "Heal several_volumes-VM of several_volumes_vnf"
280 --vdu several_volumes-VM
281 --vnf charm_vnf --cause "Heal two VMs of native_manual_scale_charm_vnf"
282 --vdu mgmtVM --count-index 1 --run-day1
283 --vdu mgmtVM --count-index 2
285 It returns the dictionary with all the params stored in ctx.params["heal_params"]
288 # logger.debug(f"Args: {value}")
289 if param
.name
!= "args":
290 raise ClientException(f
"Unexpected param: {param.name}")
291 # Split the tuple "value" by "--vnf"
292 vnfs
= iterator_split(value
, ["--vnf"])
293 logger
.debug(f
"VNFs: {vnfs}")
295 heal_dict
["healVnfData"] = []
297 # logger.debug(f"VNF: {vnf}")
299 if vnf
[1].startswith("--"):
300 raise ClientException("Expected a VNF_ID after --vnf")
301 heal_vnf
["vnfInstanceId"] = vnf
[1]
302 process_common_heal_params(heal_vnf
, vnf
[2:])
303 heal_dict
["healVnfData"].append(heal_vnf
)
304 ctx
.params
["heal_params"] = heal_dict
310 short_help
="heals (recreates) VNFs or VDUs of a NS instance",
311 context_settings
=dict(
312 ignore_unknown_options
=True,
315 @click.argument("ns_name")
319 type=click
.UNPROCESSED
,
320 callback
=process_ns_heal_params
,
322 @click.option("--timeout", type=int, default
=None, help="timeout in seconds")
327 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
330 def ns_heal(ctx
, ns_name
, args
, heal_params
, timeout
, wait
):
331 """heals (recreates) VNFs or VDUs of a NS instance
333 NS_NAME: name or ID of the NS instance
337 --vnf TEXT VNF instance ID or VNF id in the NS [required]
338 --cause TEXT human readable cause of the healing
339 --run-day1 indicates whether or not to run day1 primitives for the VNF/VDU
341 --count-index INTEGER count-index
345 osm ns-heal NS_NAME|NS_ID --vnf volumes_vnf --cause "Heal several_volumes-VM of several_volumes_vnf"
346 --vdu several_volumes-VM
347 --vnf charm_vnf --cause "Heal two VMs of native_manual_scale_charm_vnf"
348 --vdu mgmtVM --count-index 1 --run-day1
349 --vdu mgmtVM --count-index 2
352 heal_dict
= ctx
.params
["heal_params"]
353 logger
.debug(f
"Heal dict:\n{yaml.safe_dump(heal_dict)}")
354 # replace VNF id in the NS by the VNF instance ID
355 for vnf
in heal_dict
["healVnfData"]:
356 vnf_id
= vnf
["vnfInstanceId"]
357 if not validate_uuid4(vnf_id
):
358 vnf_filter
= f
"member-vnf-index-ref={vnf_id}"
359 vnf_list
= ctx
.obj
.vnf
.list(ns
=ns_name
, filter=vnf_filter
)
360 if len(vnf_list
) == 0:
361 raise ClientException(
362 f
"No VNF found in NS {ns_name} with filter {vnf_filter}"
364 elif len(vnf_list
) == 1:
365 vnf
["vnfInstanceId"] = vnf_list
[0]["_id"]
367 raise ClientException(
368 f
"More than 1 VNF found in NS {ns_name} with filter {vnf_filter}"
370 logger
.debug(f
"Heal dict:\n{yaml.safe_dump(heal_dict)}")
371 utils
.check_client_version(ctx
.obj
, ctx
.command
.name
)
372 ctx
.obj
.ns
.heal(ns_name
, heal_dict
, wait
, timeout
)
375 def process_vnf_heal_params(ctx
, param
, value
):
377 Processes the params in the command vnf-heal
378 Click does not allow advanced patterns for positional options like this:
379 --vdu mgmtVM --count-index 1 --run-day1 --vdu mgmtVM --count-index 2
381 It returns the dictionary with all the params stored in ctx.params["heal_params"]
384 # logger.debug(f"Args: {value}")
385 if param
.name
!= "args":
386 raise ClientException(f
"Unexpected param: {param.name}")
387 # Split the tuple "value" by "--vnf"
390 heal_dict
["healVnfData"] = []
391 logger
.debug(f
"VNF: {vnf}")
392 heal_vnf
= {"vnfInstanceId": "id_to_be_substituted"}
393 process_common_heal_params(heal_vnf
, vnf
)
394 heal_dict
["healVnfData"].append(heal_vnf
)
395 ctx
.params
["heal_params"] = heal_dict
401 short_help
="heals (recreates) a VNF instance or the VDUs of a VNF instance",
402 context_settings
=dict(
403 ignore_unknown_options
=True,
406 @click.argument("vnf_name")
410 type=click
.UNPROCESSED
,
411 callback
=process_vnf_heal_params
,
413 @click.option("--timeout", type=int, default
=None, help="timeout in seconds")
418 help="do not return the control immediately, but keep it until the operation is completed, or timeout",
429 """heals (recreates) a VNF instance or the VDUs of a VNF instance
431 VNF_NAME: name or ID of the VNF instance
435 --cause TEXT human readable cause of the healing of the VNF
436 --run-day1 indicates whether or not to run day1 primitives for the VNF/VDU
438 --count-index INTEGER count-index
442 osm vnf-heal VNF_INSTANCE_ID --vdu mgmtVM --count-index 1 --run-day1
443 --vdu mgmtVM --count-index 2
446 heal_dict
= ctx
.params
["heal_params"]
447 heal_dict
["healVnfData"][-1]["vnfInstanceId"] = vnf_name
448 logger
.debug(f
"Heal dict:\n{yaml.safe_dump(heal_dict)}")
449 utils
.check_client_version(ctx
.obj
, ctx
.command
.name
)
450 vnfr
= ctx
.obj
.vnf
.get(vnf_name
)
451 ns_id
= vnfr
["nsr-id-ref"]
452 ctx
.obj
.ns
.heal(ns_id
, heal_dict
, wait
, timeout
)