~ubuntu-branches/ubuntu/raring/maas/raring-updates

« back to all changes in this revision

Viewing changes to src/maastesting/httpd.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez, Raphaël Badin, Julian Edwards, Jeroen Vermeulen, Gavin Panella, Andres Rodriguez
  • Date: 2013-03-04 11:49:44 UTC
  • mfrom: (1.2.5)
  • Revision ID: package-import@ubuntu.com-20130304114944-81my0hho8arxa3ix
Tags: 1.3+bzr1452+dfsg-0ubuntu1
* New upstream release.
  - MAAS file storage mechanism is shifting from a single shared
    namespace to a per-user namespace. Operators of the majority
    of MAAS systems will not notice any change. However, operators
    of the most complex installations may find that a new
    "shared-environment" user is created, and that some resources
    are reassigned to it, such as API credentials and SSH public
    keys. This provides a transitional environment that mimics the
    behaviour of a shared namespace.

[ Raphaël Badin ]
* debian/control: maas-region-controller depends on bind9utils.
  (LP: #1103195)
* debian/maas-dns.postinst: Call write_dns_config.
  (LP: #1085865).
* debian/maas-cluster-controller.postinst: Fix the name of the config
  file (/etc/maas/pserv.yaml and not /etc/maas/pserv.conf)
  (LP: #1083542).
* debian/extras/99-maas-sudoers: Add 'SETENV:' to sudo rule
  to allow preserving the environment when running
  /usr/sbin/maas-import-pxe-files via sudo.
* debian/maas-dns.postinst: fix permissions and group ownership of
  file /etc/bind/maas/named.conf.rndc.maas. (LP: #1066935)
* debian/control: Remove the dependency of maas-cluster-controller
  on rabbitmq-server. (LP: #1072744)
* debian/extras/99-maas-sudoers: Add sudo rule for script
  /usr/sbin/maas-import-pxe-files.
* debian/maas-cluster-controller.install: Removed commissioning-user-data
  script.

[ Julian Edwards ]
* debian/maas-region-controller.install: Remove installation of maas-gc; it
  is no longer required as upstream no longer stores files in the filesystem.
  (LP: #1069734)
* debian/maas-cluster-controller.postinst: Ensure that /etc/maas/pserv.yaml
  is updated when reconfiguring. (LP: #1081212)

[ Jeroen Vermeulen ]
* debian/maas-cluster-controller.install: Install import scripts.
* debian/maas-cluster-controller.postinst: Configure tgt (the iSCSI server)
  so the import script can install files to it.
* debian/maas-cluster-controller.postrm: Clean up tgt config.
* debian/maas-region-controller.install: Move import scripts out to the
  cluster controller, and drop the maas-import-isos compatibility script.
* debian/maas-region-controller.postinst: Remove tgt config.
* debian/maas-region-controller.postrm: Remove tgt config cleanup.
* Bump code revision to include latest user_data.template fixes.

[ Gavin Panella ]
* debian/extras/99-maas: squashfs image download is no longer needed.
* debian/maas-cluster-controller.install: maas-import-squashfs and its
  configuration file are no longer part of upstream.
* debian/maas-cluster-controller.install: The maas-import-pxe-files cron
  task is no longer used.
* debian/maas-cluster-controller.postinst: Remove leading comment
  markers from the 'generator' line in pserv.yaml.

[ Andres Rodriguez ]
* debian/control:
  - maas-cluster-controller Conflicts with tftpd-hpa (LP: #1076028)
  - maas-dns: Conflicts with dnsmasq
  - maas-cluster-controller Conflicts/Replaces maas-region-controller as
    import scripts are no longer shipped in the region.
  - debian/control: Depends on distro-info for maas-cluster-controller
    instead of maas-region-controller (LP: #1103194)
* debian/maas-cluster-controller.config: If URL has been detected,
  add /MAAS if it doesn't contain it. This helps upgrades from versions
  where DEFAULT_MAAS_URL didn't use /MAAS.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
    ]
16
16
 
17
17
from BaseHTTPServer import HTTPServer
 
18
import gzip
 
19
from io import BytesIO
 
20
import os
18
21
from SimpleHTTPServer import SimpleHTTPRequestHandler
19
22
from SocketServer import ThreadingMixIn
20
23
import threading
31
34
    log_request = lambda *args, **kwargs: None
32
35
    log_error = lambda *args, **kwargs: None
33
36
 
 
37
    def _gzip_compress(self, f):
 
38
        gz_out = BytesIO()
 
39
        gz = gzip.GzipFile(mode='wb', fileobj=gz_out)
 
40
        gz.write(f.read())
 
41
        gz.flush()
 
42
        gz_out.getvalue()
 
43
        return gz_out
 
44
 
 
45
    def is_gzip_accepted(self):
 
46
        accepted = set()
 
47
        for header in self.headers.getallmatchingheaders('Accept-Encoding'):
 
48
            # getallmatchingheaders returns the whole line, so first we have to
 
49
            # split off the header definition
 
50
            _, content = header.split(':', 1)
 
51
            content = content.strip()
 
52
            # Then, you are allowed to specify a comma separated list of
 
53
            # acceptable encodings. You are also allowed to specify
 
54
            # 'encoding;q=XXX' to specify what encodings you would prefer.
 
55
            # We'll allow it to be set, but just ignore it.
 
56
            #   http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
 
57
            encodings = [encoding.strip().split(';', )[0]
 
58
                         for encoding in content.split(',')]
 
59
            accepted.update(encodings)
 
60
        if 'gzip' in accepted:
 
61
            return True
 
62
        return False
 
63
 
 
64
    # This is a copy & paste and minor modification of
 
65
    # SimpleHTTPRequestHandler's send_head code. Because to support
 
66
    # Content-Encoding gzip, we have to change what headers get returned (as it
 
67
    # affects Content-Length headers.
 
68
    def send_head(self):
 
69
        """Common code for GET and HEAD commands.
 
70
 
 
71
        This sends the response code and MIME headers.
 
72
 
 
73
        Return value is either a file object (which has to be copied
 
74
        to the outputfile by the caller unless the command was HEAD,
 
75
        and must be closed by the caller under all circumstances), or
 
76
        None, in which case the caller has nothing further to do.
 
77
 
 
78
        """
 
79
        path = self.translate_path(self.path)
 
80
        f = None
 
81
        if os.path.isdir(path):
 
82
            if not self.path.endswith('/'):
 
83
                # redirect browser - doing basically what apache does
 
84
                self.send_response(301)
 
85
                self.send_header("Location", self.path + "/")
 
86
                self.end_headers()
 
87
                return None
 
88
            for index in "index.html", "index.htm":
 
89
                index = os.path.join(path, index)
 
90
                if os.path.exists(index):
 
91
                    path = index
 
92
                    break
 
93
            else:
 
94
                return self.list_directory(path)
 
95
        ctype = self.guess_type(path)
 
96
        try:
 
97
            # Always read in binary mode. Opening files in text mode may cause
 
98
            # newline translations, making the actual size of the content
 
99
            # transmitted *less* than the content-length!
 
100
            f = open(path, 'rb')
 
101
        except IOError:
 
102
            self.send_error(404, "File not found")
 
103
            return None
 
104
        if self.is_gzip_accepted():
 
105
            return self.start_gz_response(ctype, f)
 
106
        else:
 
107
            return self.start_response(ctype, f)
 
108
 
 
109
    def start_gz_response(self, ctype, f):
 
110
        self.send_response(200)
 
111
        self.send_header("Content-type", ctype)
 
112
        self.send_header("Content-Encoding", 'gzip')
 
113
        gz_out = self._gzip_compress(f)
 
114
        self.send_header("Content-Length", str(gz_out.tell()))
 
115
        gz_out.seek(0)
 
116
        self.end_headers()
 
117
        return gz_out
 
118
 
 
119
    def start_response(self, ctype, f):
 
120
        self.send_response(200)
 
121
        self.send_header("Content-type", ctype)
 
122
        fs = os.fstat(f.fileno())
 
123
        self.send_header("Content-Length", str(fs[6]))
 
124
        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
 
125
        self.end_headers()
 
126
        return f
 
127
 
34
128
 
35
129
class HTTPServerFixture(Fixture):
36
130
    """Bring up a very simple, threaded, web server.