~pexego/openobject-addons/6.1-pexego-sale_commission

« back to all changes in this revision

Viewing changes to pexego-runbot/pxgorunbot/server.py

  • Committer: Santi Argueso (Pexego)
  • Date: 2013-02-06 17:03:36 UTC
  • mfrom: (10.1.6 pexego-addons_6.1)
  • Revision ID: santiago@pexego.es-20130206170336-ml430s6p9jknun0j
[MERGE]

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
import threading
8
8
import urllib
9
9
import urlparse
10
 
 
11
10
import pxgorunbot
12
 
 
13
 
runbot_state_lock = threading.Lock()
14
 
 
15
 
httpd = None
16
 
 
17
 
def serve(port):
18
 
    """ Serve HTTP requests via werkzeug development server.
19
 
 
20
 
    If werkzeug can not be imported, we fall back to wsgiref's simple_server.
21
 
 
22
 
    Calling this function is blocking, you might want to call it in its own
23
 
    thread.
24
 
    """
25
 
 
26
 
    global httpd
27
 
 
28
 
    interface = '127.0.0.1'
29
 
    try:
30
 
        import werkzeug.serving
31
 
        httpd = werkzeug.serving.make_server(interface, port, application, threaded=True)
32
 
        print 'HTTP service (werkzeug) running on %s:%s' % (interface, port)
33
 
    except ImportError, e:
34
 
        import wsgiref.simple_server
35
 
        httpd = wsgiref.simple_server.make_server(interface, port, application)
36
 
        print 'HTTP service (wsgiref) running on %s:%s' % (interface, port)
37
 
 
38
 
    httpd.serve_forever()
39
 
 
40
 
def start_server(port):
41
 
    """ Call serve() in its own thread.
42
 
 
43
 
    The WSGI server can be shutdown with stop_server() below.
44
 
    """
45
 
    threading.Thread(target=serve,args=(port,)).start()
46
 
 
 
11
from app import app
 
12
import sys
 
13
 
 
14
 
 
15
def serve(port, folder):
 
16
    app.run(port=port, extra_files=['../urls.conf'], )
 
17
    print 'HTTP service (Flask) running on port %s' % port
 
18
 
 
19
 
 
20
def start_server(port, folder):
 
21
    threading.Thread(target=serve,args=(port,folder,)).start()
 
22
    
47
23
def stop_server():
48
 
    """ Initiate the shutdown of the WSGI server.
49
 
 
50
 
    The server is supposed to have been started by start_server() above.
51
 
    """
52
 
    if httpd:
53
 
        httpd.shutdown()
54
 
 
55
 
def read_state():
56
 
    with runbot_state_lock:
57
 
        try:
58
 
            path = os.path.join('static', 'state.runbot')
59
 
            if os.path.exists(path):
60
 
                with open(path, 'r') as f:
61
 
                    state = simplejson.loads(f.read())
62
 
                    pxgorunbot.state = state
63
 
        except Exception, e:
64
 
            print "Exception in read_state(): ", e
65
 
 
66
 
# TODO lock
67
 
def _with_state(f):
68
 
    state = {}
69
 
    path = os.path.join('static', 'state.runbot')
70
 
 
71
 
    with runbot_state_lock:
72
 
        if os.path.exists(path):
73
 
            with open(path, 'r') as h:
74
 
                state = simplejson.loads(h.read())
75
 
 
76
 
        f(state)
77
 
 
78
 
        with open(path, 'w') as h:
79
 
            data = simplejson.dumps(state, sort_keys=True, indent=4)
80
 
            h.write(data)
81
 
 
82
 
    # Replace the whole dictionary at once.
83
 
    pxgorunbot.state = state
84
 
 
85
 
def _stick(team, group):
86
 
    print 'stick', team, group
87
 
    def f(state):
88
 
        # TODO check team and group are valid
89
 
        state.setdefault(team, {})
90
 
        state[team].setdefault(group, {})
91
 
        state[team][group]['sticky'] = True
92
 
    _with_state(f)
93
 
 
94
 
def _unstick(team, group):
95
 
    print 'unstick', team, group
96
 
    def f(state):
97
 
        # TODO check team and group are valid
98
 
        state.setdefault(team, {})
99
 
        state[team].setdefault(group, {})
100
 
        if 'sticky' in state[team][group]:
101
 
            del state[team][group]['sticky']
102
 
        if not state[team][group]:
103
 
            del state[team][group]
104
 
        if not state[team]:
105
 
            del state[team]
106
 
    _with_state(f)
107
 
 
108
 
def _build(team, group):
109
 
    print 'build', team, group
110
 
    pxgorunbot.queue.put(('build', (team, group)))
111
 
 
112
 
def _register_branch(team, project, group):
113
 
    print 'register branch', team, project, group
114
 
    def f(state):
115
 
        # TODO check team and group are valid
116
 
        state.setdefault('registered-branches', [])
117
 
        state['registered-branches'].append("~%s/%s/%s" % (team, project, group))
118
 
    _with_state(f)
119
 
 
120
 
def _register_project(project):
121
 
    print 'register project'
122
 
    def f(state):
123
 
        # TODO check project is valid
124
 
        state.setdefault('registered-projects', []) # TODO must be a {}
125
 
        state['registered-projects'].append(project)
126
 
    _with_state(f)
127
 
 
128
 
def _configure_group(project_name=None, name=None, version=None, server_branch=None,
129
 
        client_web_branch=None, web_branch=None, addons_branch_0=None,
130
 
        addons_branch_1=None, addons_branch_2=None, modules=None):
131
 
    print 'configure group'
132
 
    addons_branches = []
133
 
    for i in (addons_branch_0, addons_branch_1, addons_branch_2):
134
 
        if i:
135
 
            addons_branches.append(i)
136
 
    def f(state):
137
 
        # TODO check project is valid
138
 
        state.setdefault('configured-branches', {})
139
 
        state['configured-branches'].setdefault(project_name, {})
140
 
        state['configured-branches'][project_name].setdefault(name, {})
141
 
        state['configured-branches'][project_name][name] = dict(
142
 
            version=version,
143
 
            server_branch=server_branch,
144
 
            client_web_branch=client_web_branch,
145
 
            web_branch=web_branch,
146
 
            addons_branches=addons_branches,
147
 
            modules=modules,
148
 
        )
149
 
    _with_state(f)
150
 
 
151
 
 
152
 
def application(environ, start_response):
153
 
    def send_notice(message):
154
 
        response = pxgorunbot.templates.render_template('notice.html.mako', message=message)
155
 
        start_response('200 OK', [('Content-Type', 'text/html'), ('Content-Length', str(len(response)))])
156
 
        return [response]
157
 
 
158
 
    if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'] == ('/a/branch'):
159
 
        length = int(environ['CONTENT_LENGTH'])
160
 
        data = urllib.unquote(environ['wsgi.input'].read(length))
161
 
        data_ = urlparse.parse_qs(data).get('branch-input',[''])[0]
162
 
        m = pxgorunbot.branch_input_re.match(data_)
163
 
        if m:
164
 
            project_name = m.group(1)
165
 
            project = m.group(2)
166
 
            branch_name = m.group(3)
167
 
            _register_branch(project_name, project, branch_name)
168
 
            response = data_ + ' is registered. It will be picked by the Runbot at the next build iteration (about every two minutes).'
169
 
            return send_notice(response)
170
 
 
171
 
    if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'] == ('/a/project'):
172
 
        length = int(environ['CONTENT_LENGTH'])
173
 
        data = urllib.unquote(environ['wsgi.input'].read(length))
174
 
        data_ = urlparse.parse_qs(data).get('project-input',[''])[0]
175
 
        if data_:
176
 
            _register_project(data_)
177
 
            response = data_ + ' is registered. It will be picked by the Runbot at the next build iteration (about every two minutes).'
178
 
            return send_notice(response)
179
 
 
180
 
    if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'] == ('/a/configure-build'):
181
 
        length = int(environ['CONTENT_LENGTH'])
182
 
        data = urllib.unquote(environ['wsgi.input'].read(length))
183
 
        data_ = {}
184
 
        for n in (
185
 
            "project_name", "name", "version", "server_branch",
186
 
            "client_web_branch", "web_branch",
187
 
            "addons_branch_0", "addons_branch_1", "addons_branch_2", "modules"):
188
 
            data_[n] = urlparse.parse_qs(data).get(n,[''])[0]
189
 
        if (data_['version'] == 'trunk' or data_['version'] == '6.0') and \
190
 
            data_['project_name'] and \
191
 
            data_['name'] and \
192
 
            data_['server_branch'] and \
193
 
            (data_['web_branch'] or data_['client_web_branch']) and \
194
 
            data_['addons_branch_0']:
195
 
            _configure_group(**data_)
196
 
            response = data_['name'] + ' is registered. It will be picked by the Runbot at the next build iteration (about every two minutes).'
197
 
            return send_notice(response)
198
 
 
199
 
    # TODO must be a POST instead of a GET
200
 
    if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'] == ('/a'):
201
 
        query = urlparse.parse_qs(environ['QUERY_STRING'])
202
 
 
203
 
        if query.get('project'):
204
 
            project = query['project'][0]
205
 
 
206
 
            if query.get('build'):
207
 
                group = query['build'][0]
208
 
                _build(project, group)
209
 
                response = '`' + group + '` will be built.'
210
 
                return send_notice(response)
211
 
 
212
 
    message = 'Are you lost?\n\n\n(^____^)\n'
213
 
    response = pxgorunbot.templates.render_template('notice.html.mako', message=message)
214
 
    start_response('404 Not Found', [('Content-Type', 'text/html'), ('Content-Length', str(len(response)))])
215
 
    return [response]
216
 
 
217
 
if __name__ == '__main__':
218
 
   serve(8999)
219
 
 
220
 
 
 
24
    sys.exit(1)