def __init__(self, master=None, **kw): self.myname = type(self).__name__ super().__init__(master, **kw) self.l1 = ttk.Label(self, text=" F2-L1\ncentered", relief='ridge', anchor='center') self.l2 = ttk.Label(self, text="F2-L2", relief='ridge', anchor='center') self.l3 = ttk.Label(self, text="F2-L3", relief='ridge', anchor='center') self.l1.grid(row=0, column=0, sticky='nsew') self.l2.grid(row=0, column=1, sticky='nsew') self.l3.grid(row=0, column=2, sticky='nsew') self.grid_columnconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) self.grid_columnconfigure(2, weight=1) self.grid_rowconfigure(0, weight=1) if pydevprog: dbg.entersub() dbg.dprint(1, '->', self.myname) cfg.widgets['class'][self.myname] = self dbg.dprint(1, '<-', self.myname) dbg.leavesub()
def TEST_API(*args): """ calls the spacewalk api and prints the answer examples: api.getApiNamespaces api.getApiNamespaceCallList system errata.getDetails CESA-2019:2029 """ from __main__ import dbg, prgargs, data # import sumaconnect dbg.entersub() dbg.dprint(2, "ARGS", args) if len(args) > 0: if "help" in args: print(f"Usage: {dbg.myself().__name__} some.api.call [args]") print(f"{dbg.myself().__doc__}") dbg.leavesub() return else: dbg.setlvl(3) ### Create new arglist call = args[0] rest = args[1:] dbg.dprint(0, F"Call {call} with {rest}") sumaconnect.docall(args[0], *rest) dbg.setlvl() else: print("no valid input") dbg.leavesub() return
def handle_fdict(namelist, filedict, type=None): """ compare a list of names to a dictionary with teh available names as keys. a type for the comparison must be given: 1by1, single or items. Returns a list of matching items. """ from __main__ import dbg dbg.entersub() result = [] dbg.dprint(2, "type", type, namelist) for n in namelist: new = n.split(',') for name in new: if not name: continue dbg.dprint(2, name) if name in filedict: if type == '1by1': with open(filedict[name], 'r') as f: for line in f: if line.startswith('#'): continue else: result.append(line.strip()) elif type == 'single': result = filedict[name] elif type == 'items': result.append(filedict[name]) else: print("not yet done") else: result.append(name) dbg.leavesub() return result
def __init__(self, master=None, **kw): self.myname = type(self).__name__ if pydevprog: dbg.entersub() dbg.dprint(1, '->', self.myname) dbg.dprint(4, self.myname, "is pydevprog") cfg.widgets['class'][self.myname] = self super().__init__(master, **kw) self.pane = ttk.Panedwindow(master, orient='horizontal') self.L = ttk.Frame(self.pane) self.L.grid(column=0, row=0, sticky='nsew') self.L.rowconfigure(0, weight=1, minsize=50) self.L.columnconfigure(0, weight=1, minsize=50) self.R = ttk.Frame(self.pane) self.R.grid(column=0, row=0, sticky='nsew') self.L.rowconfigure(0, weight=1, minsize=100) self.L.columnconfigure(0, weight=1, minsize=50) self.pane.add(self.L, weight=1) self.pane.add(self.R, weight=3) self.pane.grid(column=0, row=0, sticky='nsew') if pydevprog: cfg.widgets['L'] = self.L cfg.widgets['R'] = self.R dbg.dprint(1, '<-', self.myname) dbg.leavesub()
def docall(name, *args): """ execute a known function by name. Convert string args into python objects before. return the answer of the call. """ from __main__ import dbg, data dbg.entersub() ses = data['conn']['ses'] key = data['conn']['key'] dbg.dprint(2, "name:", name) dbg.dprint(2, "args:", args, ", type of args: ", type(args)) call = getattr(ses, name) dbg.dprint(2, "len args ", len(args)) if len(args) == 0: answer = call(key) else: print("in else") newargs = [] count = 1 ### create objects and append them to new array for a in args: dbg.dprint(4, " {:02d}a - {} - {}".format(count, a, type(a))) obj = myinput.string_to_pyobj(a) dbg.dprint(4, type(obj)) newargs.append(obj) count += 1 ### Call the xmlrpc function on server answer = call(key, *newargs[0:]) ### print answer and return dbg.dprint(2, "answer for " + name, answer, "End answer") dbg.leavesub() return (answer)
def __init__(self, master=None, **kw): self.myname = type(self).__name__ if master is not None: super().__init__(master, **kw) # dbg.dprint(4,"tkcols",cfg.tkcols,'guidefs',cfg.guidefs) #style = ttk.Style(master) if pydevprog: dbg.entersub() dbg.dprint(1, '->', self.myname) # cdict = {'bg':'grey26','fg':'white','activebackground':'grey39','activeforeground':'white'} self.mainmenu = tk.Menu(master, relief='flat') self.master.config(menu=self.mainmenu) self.filemenu = tk.Menu(self.mainmenu) self.filemenu.add_command(label='Open', command=self.showc) self.filemenu.add_command(label='Save', command=self.showc) self.filemenu.add_separator() self.filemenu.add_command(label='Exit', command=self.Exit) self.mainmenu.add_cascade(menu=self.filemenu, label='File') #self.mainmenu.entryconfigure(0,tk.Menu(self.mainmenu, tearoff=0,**cdict),label) self.helpmenu = tk.Menu(self.mainmenu) self.helpmenu.add_command(label='About', command=self.showc) self.mainmenu.add_cascade(label='Help', menu=self.helpmenu) if pydevprog: cfg.widgets['class'][self.myname] = self cfg.widgets['menubar']['main'] = self.mainmenu cfg.widgets['menubar']['File'] = self.filemenu cfg.widgets['menubar']['Help'] = self.helpmenu dbg.dprint(1, '<-', self.myname) dbg.leavesub()
def create_savefile(savefile): """ Create a new statefile if it does not yet exist """ from __main__ import dbg, data #import mysumacalls dbg.entersub() mysumacalls.UpdateStateFile(savefile) dbg.leavesub()
def logout(conndict): """ Logout from currently active session. """ from __main__ import dbg dbg.entersub() session = conndict['ses'] key = conndict['key'] session.auth.logout(key) dbg.leavesub()
def Actions_Delete(*args): """ deletes archived actions older than num days. """ from __main__ import dbg, prgargs, data # import datetime,time,sumaconnect dbg.entersub() dbg.dprint(2, "ARGS", args) days = 30 ses = data['conn']['ses'] key = data['conn']['key'] if len(args) > 0: if "help" in args: print(f"Usage: {dbg.myself().__name__} [num of days]") print(f"{dbg.myself().__doc__}") print("Default:", days, "days\n") dbg.leavesub() return elif myinput.is_number(args[0]): days = float(args[0]) else: print("no valid input") dbg.leavesub() return tframe = float(days) * 24 * 3600 currts = time.time() startts = currts - tframe readable = time.ctime(startts) archlist = [] totala = 0 ret = 0 print("----- Startdate:", readable) actions = ses.schedule.listArchivedActions(key) totala = len(actions) for a in actions: exects = datetime.datetime.timestamp(a['earliest']) if exects >= startts: continue print("added Action", a['id'], a['earliest']) archlist.append(a['id']) # try : # for aid in archlist: # dbg.dprint(0,"Aid",aid, "Type", type(aid)) # sumaconnect.docall('schedule.deleteActions',str(aid)) # ret += ses.schedule.deleteActions(key,tuple(aid)) ret = ses.schedule.deleteActions(key, archlist) # except Error as e: # print ("no success,e") if myinput.is_number(ret) and ret == 1: print("deleted", len(archlist), "of", totala, "Actions") else: print(ret) dbg.leavesub() return
def list_hosts(): """ prints out the list of found hostfiles "rxe -lh" """ from __main__ import dbg, cfg dbg.entersub() fdicth = get_files(cfg.data['nodefiles']) for k in sorted(set(fdicth)): print(f"--- {k}") dbg.leavesub() sys.exit(0)
def Actions_Archive(*args): """ archives actions older than num days. """ from __main__ import dbg, prgargs, data # import datetime,time,sumaconnect dbg.entersub() dbg.dprint(2, "ARGS", args) days = 7 ses = data['conn']['ses'] key = data['conn']['key'] if len(args) > 0: if "help" in args: print(f"Usage: {dbg.myself().__name__} [num of days]") print(f"{dbg.myself().__doc__}") print("Default:", days, "days\n") dbg.leavesub() return elif myinput.is_number(args[0]): days = float(args[0]) else: print("no valid input") dbg.leavesub() return tframe = float(days) * 24 * 3600 currts = time.time() startts = currts - tframe readable = time.ctime(startts) archlist = [] totalact = 0 print("----- Startdate:", readable) calllist = { 'completed': ses.schedule.listCompletedActions, 'failed': ses.schedule.listFailedActions } for k in calllist: actions = calllist[k](key) numact = len(actions) totalact += numact for a in actions: exects = datetime.datetime.timestamp(a['earliest']) if exects >= startts: continue print("added Action", a['id'], a['earliest'], 'from', k) archlist.append(a['id']) ret = ses.schedule.archiveActions(key, archlist) if myinput.is_number(ret) and ret == 1: print("archived", len(archlist), "of", totalact, "Actions") else: print(ret) dbg.leavesub() return
def write_savefile(savefile): """ write data['sumastate'] to savefile """ from __main__ import prgname, dbg, data #import time,os,pickle dbg.entersub() with open(savefile, 'wb') as f: dbg.dprint(2, "Creating fresh Systemstate in", savefile) pickle.dump(data['sumastate'], f) dbg.leavesub() return ()
def buildlist(namelist, search, type=None): """ take a list of names and search for files with this name if a file exists append content to the returnlist """ from __main__ import dbg dbg.entersub() reslist = [] filedict = get_files(search) reslist = handle_fdict(namelist, filedict, type=type) dbg.leavesub() return sorted(set(reslist))
def login(conndict): """ Login with username and pass, do not strictly enforce cert verification """ from __main__ import dbg dbg.entersub() context = ssl.SSLContext() session = xmlrpc.client.ServerProxy(conndict['url'], verbose=0, context=context, use_datetime=True) key = session.auth.login(conndict['usr'],conndict['pwd']) conndict['ses'] = session conndict['key'] = key dbg.leavesub() return(session,key)
def get_files(path): """ return list of files found in path """ from __main__ import dbg dbg.entersub() knownfiles = {} for top, dirs, files in os.walk(path): for nm in files: path = os.path.join(top, nm) name = os.path.basename(path) knownfiles[name] = path dbg.leavesub() return knownfiles
def read_savefile(savefile): """ Read the statefile, overwrite data['sumastate'] """ from __main__ import prgname, dbg, data #import time,os,pickle dbg.entersub() with open(savefile, 'rb') as f: data['sumastate'] = pickle.load(f) dbg.dprint(4, "Start data.sumastate", data['sumastate'], "End data.sumastate") dbg.leavesub() return ()
def Systems_Status(*args): """ Prints out the state of Systems Argstring can be a blank separated list of Systems and/or groups Default: Without args prints all systems of the default dumpfile """ from __main__ import dbg, prgargs, data dbg.entersub() dbg.dprint(2, "ARGS", args) #---- Settings ses = data['conn']['ses'] key = data['conn']['key'] grplist = data['sumastate']['groups'] syslist = data['sumastate']['systems'] patlist = data['sumastate']['patches'] sysorgroup = {} if len(args): if "help" in args: print( f"Usage: {dbg.myself().__name__} [sysorgroup [sysorgroup] ...]" ) print(f"{dbg.myself().__doc__}") dbg.leavesub() return else: for sog in args: if sog in grplist: for s in grplist[sog]['systems']: sysorgroup[s] = sysorgroup.get(s, 1) elif sog in syslist: sysorgroup[sog] = sysorgroup.get(sog, 1) else: dbg.dprint(0, sog, "is not a known group or system") else: sysorgroup = syslist #---- # old = uyuni_patches.check_savefile(data['savefile']) # if old : # dbg.dprint(0, "Updating Statefile, please wait") # UpdateStateFile() print(data['formats']['systemstateheader']) for system in sorted(sysorgroup): print(data['formats']['systemstateline'].format( syslist[system]['group'], system, syslist[system]['last_boot'].strftime("%Y-%m-%d"), syslist[system]['reboot'], syslist[system]['sec'], syslist[system]['bgf'], syslist[system]['enh'], syslist[system]['updates'], syslist[system]['last_checkin'].strftime("%Y-%m-%d"))) dbg.leavesub() return
async def run_mcmds(hosts,cmd,tmout,**kwargs): from __main__ import dbg,cfg,prgargs from rxe2_mod_general import prnout dbg.entersub() dbg.dprint(2,'cmd:',cmd,', tmout:',tmout,', kwargs:',kwargs) availhosts = [] #tasks = (run_cmd(host,cmd,**kwargs) for host in hosts) tasks = (asyncio.wait_for(run_cmd(host,cmd,**kwargs),timeout=tmout) for host in hosts) results = await asyncio.gather(*tasks, return_exceptions=True) if cmd.startswith('rm /tmp/') : for i, result in enumerate(results, 0): if isinstance(result, Exception): prnout('w',"Exception in rm cmd:", hosts[i],"remove failed") elif cmd == cfg.data.chkcmd: for i, result in enumerate(results, 0): if isinstance(result, asyncio.TimeoutError): prnout('h',kwargs['username'],hosts[i],'Conncheck') prnout('e',"Timeout Exception:",str(result)) elif isinstance(result, Exception): prnout('h',kwargs['username'],hosts[i],'Conncheck') prnout('e',"Exception in conntest:", str(result)) else: if not len(prgargs.cmd): prnout('h',kwargs['username'],hosts[i],'Conncheck') prnout('i',"{}".format(result.stdout.rstrip(),end='')) availhosts.append(hosts[i]) dbg.leavesub() return availhosts else: for i, result in enumerate(results, 0): prnout('h',kwargs['username'],hosts[i],cmd) if isinstance(result, asyncio.TimeoutError): prnout('e',"Timeout Exception:",str(result)) continue if isinstance(result, Exception): prnout('e',"Execution Exception:", str(result)) continue ### always do if result.exit_status: prnout('i','exit_code:',result.exit_status) if result.stdout: prnout('i',"{}".format(result.stdout.rstrip(),end='')) if result.stderr: prnout('i',"stderr: {}".format(result.stderr.rstrip(),end='')) dbg.leavesub()
async def run_mcopy(hosts,src,dst,**kwargs): from __main__ import dbg from rxe2_mod_general import prnout dbg.entersub() dbg.dprint(2,'src:',src,', dst:',dst,', kwargs:',kwargs) availhosts = [] tasks = (copy_file(host,src,dst,**kwargs) for host in hosts) results = await asyncio.gather(*tasks, return_exceptions=True) for i, result in enumerate(results, 0): if isinstance(result, Exception): rxe2_mod_general.prnout('h',kwargs['username'],hosts[i],'Conncheck') prnout('e',"Exception in conntest:", str(result)) else: availhosts.append(hosts[i]) dbg.leavesub() return availhosts
def Get_Group_List(ses, key, grplist, syslist): """ Creates two dictionaries for Systems and Systemgroups found on the uyuni server and returns them. If Systems without group exist, they will be sorted into the special group 'No_Group'. """ from __main__ import dbg, prgargs, data dbg.entersub() (grplist, syslist) = get_all_sysgroups(ses, key, grplist, syslist) for g in grplist: if g != 'No_Group': (grplist, syslist) = get_systems_by_group(ses, key, grplist, syslist, g) (grplist, syslist) = get_systems_wo_group(ses, key, grplist, syslist, 'No_Group') dbg.leavesub() return (grplist, syslist)
def get_all_sysgroups(ses, key, grplist, syslist): """ Hilfsfunktion zur Ermittlung der Systemgruppen. """ from __main__ import dbg, prgargs, data dbg.entersub() groups = ses.systemgroup.listAllGroups(key) for ghash in groups: curgroup = ghash['name'] grplist[curgroup] = {} if 'systems' not in grplist[curgroup]: grplist[curgroup]['systems'] = {} for k in ghash: if k not in ("name"): grplist[curgroup][k] = ghash[k] dbg.leavesub() return (grplist, syslist)
def __init__(self, master=None, **kw): self.myname = type(self).__name__ super().__init__(master, **kw) if master is not None: self.style = ttk.Style(master) self.master = master else: self.style = ttk.Style() self.master = None self.theme_autochange = tk.IntVar(self, 1) if pydevprog: dbg.entersub() dbg.dprint(1, '->', self.myname) self._setup_widgets() if pydevprog: cfg.widgets['class'][self.myname] = self dbg.dprint(1, '<-', self.myname) dbg.leavesub()
def UpdateStateFile(*args): """ Gathers needed information for all managed systems, their patches and states and saves it first in the global dictionary data['sumastate'], then dumps this dictionary to dumpfile for later use. """ from __main__ import dbg, prgargs, data # import sys,pickle,uyuni_groups,uyuni_channels,uyuni_patches dbg.entersub() dbg.dprint(2, "ARGS", args) dumpfile = data['savefile'] if "help" in args: print(f"Usage: {dbg.myself().__name__} [dumpfile]") print(f"{dbg.myself().__doc__}") print("Default:", dumpfile) print("") dbg.leavesub() return if len(args): dumpfile = args[0] dbg.dprint(4, dumpfile) dbg.dprint(4, data) ses = data['conn']['ses'] key = data['conn']['key'] ### get new values in fresh dictionaries grplist = {} syslist = {} patlist = {} chnlist = {} (grplist, syslist) = uyuni_groups.Get_Group_List(ses, key, grplist, syslist) (syslist, patlist) = uyuni_patches.get_Patches_for_all_Systems( ses, key, syslist, patlist) (chnlist) = uyuni_channels.Get_Channel_List(ses, key) ### write the updated values from memory to disk data['sumastate']['groups'] = grplist data['sumastate']['systems'] = syslist data['sumastate']['patches'] = patlist data['sumastate']['channels'] = chnlist uyuni_patches.write_savefile(dumpfile) dbg.leavesub() return
def Channel_02_UpdateArchive(*args): """ create or update archive channels according to the settings in the server config to the appointed channel. if test is given only shows what will be done. Errata are always cloned for Archives. """ from __main__ import dbg, prgargs, data, modlog dbg.entersub() dbg.dprint(2, "ARGS", args) ses = data['conn']['ses'] key = data['conn']['key'] chmap = data['chmap']['02_datefreeze'] chlist = data['sumastate']['channels'] testonly = False printout = False clone = True ###### Check args and do it ################################################ if len(args) > 0: if "help" in args: print(f"Usage: {dbg.myself().__name__} [test] [-v]") print(f"{dbg.myself().__doc__}") dbg.dprint(64, "current config from data.chmap.02_datefreeze", chmap, "End data['chmap']['02_datefreeze']") print("") dbg.leavesub() return elif "test" in args: testonly = 1 else: pass modlog.info(f"----> {dbg.myself().__name__}") for (source, target, parent) in chmap: modlog.info(f"{source} -> {target}") ok = uyuni_channels.Merge_Channel(source, target, parent, test=testonly, clone=clone) if not ok: dbg.dprint(256, F"ArchiveUpdate to {target} did not succeed") modlog.error(F"ArchiveUpdate to {target} did not succeed") modlog.info(f"<---- {dbg.myself().__name__}") dbg.leavesub() return
def check_savefile(savefile): """ checks for the age of statefile. If file is younger than data['maxage'] returns 0, else returns the differnce (older than data['maxage']) in seconds. """ from __main__ import prgname, dbg, data #import time,os,datetime dbg.entersub() overdue = 0 if not os.path.exists(savefile): create_savefile(savefile) dbg.dprint(0, "Created new Systemstate") f_age = time.time() - os.path.getmtime(savefile) max_s = (data['maxage'] * 60) if (f_age > max_s): overdue = f_age #f_age = str(datetime.timedelta(seconds=f_age)) #dbg.dprint(0, "SystemState is",f_age,"old, Information may be outdated") dbg.leavesub() return (overdue)
def list_cmds(fdict): """ prints out the list of found commands "rxe -lc" """ from __main__ import dbg dbg.entersub() newdict = {} # dbg.dprint(0,fdict) for k, v in fdict.items(): group = os.path.basename(os.path.dirname(v)) if os.access(v, os.X_OK): newdict[group] = newdict.get(group, {}) newdict[group][k] = newdict[group].get(k, 1) # dbg.dprint(0, newdict) for g in sorted(newdict.keys()): print(f"- {g}") for c in sorted(newdict[g].keys()): print(f" -> {c}") dbg.leavesub() sys.exit(0)
def inittk(): top = tk.Tk() top.option_add('*tearoff', 0) top.option_add('*tearOff', False) if pydevprog: dbg.entersub() cfg.widgets = aDict() cfg.widgets['MainWindow'] = top import mygui.themestuff as themestuff themes = themestuff.load_all_themes(top) if pydevprog: #dbg.dprint(4,"Available themes", themes) cfg.guidefs.available_themes = themes cfg.guidefs.loaded = True dbg.leavesub() return top
def get_systems_by_group(ses, key, grplist, syslist, curgroup): """ Unterfunktionen für Systeme, die in Gruppen enthalten sind """ from __main__ import dbg, prgargs, data dbg.entersub() systems = ses.systemgroup.listSystemsMinimal(key, curgroup) for shash in systems: cursys = shash['name'] if cursys not in grplist[curgroup]['systems']: grplist[curgroup]['systems'][cursys] = 0 grplist[curgroup]['systems'][cursys] += 1 if cursys not in syslist: syslist[cursys] = {} syslist[cursys]['group'] = curgroup for k2 in shash: if k2 not in ("name"): syslist[cursys][k2] = shash[k2] dbg.leavesub() return (grplist, syslist)
def Patches_DeleteManual(*args): """ Delete Patches from a Cloned Channel if they have a CM- advisory """ from __main__ import dbg, prgargs, cfg # import sumaconnect dbg.entersub() dbg.dprint(2, "ARGS", args) if len(args): if "help" in args: print(f"Usage: {dbg.myself().__name__} Channel") print(f"{dbg.myself().__doc__}") dbg.leavesub() return else: chan = args[0] ### Create new arglist else: print("no valid channel") print(f"Usage: {dbg.myself().__name__} Channel") print(f"{dbg.myself().__doc__}") dbg.leavesub() return ses = data['conn']['ses'] key = data['conn']['key'] clist = ses.channel.listSoftwareChannels(key) source_exists = next( (True for channel in clist if channel['label'] == chan), False) if source_exists: srcerrata = ses.channel.software.listErrata(key, chan) # dbg.dprint(256,"List of Errata", srcerrata) for ref in srcerrata: print(ref['advisory_name']) if ref['advisory_name'].startswith('CM'): print("Delete: ", ref['advisory_name']) ses.errata.delete(key, ref['advisory_name']) else: print("no valid channel: ", channel) dbg.leavesub() return
def Channel_List(*args): """ lists channels matching search without args show all known channels """ from __main__ import dbg, prgargs, data # import uyuni_channels dbg.entersub() dbg.dprint(2, "ARGS", args) ses = data['conn']['ses'] key = data['conn']['key'] search = '' chnlist = {} arglist = list(args) if len(arglist) > 0: if "help" in args: print(f"Usage: {dbg.myself().__name__} [search]") print(f"{dbg.myself().__doc__}") dbg.leavesub() return else: search = arglist[0] (chnlist) = uyuni_channels.Get_Channel_List(ses, key) chbylabel = chnlist['byLabel'] chbyparent = chnlist['byParent'] print(data['formats']['channelheader'], end="") for pa in sorted(chbyparent): if search in pa or [key for key in chbyparent[pa] if search in key]: print(data['formats']['channelparent'] % (pa, chbylabel[pa]['id'], chbylabel[pa]['pkg'], chbylabel[pa]['errata'], chbylabel[pa]['sys'])) for cl in sorted(chbyparent[pa]): if search in cl: print(data['formats']['channelchild'] % (cl, chbylabel[cl]['id'], chbylabel[cl]['pkg'], chbylabel[cl]['errata'], chbylabel[cl]['sys'])) print() dbg.leavesub() return (chbylabel)