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
|
# Copyright 2009 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""The code import scheduler XML-RPC API."""
__metaclass__ = type
__all__ = [
'CodeImportSchedulerAPI',
]
from zope.component import getUtility
from zope.interface import implements
from zope.security.proxy import removeSecurityProxy
from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
from canonical.launchpad.webapp import (
canonical_url,
LaunchpadXMLRPCView,
)
from canonical.launchpad.xmlrpc.faults import NoSuchCodeImportJob
from canonical.launchpad.xmlrpc.helpers import return_fault
from lp.code.enums import CodeImportResultStatus
from lp.code.interfaces.codeimportjob import (
ICodeImportJobSet,
ICodeImportJobWorkflow,
)
from lp.code.interfaces.codeimportscheduler import ICodeImportScheduler
from lp.codehosting.codeimport.worker import CodeImportSourceDetails
class CodeImportSchedulerAPI(LaunchpadXMLRPCView):
"""See `ICodeImportScheduler`."""
implements(ICodeImportScheduler)
def getJobForMachine(self, hostname, worker_limit):
"""See `ICodeImportScheduler`."""
job = getUtility(ICodeImportJobSet).getJobForMachine(
hostname, worker_limit)
if job is not None:
return job.id
else:
return 0
def _getJob(self, job_id):
job_set = removeSecurityProxy(getUtility(ICodeImportJobSet))
job = removeSecurityProxy(job_set.getById(job_id))
if job is None:
raise NoSuchCodeImportJob(job_id)
return job
# Because you can't use a decorated function as the implementation of a
# method exported over XML-RPC, the implementations just thunk to an
# implementation wrapped with @return_fault.
def getImportDataForJobID(self, job_id):
"""See `ICodeImportScheduler`."""
return self._getImportDataForJobID(job_id)
def updateHeartbeat(self, job_id, log_tail):
"""See `ICodeImportScheduler`."""
return self._updateHeartbeat(job_id, log_tail)
def finishJobID(self, job_id, status_name, log_file_alias_url):
"""See `ICodeImportScheduler`."""
return self._finishJobID(job_id, status_name, log_file_alias_url)
@return_fault
def _getImportDataForJobID(self, job_id):
job = self._getJob(job_id)
arguments = CodeImportSourceDetails.fromCodeImport(
job.code_import).asArguments()
branch = job.code_import.branch
branch_url = canonical_url(branch)
log_file_name = '%s.log' % branch.unique_name[1:].replace('/', '-')
return (arguments, branch_url, log_file_name)
@return_fault
def _updateHeartbeat(self, job_id, log_tail):
job = self._getJob(job_id)
workflow = removeSecurityProxy(getUtility(ICodeImportJobWorkflow))
workflow.updateHeartbeat(job, log_tail)
return 0
@return_fault
def _finishJobID(self, job_id, status_name, log_file_alias_url):
job = self._getJob(job_id)
status = CodeImportResultStatus.items[status_name]
workflow = removeSecurityProxy(getUtility(ICodeImportJobWorkflow))
if log_file_alias_url:
library_file_alias_set = getUtility(ILibraryFileAliasSet)
# XXX This is so so so terrible:
log_file_alias_id = int(log_file_alias_url.split('/')[-2])
log_file_alias = library_file_alias_set[log_file_alias_id]
else:
log_file_alias = None
workflow.finishJob(job, status, log_file_alias)
|