Skip to content

Commit 53f709f

Browse files
authored
Merge pull request #364 from ScaleComputing/any-version-upgrade
Support HyperCore version update to any version
2 parents 6ea2c66 + 322462d commit 53f709f

File tree

10 files changed

+77
-25
lines changed

10 files changed

+77
-25
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
major_changes:
3+
- Support HyperCore update to arbitrary version, even if it is not listed under available updates.
4+
(https://github.com/ScaleComputing/HyperCoreAnsibleCollection/pull/364)

examples/version_update_single_node.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
check_mode: true
88

99
vars:
10-
desired_version: 9.2.22.212325
10+
desired_version: 9.5.5.219383
11+
force_update: false
1112

1213
tasks:
1314
- name: Show desired_version
@@ -36,3 +37,4 @@
3637
name: scale_computing.hypercore.version_update_single_node
3738
vars:
3839
version_update_single_node_desired_version: "{{ desired_version }}"
40+
version_update_single_node_force_update: "{{ force_update }}"

plugins/module_utils/errors.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ class AuthError(ScaleComputingError):
2020
pass
2121

2222

23+
class InvalidModuleParam(ScaleComputingError):
24+
def __init__(self, message: str):
25+
self.message = message
26+
super(InvalidModuleParam, self).__init__(self.message)
27+
28+
2329
class UnexpectedAPIResponse(ScaleComputingError):
2430
def __init__(self, response: Request):
2531
self.message = "Unexpected response - {0} {1}".format(

plugins/module_utils/hypercore_version.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,15 @@ def get(
245245
)
246246
return cls.from_hypercore(update)
247247

248-
def apply(self, rest_client: RestClient, check_mode: bool = False) -> TypedTaskTag:
248+
@classmethod
249+
def apply_update(
250+
cls: type["Update"],
251+
rest_client: RestClient,
252+
version: str,
253+
check_mode: bool = False,
254+
) -> TypedTaskTag:
249255
return rest_client.create_record(
250-
f"/rest/v1/Update/{self.uuid}/apply", payload=None, check_mode=check_mode
256+
f"/rest/v1/Update/{version}/apply", payload=None, check_mode=check_mode
251257
)
252258

253259

plugins/modules/dns_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ def build_entry_list(
135135
if module_entry_list is None:
136136
return api_entry_list, False
137137

138+
new_entry_list = [] # make pylint happy
138139
if module_entry_list is not None:
139140
if state == "set":
140141
new_entry_list = module_entry_list

plugins/modules/version_update.py

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030
- Hypercore version update to be installed on the cluster.
3131
type: str
3232
required: true
33+
force_update:
34+
description:
35+
- Upgrade the HyperCore cluster to the requested version,
36+
even if requested version is not listed under available versions of the HyperCore cluster.
37+
type: bool
38+
default: false
3339
notes:
3440
- C(check_mode) is not supported.
3541
"""
@@ -51,15 +57,19 @@
5157
type: dict
5258
contains:
5359
uuid:
54-
description: Unique identifier in format major_version.minor_version.revision.build_id
60+
description: Unique identifier in format major_version.minor_version.revision.build_id.
5561
type: str
5662
sample: 9.2.11.210763
5763
description:
58-
description: Human-readable name for the update
64+
description: |
65+
Human-readable name for the update.
66+
Empty if I(force_update=true).
5967
type: str
6068
sample: 9.2.11 General Availability
6169
change_log:
62-
description: Description of all changes that are in this update, in HTML format
70+
description: |
71+
Description of all changes that are in this update, in HTML format.
72+
Empty if I(force_update=true).
6373
type: str
6474
sample: ...Please allow between 20-40 minutes per node for the update to complete...
6575
build_id:
@@ -79,7 +89,9 @@
7989
type: int
8090
sample: 11
8191
timestamp:
82-
description: Unix timestamp when the update was released
92+
description: |
93+
Unix timestamp when the update was released.
94+
Value of 0 is returned if I(force_update=true).
8395
type: int
8496
sample: 0
8597
"""
@@ -99,7 +111,8 @@ def run(
99111
module: AnsibleModule, rest_client: RestClient
100112
) -> Tuple[bool, Optional[TypedUpdateToAnsible], Dict[Any, Any]]:
101113
cluster = Cluster.get(rest_client)
102-
if cluster.icos_version == module.params["icos_version"]:
114+
new_icos_version = module.params["icos_version"]
115+
if cluster.icos_version == new_icos_version:
103116
return (
104117
False,
105118
None,
@@ -108,14 +121,33 @@ def run(
108121
after=dict(icos_version=cluster.icos_version),
109122
),
110123
)
111-
update = Update.get(rest_client, module.params["icos_version"], must_exist=True)
112-
update.apply(rest_client) # type: ignore
124+
update = None
125+
if module.params["force_update"]:
126+
if len(new_icos_version.split(".")) != 4:
127+
msg = f"HyperCore version must be in format 'major_version.minor_version.revision.build_id' - value {new_icos_version} is not valid."
128+
raise errors.InvalidModuleParam(msg)
129+
update = Update(
130+
uuid=new_icos_version,
131+
description="",
132+
change_log="",
133+
build_id=new_icos_version.split(".")[3],
134+
major_version=new_icos_version.split(".")[0],
135+
minor_version=new_icos_version.split(".")[1],
136+
revision=new_icos_version.split(".")[2],
137+
timestamp=0,
138+
)
139+
else:
140+
# check the requested version is listed under available versions
141+
update = Update.get(rest_client, new_icos_version, must_exist=True)
142+
if not isinstance(update, Update):
143+
raise AssertionError("update is not of type Update") # mypy helper
144+
Update.apply_update(rest_client, new_icos_version)
113145
return (
114146
True,
115-
update.to_ansible(), # type: ignore
147+
update.to_ansible(),
116148
dict(
117149
before=dict(icos_version=cluster.icos_version),
118-
after=dict(icos_version=update.uuid), # type: ignore
150+
after=dict(icos_version=new_icos_version),
119151
),
120152
)
121153

@@ -126,6 +158,7 @@ def main() -> None:
126158
argument_spec=dict(
127159
arguments.get_spec("cluster_instance"),
128160
icos_version=dict(type="str", required=True),
161+
force_update=dict(type="bool", default=False),
129162
),
130163
)
131164

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
version_update_single_node_shutdown_wait_time: "{{ scale_computing_hypercore_shutdown_wait_time | default(300) }}"
33
version_update_single_node_shutdown_tags: "{{ scale_computing_hypercore_shutdown_tags | default([]) }}"
4+
version_update_single_node_force_update: false
45
# renamed variables - if new name is not present, use deprecated name as default value
56
version_update_single_node_shutdown_vms: "{{ scale_computing_hypercore_shutdown_vms | default(omit) }}"
67
version_update_single_node_restart_vms: "{{ scale_computing_hypercore_restart_vms | default(omit) }}"

roles/version_update_single_node/meta/argument_specs.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ argument_specs:
2020
- After wait time expires a force shutdown is issued. Force shutdown can corrupt VM disk data.
2121
default: 300
2222
type: int
23+
version_update_single_node_force_update:
24+
description:
25+
- Upgrade the HyperCore cluster to the requested version,
26+
even if requested version is not listed under available versions of the HyperCore cluster.
27+
default: false
28+
type: bool
2329
# -------------
2430
# Renamed/deprecated vars
2531
scale_computing_hypercore_desired_version:

roles/version_update_single_node/tasks/main.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@
5252
msg: >-
5353
Requested update {{ version_update_single_node_desired_version }} is not
5454
in version_update_single_node_available_updates {{ version_update_single_node_available_updates.records | map(attribute='uuid') | list }}
55-
when: not version_update_single_node_desired_version in (version_update_single_node_available_updates.records | map(attribute='uuid') | list)
55+
when:
56+
- not version_update_single_node_force_update
57+
- not version_update_single_node_desired_version in (version_update_single_node_available_updates.records | map(attribute='uuid') | list)
5658

5759
- name: Get all available running VMs
5860
scale_computing.hypercore.vm_info:
@@ -69,6 +71,7 @@
6971
- name: Update single-node system
7072
scale_computing.hypercore.version_update:
7173
icos_version: "{{ version_update_single_node_desired_version }}"
74+
force_update: "{{ version_update_single_node_force_update }}"
7275
register: version_update_single_node_update_result
7376

7477
- name: Check update status

tests/unit/plugins/module_utils/test_hypercore_version.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -278,18 +278,8 @@ def test_update_equal_false(self):
278278
assert update1 != update2
279279

280280
def test_apply_update(self, rest_client):
281-
update = Update(
282-
uuid="9.2.11.210763",
283-
description="9.1.11 General Availability",
284-
change_log="...Please allow between 20-40 minutes per node for the update to complete...",
285-
build_id=210763,
286-
major_version=9,
287-
minor_version=2,
288-
revision=11,
289-
timestamp=0,
290-
)
291-
292-
update.apply(rest_client)
281+
new_icos_version = "9.2.11.210763"
282+
Update.apply_update(rest_client, new_icos_version)
293283

294284
rest_client.create_record.assert_called_with(
295285
"/rest/v1/Update/9.2.11.210763/apply", payload=None, check_mode=False

0 commit comments

Comments
 (0)