All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lucas Meneghel Rodrigues <lmr@redhat.com>
To: autotest@test.kernel.org
Cc: kvm@vger.kernel.org
Subject: [PATCH 09/16] Virt: builtin HTTP server for unattended installs
Date: Thu,  3 Nov 2011 19:26:15 -0200	[thread overview]
Message-ID: <1320355582-4342-10-git-send-email-lmr@redhat.com> (raw)
In-Reply-To: <1320355582-4342-1-git-send-email-lmr@redhat.com>

From: Cleber Rosa <crosa@redhat.com>

This adds a simple HTTP server that is good enough to support unattended
installs. Tested serving kickstart files and RHEL/Fedora content to
anaconda.

Signed-off-by: Cleber Rosa <crosa@redhat.com>
---
 client/virt/virt_http_server.py |  124 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 124 insertions(+), 0 deletions(-)
 create mode 100644 client/virt/virt_http_server.py

diff --git a/client/virt/virt_http_server.py b/client/virt/virt_http_server.py
new file mode 100644
index 0000000..286285a
--- /dev/null
+++ b/client/virt/virt_http_server.py
@@ -0,0 +1,124 @@
+import os, posixpath, urlparse, urllib, logging
+import BaseHTTPServer, SimpleHTTPServer
+
+
+class HTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+
+    def do_GET(self):
+        """
+        Serve a GET request.
+        """
+        range = self.parse_header_byte_range()
+        if range:
+            f = self.send_head_range(range[0], range[1])
+            if f:
+                self.copyfile_range(f, self.wfile, range[0], range[1])
+                f.close()
+        else:
+            f = self.send_head()
+            if f:
+                self.copyfile(f, self.wfile)
+                f.close()
+
+
+    def parse_header_byte_range(self):
+        range_param = 'Range'
+        range_discard = 'bytes='
+        if self.headers.has_key(range_param):
+            range = self.headers.get(range_param)
+            if range.startswith(range_discard):
+                range = range[len(range_discard):]
+                begin, end = range.split('-')
+                return (int(begin), int(end))
+        return None
+
+
+    def copyfile_range(self, source_file, output_file, range_begin, range_end):
+        """
+        Copies a range of a file to destination.
+        """
+        range_size = range_end - range_begin + 1
+        source_file.seek(range_begin)
+        buf = source_file.read(range_size)
+        output_file.write(buf)
+
+
+    def send_head_range(self, range_begin, range_end):
+        path = self.translate_path(self.path)
+        f = None
+        if os.path.isdir(path):
+            for index in "index.html", "index.htm":
+                index = os.path.join(path, index)
+                if os.path.exists(index):
+                    path = index
+                    break
+            else:
+                return self.list_directory(path)
+        ctype = self.guess_type(path)
+        try:
+            # Always read in binary mode. Opening files in text mode may cause
+            # newline translations, making the actual size of the content
+            # transmitted *less* than the content-length!
+            f = open(path, 'rb')
+        except IOError:
+            self.send_error(404, "File not found")
+            return None
+        self.send_response(206, "Partial Content")
+        file_size = str(os.fstat(f.fileno())[6])
+        range_size = str(range_end - range_begin + 1)
+        self.send_header("Accept-Ranges", "bytes")
+        self.send_header("Content-Length", range_size)
+        self.send_header("Content-Range", "bytes %s-%s/%s" % (range_begin,
+                                                              range_end,
+                                                              file_size))
+        self.send_header("Content-type", ctype)
+        self.end_headers()
+        return f
+
+
+    def translate_path(self, path):
+        """
+        Translate a /-separated PATH to the local filename syntax.
+
+        Components that mean special things to the local file system
+        (e.g. drive or directory names) are ignored.  (XXX They should
+        probably be diagnosed.)
+
+        """
+        # abandon query parameters
+        path = urlparse.urlparse(path)[2]
+        path = posixpath.normpath(urllib.unquote(path))
+        words = path.split('/')
+        words = filter(None, words)
+        path = self.server.cwd
+        for word in words:
+            drive, word = os.path.splitdrive(word)
+            head, word = os.path.split(word)
+            if word in (os.curdir, os.pardir): continue
+            path = os.path.join(path, word)
+        return path
+
+
+    def log_message(self, format, *args):
+        logging.debug("builtin http server handling request from %s: %s" %
+                      (self.address_string(), format%args))
+
+
+def http_server(port=8000, cwd=None, terminate_callable=None):
+    http = BaseHTTPServer.HTTPServer(('', port), HTTPRequestHandler)
+    if cwd is None:
+        cwd = os.getcwd()
+    http.cwd = cwd
+
+    while True:
+        if terminate_callable is not None:
+            terminate = terminate_callable()
+        else:
+            terminate = False
+
+        if not terminate:
+            http.handle_request()
+
+
+if __name__ == '__main__':
+    http_server()
-- 
1.7.7

  parent reply	other threads:[~2011-11-03 21:26 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-03 21:26 [PATCH 00/16] Libvirt test v5 Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 02/16] virt: Introducing virt_test.virt_test class Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 03/16] Moving unattended_install test from kvm test to common virt location Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 04/16] Moving get_started code to client.virt.virt_utils Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 05/16] virt: Introducing libvirt VM class Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 06/16] virt: Introducing libvirt monitor Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 07/16] virt.virt_env_process: Add libvirt vm handling Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 08/16] client.tests: Introducing libvirt test Lucas Meneghel Rodrigues
2011-11-03 21:26 ` Lucas Meneghel Rodrigues [this message]
2011-11-03 21:26 ` [PATCH 10/16] Virt: support XEN via libvirt and auto url installer Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 11/16] Virt: add support for XEN via libvirt installs and auto url Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 12/16] Virt: small fixes related to libvirt unattended install when using " Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 13/16] Virt: pass verbatim hvm_or_pv option to virt_install Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 14/16] Virt: add sample configuration for XEN HVM domains Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 15/16] virt: Fix unattended install for libvirt case Lucas Meneghel Rodrigues
2011-11-03 21:26 ` [PATCH 16/16] Virt: adjust auto http servers (content/kickstart) ports to not overlap Lucas Meneghel Rodrigues
2011-11-04  3:57 ` [PATCH 00/16] Libvirt test v5 Lucas Meneghel Rodrigues

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1320355582-4342-10-git-send-email-lmr@redhat.com \
    --to=lmr@redhat.com \
    --cc=autotest@test.kernel.org \
    --cc=kvm@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.