Commit b1accb72 authored by Łukasz Nowak's avatar Łukasz Nowak

Merge branch 'bug_778748'

parents b19763cf 41062088
[buildout] [buildout]
extends = buildout.cfg extends = buildout.cfg
#develop += path_to_slapos.libnetworkcache parts += nc pync testnc
parts += cached [nc]
[cached]
recipe = z3c.recipe.scripts recipe = z3c.recipe.scripts
eggs = eggs =
slapos.libnetworkcache slapos.libnetworkcache
zc.buildout zc.buildout
scripts = scripts =
buildout=buildout_cached buildout=buildout_nc
[pync]
recipe = z3c.recipe.scripts
eggs = slapos.libnetworkcache
interpreter =
pync
executable = ${buildout:bin-directory}/pync
[test] [testnc]
eggs += recipe = ${test:recipe}
eggs = ${test:eggs}
slapos.libnetworkcache slapos.libnetworkcache
python = pync
...@@ -337,7 +337,7 @@ class Buildout(UserDict.DictMixin): ...@@ -337,7 +337,7 @@ class Buildout(UserDict.DictMixin):
os.chdir(options['directory']) os.chdir(options['directory'])
if not LIBNETWORKCACHE_ENABLED: if not LIBNETWORKCACHE_ENABLED:
self._logger.warning('Networkache disabled, no ' self._logger.debug('Networkache disabled, no '
'slapos.libnetworkache available.') 'slapos.libnetworkache available.')
self.download_cache_url = None self.download_cache_url = None
self.download_dir_url = None self.download_dir_url = None
...@@ -367,7 +367,7 @@ class Buildout(UserDict.DictMixin): ...@@ -367,7 +367,7 @@ class Buildout(UserDict.DictMixin):
options['__networkcache__upload-cache-url'] = self.upload_cache_url options['__networkcache__upload-cache-url'] = self.upload_cache_url
options['__networkcache__upload-dir-url'] = self.upload_dir_url options['__networkcache__upload-dir-url'] = self.upload_dir_url
else: else:
self._logger.warning('Networkcache functionality not enabled.' self._logger.debug('Networkcache functionality not enabled. '
'In order to activate use networkcache-section.') 'In order to activate use networkcache-section.')
self.download_cache_url = None self.download_cache_url = None
self.download_dir_url = None self.download_dir_url = None
......
...@@ -17,6 +17,7 @@ import hashlib ...@@ -17,6 +17,7 @@ import hashlib
import os import os
import posixpath import posixpath
import re import re
import shutil
try: try:
from slapos.libnetworkcache import NetworkcacheClient, UploadError, \ from slapos.libnetworkcache import NetworkcacheClient, UploadError, \
...@@ -67,27 +68,28 @@ def download_network_cached(dir_url, cache_url, path, url, logger, md5sum=None): ...@@ -67,27 +68,28 @@ def download_network_cached(dir_url, cache_url, path, url, logger, md5sum=None):
directory_key = get_directory_key(url) directory_key = get_directory_key(url)
file_name = os.path.basename(url) url = os.path.basename(url)
logger.info('Downloading %s from network cache.' % file_name) logger.info('Downloading %s from network cache.' % url)
try: try:
nc = NetworkcacheClient(shacache=cache_url, shadir=dir_url) nc = NetworkcacheClient(shacache=cache_url, shadir=dir_url)
file_content = nc.select(directory_key) file_descriptor = nc.select(directory_key)
buffer_size = min(1024, os.path.getsize(file_descriptor.name))
f = open(path, 'w+b') f = open(path, 'w+b')
try: try:
f.seek(0) shutil.copyfileobj(file_descriptor, f, buffer_size)
f.write(file_content)
finally: finally:
f.close() f.close()
file_descriptor.close()
if not check_md5sum(path, md5sum): if not check_md5sum(path, md5sum):
logger.info('MD5 checksum mismatch downloading %s' % file_name) logger.info('MD5 checksum mismatch downloading %s' % url)
return False return False
except (IOError, DirectoryNotFound), e: except (IOError, DirectoryNotFound), e:
logger.info('Failed to download from network cache %s: %s' % \ logger.info('Failed to download from network cache %s: %s' % \
(file_name, str(e))) (url, str(e)))
return False return False
return True return True
......
Using buildout with cache over network Using buildout with cache over network
====================================== ======================================
Note: We are in process of preparing docs. This is only showcase. >>> nc_data = tmpdir('nc_data')
>>> nc_url = start_nc(nc_data)
Networkcache in buildout is optional, and during normal run no information
is shown:
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts =
... ''')
>>> print system(buildout)
But whenever networkcache configuration is enabled, it is possible to use it:
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
...
... networkcache-section = networkcache
... find-links = %(link_server)s
... parts = eggs
...
... [eggs]
... recipe = zc.recipe.egg:eggs
... eggs = demoneeded ==1.2c1
...
... [networkcache]
... download-cache-url = %(nc_url)sshacache
... download-dir-url = %(nc_url)sshadir
... upload-cache-url = %(nc_url)sshacache
... upload-dir-url = %(nc_url)sshadir
... ''' % globals())
>>> print system(buildout)
Networkcache enabled.
Networkcache download cache: 'http://localhost/shacache', directory 'http://localhost/shadir'
Networkcache upload cache: 'http://localhost/shacache', directory 'http://localhost/shadir'
Installing eggs.
Getting distribution for 'demoneeded==1.2c1'.
Downloading demoneeded-1.2c1.zip from network cache.
Failed to download from network cache demoneeded-1.2c1.zip:
Uploading http://localhost/demoneeded-1.2c1.zip into network cache.
Got demoneeded 1.2c1.
<BLANKLINE>
Now lets clean up buildout directory:
>>> import os, glob
>>> [remove(q) for q in glob.glob(os.path.join(sample_buildout, 'eggs', 'demoneeded*'))]
[None]
>>> remove('.installed.cfg')
And run it again, data will be downloaded from networkcache:
>>> print system(buildout)
Networkcache enabled.
Networkcache download cache: 'http://localhost/shacache', directory 'http://localhost/shadir'
Networkcache upload cache: 'http://localhost/shacache', directory 'http://localhost/shadir'
Installing eggs.
Getting distribution for 'demoneeded==1.2c1'.
Downloading demoneeded-1.2c1.zip from network cache.
Got demoneeded 1.2c1.
<BLANKLINE>
Now lets clean up buildout directory:
>>> import os, glob
>>> [remove(q) for q in glob.glob(os.path.join(sample_buildout, 'eggs', 'demoneeded*'))]
[None]
>>> remove('.installed.cfg')
As one can see, in case if upload is not working, there is no problem with running buildout:
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
...
... networkcache-section = networkcache
... find-links = %(link_server)s
... parts = eggs
...
... [eggs]
... recipe = zc.recipe.egg:eggs
... eggs = demo
...
... [networkcache]
... download-cache-url = %(nc_url)sshacache
... download-dir-url = %(nc_url)sshadir
... upload-cache-url = http://127.0.0.1:1/sshacache
... upload-dir-url = http://127.0.0.1:1/sshadir
... ''' % globals())
>>> print system(buildout)
Networkcache enabled.
Networkcache download cache: 'http://localhost/shacache', directory 'http://localhost/shadir'
Networkcache upload cache: 'http://127.0.0.1:1/sshacache', directory 'http://127.0.0.1:1/sshadir'
Installing eggs.
Getting distribution for 'demo'.
Downloading demo-0.4c1-py2.7.egg from network cache.
Failed to download from network cache demo-0.4c1-py2.7.egg:
Uploading http://localhost/demo-0.4c1-py2.7.egg into network cache.
Fail to upload file. [Errno 111] Connection refused
Got demo 0.4c1.
Getting distribution for 'demoneeded'.
Downloading demoneeded-1.2c1.zip from network cache.
Got demoneeded 1.2c1.
<BLANKLINE>
Now lets clean up buildout directory:
>>> import os, glob
>>> [remove(q) for q in glob.glob(os.path.join(sample_buildout, 'eggs', 'demo*'))]
[None, None]
>>> remove('.installed.cfg')
Upload is optional, and then no upload will be tried:
>>> write(sample_buildout, 'buildout.cfg', >>> write(sample_buildout, 'buildout.cfg',
... ''' ... '''
...@@ -13,31 +127,64 @@ Note: We are in process of preparing docs. This is only showcase. ...@@ -13,31 +127,64 @@ Note: We are in process of preparing docs. This is only showcase.
... ...
... [eggs] ... [eggs]
... recipe = zc.recipe.egg:eggs ... recipe = zc.recipe.egg:eggs
... eggs = demo ==0.2 ... eggs = demo
... ...
... [networkcache] ... [networkcache]
... download-cache-url = http://127.0.0.1:1/ ... download-cache-url = %(nc_url)sshacache
... download-dir-url = http://127.0.0.1:1/ ... download-dir-url = %(nc_url)sshadir
... upload-cache-url = http://127.0.0.1:1/
... upload-dir-url = http://127.0.0.1:1/
... ''' % globals()) ... ''' % globals())
>>> print system(buildout)
Networkcache enabled.
Networkcache download cache: 'http://localhost/shacache', directory 'http://localhost/shadir'
Networkcache upload cache: '', directory ''
Installing eggs.
Getting distribution for 'demo'.
Downloading demo-0.4c1-py2.7.egg from network cache.
Failed to download from network cache demo-0.4c1-py2.7.egg:
Got demo 0.4c1.
Getting distribution for 'demoneeded'.
Downloading demoneeded-1.2c1.zip from network cache.
Got demoneeded 1.2c1.
<BLANKLINE>
Now lets clean up buildout directory:
>>> import os, glob
>>> [remove(q) for q in glob.glob(os.path.join(sample_buildout, 'eggs', 'demo*'))]
[None, None]
>>> remove('.installed.cfg')
>>> from glob import glob In case if download cache is failing, original resources are used:
>>> from os.path import join
>>> for egg in glob(join(sample_buildout, 'eggs', 'demoneeded*.egg')):
... remove(sample_buildout, 'eggs', egg)
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
...
... networkcache-section = networkcache
... find-links = %(link_server)s
... parts = eggs
...
... [eggs]
... recipe = zc.recipe.egg:eggs
... eggs = demo
...
... [networkcache]
... download-cache-url = http://127.0.0.1:1/shacache
... download-dir-url = http://127.0.0.1:1/shadir
... upload-cache-url = http://127.0.0.1:1/sshacache
... upload-dir-url = http://127.0.0.1:1/sshadir
... ''' % globals())
>>> print system(buildout) >>> print system(buildout)
Networkcache enabled. Networkcache enabled.
Networkcache download cache: 'http://127.0.0.1:1/', directory 'http://127.0.0.1:1/' Networkcache download cache: 'http://127.0.0.1:1/shacache', directory 'http://127.0.0.1:1/shadir'
Networkcache upload cache: 'http://127.0.0.1:1/', directory 'http://127.0.0.1:1/' Networkcache upload cache: 'http://127.0.0.1:1/sshacache', directory 'http://127.0.0.1:1/sshadir'
Installing eggs. Installing eggs.
Getting distribution for 'demo==0.2'. Getting distribution for 'demo'.
Downloading demo-0.2-py2.7.egg from network cache. Downloading demo-0.4c1-py2.7.egg from network cache.
Failed to download from network cache demo-0.2-py2.7.egg: [Errno 111] Connection refused Failed to download from network cache demo-0.4c1-py2.7.egg: [Errno 111] Connection refused
Uploading http://localhost/demo-0.2-py2.7.egg into network cache. Uploading http://localhost/demo-0.4c1-py2.7.egg into network cache.
Fail to upload file. [Errno 111] Connection refused Fail to upload file. [Errno 111] Connection refused
Got demo 0.2. Got demo 0.4c1.
Getting distribution for 'demoneeded'. Getting distribution for 'demoneeded'.
Downloading demoneeded-1.2c1.zip from network cache. Downloading demoneeded-1.2c1.zip from network cache.
Failed to download from network cache demoneeded-1.2c1.zip: [Errno 111] Connection refused Failed to download from network cache demoneeded-1.2c1.zip: [Errno 111] Connection refused
......
...@@ -17,6 +17,7 @@ $Id$ ...@@ -17,6 +17,7 @@ $Id$
""" """
import BaseHTTPServer import BaseHTTPServer
import SimpleHTTPServer
import errno import errno
import logging import logging
import os import os
...@@ -32,6 +33,7 @@ import textwrap ...@@ -32,6 +33,7 @@ import textwrap
import threading import threading
import time import time
import urllib2 import urllib2
import json
import zc.buildout.buildout import zc.buildout.buildout
import zc.buildout.easy_install import zc.buildout.easy_install
...@@ -267,7 +269,7 @@ def make_buildout(executable=None): ...@@ -267,7 +269,7 @@ def make_buildout(executable=None):
"""Make a buildout that uses this version of zc.buildout.""" """Make a buildout that uses this version of zc.buildout."""
# Create a basic buildout.cfg to avoid a warning from buildout. # Create a basic buildout.cfg to avoid a warning from buildout.
open('buildout.cfg', 'w').write( open('buildout.cfg', 'w').write(
"[buildout]\nparts =\n" "[buildout]\nparts =\nfind-links = http://pypi.python.org/pypi/slapos.libnetworkcache"
) )
# Get state of installer defaults so we can reinstate them (instantiating # Get state of installer defaults so we can reinstate them (instantiating
# a Buildout will force the Buildout's defaults on the installer). # a Buildout will force the Buildout's defaults on the installer).
...@@ -347,6 +349,12 @@ def buildoutSetUp(test): ...@@ -347,6 +349,12 @@ def buildoutSetUp(test):
os.chdir(sample) os.chdir(sample)
make_buildout() make_buildout()
def start_nc(path):
port, thread = _start_nc(path, name=path)
url = 'http://localhost:%s/' % port
register_teardown(lambda: stop_server(url, thread))
return url
def start_server(path): def start_server(path):
port, thread = _start_server(path, name=path) port, thread = _start_server(path, name=path)
url = 'http://localhost:%s/' % port url = 'http://localhost:%s/' % port
...@@ -416,6 +424,7 @@ def buildoutSetUp(test): ...@@ -416,6 +424,7 @@ def buildoutSetUp(test):
sdist = sdist, sdist = sdist,
bdist_egg = bdist_egg, bdist_egg = bdist_egg,
start_server = start_server, start_server = start_server,
start_nc = start_nc,
buildout = os.path.join(sample, 'bin', 'buildout'), buildout = os.path.join(sample, 'bin', 'buildout'),
wait_until = wait_until, wait_until = wait_until,
make_py = make_py make_py = make_py
...@@ -511,11 +520,37 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -511,11 +520,37 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
if self.__server.__log: if self.__server.__log:
print '%s %s %s' % (self.command, code, self.path) print '%s %s %s' % (self.command, code, self.path)
class NCHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
if '__stop__' in self.path:
raise SystemExit
SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
def do_PUT(self):
path = self.translate_path(self.path)
d = os.path.dirname(path)
if not os.path.exists(d):
os.makedirs(d)
data = self.rfile.read(int(self.headers.getheader('content-length')))
try:
d = json.loads(data)
except ValueError:
pass
else:
data = json.dumps([d])
open(path, 'wb').write(data)
self.send_response(201)
def _run(tree, port): def _run(tree, port):
server_address = ('localhost', port) server_address = ('localhost', port)
httpd = Server(tree, server_address, Handler) httpd = Server(tree, server_address, Handler)
httpd.serve_forever() httpd.serve_forever()
def _run_nc(tree, port):
server_address = ('localhost', port)
httpd = Server(tree, server_address, NCHandler)
httpd.serve_forever()
def get_port(): def get_port():
for i in range(10): for i in range(10):
port = random.randrange(20000, 30000) port = random.randrange(20000, 30000)
...@@ -529,6 +564,17 @@ def get_port(): ...@@ -529,6 +564,17 @@ def get_port():
s.close() s.close()
raise RuntimeError, "Can't find port" raise RuntimeError, "Can't find port"
def _start_nc(tree, name=''):
port = get_port()
thread = threading.Thread(target=_run_nc, args=(tree, port), name=name)
thread.setDaemon(True)
thread.start()
wait(port, up=True)
return port, thread
def start_nc(tree):
return _start_nc(tree)[0]
def _start_server(tree, name=''): def _start_server(tree, name=''):
port = get_port() port = get_port()
thread = threading.Thread(target=_run, args=(tree, port), name=name) thread = threading.Thread(target=_run, args=(tree, port), name=name)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment