regen queue instead of annoying poller
This commit is contained in:
parent
51ba72f042
commit
4f5966b415
|
@ -11,11 +11,11 @@ from tempfile import TemporaryDirectory
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
from time import sleep
|
|
||||||
import gnupg
|
import gnupg
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import traceback
|
import traceback
|
||||||
import json
|
import json
|
||||||
|
import queue
|
||||||
|
|
||||||
|
|
||||||
class AptRepo(Base):
|
class AptRepo(Base):
|
||||||
|
@ -150,6 +150,8 @@ class AptProvider(object):
|
||||||
self.bucket = bucket
|
self.bucket = bucket
|
||||||
"""base path within the s3 bucket"""
|
"""base path within the s3 bucket"""
|
||||||
self.basepath = "data/provider/apt"
|
self.basepath = "data/provider/apt"
|
||||||
|
"""queue entries are tuples containing the database id of the dist to regenerate indexes and signatures for"""
|
||||||
|
self.queue = queue.Queue()
|
||||||
|
|
||||||
cherrypy.tree.mount(AptWeb(self), "/repo/apt", {'/': {'tools.trailing_slash.on': False,
|
cherrypy.tree.mount(AptWeb(self), "/repo/apt", {'/': {'tools.trailing_slash.on': False,
|
||||||
'tools.db.on': True}})
|
'tools.db.on': True}})
|
||||||
|
@ -166,96 +168,99 @@ class AptProvider(object):
|
||||||
Session = sqlalchemy.orm.sessionmaker(autoflush=True, autocommit=False)
|
Session = sqlalchemy.orm.sessionmaker(autoflush=True, autocommit=False)
|
||||||
Session.configure(bind=get_engine())
|
Session.configure(bind=get_engine())
|
||||||
while True:
|
while True:
|
||||||
sleep(2)
|
try:
|
||||||
|
work = self.queue.get(block=True, timeout=5)
|
||||||
|
except queue.Empty:
|
||||||
|
continue
|
||||||
|
|
||||||
session = Session()
|
session = Session()
|
||||||
try:
|
try:
|
||||||
self._sign_packages(session)
|
self._sign_packages(session, work)
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
finally:
|
finally:
|
||||||
session.close()
|
session.close()
|
||||||
sleep(10)
|
|
||||||
|
|
||||||
def _sign_packages(self, session):
|
def _sign_packages(self, session, work):
|
||||||
dirtydists = session.query(AptDist).filter(AptDist.dirty == True).all()
|
dist_id = work[0]
|
||||||
|
dist = session.query(AptDist).filter(AptDist.id == dist_id).first()
|
||||||
|
print("Generating metadata for repo:{} dist:{}".format(dist.repo.name, dist.name))
|
||||||
|
|
||||||
for dist in dirtydists:
|
str_packages = ""
|
||||||
print("Generating metadata for repo:{} dist:{}".format(dist.repo.name, dist.name))
|
|
||||||
|
|
||||||
str_packages = ""
|
for package in session.query(AptPackage) \
|
||||||
|
.filter(AptPackage.repo == dist.repo,
|
||||||
|
AptPackage.dist == dist) \
|
||||||
|
.order_by(AptPackage.id).all():
|
||||||
|
fields = json.loads(package.fields)
|
||||||
|
for k, v in fields.items():
|
||||||
|
str_packages += "{}: {}\n".format(k, v)
|
||||||
|
for algo, algoname in algos.items():
|
||||||
|
str_packages += "{}: {}\n".format(algoname, getattr(package, algo))
|
||||||
|
|
||||||
for package in session.query(AptPackage) \
|
str_packages += "Filename: packages/{}/{}\n".format(package.fname[0], package.fname)
|
||||||
.filter(AptPackage.repo == dist.repo,
|
str_packages += "Size: {}\n".format(package.size)
|
||||||
AptPackage.dist == dist) \
|
|
||||||
.order_by(AptPackage.id).all():
|
|
||||||
fields = json.loads(package.fields)
|
|
||||||
for k, v in fields.items():
|
|
||||||
str_packages += "{}: {}\n".format(k, v)
|
|
||||||
for algo, algoname in algos.items():
|
|
||||||
str_packages += "{}: {}\n".format(algoname, getattr(package, algo))
|
|
||||||
|
|
||||||
str_packages += "Filename: packages/{}/{}\n".format(package.fname[0], package.fname)
|
str_packages += "\n"
|
||||||
str_packages += "Size: {}\n".format(package.size)
|
|
||||||
|
|
||||||
str_packages += "\n"
|
dist.packages_cache = str_packages.encode("utf-8")
|
||||||
|
|
||||||
dist.packages_cache = str_packages.encode("utf-8")
|
release_hashes = hashmany(dist.packages_cache)
|
||||||
|
|
||||||
release_hashes = hashmany(dist.packages_cache)
|
str_release = """Origin: . {dist}
|
||||||
|
|
||||||
str_release = """Origin: . {dist}
|
|
||||||
Label: . {dist}
|
Label: . {dist}
|
||||||
Suite: {dist}
|
Suite: {dist}
|
||||||
Codename: {dist}
|
Codename: {dist}
|
||||||
Date: {time}
|
Date: {time}
|
||||||
Architectures: amd64
|
Architectures: amd64
|
||||||
Components: main
|
Components: main
|
||||||
Description: Generated by yolo
|
Description: Generated by Repobot
|
||||||
""".format(dist=dist.name, time=datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S UTC"))
|
""".format(dist=dist.name, time=datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S UTC"))
|
||||||
for algo, algoname in algos.items():
|
for algo, algoname in algos.items():
|
||||||
str_release += "{}:\n {} {} {}/{}/{}\n".format(algoname,
|
str_release += "{}:\n {} {} {}/{}/{}\n".format(algoname,
|
||||||
release_hashes[algo],
|
release_hashes[algo],
|
||||||
len(dist.packages_cache),
|
len(dist.packages_cache),
|
||||||
"main", #TODO component
|
"main", #TODO component
|
||||||
"binary-amd64", #TODO whatever this was
|
"binary-amd64", #TODO whatever this was
|
||||||
"Packages")
|
"Packages")
|
||||||
|
|
||||||
dist.release_cache = str_release.encode("utf-8")
|
dist.release_cache = str_release.encode("utf-8")
|
||||||
|
|
||||||
keyemail = 'debian_signing@localhost'
|
keyemail = 'debian_signing@localhost'
|
||||||
|
|
||||||
with TemporaryDirectory() as tdir:
|
with TemporaryDirectory() as tdir:
|
||||||
gpg = gnupg.GPG(gnupghome=tdir)
|
gpg = gnupg.GPG(gnupghome=tdir)
|
||||||
|
|
||||||
def getkey():
|
def getkey():
|
||||||
keys = [i for i in gpg.list_keys(secret=True) if any([keyemail in k for k in i["uids"]])]
|
keys = [i for i in gpg.list_keys(secret=True) if any([keyemail in k for k in i["uids"]])]
|
||||||
if keys:
|
if keys:
|
||||||
return keys[0]
|
return keys[0]
|
||||||
|
|
||||||
fingerprint = None
|
fingerprint = None
|
||||||
|
|
||||||
if not dist.repo.gpgkey:
|
if not dist.repo.gpgkey:
|
||||||
print("Generating key for", dist.repo.name)
|
print("Generating key for", dist.repo.name)
|
||||||
key = gpg.gen_key(gpg.gen_key_input(name_email=keyemail,
|
key = gpg.gen_key(gpg.gen_key_input(name_email=keyemail,
|
||||||
expire_date='2029-04-28',
|
expire_date='2029-04-28',
|
||||||
key_type='RSA',
|
key_type='RSA',
|
||||||
key_length=4096,
|
key_length=4096,
|
||||||
key_usage='encrypt,sign,auth',
|
key_usage='encrypt,sign,auth',
|
||||||
passphrase="secret"))
|
passphrase="secret"))
|
||||||
fingerprint = key.fingerprint
|
fingerprint = key.fingerprint
|
||||||
dist.repo.gpgkey = gpg.export_keys(fingerprint, secret=True, passphrase="secret")
|
dist.repo.gpgkey = gpg.export_keys(fingerprint, secret=True, passphrase="secret")
|
||||||
dist.repo.gpgkeyprint = fingerprint
|
dist.repo.gpgkeyprint = fingerprint
|
||||||
dist.repo.gpgpubkey = gpg.export_keys(fingerprint)
|
dist.repo.gpgpubkey = gpg.export_keys(fingerprint)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
import_result = gpg.import_keys(dist.repo.gpgkey)
|
import_result = gpg.import_keys(dist.repo.gpgkey)
|
||||||
fingerprint = import_result.results[0]['fingerprint'] # errors here suggests some gpg import issue
|
fingerprint = import_result.results[0]['fingerprint'] # errors here suggests some gpg import issue
|
||||||
assert(fingerprint == getkey()['fingerprint'])
|
assert(fingerprint == getkey()['fingerprint'])
|
||||||
|
|
||||||
dist.sig_cache = gpg.sign(dist.release_cache, keyid=fingerprint, passphrase='secret',
|
dist.sig_cache = gpg.sign(dist.release_cache, keyid=fingerprint, passphrase='secret',
|
||||||
detach=True, clearsign=False).data
|
detach=True, clearsign=False).data
|
||||||
dist.dirty = False
|
dist.dirty = False
|
||||||
session.commit()
|
session.commit()
|
||||||
|
print("Metadata generation complete")
|
||||||
|
|
||||||
def web_addpkg(self, reponame, name, version, fobj, dist):
|
def web_addpkg(self, reponame, name, version, fobj, dist):
|
||||||
repo = get_repo(db(), reponame)
|
repo = get_repo(db(), reponame)
|
||||||
|
@ -300,6 +305,11 @@ Description: Generated by yolo
|
||||||
db().add(pkg)
|
db().add(pkg)
|
||||||
db().commit()
|
db().commit()
|
||||||
|
|
||||||
|
self.regen_dist(dist.id)
|
||||||
|
|
||||||
|
def regen_dist(self, dist_id):
|
||||||
|
self.queue.put((dist_id, ))
|
||||||
|
|
||||||
#TODO
|
#TODO
|
||||||
# - verify dpkg name & version match params
|
# - verify dpkg name & version match params
|
||||||
# - copy to persistent storage
|
# - copy to persistent storage
|
||||||
|
@ -315,14 +325,17 @@ class AptWeb(object):
|
||||||
self.packages = AptFiles(base)
|
self.packages = AptFiles(base)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def index(self, reponame=None):
|
def index(self, reponame=None, regen=False):
|
||||||
if reponame:
|
if reponame:
|
||||||
repo = get_repo(db(), reponame, create_ok=False)
|
repo = get_repo(db(), reponame, create_ok=False)
|
||||||
|
|
||||||
yield "<a href='/repo/apt/{reponame}/pubkey'>pubkey</a><hr/>".format(reponame=repo.name)
|
yield "<a href='/repo/apt/{reponame}/pubkey'>pubkey</a> " \
|
||||||
|
"<a href='/repo/apt/{reponame}?regen=1'>regen</a><hr/>".format(reponame=repo.name)
|
||||||
|
|
||||||
for dist in db().query(AptDist).filter(AptDist.repo == repo).order_by(AptDist.name).all():
|
for dist in db().query(AptDist).filter(AptDist.repo == repo).order_by(AptDist.name).all():
|
||||||
yield "<a href='/repo/apt/{reponame}/dists/{name}'>{name}</a>: <a href='/repo/apt/{reponame}/dists/{name}/main/indexname/Packages'>Packages</a> <a href='/repo/apt/{reponame}/dists/{name}/Release'>Release</a> <a href='/repo/apt/{reponame}/dists/{name}/Release.gpg'>Release.gpg</a><br />".format(reponame=repo.name, name=dist.name)
|
yield "<a href='/repo/apt/{reponame}/dists/{name}'>{name}</a>: <a href='/repo/apt/{reponame}/dists/{name}/main/indexname/Packages'>Packages</a> <a href='/repo/apt/{reponame}/dists/{name}/Release'>Release</a> <a href='/repo/apt/{reponame}/dists/{name}/Release.gpg'>Release.gpg</a><br />".format(reponame=repo.name, name=dist.name)
|
||||||
|
if regen:
|
||||||
|
self.base.regen_dist(dist.id)
|
||||||
|
|
||||||
# yield "about apt repo '{}'".format(reponame)
|
# yield "about apt repo '{}'".format(reponame)
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue