#!/usr/bin/env python3 from xmlrpc.client import ServerProxy from datetime import date from datetime import datetime import json import sys import numpy as np MANAGER_URL = "http://sumaserver.domain.com/rpc/api" MANAGER_LOGIN = "sumaadmin" MANAGER_PASSWORD = "password" now = datetime.now() client = ServerProxy(MANAGER_URL) key = client.auth.login(MANAGER_LOGIN, MANAGER_PASSWORD) #Script based on API examples from documentation here: #https://documentation.suse.com/suma/4.3/api/suse-manager/api/system.html #Example to get "SystemID" by hostname: #print(client.system.getId(key,'s15s3test')[0]['id']) #Another example to get "SystemID" by hostname: #print(client.system.search.hostname(key,hostname)[0]['id']) #Example of Target Migration destination... #print(client.system.listMigrationTargets(key,1000010029, 'excludeTargetWhereMissingSuccessors' )[0]['friendly']) #basic descriptions: #List migration targets of System with ID "1000010029" #print(client.system.listMigrationTargets(key,1000010029)) #List migration targets with LTSS or other repos that are not available in new Service Pack #print(client.system.listMigrationTargets(key,1000010029, 'excludeTargetWhereMissingSuccessors' )) #Get specific list of target module IDs #print(client.system.listMigrationTargets(key,1000010029, 'excludeTargetWhereMissingSuccessors' )[0]['ident']) #[{'ident': '[1564,1593,1599,1603,1581,1585,1110,1573,1589,1615,1577]', 'friendly': '[base: SUSE Linux Enterprise Server 15 SP5 x86_64, addon: Web and Scripting Module 15 SP5 x86_64, Legacy Module 15 SP5 x86_64, Public Cloud Module 15 SP5 x86_64, Server Applications Module 15 SP5 x86_64, Containers Module 15 SP5 x86_64, SUSE Manager Client Tools for SLE 15 x86_64, Basesystem Module 15 SP5 x86_64, Development Tools Module 15 SP5 x86_64, SUSE Linux Enterprise High Availability Extension 15 SP5 x86_64, Desktop Applications Module 15 SP5 x86_64]'}, {'ident': '[1385,1412,1416,1420,1400,1404,1110,1392,1408,1431,1396]', 'friendly': '[base: SUSE Linux Enterprise Server 15 SP4 x86_64, addon: Web and Scripting Module 15 SP4 x86_64, Legacy Module 15 SP4 x86_64, Public Cloud Module 15 SP4 x86_64, Server Applications Module 15 SP4 x86_64, Containers Module 15 SP4 x86_64, SUSE Manager Client Tools for SLE 15 x86_64, Basesystem Module 15 SP4 x86_64, Development Tools Module 15 SP4 x86_64, SUSE Linux Enterprise High Availability Extension 15 SP4 x86_64, Desktop Applications Module 15 SP4 x86_64]'}] #get the output of the previous command and plug the "ident" values into the next command: #The first set of IDs need to be used (if you're going up to 15-SP5 in this case): #'[1564,1593,1599,1603,1581,1585,1110,1573,1589,1615,1577]' #Then plug those IDs into this function: #plugin the "ident" list example: #print(client.system.scheduleProductMigration(key,1000010029, "[1564,1593,1599,1603,1581,1585,1110,1573,1589,1577]" , 'sle-product-sles15-sp5-pool-x86_64' ,[],True,True,True, now )) #plugin the "identlist" variable: #print(client.system.scheduleProductMigration(key,1000010029, identlist , 'sle-product-sles15-sp5-pool-x86_64' ,[],True,True,True, now )) #example format from documetnation page: #string sessionKey,int sid, string targetIdent,string baseChannelLabel,string array optionalChildChannels,boolean dryRun,boolean allowVendorChange,boolean removeProductsWithNoSuccessorAfterMigration,date. #print("now =", now) #This will schedule the update of the specified system: #print(client.system.schedulePackageUpdate(key,1000010028, now)) #This will schedule the client for a reboot: #print(client.system.scheduleReboot(key,1000010028, now)) #The "now" variable is defined: #now = datetime.now() #Which results in: #now = 2024-04-24 12:29:12.883187 #client.auth.logout(key) #Putting steps into an easy to follow script: #Usage, pass the "hostname" on the CMDLINE as the first argument... #ex: ./MigrateClientw.py s15s3test #or pass nothing and the script will ask for hostname: #./MigrateClientw.py if len(sys.argv) <= 1: print("No cmdline arguments, asking for hostname...") hostname = input("Type the SUMA Client Hostname to migrate: \n") else: print(sys.argv[1]) hostname = sys.argv[1] #print(client.system.getId(key,hostname)[0]['id']) #print(client.system.getId(key,hostname)[0]['id']) #sumasystemid=client.system.getId(key,hostname)[0]['id'] try: sumasystemid=client.system.getId(key,hostname)[0]['id'] except (IndexError, ValueError): print("Invalid hostname, aka hostname not found") exit() print("SUMA SystemID for",hostname,"is ",sumasystemid) print("List of repo names to migrate: \n") try: print(client.system.listMigrationTargets(key,sumasystemid, 'excludeTargetWhereMissingSuccessors' )[0]['friendly']) identlist=client.system.listMigrationTargets(key,sumasystemid, 'excludeTargetWhereMissingSuccessors' )[0]['ident'] except (IndexError, ValueError): print("NO migration options available, check SUMA WebUI") exit() print("\n") print("List of repo IDs to migrate: \n",identlist) print("\n") answer = input("Is this correct? Continue: y/n ") print(answer) if answer.lower() == "y": print("Yes, starting migration now...") #Remove the comment from the next line to schedule the migration: #print(client.system.scheduleProductMigration(key,sumasystemid, identlist , 'sle-product-sles15-sp5-pool-x86_64' ,[],True,True,True, now )) print("now =", now) client.auth.logout(key) elif answer.lower() == "n": print("No, quiting now...") client.auth.logout(key) exit() else: print("Please enter y or n ") client.auth.logout(key) #One caveat is that the migration might fail with this message: ####xmlrpc.client.Fault: #This means the SUMA client requires updates before the migration can be completed. #To install updates via API these commands can be used(with the "sumasystemid" variable from line#72: #This will schedule the update of the specified system: #print(client.system.schedulePackageUpdate(key,sumasystemid, now)) #This will schedule the client for a reboot: #print(client.system.scheduleReboot(key,sumasystemid, now))