]>
git.ipfire.org Git - pbs.git/blob - src/buildservice/__init__.py
12 from . import bugtracker
13 from . import builders
16 from . import database
17 from . import distribution
19 from . import jobqueue
23 from . import messages
25 from . import packages
26 from . import repository
27 from . import settings
28 from . import sessions
34 log
= logging
.getLogger("backend")
38 from .__version
__ import VERSION
as __version__
40 from .decorators
import *
41 from .constants
import *
43 class Backend(object):
46 def __init__(self
, config_file
=None):
47 # Read configuration file.
48 self
.config
= self
.read_config(config_file
)
50 # Global pakfire settings (from database).
51 self
.settings
= settings
.Settings(self
)
53 self
.aws
= aws
.AWS(self
)
54 self
.builds
= builds
.Builds(self
)
55 self
.cache
= cache
.Cache(self
)
56 self
.jobs
= jobs
.Jobs(self
)
57 self
.builders
= builders
.Builders(self
)
58 self
.distros
= distribution
.Distributions(self
)
59 self
.events
= events
.Events(self
)
60 self
.jobqueue
= jobqueue
.JobQueue(self
)
61 self
.keys
= keys
.Keys(self
)
62 self
.messages
= messages
.Messages(self
)
63 self
.mirrors
= mirrors
.Mirrors(self
)
64 self
.packages
= packages
.Packages(self
)
65 self
.repos
= repository
.Repositories(self
)
66 self
.sessions
= sessions
.Sessions(self
)
67 self
.sources
= sources
.Sources(self
)
68 self
.updates
= updates
.Updates(self
)
69 self
.uploads
= uploads
.Uploads(self
)
70 self
.users
= users
.Users(self
)
72 # Open a connection to bugzilla.
73 self
.bugzilla
= bugtracker
.Bugzilla(self
)
76 def _environment_configuration(self
):
79 # Get database configuration
81 "name" : os
.environ
.get("PBS_DATABASE_NAME"),
82 "hostname" : os
.environ
.get("PBS_DATABASE_HOSTNAME"),
83 "user" : os
.environ
.get("PBS_DATABASE_USER"),
84 "password" : os
.environ
.get("PBS_DATABASE_PASSWORD"),
89 def read_config(self
, path
):
90 c
= configparser
.SafeConfigParser()
92 # Import configuration from environment
93 for section
in self
._environment
_configuration
:
94 c
.add_section(section
)
96 for k
in self
._environment
_configuration
[section
]:
97 c
.set(section
, k
, self
._environment
_configuration
[section
][k
] or "")
99 # Load default configuration file first
101 os
.path
.join(CONFIGSDIR
, "pbs.conf"),
107 # Load all configuration files
109 if os
.path
.exists(path
):
110 log
.debug("Loading configuration from %s" % path
)
113 log
.error("No such file %s" % path
)
120 name
= self
.config
.get("database", "name")
121 hostname
= self
.config
.get("database", "hostname")
122 user
= self
.config
.get("database", "user")
123 password
= self
.config
.get("database", "password")
124 except configparser
.Error
as e
:
125 log
.error("Error parsing the config: %s" % e
.message
)
127 log
.debug("Connecting to database %s @ %s" % (name
, hostname
))
129 return database
.Connection(hostname
, name
, user
=user
, password
=password
)
131 def path_to_url(self
, path
):
133 Takes a path to a file on the file system and converts it into a URL
136 baseurl
= self
.settings
.get("baseurl")
140 "files", os
.path
.relpath(path
, PAKFIRE_DIR
),
143 # Join it all together
144 return urllib
.parse
.urljoin(baseurl
, path
)
146 def pakfire(self
, config
, offline
=True, **kwargs
):
148 Launches a new Pakfire instance with the given configuration
150 log
.debug("Launching pakfire with configuration:\n%s" % config
)
152 # Write configuration to file
153 t
= self
._write
_tempfile
(config
)
155 # Launch a new Pakfire instance
157 return pakfire
.Pakfire(conf
=t
, logger
=log
.log
, offline
=offline
, **kwargs
)
160 # Delete the configuration file
165 async def command(self
, *args
, krb5_auth
=False, **kwargs
):
167 Runs this shell command
169 # Authenticate using Kerberos
171 await self
.krb5_auth()
173 log
.debug("Running command: %s" % " ".join(args
))
176 process
= await asyncio
.create_subprocess_exec(
178 stdin
=asyncio
.subprocess
.DEVNULL
,
179 stdout
=asyncio
.subprocess
.PIPE
,
180 stderr
=asyncio
.subprocess
.STDOUT
,
184 # Fetch output of command and send it to the logger
186 line
= await process
.stdout
.readline()
198 # Wait until the process has finished
201 async def krb5_auth(self
):
202 log
.debug("Performing Kerberos authentication...")
204 # Fetch path to keytab
205 keytab
= self
.settings
.get("krb5-keytab")
207 log
.warning("No keytab configured")
210 # Fetch Kerberos principal
211 principal
= self
.settings
.get("krb5-principal")
213 log
.warning("No Kerberos principal configured")
216 # Fetch a Kerberos ticket
218 "kinit", "-k", "-t", keytab
, principal
,
221 async def copy(self
, src
, dst
):
223 Copies a file from src to dst
225 log
.debug("Copying %s to %s" % (src
, dst
))
227 path
= os
.path
.dirname(dst
)
229 # Create destination path (if it does not exist)
231 await asyncio
.to_thread(os
.makedirs
, path
)
232 except FileExistsError
:
235 # Copy data without any metadata
236 await asyncio
.to_thread(shutil
.copyfile
, src
, dst
)
238 def _write_tempfile(self
, content
):
240 Writes the content to a temporary file and returns its path
242 t
= tempfile
.NamedTemporaryFile(delete
=False)
245 t
.write(content
.encode())
250 async def open(self
, path
):
252 Opens a package and returns the archive
254 return await asyncio
.to_thread(self
._open
, path
)
256 def _open(self
, path
):
257 # Create a dummy Pakfire instance
258 p
= pakfire
.Pakfire(offline
=True)
263 def delete_file(self
, path
, not_before
=None):
264 self
.db
.execute("INSERT INTO queue_delete(path, not_before) \
265 VALUES(%s, %s)", path
, not_before
)
267 def cleanup_files(self
):
268 query
= self
.db
.query("SELECT * FROM queue_delete \
269 WHERE (not_before IS NULL OR not_before <= NOW())")
277 if not path
or not path
.startswith("%s/" % PAKFIRE_DIR
):
278 log
.warning("Cannot delete file outside of the tree")
282 logging
.debug("Removing %s..." % path
)
285 logging
.error("Could not remove %s: %s" % (path
, e
))
288 path
= os
.path
.dirname(path
)
290 # Stop if we are running outside of the tree.
291 if not path
.startswith(PAKFIRE_DIR
):
294 # If the directory is not empty, we cannot remove it.
295 if os
.path
.exists(path
) and os
.listdir(path
):
299 logging
.debug("Removing %s..." % path
)
302 logging
.error("Could not remove %s: %s" % (path
, e
))
305 self
.db
.execute("DELETE FROM queue_delete WHERE id = %s", row
.id)