Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions input/config/x86_64/rhel/10.0/service_k8s_v1.35.1.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

{
"service_k8s": {
"cluster": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,24 @@
import yaml


def merge_values(v21_file_path, v216_file_path, output_file_path):
def merge_values(vold_file_path, vnew_file_path, output_file_path):
"""
Merge v2.1 PowerScale values into v2.16 template.
Merge old PowerScale values into new template.

Args:
v21_file_path: Path to v2.1 values.yaml (source settings)
v216_file_path: Path to v2.16 values.yaml (target structure)
vold_file_path: Path to old values.yaml (source settings)
vnew_file_path: Path to new values.yaml (target structure)
output_file_path: Path to write merged values.yaml
"""
# Load v2.1 values (source of user settings)
with open(v21_file_path, 'r', encoding='utf-8') as file_handle:
v21_values = yaml.safe_load(file_handle)
# Load old values (source of user settings)
with open(vold_file_path, 'r', encoding='utf-8') as file_handle:
vold_values = yaml.safe_load(file_handle)

# Load v2.16 values (target structure with new defaults)
with open(v216_file_path, 'r', encoding='utf-8') as file_handle:
v216_values = yaml.safe_load(file_handle)
# Load new values (target structure with new defaults)
with open(vnew_file_path, 'r', encoding='utf-8') as file_handle:
vnew_values = yaml.safe_load(file_handle)

# Parameters to preserve from v2.1
# Parameters to preserve from old version
preserve_params = [
'isiPath',
'isiAccessZone',
Expand All @@ -49,12 +49,12 @@ def merge_values(v21_file_path, v216_file_path, output_file_path):

# Preserve top-level parameters
for param in preserve_params:
if param in v21_values:
v216_values[param] = v21_values[param]
print(f"Preserved {param}: {v21_values[param]}",
if param in vold_values:
vnew_values[param] = vold_values[param]
print(f"Preserved {param}: {vold_values[param]}",
file=sys.stderr)

# Preserve feature flags if enabled in v2.1
# Preserve feature flags if enabled in old version
feature_flags = [
'storageCapacity',
'podmon',
Expand All @@ -64,62 +64,88 @@ def merge_values(v21_file_path, v216_file_path, output_file_path):
]

for feature in feature_flags:
if feature in v21_values and isinstance(v21_values[feature], dict):
if 'enabled' in v21_values[feature]:
if feature not in v216_values:
v216_values[feature] = {}
v216_values[feature]['enabled'] = \
v21_values[feature]['enabled']
if feature in vold_values and isinstance(vold_values[feature], dict):
if 'enabled' in vold_values[feature]:
if feature not in vnew_values:
vnew_values[feature] = {}
vnew_values[feature]['enabled'] = \
vold_values[feature]['enabled']
print(f"Preserved {feature}.enabled: "
f"{v21_values[feature]['enabled']}",
f"{vold_values[feature]['enabled']}",
file=sys.stderr)

# Preserve healthMonitor with both enabled and interval
if 'healthMonitor' in vold_values and isinstance(vold_values['healthMonitor'], dict):
if 'healthMonitor' not in vnew_values:
vnew_values['healthMonitor'] = {}
for param in ['enabled', 'interval']:
if param in vold_values['healthMonitor']:
vnew_values['healthMonitor'][param] = vold_values['healthMonitor'][param]
print(f"Preserved healthMonitor.{param}: {vold_values['healthMonitor'][param]}", file=sys.stderr)

# Preserve controller settings
if 'controller' in v21_values and \
isinstance(v21_values['controller'], dict):
if 'controller' not in v216_values:
v216_values['controller'] = {}
if 'controller' in vold_values and \
isinstance(vold_values['controller'], dict):
if 'controller' not in vnew_values:
vnew_values['controller'] = {}

controller_params = ['nodeSelector', 'tolerations', 'controllerCount']
for param in controller_params:
if param in v21_values['controller']:
v216_values['controller'][param] = \
v21_values['controller'][param]
print(f"Preserved controller.{param}: {v21_values['controller'][param]}", file=sys.stderr)
if param in vold_values['controller']:
vnew_values['controller'][param] = \
vold_values['controller'][param]
print(f"Preserved controller.{param}: {vold_values['controller'][param]}", file=sys.stderr)

# Preserve controller-level healthMonitor
if 'healthMonitor' in vold_values['controller'] and isinstance(vold_values['controller']['healthMonitor'], dict):
if 'healthMonitor' not in vnew_values['controller']:
vnew_values['controller']['healthMonitor'] = {}
for param in ['enabled', 'interval']:
if param in vold_values['controller']['healthMonitor']:
vnew_values['controller']['healthMonitor'][param] = vold_values['controller']['healthMonitor'][param]
print(f"Preserved controller.healthMonitor.{param}: {vold_values['controller']['healthMonitor'][param]}", file=sys.stderr)

# Preserve node settings
if 'node' in v21_values and isinstance(v21_values['node'], dict):
if 'node' not in v216_values:
v216_values['node'] = {}
if 'node' in vold_values and isinstance(vold_values['node'], dict):
if 'node' not in vnew_values:
vnew_values['node'] = {}

node_params = ['nodeSelector', 'tolerations']
for param in node_params:
if param in v21_values['node']:
v216_values['node'][param] = v21_values['node'][param]
if param in vold_values['node']:
vnew_values['node'][param] = vold_values['node'][param]
print(f"Preserved node.{param}", file=sys.stderr)

# Preserve node-level healthMonitor
if 'healthMonitor' in vold_values['node'] and isinstance(vold_values['node']['healthMonitor'], dict):
if 'healthMonitor' not in vnew_values['node']:
vnew_values['node']['healthMonitor'] = {}
if 'enabled' in vold_values['node']['healthMonitor']:
vnew_values['node']['healthMonitor']['enabled'] = vold_values['node']['healthMonitor']['enabled']
print(f"Preserved node.healthMonitor.enabled: {vold_values['node']['healthMonitor']['enabled']}", file=sys.stderr)

# Write merged values to output file
with open(output_file_path, 'w', encoding='utf-8') as file_handle:
yaml.dump(v216_values, file_handle,
yaml.dump(vnew_values, file_handle,
default_flow_style=False, sort_keys=False)

print("Successfully merged v2.1 settings into v2.16 values.yaml",
print("Successfully merged old settings into new values.yaml",
file=sys.stderr)
print(f"Output written to: {output_file_path}", file=sys.stderr)


if __name__ == '__main__':
if len(sys.argv) != 4:
print("Usage: merge_powerscale_values.py <v21_values.yaml> "
"<v216_values.yaml> <output.yaml>", file=sys.stderr)
print("Usage: merge_powerscale_values.py <old_values.yaml> "
"<new_values.yaml> <output.yaml>", file=sys.stderr)
sys.exit(1)

v21_input = sys.argv[1]
v216_input = sys.argv[2]
vold_input = sys.argv[1]
vnew_input = sys.argv[2]
output_path = sys.argv[3]

try:
merge_values(v21_input, v216_input, output_path)
merge_values(vold_input, vnew_input, output_path)
except (IOError, yaml.YAMLError) as error:
print(f"ERROR: Failed to merge PowerScale values.yaml: {error}",
file=sys.stderr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
# These are the target versions for software entries that should be updated
TARGET_VERSIONS = {
"service_k8s": "1.35.1",
"csi_driver_powerscale": "v2.16.0"
"csi_driver_powerscale": "v2.17.0"
}

with open(backup_file, 'r', encoding='utf-8') as f:
Expand Down
73 changes: 73 additions & 0 deletions upgrade/roles/upgrade_telemetry/tasks/apply_victoria_crs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,79 @@
delegate_to: "{{ kube_vip }}"
connection: ssh

# ── Inject preserved LoadBalancer IPs into VMCluster manifest before apply ──
# When migrating from 2.1 StatefulSet to operator, old services are deleted
# and the operator creates new ones. To preserve IPs, we inject loadBalancerIP
# directly into the VMCluster CR's serviceSpec BEFORE applying, so the operator
# creates services with the correct IPs from the start (no race condition).
- name: Create LoadBalancer IP injection script
ansible.builtin.copy:
dest: /tmp/inject_vm_lb_ips.py
mode: "0755"
content: |
#!/usr/bin/env python3
import yaml
import sys
manifest_path = sys.argv[1]
vmselect_ip = sys.argv[2] if len(sys.argv) > 2 and sys.argv[2] else ""
vminsert_ip = sys.argv[3] if len(sys.argv) > 3 and sys.argv[3] else ""
with open(manifest_path) as f:
doc = yaml.safe_load(f)
spec = doc.get("spec", {})
changed = False
if vmselect_ip and "vmselect" in spec:
svc = spec["vmselect"].setdefault("serviceSpec", {}).setdefault("spec", {})
if svc.get("loadBalancerIP") != vmselect_ip:
svc["loadBalancerIP"] = vmselect_ip
changed = True
if vminsert_ip and "vminsert" in spec:
svc = spec["vminsert"].setdefault("serviceSpec", {}).setdefault("spec", {})
if svc.get("loadBalancerIP") != vminsert_ip:
svc["loadBalancerIP"] = vminsert_ip
changed = True
if changed:
with open(manifest_path, "w") as f:
yaml.dump(doc, f, default_flow_style=False, sort_keys=False)
print("Injected vmselect=" + vmselect_ip + " vminsert=" + vminsert_ip)
else:
print("IPs already present - no change needed")
sys.exit(0 if changed else 2)
delegate_to: "{{ kube_vip }}"
connection: ssh
when:
- preserved_vmselect_ip | default('') | length > 0 or preserved_vminsert_ip | default('') | length > 0

- name: Inject preserved LoadBalancer IPs into VMCluster manifest
ansible.builtin.command:
cmd: >-
python3 /tmp/inject_vm_lb_ips.py
"{{ telemetry_deploy_dir }}/deployments/victoria-operator-vmcluster.yaml"
"{{ preserved_vmselect_ip | default('') }}"
"{{ preserved_vminsert_ip | default('') }}"
register: ip_inject_result
changed_when: ip_inject_result.rc == 0
failed_when: ip_inject_result.rc not in [0, 2]
delegate_to: "{{ kube_vip }}"
connection: ssh
when:
- preserved_vmselect_ip | default('') | length > 0 or preserved_vminsert_ip | default('') | length > 0

- name: Clean up LoadBalancer IP injection script
ansible.builtin.file:
path: /tmp/inject_vm_lb_ips.py
state: absent
delegate_to: "{{ kube_vip }}"
connection: ssh
changed_when: false

- name: Display LoadBalancer IP injection status
ansible.builtin.debug:
msg: >-
{{ victoria_lb_ips_preserved
if (preserved_vminsert_ip | default('') | length > 0)
or (preserved_vmselect_ip | default('') | length > 0)
else victoria_lb_ips_not_preserved }}

# ── Apply main CR (VMCluster only — 2.2 cluster mode only) ──
- name: Apply VMCluster CR (cluster mode only) with retry
ansible.builtin.command:
Expand Down
22 changes: 9 additions & 13 deletions upgrade/roles/upgrade_telemetry/tasks/backup_telemetry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,34 @@
when:
- k8s_client_mount_path is defined
- k8s_client_mount_path | length > 0
- kube_vip is defined
- kube_vip | length > 0
block:
- name: Set telemetry backup directory
ansible.builtin.set_fact:
tel_backup_dir: "{{ k8s_client_mount_path }}/upgrade/telemetry/omnia_{{ manifest.source_version | default('unknown') }}"
delegate_to: oim
connection: ssh

- name: Create telemetry backup directory
ansible.builtin.file:
path: "{{ tel_backup_dir }}"
path: "{{ telemetry_backup_dir }}"
state: directory
mode: '0755'
delegate_to: oim
delegate_to: "{{ kube_vip }}"
connection: ssh

- name: Backup telemetry folder (pre-provision)
ansible.builtin.copy:
src: "{{ k8s_client_mount_path }}/telemetry"
dest: "{{ tel_backup_dir }}/telemetry"
dest: "{{ telemetry_backup_dir }}/telemetry"
remote_src: true
mode: preserve
delegate_to: oim
delegate_to: "{{ kube_vip }}"
connection: ssh
failed_when: false

- name: Backup idrac_telemetry folder (pre-provision)
ansible.builtin.copy:
src: "{{ k8s_client_mount_path }}/idrac_telemetry"
dest: "{{ tel_backup_dir }}/idrac_telemetry"
dest: "{{ telemetry_backup_dir }}/idrac_telemetry"
remote_src: true
mode: preserve
delegate_to: oim
delegate_to: "{{ kube_vip }}"
connection: ssh
failed_when: false

Expand All @@ -74,7 +70,7 @@
- name: Backup telemetry.sh from control plane
ansible.builtin.copy:
src: /root/telemetry.sh
dest: "{{ tel_backup_dir }}/telemetry.sh"
dest: "{{ telemetry_backup_dir }}/telemetry.sh"
mode: "{{ executable_mode }}"
remote_src: true
delegate_to: "{{ kube_vip }}"
Expand Down
2 changes: 1 addition & 1 deletion upgrade/roles/upgrade_telemetry/tasks/backup_victoria.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
path: "{{ telemetry_backup_dir }}"
state: directory
mode: "0755"
delegate_to: "{{ oim_host }}"
delegate_to: "{{ kube_vip }}"
connection: ssh

# ── Backup namespace-level resources ──
Expand Down
Loading
Loading