Skip to content

Commit 70b7958

Browse files
committed
added script to sync the unmirrored client tools channels for already mirrored products
1 parent 4698987 commit 70b7958

File tree

2 files changed

+124
-6
lines changed

2 files changed

+124
-6
lines changed

uyuni-tools/migrate_to_new_client_tools.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
#
88
# Created by: Abid Mehmood
99
#
10-
# Using this cscript you can update your actiavation keys and CLM projects by removing the old client tools and switching to new client tools.
11-
# This script assumes that new client tools have been already syned in your MLM/Uyuni instance.
10+
# Using this script user can update their actiavation keys and CLM projects by removing the old client tools and switching to new client tools.
11+
# This script assumes that new client tools have been already syned in your SUSE Multi-Linux Manager and Uyuni instance. One can use sync_client_tools.py script to sync the new client tools.
1212
#
1313
# Releasmt.session:
14-
# 2017-01-2 Abid - initial release.
14+
# 2025-10-14 Abid - initial release.
1515
1616
"""
17+
#!/usr/bin/env python3
1718
import xmlrpc.client
1819
import time
1920
import sys
@@ -25,6 +26,7 @@
2526
USERNAME = "<username>"
2627
PASSWORD = "<password>"
2728

29+
2830
def log(message):
2931
print(f"[INFO] {message}")
3032

@@ -84,7 +86,8 @@ def process_clm_project(client, key, project_label, base_channels, dry_run):
8486
if base_channel_label:
8587
log(f"Base channel determined for project: {base_channel_label}")
8688
children = client.channel.software.listChildren(key, base_channel_label)
87-
managertools_labels = [c['label'] for c in children if c.get('channel_family_label') == 'SLE-M-T']
89+
managertools_labels = [s['label'] for s in children if 'managertools' in s.get('label', '').lower()]
90+
#managertools_labels = [c['label'] for c in children if c.get('channel_family_label') == 'SLE-M-T']
8891

8992
if managertools_labels:
9093
for label in managertools_labels:
@@ -187,8 +190,7 @@ def process_activation_keys(client, key, activation_keys, dry_run):
187190
channels_to_attach = []
188191
# Find the new 'managertools' channel based on the base channel of the activation key
189192
base_channel_label = detail.get('base_channel_label')
190-
191-
if base_channel_label:
193+
if base_channel_label and base_channel_label != 'none':
192194
# Find children of the base channel
193195
children = client.channel.software.listChildren(key, base_channel_label)
194196
# Filter for the new client tools channel

uyuni-tools/sync_client_tools.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
"""
2+
# (c) 2019 SUSE Linux GmbH, Germany.
3+
# GNU Public License. No warranty. No Support
4+
# For question/suggestions/bugs mail: [email protected]
5+
#
6+
# Version:2025-10-15
7+
#
8+
# Created by: Abid Mehmood
9+
#
10+
# Using this script user can sync the client tools if they are not already synced for already mirrored products on SUSE Multi-Linux Manager and Uyuni.
11+
#
12+
# Releasmt.session:
13+
# 2025-10-15 Abid - initial release.
14+
15+
"""
16+
17+
#!/usr/bin/env python3
18+
import xmlrpc.client
19+
import time
20+
import argparse
21+
22+
SUSE_MULTI_LINUX_MANAGER_SERVER = "<your-server>"
23+
USERNAME = "<username>"
24+
PASSWORD = "<password>"
25+
26+
27+
28+
def log(message):
29+
"""Simple logging function."""
30+
print(f"[INFO] {message}")
31+
32+
def dry_run_log(message):
33+
"""Dry-run logging function."""
34+
print(f"[DRY-RUN] {message}")
35+
36+
def connect_and_login():
37+
"""Connects to the XML-RPC API and returns a session key."""
38+
try:
39+
log(f"Connecting to {SUSE_MULTI_LINUX_MANAGER_SERVER}...")
40+
client = xmlrpc.client.Server(f"http://{SUSE_MULTI_LINUX_MANAGER_SERVER}/rpc/api")
41+
key = client.auth.login(USERNAME, PASSWORD)
42+
log("Successfully logged in.")
43+
return client, key
44+
except Exception as e:
45+
print(f"[ERROR] Failed to connect or login: {e}")
46+
return None, None
47+
48+
def find_extensions_of_synced_products(client, key):
49+
"""Get all the extensions of the already synced products"""
50+
all_extensions = []
51+
products = client.sync.content.listProducts(key)
52+
for product in products:
53+
if product.get('status', '').lower() == 'installed':
54+
product_name = product.get('friendly_name', 'Unknown Product')
55+
extensions = product.get('extensions', [])
56+
if extensions:
57+
for ext in extensions:
58+
all_extensions.append(ext)
59+
else:
60+
print(f"No extensions found for {product_name}.")
61+
return all_extensions
62+
63+
def add_client_tools_channels(client, key, extensions, dry_run):
64+
"""Add all the client tools channels available which aren't synced yet"""
65+
for ext in extensions:
66+
if "Client Tools" in ext.get('friendly_name', ''):
67+
channels = ext.get('channels', [])
68+
if not channels:
69+
print(" No channels found.")
70+
continue
71+
for ch in channels:
72+
if ch.get('family') == 'SLE-M-T' and ch.get('optional') != True:
73+
if ch.get('status', '').lower() != 'installed':
74+
log(f"already synced: {ch.get('label')}")
75+
continue
76+
label = ch.get('label', 'N/A')
77+
family = ch.get('family', 'N/A')
78+
if dry_run:
79+
dry_run_log(f"Would add channel: {label}")
80+
else:
81+
log(f"Adding channel: {label}")
82+
client.sync.content.addChannel(key, label, '')
83+
84+
def main():
85+
"""Main function to run the entire workflow."""
86+
parser = argparse.ArgumentParser(description="A script to add client tools channels to SUSE Manager.",
87+
formatter_class=argparse.RawTextHelpFormatter)
88+
parser.add_argument("--no-dry-run", action="store_true",
89+
help="Perform actual changes instead of a dry run.\n"
90+
"The script runs in dry-run mode by default.")
91+
args = parser.parse_args()
92+
dry_run = not args.no_dry_run
93+
94+
if dry_run:
95+
log("Script is running in DRY-RUN mode. No changes will be made.")
96+
else:
97+
log("WARNING: Script is running in LIVE mode. Changes will be applied.")
98+
99+
client, key = connect_and_login()
100+
if not client:
101+
return
102+
103+
try:
104+
extensions = find_extensions_of_synced_products(client, key)
105+
add_client_tools_channels(client, key, extensions, dry_run)
106+
log("INFO: Channels have been added and will be synced with the next scheduled repository sync. If you want to sync them now, you can schedule the 'Single run schedule' task from the 'mgr-sync-refresh-bunch' family of tasks.")
107+
108+
except Exception as e:
109+
print(f"[ERROR] An unexpected error occurred: {e}")
110+
finally:
111+
if key:
112+
client.auth.logout(key)
113+
log("Logged out successfully.")
114+
115+
if __name__ == "__main__":
116+
main()

0 commit comments

Comments
 (0)