Vinzenz Feenstra has uploaded a new change for review. Change subject: agent: Pep8 fixes ......................................................................
agent: Pep8 fixes * CredServer * GuestAgentLinux2 * VirtIoChannel * WinFile * version * setup.py - FP on py2exe import * OVirtGuestAgent * OVirtAgentLogic * ovirt-guest-agent * LockActiveSession * GuestAgentWin32 Change-Id: I74c33ed2ef2e5c33b9d25cb8b38e4201d67a957b Signed-off-by: Vinzenz Feenstra <[email protected]> --- M ovirt-guest-agent/CredServer.py M ovirt-guest-agent/GuestAgentLinux2.py M ovirt-guest-agent/GuestAgentWin32.py M ovirt-guest-agent/LockActiveSession.py M ovirt-guest-agent/OVirtAgentLogic.py M ovirt-guest-agent/OVirtGuestService.py M ovirt-guest-agent/VirtIoChannel.py M ovirt-guest-agent/WinFile.py M ovirt-guest-agent/ovirt-guest-agent.py M ovirt-guest-agent/setup.py M ovirt-guest-agent/version.py 11 files changed, 410 insertions(+), 207 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-guest-agent refs/changes/59/10759/1 diff --git a/ovirt-guest-agent/CredServer.py b/ovirt-guest-agent/CredServer.py index 2f03bc0..6e67dd9 100644 --- a/ovirt-guest-agent/CredServer.py +++ b/ovirt-guest-agent/CredServer.py @@ -16,17 +16,28 @@ # Refer to the README and COPYING files for full details of the license. # -import array, dbus, dbus.service, errno, gobject, pwd -import logging, socket, time, threading, random, struct +import array +import dbus +import dbus.service +import errno +import gobject +import pwd +import logging +import socket +import time +import threading +import random +import struct -from ctypes import * +from ctypes import Structure, POINTER, CDLL, c_ubyte, c_uint, c_void_p, \ + c_size_t, c_int, sizeof, cast, pointer, c_short, byref, get_errno from ctypes.util import find_library # Initializes the use of Python threading in the gobject module. gobject.threads_init() from dbus.mainloop.glib import DBusGMainLoop -DBusGMainLoop(set_as_default = True) +DBusGMainLoop(set_as_default=True) libc = CDLL(find_library('c'), use_errno=True) @@ -34,11 +45,13 @@ SCM_CREDENTIALS = 2 + class iovec(Structure): _fields_ = [ ('iov_base', POINTER(c_ubyte)), ('iov_len', c_uint) ] + class msghdr(Structure): _fields_ = [ @@ -51,6 +64,7 @@ ('msg_flags', c_int) ] + class cmsghdr(Structure): _fields_ = [ ('cmsg_len', c_size_t), @@ -59,6 +73,7 @@ ('cmsg_data', POINTER(c_ubyte)) ] + class ucred(Structure): _fields_ = [ ('pid', c_int), @@ -66,27 +81,31 @@ ('gid', c_int) ] + def CMSG_FIRSTHDR(mhdr): if mhdr.msg_controllen >= sizeof(cmsghdr): return cast(mhdr.msg_control, POINTER(cmsghdr)).contents else: return None + def CMSG_NXTHDR(mhdr, cmsg): return None + def CMSG_ALIGN(x): return ((x + sizeof(c_uint) - 1) & ~(sizeof(c_uint) - 1)) + def CMSG_SPACE(x): return (CMSG_ALIGN(x) + CMSG_ALIGN(sizeof(cmsghdr))) + # # The socket credential code is based on knowlage learned from the "Linux # Socket Programming by Example (Warren Gay)" book. # - -def packcreds(user, password, domain = ''): +def packcreds(user, password, domain=''): if domain != '': username = user + '@' + domain else: @@ -94,12 +113,12 @@ username = username.encode('utf-8') password = password.encode('utf-8') s = struct.pack('>6sI%ds%ds' % (len(username), len(password) + 1), - 'login', len(username), username, password) + 'login', len(username), username, password) return s -class CredDBusObject(dbus.service.Object): - DBUS_PATH = '/org/ovirt/vdsm/Credentials' +class CredDBusObject(dbus.service.Object): + DBUS_PATH = '/org/ovirt/vdsm/Credentials' DBUS_INTERFACE = 'org.ovirt.vdsm.Credentials' def __init__(self): @@ -107,9 +126,11 @@ dbus.service.Object.__init__(self, bus, '/org/ovirt/vdsm/Credentials') self._name = dbus.service.BusName('org.ovirt.vdsm.Credentials', bus) - @dbus.service.signal(dbus_interface='org.ovirt.vdsm.Credentials', signature='s') + @dbus.service.signal(dbus_interface='org.ovirt.vdsm.Credentials', + signature='s') def UserAuthenticated(self, token): logging.info("Emitting user authenticated signal (%s)." % (token)) + class CredChannel(threading.Thread): @@ -134,14 +155,15 @@ # Initialize a message control structure. msgh = msghdr() - msgh.msg_iov= pointer(iov) + msgh.msg_iov = pointer(iov) msgh.msg_iovlen = 1 msgh.msg_control = ctrl.buffer_info()[0] msgh.msg_controllen = ctrl.buffer_info()[1] while True: ret = libc.recvmsg(conn.fileno(), byref(msgh), socket.MSG_PEEK) - logging.debug("Receiving user's credential ret = %d errno = %d" % (ret, get_errno())) + logging.debug("Receiving user's credential ret = %d errno = %d", + ret, get_errno()) if (ret >= 0) or (get_errno() != errno.EINTR): break @@ -151,10 +173,13 @@ cmsgp = CMSG_FIRSTHDR(msgh) while cmsgp is not None: logging.debug("cmsgp: len=%d level=%d type=%d", - cmsgp.cmsg_len, cmsgp.cmsg_level, cmsgp.cmsg_type) - if (cmsgp.cmsg_level == socket.SOL_SOCKET) and (cmsgp.cmsg_type == SCM_CREDENTIALS): - result = cast(pointer(cmsgp.cmsg_data), POINTER(ucred)).contents - break + cmsgp.cmsg_len, cmsgp.cmsg_level, + cmsgp.cmsg_type) + if cmsgp.cmsg_level == socket.SOL_SOCKET: + if cmsgp.cmsg_type == SCM_CREDENTIALS: + data = cast(pointer(cmsgp.cmsg_data), POINTER(ucred)) + result = data.contents + break # This doesn't really work, but I got only one record during # development. cmsgp = CMSG_NXTHDR(msgh, cmsgp) @@ -178,7 +203,8 @@ self._allowed.append(pwd.getpwnam(user)[2]) except KeyError, err: logging.error(str(err)[1:-1]) - logging.info("The following users are allowed to connect: %s", self._allowed) + logging.info("The following users are allowed to connect: %s", + self._allowed) def run(self): self._channel = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) @@ -193,10 +219,10 @@ logging.error("Error receiving user's credential from socket.") return if cred.uid not in self._allowed: - logging.error("User %d is not allowed to connect!" % (cred.uid)) + logging.error("User %d is not allowed to connect!", cred.uid) return - logging.info("Incomming connection from user: %d process: %d" % - (cred.uid, cred.pid)) + logging.info("Incomming connection from user: %d process: %d", + cred.uid, cred.pid) token = conn.recv(1024) if not token: @@ -206,13 +232,15 @@ logging.info("Sending user's credential (token: %s)", token) conn.send(self._credentials[1]) else: - logging.warning("Unexpect token was received (token: %s)", token) + logging.warning("Unexpect token was received (token: %s)", + token) conn.close() except socket.timeout: logging.info("Credentials channel timed out.") self._channel.close() + class CredServer(threading.Thread): @@ -239,7 +267,7 @@ def user_authenticated(self, credentials): if self._cred_channel is None: self._cred_channel = CredChannel() - self._cred_channel.set_allowed([ 0 ]) + self._cred_channel.set_allowed([0]) token = str(random.randint(100000, 999999)) logging.debug("Token: %s", token) logging.info("Opening credentials channel...") @@ -249,7 +277,9 @@ logging.info("Credentials channel was closed.") self._cred_channel = None else: - logging.warn("Ignored authentication while another one is in progress.") + logging.warn("Ignored authentication while another one is " + "in progress.") + def main(): try: @@ -257,7 +287,8 @@ server.start() time.sleep(2) server.user_authenticated(packcreds('user@domain', 'pass')[6:]) - while True: time.sleep(1) + while True: + time.sleep(1) except (KeyboardInterrupt, SystemExit): server.join() diff --git a/ovirt-guest-agent/GuestAgentLinux2.py b/ovirt-guest-agent/GuestAgentLinux2.py index c7d8384..009132c 100644 --- a/ovirt-guest-agent/GuestAgentLinux2.py +++ b/ovirt-guest-agent/GuestAgentLinux2.py @@ -24,14 +24,17 @@ import time from OVirtAgentLogic import AgentLogicBase, DataRetriverBase +CredServer = None try: - from CredServer import CredServer + from CredServer import CredServer as CredServerImported + CredServer = CredServerImported except ImportError: # The CredServer doesn't exist in RHEL-5. So we provide a # fake server that do nothing. - class CredServer(threading.Thread): + class CredServerFake(threading.Thread): def user_authenticated(self, credentials): pass + CredServer = CredServerFake class PkgMgr(object): @@ -257,8 +260,8 @@ self.vmstat[field + '_cur'] = None def _get_meminfo(self): - fields = {'MemTotal:' : 0, 'MemFree:' : 0, 'Buffers:' : 0, \ - 'Cached:' : 0} + fields = {'MemTotal:': 0, 'MemFree:': 0, 'Buffers:': 0, + 'Cached:': 0} free = 0 for line in open('/proc/meminfo'): (key, value) = line.strip().split()[0:2] diff --git a/ovirt-guest-agent/GuestAgentWin32.py b/ovirt-guest-agent/GuestAgentWin32.py index 9cdff4a..b1b0ba7 100644 --- a/ovirt-guest-agent/GuestAgentWin32.py +++ b/ovirt-guest-agent/GuestAgentWin32.py @@ -1,6 +1,8 @@ #!/usr/bin/python -import time, os, logging, types +import time +import os +import logging import win32netcon import win32net import win32ts @@ -14,12 +16,14 @@ import subprocess import socket from OVirtAgentLogic import AgentLogicBase, DataRetriverBase -from ctypes import * +from ctypes import c_ulong, byref, windll, create_unicode_buffer,\ + Structure, sizeof, c_void_p from ctypes.util import find_library -from ctypes.wintypes import * +from ctypes.wintypes import DWORD import _winreg -# Both _winreg.QueryValueEx and win32api.RegQueryValueEx doesn't support reading + +# _winreg.QueryValueEx and win32api.RegQueryValueEx don't support reading # Unicode strings from the registry (at least on Python 2.5.1). def QueryStringValue(hkey, name): #if type(hkey) != type(PyHKEY): @@ -28,14 +32,20 @@ raise TypeError("2nd arg must be a unicode.") key_type = c_ulong(0) key_len = c_ulong(0) - if windll.advapi32.RegQueryValueExW(hkey.handle, name, None, byref(key_type), None, byref(key_len)) != 0: + res = windll.advapi32.RegQueryValueExW(hkey.handle, name, None, + byref(key_type), None, + byref(key_len)) + if res != 0: return unicode() if (key_type.value != win32con.REG_SZ): return unicode() key_value = create_unicode_buffer(key_len.value) - if windll.advapi32.RegQueryValueExW(hkey.handle, name, None, None, byref(key_value), byref(key_len)) != 0: + res = windll.advapi32.RegQueryValueExW(hkey.handle, name, None, None, + byref(key_value), byref(key_len)) + if res != 0: return unicode() return key_value.value + def GetNetworkInterfaces(): interfaces = list() @@ -56,12 +66,15 @@ except socket.error: # Assume IPv6 if parsing as IPv4 was failed. inet6.append(ip) - interfaces.append({ 'name' : adapter.Description, - 'inet' : inet, 'inet6' : inet6, - 'hw' : adapter.MacAddress.lower() }) + interfaces.append({ + 'name': adapter.Description, + 'inet': inet, + 'inet6': inet6, + 'hw': adapter.MacAddress.lower()}) except: logging.exception("Error retrieving network interfaces.") return interfaces + class PERFORMANCE_INFORMATION(Structure): _fields_ = [ @@ -81,66 +94,73 @@ ('ThreadCount', DWORD) ] + def get_perf_info(): pi = PERFORMANCE_INFORMATION() pi.cb = sizeof(pi) windll.psapi.GetPerformanceInfo(byref(pi), pi.cb) return pi + class IncomingMessageTypes: Credentials = 11 + class WinOsTypeHandler: - WINNT3_51 = 'Win NT 3.51' - WINNT4 = 'Win NT 4' - WIN2K = 'Win 2000' - WINXP = 'Win XP' - WIN2003 = 'Win 2003' - WIN2008 = 'Win 2008' - WIN2008R2 = 'Win 2008 R2' - WIN2012 = 'Win 2012' - WIN7 = 'Win 7' - WIN8 = 'Win 8' + WINNT3_51 = 'Win NT 3.51' + WINNT4 = 'Win NT 4' + WIN2K = 'Win 2000' + WINXP = 'Win XP' + WIN2003 = 'Win 2003' + WIN2008 = 'Win 2008' + WIN2008R2 = 'Win 2008 R2' + WIN2012 = 'Win 2012' + WIN7 = 'Win 7' + WIN8 = 'Win 8' WINCE3_1_0 = 'Win CE 1.0' WINCE3_2_0 = 'Win CE 2.0' WINCE3_2_1 = 'Win CE 2.1' WINCE3_3_0 = 'Win CE 3.0' - UNKNOWN = 'Unknown' - #winVersionMatrix is constructed from 3 fields <platformId>.<MajorVersion>.<MinorVersion> + UNKNOWN = 'Unknown' + # winVersionMatrix is constructed from 3 fields + # <platformId>.<MajorVersion>.<MinorVersion> winVersionMatrix = { - '2.3.51' : WINNT3_51, - '2.4.0' : WINNT4, - '2.5.0' : WIN2K, - '2.5.1' : WINXP, - '2.5.2' : WIN2003, - '2.6.0' : WIN2008, - '2.6.1' : WIN2008R2, # Window Server 2008 R2 - '2.6.2' : WIN2012, - '3.1.0' : WINCE3_1_0, - '3.2.0' : WINCE3_2_0, - '3.2.1' : WINCE3_2_1 , - '3.3.0' : WINCE3_3_0} + '2.3.51': WINNT3_51, + '2.4.0': WINNT4, + '2.5.0': WIN2K, + '2.5.1': WINXP, + '2.5.2': WIN2003, + '2.6.0': WIN2008, + '2.6.1': WIN2008R2, # Window Server 2008 R2 + '2.6.2': WIN2012, + '3.1.0': WINCE3_1_0, + '3.2.0': WINCE3_2_0, + '3.2.1': WINCE3_2_1, + '3.3.0': WINCE3_3_0} + def getWinOsType(self): retval = self.UNKNOWN try: versionTupple = win32api.GetVersionEx(1) key = "%d.%d.%d" % ( versionTupple[3], versionTupple[0], versionTupple[1]) - if self.winVersionMatrix.has_key(key): + if key in self.winVersionMatrix: retval = self.winVersionMatrix[key] # Window 7 and Window Server 2008 R2 share the same version. # Need to fix it using the wProductType field. VER_NT_WORKSTATION = 1 if (retval == WinOsTypeHandler.WIN2008R2 and - versionTupple[8] == VER_NT_WORKSTATION): - retval = WinOsTypeHandler.WIN7 + versionTupple[8] == VER_NT_WORKSTATION): + retval = WinOsTypeHandler.WIN7 elif (retval == WinOsTypeHandler.WIN2012 and - versionTupple[8] == VER_NT_WORKSTATION): + versionTupple[8] == VER_NT_WORKSTATION): retval = WinOsTypeHandler.WIN8 - logging.debug("WinOsTypeHandler::getWinOsType osType = '%s'", retval) + logging.debug("WinOsTypeHandler::getWinOsType osType = '%s'", + retval) except: logging.exception("getWinOsType - failed") return retval + class CommandHandlerWin: @@ -159,12 +179,14 @@ while retries <= RETIRES: try: time.sleep(1) - win32pipe.CallNamedPipe(PIPE_NAME, credentials, BUFSIZE, win32pipe.NMPWAIT_WAIT_FOREVER) + win32pipe.CallNamedPipe(PIPE_NAME, credentials, BUFSIZE, + win32pipe.NMPWAIT_WAIT_FOREVER) logging.debug("Credentials were written to pipe.") break except: error = windll.kernel32.GetLastError() - logging.error("Error writing credentials to pipe [%d/%d] (error = %d)", retries, RETIRES, error) + logging.error("Error writing credentials to pipe [%d/%d] " + "(error = %d)", retries, RETIRES, error) retries += 1 except: logging.exception("Error occurred during user login.") @@ -173,12 +195,14 @@ sessionId = win32ts.WTSGetActiveConsoleSessionId() if sessionId != 0xffffffff: logging.debug("Logging off current user (session %d)", sessionId) - win32ts.WTSLogoffSession(win32ts.WTS_CURRENT_SERVER_HANDLE, sessionId, 0) + win32ts.WTSLogoffSession(win32ts.WTS_CURRENT_SERVER_HANDLE, + sessionId, 0) else: logging.debug("No active session. Ignoring log off command.") def shutdown(self, timeout, msg): - cmd = "%s\\system32\\shutdown.exe -s -t %d -f -c \"%s\"" % (os.environ['WINDIR'], timeout, msg) + cmd = "%s\\system32\\shutdown.exe -s -t %d -f -c \"%s\"" \ + % (os.environ['WINDIR'], timeout, msg) logging.debug("Executing shutdown command: '%s'", cmd) # Since we're a 32-bit application that sometimes is executed on @@ -203,20 +227,26 @@ windll.kernel32.Wow64DisableWow64FsRedirection(old_value) def hibernate(self, state): - token = win32security.OpenProcessToken(win32api.GetCurrentProcess(), + token = win32security.OpenProcessToken( + win32api.GetCurrentProcess(), win32security.TOKEN_QUERY | win32security.TOKEN_ADJUST_PRIVILEGES) - shutdown_priv = win32security.LookupPrivilegeValue(None, + shutdown_priv = win32security.LookupPrivilegeValue( + None, win32security.SE_SHUTDOWN_NAME) - privs = win32security.AdjustTokenPrivileges(token, False, - [ (shutdown_priv, win32security.SE_PRIVILEGE_ENABLED) ]) + privs = win32security.AdjustTokenPrivileges( + token, + False, + [(shutdown_priv, win32security.SE_PRIVILEGE_ENABLED)]) logging.debug("Privileges before hibernation: %s", privs) - if windll.powrprof.SetSuspendState(state=='disk', True, False) != 0: + if windll.powrprof.SetSuspendState(state == 'disk', True, False) != 0: logging.info("System was in hibernation state.") else: - logging.error("Error setting system to hibernation state: %d", + logging.error( + "Error setting system to hibernation state: %d", win32api.GetLastError()) - # The LockWorkStation function is callable only by processes running on the interactive desktop. + # The LockWorkStation function is callable only by processes running on the + # interactive desktop. def LockWorkStation(self): try: logging.debug("LockWorkStation was called.") @@ -227,20 +257,35 @@ userToken = win32ts.WTSQueryUserToken(sessionId) if userToken is not None: logging.debug("Got the active user token.") - # The following access rights are required for CreateProcessAsUser. - access = win32security.TOKEN_QUERY|win32security.TOKEN_DUPLICATE|win32security.TOKEN_ASSIGN_PRIMARY - dupToken = win32security.DuplicateTokenEx(userToken, win32security.SecurityImpersonation, access, win32security.TokenPrimary, None) + # The following access rights are required for + # CreateProcessAsUser. + access = win32security.TOKEN_QUERY + access |= win32security.TOKEN_DUPLICATE + access |= win32security.TOKEN_ASSIGN_PRIMARY + dupToken = win32security.DuplicateTokenEx( + userToken, + win32security.SecurityImpersonation, + access, + win32security.TokenPrimary, + None) userToken.Close() if dupToken is not None: logging.debug("Duplicated the active user token.") - lockCmd = "%s\\system32\\rundll32.exe user32.dll,LockWorkStation" % (os.environ['WINDIR']) + lockCmd = os.path.join(os.environ['WINDIR'], + "system32\\rundll32.exe") + lockCmd += " user32.dll,LockWorkStation" logging.debug("Executing \"%s\".", lockCmd) - win32process.CreateProcessAsUser(dupToken, None, lockCmd, None, None, 0, 0, None, None, win32process.STARTUPINFO()) + win32process.CreateProcessAsUser( + dupToken, None, lockCmd, + None, None, 0, 0, None, + None, win32process.STARTUPINFO()) dupToken.Close() else: - logging.debug("No active session. Ignoring lock workstation command.") + logging.debug("No active session. Ignoring lock workstation " + "command.") except: logging.exception("LockWorkStation exception") + class WinDataRetriver(DataRetriverBase): def __init__(self): @@ -282,22 +327,23 @@ def getAvailableRAM(self): ## Returns the available physical memory (including the system cache). pi = get_perf_info() - return str(int((pi.PhysicalAvailable * pi.PageSize) / (1024**2))) + return str(int((pi.PhysicalAvailable * pi.PageSize) / (1024 ** 2))) def getUsers(self): - total_list=[] + total_list = [] try: server = self.getMachineName() res = 1 # initially set it to true pref = win32netcon.MAX_PREFERRED_LENGTH - level = 1 # setting it to 1 will provide more detailed info - while res: # loop until res2 - (user_list,total,res2)=win32net.NetWkstaUserEnum(server,level,res,pref) + level = 1 # setting it to 1 will provide more detailed info + while res: # loop until res2 + (user_list, total, res2) = \ + win32net.NetWkstaUserEnum(server, level, res, pref) logging.debug("getUsers: user_list = '%s'", user_list) for i in user_list: if not i['username'].startswith(server): - total_list.append([i['username'],i['logon_domain']]) - res=res2 + total_list.append([i['username'], i['logon_domain']]) + res = res2 except win32net.error: logging.exception("WinDataRetriver::getUsers") logging.debug("WinDataRetriver::getUsers retval = '%s'", total_list) @@ -309,19 +355,26 @@ domain = "" sessionId = win32ts.WTSGetActiveConsoleSessionId() if sessionId != 0xffffffff: - user = win32ts.WTSQuerySessionInformation(win32ts.WTS_CURRENT_SERVER_HANDLE, - sessionId, win32ts.WTSUserName) - domain = win32ts.WTSQuerySessionInformation(win32ts.WTS_CURRENT_SERVER_HANDLE, - sessionId, win32ts.WTSDomainName) + user = win32ts.WTSQuerySessionInformation( + win32ts.WTS_CURRENT_SERVER_HANDLE, + sessionId, + win32ts.WTSUserName) + domain = win32ts.WTSQuerySessionInformation( + win32ts.WTS_CURRENT_SERVER_HANDLE, + sessionId, + win32ts.WTSDomainName) if domain == "": pass elif domain.lower() != self.getMachineName().lower(): # Use FQDN as user name if computer is part of a domain. try: user = u"%s\\%s" % (domain, user) - user = win32security.TranslateName(user, - win32api.NameSamCompatible, win32api.NameUserPrincipal) - # Check for error because no exception is raised when running under Windows XP. + user = win32security.TranslateName( + user, + win32api.NameSamCompatible, + win32api.NameUserPrincipal) + # Check for error because no exception is raised when + # running under Windows XP. err = win32api.GetLastError() if err != 0: raise RuntimeError(err, 'TranslateName') @@ -343,10 +396,15 @@ path_name = path + ':\\' if (drives_mask & 1): try: - (free, total) = win32api.GetDiskFreeSpaceEx(path_name)[:2] + res = win32api.GetDiskFreeSpaceEx(path_name) + (free, total) = res[:2] fs = win32api.GetVolumeInformation(path_name)[4] used = total - free - usages.append({ 'path' : path_name, 'fs' : fs, 'total' : total, 'used' : used }) + usages.append({ + 'path': path_name, + 'fs': fs, + 'total': total, + 'used': used}) except: pass drives_mask >>= 1 @@ -358,16 +416,23 @@ def getMemoryStats(self): pi = get_perf_info() # keep the unit consistent with Linux guests - self.memStats['mem_total'] = str(int((pi.PhysicalTotal * pi.PageSize) / 1024)) - self.memStats['mem_free'] = str(int((pi.PhysicalAvailable * pi.PageSize) / 1024)) + self.memStats['mem_total'] = \ + str(int((pi.PhysicalTotal * pi.PageSize) / 1024)) + self.memStats['mem_free'] = \ + str(int((pi.PhysicalAvailable * pi.PageSize) / 1024)) self.memStats['mem_unused'] = self.memStats['mem_free'] try: strComputer = "." - objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator") - objSWbemServices = objWMIService.ConnectServer(strComputer, "root\cimv2") - colItems = objSWbemServices.ExecQuery("SELECT * FROM Win32_PerfFormattedData_PerfOS_Memory") + objWMIService = \ + win32com.client.Dispatch("WbemScripting.SWbemLocator") + objSWbemServices = \ + objWMIService.ConnectServer(strComputer, "root\cimv2") + colItems = \ + objSWbemServices.ExecQuery( + "SELECT * FROM Win32_PerfFormattedData_PerfOS_Memory") for objItem in colItems: - # Please see the definition of Win32_PerfFormattedData_PerfOS_Memory class in MSDN manual + # Please see the definition of + # Win32_PerfFormattedData_PerfOS_Memory class in the MSDN # for the explanations of the following fields. self.memStats['swap_in'] = objItem.PagesInputPersec self.memStats['swap_out'] = objItem.PagesOutputPersec @@ -376,6 +441,7 @@ except: logging.exception("Error retrieving detailed memory stats") return self.memStats + class WinVdsAgent(AgentLogicBase): @@ -393,15 +459,22 @@ logging.exception("WinVdsAgent::run") def doWork(self): - # CoInitialize() should be called in multi-threading program according to msdn document. + # CoInitialize() should be called in multi-threading program according + # to msdn document. pythoncom.CoInitialize() AgentLogicBase.doWork(self) def disable_screen_saver(self): - keyHandle = win32api.RegOpenKeyEx(win32con.HKEY_USERS, ".DEFAULT\Control Panel\Desktop", 0, win32con.KEY_WRITE) - win32api.RegSetValueEx(keyHandle, "ScreenSaveActive", 0, win32con.REG_SZ, "0") + keyHandle = win32api.RegOpenKeyEx( + win32con.HKEY_USERS, + ".DEFAULT\Control Panel\Desktop", + 0, + win32con.KEY_WRITE) + win32api.RegSetValueEx(keyHandle, "ScreenSaveActive", 0, + win32con.REG_SZ, "0") keyHandle.Close() + def test(): dr = WinDataRetriver() print "Machine Name:", dr.getMachineName() diff --git a/ovirt-guest-agent/LockActiveSession.py b/ovirt-guest-agent/LockActiveSession.py index 206a9dc..aed5aa0 100644 --- a/ovirt-guest-agent/LockActiveSession.py +++ b/ovirt-guest-agent/LockActiveSession.py @@ -15,34 +15,47 @@ # Refer to the README and COPYING files for full details of the license. # -import dbus, logging, os +import dbus +import logging +import os + def GetActiveSession(): session = None try: bus = dbus.SystemBus() - manager = dbus.Interface(bus.get_object('org.freedesktop.ConsoleKit', - '/org/freedesktop/ConsoleKit/Manager'), + manager = dbus.Interface( + bus.get_object( + 'org.freedesktop.ConsoleKit', + '/org/freedesktop/ConsoleKit/Manager'), dbus_interface='org.freedesktop.ConsoleKit.Manager') sessions = manager.GetSessions() for session_path in sessions: - s = dbus.Interface(bus.get_object('org.freedesktop.ConsoleKit', session_path), + s = dbus.Interface( + bus.get_object( + 'org.freedesktop.ConsoleKit', session_path), dbus_interface='org.freedesktop.ConsoleKit.Session') if s.IsActive(): session = s except: - logging.exception("Error retrieving active session (ignore if running on a system without ConsoleKit installed).") + logging.exception("Error retrieving active session (ignore if running " + "on a system without ConsoleKit installed).") return session + def GetScreenSaver(): try: bus = dbus.SessionBus() - screensaver = dbus.Interface(bus.get_object('org.freedesktop.ScreenSaver', '/ScreenSaver'), + screensaver = dbus.Interface( + bus.get_object( + 'org.freedesktop.ScreenSaver', '/ScreenSaver'), dbus_interface='org.freedesktop.ScreenSaver') except dbus.DBusException: - logging.exception("Error retrieving ScreenSaver interface (ignore if running on GNOME).") + logging.exception("Error retrieving ScreenSaver interface (ignore if " + "running on GNOME).") screensaver = None return screensaver + def LockSession(session): # First try to lock in the KDE "standard" interface. Since KDE is @@ -59,20 +72,21 @@ else: exitcode = 1 os._exit(exitcode) - + result = os.waitpid(pid, 0) - logging.debug("Process %d terminated (result = %s)" % (pid, result)) - + logging.debug("Process %d terminated (result = %s)", pid, result) + # If our first try failed, try the GNOME "standard" interface. if result[1] != 0: - session.Lock() + session.Lock() + def main(): session = GetActiveSession() if session is not None: try: LockSession(session) - logging.info("Session %s should be locked now." % (session.GetId())) + logging.info("Session %s should be locked now.", session.GetId()) except: logging.exception("Error while trying to lock session.") else: diff --git a/ovirt-guest-agent/OVirtAgentLogic.py b/ovirt-guest-agent/OVirtAgentLogic.py index e32836e..43c9635 100644 --- a/ovirt-guest-agent/OVirtAgentLogic.py +++ b/ovirt-guest-agent/OVirtAgentLogic.py @@ -16,9 +16,13 @@ # Refer to the README and COPYING files for full details of the license. # -import thread, time, logging, struct +import thread +import time +import logging +import struct from threading import Event from VirtIoChannel import VirtIoChannel + # Return a safe (password masked) repr of the credentials block. def safe_creds_repr(creds): @@ -26,30 +30,47 @@ user_len = struct.unpack('>I', creds[:int_len])[0] pass_len = len(creds) - user_len - int_len - 1 cut = user_len + int_len - return repr(creds[:cut] + ('*' * 8)+ creds[cut + pass_len:]) + return repr(creds[:cut] + ('*' * 8) + creds[cut + pass_len:]) + class DataRetriverBase: def __init__(self): - self.memStats = {'mem_total' : 0, 'mem_free': 0, 'mem_unused' : 0, - 'swap_in' : 0, 'swap_out' : 0, 'pageflt' : 0, 'majflt' : 0} + self.memStats = { + 'mem_total': 0, + 'mem_free': 0, + 'mem_unused': 0, + 'swap_in': 0, + 'swap_out': 0, + 'pageflt': 0, + 'majflt': 0} + def getMachineName(self): pass + def getOsVersion(self): pass + def getAllNetworkInterfaces(self): pass + def getApplications(self): pass + def getAvailableRAM(self): pass + def getUsers(self): pass + def getActiveUser(self): pass + def getDisksUsage(self): pass + def getMemoryStats(self): pass + class AgentLogicBase: @@ -58,7 +79,8 @@ self.wait_stop = Event() self.heartBitRate = config.getint("general", "heart_beat_rate") self.userCheckRate = config.getint("general", "report_user_rate") - self.appRefreshRate = config.getint("general", "report_application_rate") + self.appRefreshRate = config.getint("general", + "report_application_rate") self.disksRefreshRate = config.getint("general", "report_disk_usage") self.activeUser = "" self.vio = VirtIoChannel(config.get("virtio", "device")) @@ -95,15 +117,15 @@ try: while not self.wait_stop.isSet(): - counter +=1 + counter += 1 hbsecs -= 1 if hbsecs <= 0: self.vio.write('heartbeat', - {'free-ram' : self.dr.getAvailableRAM(), - 'memory-stat' : self.dr.getMemoryStats()}) + {'free-ram': self.dr.getAvailableRAM(), + 'memory-stat': self.dr.getMemoryStats()}) hbsecs = self.heartBitRate - usersecs -=1 - if usersecs <=0: + usersecs -= 1 + if usersecs <= 0: self.sendUserInfo() usersecs = self.userCheckRate appsecs -= 1 @@ -122,17 +144,20 @@ def doListen(self): logging.debug("AgentLogicBase::doListen() - entered") - if self.commandHandler == None: - logging.debug("AgentLogicBase::doListen() - no commandHandler ... exiting doListen thread") + if self.commandHandler is None: + logging.debug("AgentLogicBase::doListen() - no commandHandler " + "... exiting doListen thread") return while not self.wait_stop.isSet(): try: - logging.debug("AgentLogicBase::doListen() - in loop before vio.read") + logging.debug("AgentLogicBase::doListen() - " + "in loop before vio.read") cmd, args = self.vio.read() if cmd: self.parseCommand(cmd, args) except: - logging.exception('Error while reading the virtio-serial channel.') + logging.exception('Error while reading the virtio-serial ' + 'channel.') logging.debug("AgentLogicBase::doListen() - exiting") def parseCommand(self, command, args): @@ -150,14 +175,17 @@ msg = args['message'] except: msg = 'System is going down' - logging.info("Shutting down (timeout = %d, message = '%s')" % (timeout, msg)) + logging.info("Shutting down (timeout = %d, message = '%s')" + % (timeout, msg)) self.commandHandler.shutdown(timeout, msg) elif command == 'login': username = args['username'].encode('utf8') password = args['password'].encode('utf8') - credentials = struct.pack('>I%ds%ds' % (len(username), len(password) + 1), + credentials = struct.pack( + '>I%ds%ds' % (len(username), len(password) + 1), len(username), username, password) - logging.debug("User log-in (credentials = %s)" % (safe_creds_repr(credentials))) + logging.debug("User log-in (credentials = %s)" + % (safe_creds_repr(credentials))) self.commandHandler.login(credentials) elif command == 'refresh': self.sendUserInfo(True) @@ -171,28 +199,32 @@ state = args.get('state', 'disk') self.commandHandler.hibernate(state) else: - logging.error("Unknown external command: %s (%s)" % (command, args)) + logging.error("Unknown external command: %s (%s)" + % (command, args)) def sendUserInfo(self, force=False): cur_user = str(self.dr.getActiveUser()) - logging.debug("AgentLogicBase::sendUserInfo - cur_user = '%s'"%(cur_user)) + logging.debug("AgentLogicBase::sendUserInfo - cur_user = '%s'" % + (cur_user)) if cur_user != self.activeUser or force: - self.vio.write('active-user', { 'name' : cur_user }) + self.vio.write('active-user', {'name': cur_user}) self.activeUser = cur_user def sendInfo(self): - self.vio.write('host-name', { 'name' : self.dr.getMachineName() }) - self.vio.write('os-version', { 'version' : self.dr.getOsVersion() }) - self.vio.write('network-interfaces', { 'interfaces' : self.dr.getAllNetworkInterfaces() }) + self.vio.write('host-name', {'name': self.dr.getMachineName()}) + self.vio.write('os-version', {'version': self.dr.getOsVersion()}) + self.vio.write('network-interfaces', + {'interfaces': self.dr.getAllNetworkInterfaces()}) def sendAppList(self): - self.vio.write('applications', { 'applications' : self.dr.getApplications() }) + self.vio.write('applications', + {'applications': self.dr.getApplications()}) def sendDisksUsages(self): - self.vio.write('disks-usage', { 'disks' : self.dr.getDisksUsage() }) + self.vio.write('disks-usage', {'disks': self.dr.getDisksUsage()}) def sendMemoryStats(self): - self.vio.write('memory-stats', { 'memory' : self.dr.getMemoryStats() }) + self.vio.write('memory-stats', {'memory': self.dr.getMemoryStats()}) def sessionLogon(self): logging.debug("AgentLogicBase::sessionLogon: user logs on the system.") @@ -206,17 +238,20 @@ self.vio.write('session-logon') def sessionLogoff(self): - logging.debug("AgentLogicBase::sessionLogoff: user logs off from the system.") + logging.debug("AgentLogicBase::sessionLogoff: " + "user logs off from the system.") self.activeUser = 'None' self.vio.write('session-logoff') - self.vio.write('active-user', { 'name' : self.activeUser }) + self.vio.write('active-user', {'name': self.activeUser}) def sessionLock(self): - logging.debug("AgentLogicBase::sessionLock: user locks the workstation.") + logging.debug("AgentLogicBase::sessionLock: " + "user locks the workstation.") self.vio.write('session-lock') def sessionUnlock(self): - logging.debug("AgentLogicBase::sessionUnlock: user unlocks the workstation.") + logging.debug("AgentLogicBase::sessionUnlock: " + "user unlocks the workstation.") self.vio.write('session-unlock') def sessionStartup(self): diff --git a/ovirt-guest-agent/OVirtGuestService.py b/ovirt-guest-agent/OVirtGuestService.py index d848492..65ba8fd 100644 --- a/ovirt-guest-agent/OVirtGuestService.py +++ b/ovirt-guest-agent/OVirtGuestService.py @@ -5,39 +5,49 @@ import win32service import win32evtlogutil from GuestAgentWin32 import WinVdsAgent -import logging, logging.config +import logging +import logging.config import servicemanager import ConfigParser -import os -import _winreg +# import os +# import _winreg AGENT_CONFIG = 'ovirt-guest-agent.ini' -# Values from WM_WTSSESSION_CHANGE message (http://msdn.microsoft.com/en-us/library/aa383828.aspx) +# Values from WM_WTSSESSION_CHANGE message +# (http://msdn.microsoft.com/en-us/library/aa383828.aspx) WTS_SESSION_LOGON = 0x5 WTS_SESSION_LOGOFF = 0x6 WTS_SESSION_LOCK = 0x7 WTS_SESSION_UNLOCK = 0x8 + class OVirtGuestService(win32serviceutil.ServiceFramework): _svc_name_ = "OVirtGuestService" _svc_display_name_ = "OVirt Guest Agent Service" _svc_description_ = "OVirt Guest Agent Service" _svc_deps_ = ["EventLog"] + def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) self._shutting_down = False #global AGENT_CONFIG - #hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Redhat\\RHEV\\Tools\\OVirt Guest Agent") - #AGENT_CONFIG = os.path.join( _winreg.QueryValueEx(hkey, "InstallDir")[0], AGENT_CONFIG) + #hkey = _winreg.OpenKey( + # _winreg.HKEY_LOCAL_MACHINE, + # "SOFTWARE\\Redhat\\RHEV\\Tools\\OVirt Guest Agent") + #AGENT_CONFIG = os.path.join( + # _winreg.QueryValueEx(hkey, + # "InstallDir")[0], + # AGENT_CONFIG) #hkey.Close() logging.config.fileConfig(AGENT_CONFIG) # Overriding this method in order to accept session change notifications. def GetAcceptedControls(self): - accepted = win32serviceutil.ServiceFramework.GetAcceptedControls(self) | win32service.SERVICE_ACCEPT_SESSIONCHANGE + accepted = win32serviceutil.ServiceFramework.GetAcceptedControls(self) + accepted |= win32service.SERVICE_ACCEPT_SESSIONCHANGE return accepted def SvcStop(self): @@ -83,11 +93,12 @@ def ReportEvent(self, EventID): try: - win32evtlogutil.ReportEvent(self._svc_name_, - EventID, - 0, # category - servicemanager.EVENTLOG_INFORMATION_TYPE, - (self._svc_name_, '')) + win32evtlogutil.ReportEvent( + self._svc_name_, + EventID, + 0, # category + servicemanager.EVENTLOG_INFORMATION_TYPE, + (self._svc_name_, '')) except: logging.exception("Failed to write to the event log") diff --git a/ovirt-guest-agent/VirtIoChannel.py b/ovirt-guest-agent/VirtIoChannel.py index 0dbb872..e4ca77f 100644 --- a/ovirt-guest-agent/VirtIoChannel.py +++ b/ovirt-guest-agent/VirtIoChannel.py @@ -16,17 +16,27 @@ # Refer to the README and COPYING files for full details of the license. # -import os, platform, time +import os +import platform +import time -try: - import json -except ImportError: - import simplejson as json + +# avoid pep8 warnings +def import_json(): + try: + import json + return json + except ImportError: + import simplejson + return simplejson +json = import_json() + class VirtIoChannel: - # Python on Windows 7 return 'Microsoft' rather than 'Windows' as documented. - is_windows = (platform.system() == 'Windows') or (platform.system() == 'Microsoft') + # Python on Windows 7 returns 'Microsoft' rather than 'Windows' as + # documented. + is_windows = platform.system() in ['Windows', 'Microsoft'] def __init__(self, vport_name): if self.is_windows: @@ -75,7 +85,7 @@ def read(self): return self._parseLine(self._readline()) - def write(self, name, args = {}): + def write(self, name, args={}): if not isinstance(name, str): raise TypeError("1nd arg must be a str.") if not isinstance(args, dict): @@ -89,6 +99,7 @@ written = os.write(self._vport, message) message = message[written:] + def _create_vio(): if (platform.system() == 'Windows') or (platform.system() == 'Microsoft'): vport_name = '\\\\.\\Global\\com.redhat.rhevm.vdsm' @@ -96,11 +107,18 @@ vport_name = '/dev/virtio-ports/com.redhat.rhevm.vdsm' return VirtIoChannel(vport_name) + def _test_write(): vio = _create_vio() - vio.write('network-interfaces', { 'interfaces' : - [{ 'name': 'eth0', 'inet': [ '10.0.0.2' ], 'inet6': [ 'fe80::213:20ff:fef5:f9d6' ], 'hw': '00:1a:4a:23:10:00' }] }) - vio.write('applications', { 'applications' : [ 'kernel-2.6.32-131.4.1.el6', 'rhev-agent-2.3.11-1.el6'] }) + vio.write('network-interfaces', + {'interfaces': [{ + 'name': 'eth0', + 'inet': ['10.0.0.2'], + 'inet6': ['fe80::213:20ff:fef5:f9d6'], + 'hw': '00:1a:4a:23:10:00'}]}) + vio.write('applications', {'applications': ['kernel-2.6.32-131.4.1.el6', + 'rhev-agent-2.3.11-1.el6']}) + def _test_read(): vio = _create_vio() diff --git a/ovirt-guest-agent/WinFile.py b/ovirt-guest-agent/WinFile.py index 3436919..a561c13 100644 --- a/ovirt-guest-agent/WinFile.py +++ b/ovirt-guest-agent/WinFile.py @@ -23,14 +23,15 @@ import win32con import pywintypes + # Using Python's os.read() to do a blocking-read doesn't allow # to use os.write() on a different thread. This class overrides # this problem by using Windows's API. - class WinFile(object): def __init__(self, filename): - self._hfile = win32file.CreateFile(filename, + self._hfile = win32file.CreateFile( + filename, win32con.GENERIC_READ | win32con.GENERIC_WRITE, win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, win32security.SECURITY_ATTRIBUTES(), @@ -38,19 +39,28 @@ win32con.FILE_FLAG_OVERLAPPED, 0) self._read_ovrlpd = pywintypes.OVERLAPPED() - self._read_ovrlpd.hEvent = win32event.CreateEvent(None, True, False, None) + self._read_ovrlpd.hEvent = win32event.CreateEvent(None, True, False, + None) self._write_ovrlpd = pywintypes.OVERLAPPED() - self._write_ovrlpd.hEvent = win32event.CreateEvent(None, True, False, None) + self._write_ovrlpd.hEvent = win32event.CreateEvent(None, True, False, + None) def read(self, n): (nr, buf) = (0, ()) try: - (hr, buf) = win32file.ReadFile(self._hfile, win32file.AllocateReadBuffer(n), self._read_ovrlpd) - nr = win32file.GetOverlappedResult(self._hfile, self._read_ovrlpd, True) + (hr, buf) = win32file.ReadFile( + self._hfile, + win32file.AllocateReadBuffer(n), + self._read_ovrlpd) + nr = win32file.GetOverlappedResult(self._hfile, + self._read_ovrlpd, + True) except: pass return buf[:nr] def write(self, s): win32file.WriteFile(self._hfile, s, self._write_ovrlpd) - return win32file.GetOverlappedResult(self._hfile, self._write_ovrlpd, True) + return win32file.GetOverlappedResult(self._hfile, + self._write_ovrlpd, + True) diff --git a/ovirt-guest-agent/ovirt-guest-agent.py b/ovirt-guest-agent/ovirt-guest-agent.py index 23b036a..c7d60c8 100644 --- a/ovirt-guest-agent/ovirt-guest-agent.py +++ b/ovirt-guest-agent/ovirt-guest-agent.py @@ -15,13 +15,18 @@ # Refer to the README and COPYING files for full details of the license. # -import logging, logging.config, os, signal, sys +import logging +import logging.config +import os +import signal +import sys import getopt import ConfigParser from GuestAgentLinux2 import LinuxVdsAgent AGENT_CONFIG = '/etc/ovirt-guest-agent.conf' AGENT_PIDFILE = '/run/ovirt-guest-agent.pid' + class OVirtAgentDaemon: @@ -42,8 +47,8 @@ f = file(pidfile, "w") f.write("%s\n" % (os.getpid())) f.close() - os.chmod(pidfile, 0x1b4) # rw-rw-r-- (664) - + os.chmod(pidfile, 0644) # rw-rw-r-- (664) + self.register_signal_handler() self.agent.run() @@ -51,7 +56,7 @@ def _daemonize(self): if os.getppid() == 1: - raise RuntimeError, "already a daemon" + raise RuntimeError("already a daemon") pid = os.fork() if pid == 0: os.umask(0) @@ -69,19 +74,20 @@ nullfile.close() def register_signal_handler(self): - + def sigterm_handler(signum, frame): logging.debug("Handling signal %d" % (signum)) if signum == signal.SIGTERM: logging.info("Stopping oVirt guest agent") self.agent.stop() - + signal.signal(signal.SIGTERM, sigterm_handler) + def usage(): print "Usage: %s [OPTION]..." % (sys.argv[0]) print "" - print " -p, --pidfile\t\tset pid file name (default: %s)" % (AGENT_PIDFILE) + print " -p, --pidfile\t\tset pid file name (default: %s)" % AGENT_PIDFILE print " -d\t\t\trun program as a daemon." print " -h, --help\t\tdisplay this help and exit." print "" @@ -89,7 +95,8 @@ if __name__ == '__main__': try: try: - opts, args = getopt.getopt(sys.argv[1:], "?hp:d", ["help", "pidfile="]) + opts, args = getopt.getopt(sys.argv[1:], + "?hp:d", ["help", "pidfile="]) pidfile = AGENT_PIDFILE daemon = False for opt, value in opts: diff --git a/ovirt-guest-agent/setup.py b/ovirt-guest-agent/setup.py index 7b1c36c..8cf2768 100644 --- a/ovirt-guest-agent/setup.py +++ b/ovirt-guest-agent/setup.py @@ -6,38 +6,39 @@ import os import version -dsa_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))), "re") +dsa_path = os.path.join( + os.path.dirname( + os.path.dirname( + os.path.dirname( + os.path.abspath( + sys.argv[0])))), + "re") sys.path.append(dsa_path) if len(sys.argv) == 1: sys.argv.append("py2exe") sys.argv.append("-b 1") + class Target: def __init__(self, **kw): self.__dict__.update(kw) - self.version = "%s.%s"%(version.version_info['software_version'], - version.version_info['software_revision']) + self.version = "%s.%s" % (version.version_info['software_version'], + version.version_info['software_revision']) self.company_name = "Red Hat" self.copyright = "Copyright(C) Red Hat Inc." self.name = "Guest VDS Agent " -OVirtAgentTarget = Target( - description = "Ovirt Guest Agent", - modules = ["OVirtGuestService"] - ) +OVirtAgentTarget = Target(description="Ovirt Guest Agent", + modules=["OVirtGuestService"]) -DLL_EXCLUDES = [ 'POWRPROF.dll', 'KERNELBASE.dll', 'WTSAPI32.dll', 'MSWSOCK.dll' ] +DLL_EXCLUDES = ['POWRPROF.dll', 'KERNELBASE.dll', + 'WTSAPI32.dll', 'MSWSOCK.dll'] for name in glob(os.getenv('windir') + '\*\API-MS-Win-*.dll'): DLL_EXCLUDES.append(name[name.rfind('\\') + 1:]) -setup( - service = [OVirtAgentTarget], - options = { - 'py2exe': { - 'bundle_files': 1, - 'dll_excludes': DLL_EXCLUDES - } - }, - zipfile = None -) +setup(service=[OVirtAgentTarget], + options={'py2exe': { + 'bundle_files': 1, + 'dll_excludes': DLL_EXCLUDES}}, + zipfile=None) diff --git a/ovirt-guest-agent/version.py b/ovirt-guest-agent/version.py index f6da6cf..4bdffc1 100644 --- a/ovirt-guest-agent/version.py +++ b/ovirt-guest-agent/version.py @@ -8,7 +8,7 @@ python based components """ version_name = "Ice Coffee" -build_name = "trunk" +build_name = "trunk" software_version = "4.7" # software_revision should be replaced by build system to the real revision software_revision = "1" -- To view, visit http://gerrit.ovirt.org/10759 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I74c33ed2ef2e5c33b9d25cb8b38e4201d67a957b Gerrit-PatchSet: 1 Gerrit-Project: ovirt-guest-agent Gerrit-Branch: master Gerrit-Owner: Vinzenz Feenstra <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
