Skip to content

Commit

Permalink
Stop using ostree trivial-httpd (#108)
Browse files Browse the repository at this point in the history
I'd like to remove it - working on a libcurl port. For our purposes Python's
builtin webserver is fine, I actually learned recently it can dynamically
allocate a port too.

Obvoiusly this code is crappy, but oh well.
  • Loading branch information
cgwalters committed Jan 4, 2017
1 parent 7e38e5c commit 7d280b3
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 52 deletions.
2 changes: 1 addition & 1 deletion src/py/rpmostreecompose/docker_image.py
Expand Up @@ -28,7 +28,7 @@
import tarfile
import shutil

from .utils import fail_msg, run_sync, TrivialHTTP, log
from .utils import fail_msg, run_sync, log

from gi.repository import GLib # pylint: disable=no-name-in-module

Expand Down
18 changes: 8 additions & 10 deletions src/py/rpmostreecompose/imagefactory.py
Expand Up @@ -43,7 +43,7 @@

from .taskbase import ImageTaskBase

from .utils import run_sync, fail_msg, TrivialHTTP, log
from .utils import run_sync, fail_msg, TemporaryWebserver, log


class ImgBuilder(object):
Expand Down Expand Up @@ -174,7 +174,7 @@ class AbstractImageFactoryTask(ImageTaskBase):
def __init__(self, *args, **kwargs):
ImageTaskBase.__init__(self, *args, **kwargs)
self.httpd_port = None
self._trivial_httpd = None
self._tmpweb = None

# TDL
if 'tdl' in self.args and self.args.tdl is not None:
Expand Down Expand Up @@ -208,18 +208,16 @@ def _ensure_httpd(self):
"""
if not self.ostree_repo_is_remote:
# Start trivial-httpd
self._trivial_httpd = TrivialHTTP()
self._trivial_httpd.start(self.ostree_repo)
self.httpd_port = str(self._trivial_httpd.http_port)
log("trivial httpd port=%s, pid=%s" % (self.httpd_port, self._trivial_httpd.http_pid))
self._tmpweb = TemporaryWebserver()
self.httpd_port = self._tmpweb.start(self.ostree_repo)
log("tmp httpd port={}".format(self.httpd_port))
else:
self.httpd_port = self.ostree_port

def _destroy_httpd(self):
if self._trivial_httpd is not None:
self._trivial_httpd.stop()
self._trivial_httpd = None
if self._tmpweb is not None:
self._tmpweb.stop()
self._tmpweb = None

def addozoverride(self, cfgsec, key, value):
"""
Expand Down
10 changes: 4 additions & 6 deletions src/py/rpmostreecompose/installer.py
Expand Up @@ -27,7 +27,7 @@
import shutil

from .taskbase import ImageTaskBase
from .utils import fail_msg, run_sync, TrivialHTTP, log
from .utils import fail_msg, run_sync, TemporaryWebserver, log
from .imagefactory import AbstractImageFactoryTask
from .imagefactory import ImgFacBuilder
from imgfac.BuildDispatcher import BuildDispatcher
Expand Down Expand Up @@ -156,13 +156,11 @@ def impl_create(self, post=None):

port_file_path = self.workdir + '/repo-port'
if not self.ostree_repo_is_remote:
# Start trivial-httpd
trivhttp = TrivialHTTP()
trivhttp.start(self.ostree_repo)
httpd_port = str(trivhttp.http_port)
tmpweb = TemporaryWebserver()
httpd_port = tmpweb.start(self.ostree_repo)
httpd_url = '127.0.0.1'
log("trivial httpd serving %s on port=%s, pid=%s" % (self.ostree_repo, httpd_port, trivhttp.http_pid))
ostree_url = "http://{0}:{1}".format(httpd_url, httpd_port)
log("tmp httpd serving {} at {}".format(self.ostree_repo, ostree_url))
else:
httpd_port = self.httpd_port
httpd_url = self.httpd_host
Expand Down
73 changes: 38 additions & 35 deletions src/py/rpmostreecompose/utils.py
Expand Up @@ -19,6 +19,11 @@

import sys
import subprocess
import posixpath
import urllib
from SimpleHTTPServer import SimpleHTTPRequestHandler
import SocketServer
import threading
import os
import signal
import ctypes
Expand All @@ -41,45 +46,43 @@ def log(msg):
sys.stdout.write('\n')
sys.stdout.flush()

class TrivialHTTP(object):
""" This class is used to control ostree's trivial-httpd which is used
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass

class RequestHandler(SimpleHTTPRequestHandler):
def translate_path(self, path):
# Copy of python's, but using server._cwd instead of os.getcwd()
# abandon query parameters
path = path.split('?',1)[0]
path = path.split('#',1)[0]
# Don't forget explicit trailing slash when normalizing. Issue17324
trailing_slash = path.rstrip().endswith('/')
path = posixpath.normpath(urllib.unquote(path))
words = path.split('/')
words = filter(None, words)
path = self.server._cwd # HACKED HERE
for word in words:
if os.path.dirname(word) or word in (os.curdir, os.pardir):
# Ignore components that are not a simple file/directory name
continue
path = os.path.join(path, word)
if trailing_slash:
path += '/'
return path

class TemporaryWebserver(object):
""" This class is used to control a temporary webserver which is used
by the installer and imagefactory rpm-ostree-toolbox subcommands to get
content from the from the host to the builds
"""

def __init__(self):
self.f = None
self.libc = ctypes.CDLL('libc.so.6')
self.PR_SET_PDEATHSIG = 1
self.SIGINT = signal.SIGINT
self.SIGTERM = signal.SIGTERM

def set_death_signal(self, signal):
self.libc.prctl(self.PR_SET_PDEATHSIG, signal)

def set_death_signal_int(self):
self.set_death_signal(self.SIGINT)

# trivial-httpd does not close its output pipe so we use
# monitor to deal with it. If ostree is fixed, this can
# likely be removed

def monitor(self):
lines = iter(self.f.stdout.readline, "")

for line in lines:
if int(line) > 0:
self.http_port = int(line)
break

def start(self, repopath):
self.f = subprocess.Popen(['ostree', 'trivial-httpd', '--autoexit', '-p', "-"],
cwd=repopath, stdout=subprocess.PIPE, preexec_fn=self.set_death_signal_int)
self.http_pid = self.f.pid
while True:
if self.f is not None:
break
self.monitor()
self.httpd = SocketServer.ThreadingTCPServer(("", 0), RequestHandler)
self.httpd._cwd = repopath
server_thread = threading.Thread(target=self.httpd.serve_forever)
server_thread.daemon = True
server_thread.start()
return self.httpd.server_address[1]

def stop(self):
os.kill(self.http_pid, signal.SIGQUIT)
del self.httpd

0 comments on commit 7d280b3

Please sign in to comment.