extras-buildsys/common Commands.py, NONE, 1.1 HTTPServer.py, 1.12, 1.13 Makefile, 1.11, 1.12 URLopener.py, 1.1, 1.2

Daniel Williams (dcbw) fedora-extras-commits at redhat.com
Fri Apr 28 03:17:43 UTC 2006


Author: dcbw

Update of /cvs/fedora/extras-buildsys/common
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv5292/common

Modified Files:
	HTTPServer.py Makefile URLopener.py 
Added Files:
	Commands.py 
Log Message:
2006-04-27  Dan Williams  <dcbw at redhat.com>

    Commit partial rework of builder<->server communcation.




--- NEW FILE Commands.py ---
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Copyright 2006 Dan Williams <dcbw at redhat.com> and Red Hat, Inc.


""" Common functions and constants for command parsing, receiving, and sending """


import threading



CMD_NAME_ERROR = "Error"
CMD_NAME_NOP = "NOP"
CMD_NAME_TARGETS = "Targets"
CMD_NAME_SLOTS = "Slots"
CMD_NAME_NEW_JOB_REQ = "NewJob"
CMD_NAME_NEW_JOB_ACK = "NewJobAck"


class SequenceGenerator(object):
    """An class that atomically increments a number."""
    def __init__(self):
        self._lock = threading.Lock()
        self._seq = 0

    def __del__(self):
        del self._lock
        del self._seq

    def next(self):
        """Returns the next number in the object's sequence."""
        self._lock.acquire()
        num = self._seq = self._seq + 1
        self._lock.release()
        return num


def serialize_to_command_stream(cmds):
    stream = []
    for cmd in cmds:
        stream.append(cmd.serialize())
    return stream


def deserialize_command_stream(cmd_stream):
    """ Converts a command stream into a list of command objects.

    Argument is a python list of serialized command objects, each
    represented by a python dict.
    
    Return value is a python list of command objects.
    """

    cmds = []
    for item in cmd_stream:
        cmd = PlgCommand.deserialize(item)
        cmds.append(cmd)
    return cmds


class PlgCommand(object):
    """Abstract base class for all builder<->server command
    objects."""

    _need_ack = False

    def __init__(self, name, seq=0):
        """Initialize the command object.  Not used directly,
        but called by subclasses.
        
        The NAME argument is the name (type) of the command.
        
        The SEQ argument is the command's sequence number, which
        should be unique among all commands the program sends.
        """
        self._name = name
        self._seq = seq

    def deserialize(cmd_stream):
        """Class method that deserializes a command stream into
        a particular subclass of command object.
        
        The CMD_STREAM argument is a python dict representing the
        serialized state of the command.

        Return value is the command object.
        """
        cmd = name = args = seq = None
        try:
            # Pull out required fields
            name = cmd_stream['name']
            args = cmd_stream['args']
            seq = cmd_stream['sequence']
        except (KeyError, TypeError), e:
            print "PlgCommand deserialize error: %s" % e
            return None

        # Create the specific command object from the command's name
        if name == CMD_NAME_ERROR:
            cmd = PlgCommandError._deserialize(args)
        elif name == CMD_NAME_TARGETS:
            cmd = PlgCommandTargets._deserialize(args)
        elif name == CMD_NAME_SLOTS:
            cmd = PlgCommandSlots._deserialize(args)
        elif name == CMD_NAME_NEW_JOB_REQ:
            cmd = PlgCommandNewJobReq._deserialize(args)
        elif name == CMD_NAME_NEW_JOB_ACK:
            cmd = PlgCommandNewJobAck._deserialize(args)

        # If command creation was successful, set the sequence
        # number from the command stream on the command.  We don't
        # want to expose the sequence number to subclasses because
        # they should never need it.
        if cmd:
            cmd._seq = seq

        return cmd

    deserialize = staticmethod(deserialize)

    def name(self):
        """Returns the command's name."""
        return self._name

    def seq(self):
        """Returns the command's sequece number."""
        return self._seq

    def need_ack(self):
        """Returns a boolean stating whether this command requires
        an acknowledgement command or not."""
        return self._need_ack

    def _serialize(self, args):
        """Serializes the basic command information into the command
        stream, returning a python dict.  Should only be called by
        subclasses, after determining the arguments the subclass wishes
        to serialize into the command.
        
        Argument ARGS is a python dict containing the subclass-specific
        command's arguments.
        """
        if not args:
            raise ValueError("args cannot be None")
        cmd = {}
        cmd['name'] = self._name
        cmd['sequence'] = self._seq
        cmd['args'] = args
        return cmd

    def __str__(self):
        return "%s(seq: %d)" % (self._name, self._seq)
    __repr__ = __str__


class PlgCommandAck(PlgCommand):
    """Abstract base class for acknowledgement commands."""

    def __init__(self, name, acked_seq, seq=0):
        PlgCommand.__init__(self, name, seq)
        self._acked_seq = acked_seq

    def _deserialize_acked_seq(args):
        try:
            acked_seq = args['acked_seq']
        except KeyError, TypeError:
            raise ValueError("No 'acked_seq' argument found.")
        return acked_seq

    _deserialize_acked_seq = staticmethod(_deserialize_acked_seq)

    def _serialize(self, args):
        args['acked_seq'] = self._acked_seq
        return PlgCommand._serialize(self, args)

    def acked_seq(self):
        return self._acked_seq


class PlgCommandNop(PlgCommand):
    def __init__(self, seq=0):
        PlgCommand.__init__(self, CMD_NAME_NOP, seq)

    def _deserialize(args):
        return PlgCommandNop()

    _deserialize = staticmethod(_deserialize)

    def serialize(self):
        return PlgCommand._serialize(self, {})


class PlgCommandError(PlgCommand):
    def __init__(self, reason, seq=0):
        PlgCommand.__init__(self, CMD_NAME_ERROR, seq)
        self._reason = reason

    def _deserialize(args):
        try:
            reason = args['reason']
        except KeyError, TypeError:
            raise ValueError("No 'reason' argument found.")
        return PlgCommandError(reason)

    _deserialize = staticmethod(_deserialize)

    def serialize(self):
        args = {}
        args['reason'] = self._reason
        return PlgCommand._serialize(self, args)

    def reason(self):
        return self._reason

    def __str__(self):
        return "%s(seq: %d, reason: %s)" % (self._name, self._seq, self._reason)


class PlgCommandSlots(PlgCommand):
    def __init__(self, free, maximum, seq=0):
        PlgCommand.__init__(self, CMD_NAME_SLOTS, seq)
        self._free_slots = free
        self._max_slots = maximum

    def _deserialize(args):
        try:
            free = args['free']
        except ValueError, TypeError:
            raise ValueError("No 'free' argument found.")
        try:
            maximum = args['max']
        except KeyError, TypeError:
            raise ValueError("No 'max' argument found.")
        return PlgCommandSlots(free, maximum)

    _deserialize = staticmethod(_deserialize)

    def serialize(self):
        args = {}
        args['free'] = self._free_slots
        args['max'] = self._max_slots
        return PlgCommand._serialize(self, args)

    def free_slots(self):
        return self._free_slots

    def max_slots(self):
        return self._max_slots

    def __str__(self):
        return "%s(seq: %d, slots: (%d of %d))" % (self._name, self._seq, self._free_slots, self._max_slots)


class PlgCommandTargets(PlgCommand):
    def __init__(self, targets, seq=0):
        PlgCommand.__init__(self, CMD_NAME_TARGETS, seq)
        self._targets = targets

    def _deserialize(args):
        try:
            targets = args['targets']
        except KeyError, TypeError:
            raise ValueError("No 'targets' argument found.")

        # Sanity checking on targets argument
        if type(targets) != type([]):
            raise ValueError("'targets' argument was not a list.")
        for target in targets:
            try:
                distro = target['distro']
                tg = target['target']
                basearch = target['arch']
                repo = target['repo']
                suparch = target['supported_arches']
            except KeyError, e:
                raise ValueError("Required item '%s' not found in a target." % e)

        return PlgCommandTargets(targets)

    _deserialize = staticmethod(_deserialize)

    def serialize(self):
        args = {}
        args['targets'] = self._targets
        return PlgCommand._serialize(self, args)

    def targets(self):
        return self._targets

    def __str__(self):
        return "%s(seq: %d, targets: %s)" % (self._name, self._seq, self._targets)


class PlgCommandNewJobReq(PlgCommand):

    _need_ack = True

    def __init__(self, parent_job, target_dict, srpm_url, seq=0):
        PlgCommand.__init__(self, CMD_NAME_NEW_JOB_REQ, seq)
        self._parent_job = parent_job  # doesn't get serialized
        self._target_dict = target_dict
        self._srpm_url = srpm_url

    def _deserialize(args):
        try:
            target_dict = args['target_dict']
        except KeyError, TypeError:
            raise ValueError("No 'target_dict' argument found.")
        try:
            srpm_url = args['srpm_url']
        except KeyError, TypeError:
            raise ValueError("No 'srpm_url' argument found.")

        return PlgCommandNewJobReq(None, target_dict, srpm_url)

    _deserialize = staticmethod(_deserialize)

    def serialize(self):
        args = {}
        args['target_dict'] = self._target_dict
        args['srpm_url'] = self._srpm_url
        return PlgCommand._serialize(self, args)

    def parent_job(self):
        return self._parent_job

    def target_dict(self):
        return self._target_dict

    def srpm_url(self):
        return self._srpm_url

    def __str__(self):
        return "%s(seq: %d, target_dict: %s, srpm_url: %s)" % (self._name, self._seq, self._target_dict, self._srpm_url)


class PlgCommandNewJobAck(PlgCommandAck):
    def __init__(self, archjob_id, msg, req_seq, seq=0):
        PlgCommandAck.__init__(self, CMD_NAME_NEW_JOB_ACK, req_seq, seq)
        self._archjob_id = archjob_id
        self._msg = msg

    def _deserialize(args):
        try:
            archjob_id = args['archjob_id']
            msg = args['msg']
        except KeyError, TypeError:
            raise ValueError("No 'archjob_id' argument found.")
        req_seq = PlgCommandAck._deserialize_acked_seq(args)
        return PlgCommandNewJobAck(archjob_id, msg, req_seq)

    _deserialize = staticmethod(_deserialize)

    def serialize(self):
        args = {}
        args['archjob_id'] = self._archjob_id
        args['msg'] = self._msg
        return PlgCommandAck._serialize(self, args)

    def archjob_id(self):
        return self._archjob_id

    def message(self):
        return self._msg



Index: HTTPServer.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/HTTPServer.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- HTTPServer.py	27 Mar 2006 15:45:39 -0000	1.12
+++ HTTPServer.py	28 Apr 2006 03:17:40 -0000	1.13
@@ -183,8 +183,11 @@
         self._server.stop()
         t = time.time()
         while not self._stopped:
-            if time.time() > t + 2:
-                break
+            try:
+                if time.time() > t + 2:
+                    break
+            except KeyboardInterrupt:
+                pass
 
 
 ###########################################################


Index: Makefile
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/Makefile,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- Makefile	22 Jan 2006 02:08:56 -0000	1.11
+++ Makefile	28 Apr 2006 03:17:40 -0000	1.12
@@ -9,18 +9,20 @@
 
 FILES = \
 	ArchUtils.py \
+	AuthedXMLRPCServer.py \
 	BaseConfig.py \
+	Commands.py \
 	CommonErrors.py \
+	daemonize.py \
 	DebugUtils.py \
 	ExecUtils.py \
 	FileDownloader.py \
-	HTTPSURLopener.py \
+    FileUploader.py \
 	HTTPServer.py \
-	AuthedXMLRPCServer.py \
 	SSLCommon.py \
 	SSLConnection.py \
+	URLopener.py \
 	XMLRPCServerProxy.py \
-	daemonize.py \
 	__init__.py
 
 clean:


Index: URLopener.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/URLopener.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- URLopener.py	27 Mar 2006 04:12:11 -0000	1.1
+++ URLopener.py	28 Apr 2006 03:17:40 -0000	1.2
@@ -40,7 +40,7 @@
         buffer += '\r\n'
         buffer += str(v) + '\r\n'
         if sock:
-        	sock.send(buffer)
+            sock.send(buffer)
         l += len(buffer)
     for (k, v) in v_files:
         fd = v
@@ -49,7 +49,7 @@
         buffer=''
         buffer += '--%s\r\n' % boundary
         buffer += 'Content-Disposition: form-data; name="%s"; filename="%s"\r\n' \
-        		  % (k, name)
+                  % (k, name)
         buffer += 'Content-Type: %s\r\n' % get_content_type(name)
         buffer += 'Content-Length: %s\r\n' % file_size
         buffer += '\r\n'
@@ -163,14 +163,14 @@
             raise IOError(e)
 
         if data is not None:
-			if len(v_files) > 0:
-				l = send_data(v_vars, v_files, boundary, h)
-			elif len(v_vars) > 0:
-				# if data is passed as dict ...
-				data = urllib.urlencode(v_vars)
-				h.send(data)
-			else:
-				h.send(data)
+            if len(v_files) > 0:
+                l = send_data(v_vars, v_files, boundary, h)
+            elif len(v_vars) > 0:
+                # if data is passed as dict ...
+                data = urllib.urlencode(v_vars)
+                h.send(data)
+            else:
+                h.send(data)
 
         # close files
         if data is not None:




More information about the fedora-extras-commits mailing list