aboutsummaryrefslogtreecommitdiff
blob: c6d470b397bc9c7c234ba03ef996074ca7001957 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import socket
import thread
import protocol
import pickle
import StringIO
import os
import sys
import time
import portage
import random

import matchbox.db
import matchbox.db.main.models as dbm
from matchbox.db import DjangoDB

class MatchboxServer(object):

    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.sock = None
        self.db = DjangoDB()
        self.portsettings = portage.config(clone=portage.settings)

    def start_server(self):
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        except socket.error:
            print "matchbox: Unable to bind socket"
            self.sock = None
            return None
        self.sock.bind((self.host, self.port))
        self.sock.listen(5)

        while 1:
            client_socket, address = self.sock.accept()
            print "connection from: ", address
            thread.start_new_thread(self.client_handler, (client_socket, address))

    def stop_server(self):
        if self.sock:
            self.sock.close()
            self.sock = None



    def client_handler(self, client_socket, client_address):
        while 1:
            buffer = client_socket.recv(4096)
            data = ""
            while len(buffer) == 4096:
                data = data + buffer
                buffer = client_socket.recv(4096)
            data = data + buffer

            if not data:
                break;

            # potentially dangerous if coming from malicious source
            command = pickle.loads(data)

            if type(command) is protocol.GetNextPackage:
                print "returning next package to compile"
                # TODO get real package from database with missing info
                repl = protocol.GetNextPackageReply(self._get_next_package(), None, None)
                print "name: %s" % repl.package_name

                client_socket.sendall(pickle.dumps(repl))
            elif type(command) is protocol.AddPackageInfo:
                fout = open("/tmp/collagen_%s" % str(time.time()), "w")
                for pi in command.package_infos:
                    print "adding package info"
                    print pi
                    sys.stdout = fout
                    print pi
                    sys.stdout = sys.__stdout__
                    self._db_add_package_info(pi, client_address)

                fout.close()
                # TODO
            else:
                print "unknown command: %s" % command


        print "closing client connection"
        client_socket.close()

    def _get_next_package(self):
        override  = self.__get_override_package()
        if override:
            return override
        categories = os.listdir(self.portsettings["PORTDIR"])
        cat_ind = random.randint(0,len(categories)-1)
        selcat = categories[cat_ind]
        checkdir = "%s/%s" % (self.portsettings["PORTDIR"], selcat)
        if not os.path.isdir(checkdir):
            return self._get_next_package()


        packages = os.listdir(checkdir)
        pkg_ind = random.randint(0,len(packages)-1)
        selpkg = packages[pkg_ind]

        checkdir = "%s/%s/%s" % (self.portsettings["PORTDIR"], selcat, selpkg)
        if not os.path.isdir(checkdir):
            return self._get_next_package()

        return "%s/%s" % (selcat,selpkg)

    def _db_add_package_info(self, pi, tinderbox_address):
        db = self.db

        pcat, pname = portage.catsplit(pi.name)
        pid = db.add_package(pname)
        package = dbm.Package.objects.get(pk=pid)
        cid = db.add_category(pcat)
        category = dbm.PackageCategory.objects.get(pk=cid)

        pvid = db.add_package_version(package.id, category.id, pi.version)
        packageversion = dbm.PackageVersion.objects.get(pk=pvid)
        packageversion.dependencies.clear()
        #we will update deps after all package infos have been inserted

        profileid = db.add_portage_profile(pi.profile)
        profile = dbm.PortageProfile.objects.get(pk=profileid)
        tid = db.add_tinderbox(tinderbox_address[0])
        tinderbox = dbm.Tinderbox.objects.get(pk=tid)
        useflag_ids = []
        if not pi.use_flags:
            pi.use_flags = []
        for useflag in pi.use_flags:
            useflag_ids.append(db.add_useflag(useflag))
        ecode = 0
        if pi.error:
            ecode = pi.error
        ppid = db.add_packageproperties(pvid, profile.id, tinderbox.id, ecode)

        db.add_useflags_to_packageproperies(ppid, useflag_ids)

        for key in pi.attachments.keys():
            db.add_attachment(ppid, key, pi.attachments[key], 'text/plain')

        db.add_contents_to_packageproperties(ppid, pi.content)


    def __get_override_package(self):
        try:
            line = None
            fin = open("/tmp/matchbox_override","r")
            line = fin.readline()
            line = line.strip()
        except:
            pass
        finally:
            return line