Revision f93f2016

b/daemons/ganeti-masterd
108 108
    """Add task to workerpool to process request.
109 109

  
110 110
    """
111
    (pid, uid, gid) = utils.GetSocketCredentials(request)
112
    logging.info("Accepted connection from pid=%s, uid=%s, gid=%s",
113
                 pid, uid, gid)
114

  
111 115
    self.request_workers.AddTask(self, request, client_address)
112 116

  
117
  def handle_error(self, request, client_address):
118
    logging.exception("Error while handling request")
119

  
113 120
  @utils.SignalHandled([signal.SIGINT, signal.SIGTERM])
114 121
  def serve_forever(self, signal_handlers=None): # pylint: disable-msg=W0221
115 122
    """Handle one request at a time until told to quit."""
b/lib/utils.py
46 46
import datetime
47 47
import calendar
48 48
import collections
49
import struct
50
import IN
49 51

  
50 52
from cStringIO import StringIO
51 53

  
......
69 71

  
70 72
_RANDOM_UUID_FILE = "/proc/sys/kernel/random/uuid"
71 73

  
74
# Structure definition for getsockopt(SOL_SOCKET, SO_PEERCRED, ...):
75
# struct ucred { pid_t pid; uid_t uid; gid_t gid; };
76
#
77
# The GNU C Library defines gid_t and uid_t to be "unsigned int" and
78
# pid_t to "int".
79
#
80
# IEEE Std 1003.1-2008:
81
# "nlink_t, uid_t, gid_t, and id_t shall be integer types"
82
# "blksize_t, pid_t, and ssize_t shall be signed integer types"
83
_STRUCT_UCRED = "iII"
84
_STRUCT_UCRED_SIZE = struct.calcsize(_STRUCT_UCRED)
85

  
72 86

  
73 87
class RunResult(object):
74 88
  """Holds the result of running external programs.
......
328 342
  return rr
329 343

  
330 344

  
345
def GetSocketCredentials(sock):
346
  """Returns the credentials of the foreign process connected to a socket.
347

  
348
  @param sock: Unix socket
349
  @rtype: tuple; (number, number, number)
350
  @return: The PID, UID and GID of the connected foreign process.
351

  
352
  """
353
  peercred = sock.getsockopt(socket.SOL_SOCKET, IN.SO_PEERCRED,
354
                             _STRUCT_UCRED_SIZE)
355
  return struct.unpack(_STRUCT_UCRED, peercred)
356

  
357

  
331 358
def RemoveFile(filename):
332 359
  """Remove a file ignoring some errors.
333 360

  
b/test/ganeti.utils_unittest.py
44 44
from ganeti import constants
45 45
from ganeti import utils
46 46
from ganeti import errors
47
from ganeti import serializer
47 48
from ganeti.utils import IsProcessAlive, RunCmd, \
48 49
     RemoveFile, MatchNameComponent, FormatUnit, \
49 50
     ParseUnit, AddAuthorizedKey, RemoveAuthorizedKey, \
......
910 911
    self.failIf(OwnIpAddress(DST_IP), "Should not own IP address %s" % DST_IP)
911 912

  
912 913

  
914
def _GetSocketCredentials(path):
915
  """Connect to a Unix socket and return remote credentials.
916

  
917
  """
918
  sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
919
  try:
920
    sock.settimeout(10)
921
    sock.connect(path)
922
    return utils.GetSocketCredentials(sock)
923
  finally:
924
    sock.close()
925

  
926

  
927
class TestGetSocketCredentials(unittest.TestCase):
928
  def setUp(self):
929
    self.tmpdir = tempfile.mkdtemp()
930
    self.sockpath = utils.PathJoin(self.tmpdir, "sock")
931

  
932
    self.listener = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
933
    self.listener.settimeout(10)
934
    self.listener.bind(self.sockpath)
935
    self.listener.listen(1)
936

  
937
  def tearDown(self):
938
    self.listener.shutdown(socket.SHUT_RDWR)
939
    self.listener.close()
940
    shutil.rmtree(self.tmpdir)
941

  
942
  def test(self):
943
    (c2pr, c2pw) = os.pipe()
944

  
945
    # Start child process
946
    child = os.fork()
947
    if child == 0:
948
      try:
949
        data = serializer.DumpJson(_GetSocketCredentials(self.sockpath))
950

  
951
        os.write(c2pw, data)
952
        os.close(c2pw)
953

  
954
        os._exit(0)
955
      finally:
956
        os._exit(1)
957

  
958
    os.close(c2pw)
959

  
960
    # Wait for one connection
961
    (conn, _) = self.listener.accept()
962
    conn.recv(1)
963
    conn.close()
964

  
965
    # Wait for result
966
    result = os.read(c2pr, 4096)
967
    os.close(c2pr)
968

  
969
    # Check child's exit code
970
    (_, status) = os.waitpid(child, 0)
971
    self.assertFalse(os.WIFSIGNALED(status))
972
    self.assertEqual(os.WEXITSTATUS(status), 0)
973

  
974
    # Check result
975
    (pid, uid, gid) = serializer.LoadJson(result)
976
    self.assertEqual(pid, os.getpid())
977
    self.assertEqual(uid, os.getuid())
978
    self.assertEqual(gid, os.getgid())
979

  
980

  
913 981
class TestListVisibleFiles(unittest.TestCase):
914 982
  """Test case for ListVisibleFiles"""
915 983

  

Also available in: Unified diff