Commit 4c4393b6 authored by Julien Muchembled's avatar Julien Muchembled

Add support for Python 3

Not fully tested. With this commit, it is at least possible to
bootstrap SlapOS from Python 3.
parent d5f5d399
...@@ -18,7 +18,7 @@ def generatePassword(length=8): ...@@ -18,7 +18,7 @@ def generatePassword(length=8):
def rmtree(path): def rmtree(path):
try: try:
os.remove(path) os.remove(path)
except OSError, e: except OSError as e:
if e.errno != errno.EISDIR: if e.errno != errno.EISDIR:
raise raise
shutil.rmtree(path) shutil.rmtree(path)
...@@ -45,7 +45,7 @@ class EnvironMixin: ...@@ -45,7 +45,7 @@ class EnvironMixin:
env[k] = v.strip() % environ env[k] = v.strip() % environ
else: else:
self._environ = dict((k, v.strip() % environ) self._environ = dict((k, v.strip() % environ)
for k, v in self.buildout[environment].iteritems()) for k, v in self.buildout[environment].items())
else: else:
self._environ = None if allow_none else {} self._environ = None if allow_none else {}
...@@ -54,10 +54,10 @@ class EnvironMixin: ...@@ -54,10 +54,10 @@ class EnvironMixin:
if self._environ is not None: if self._environ is not None:
from os import environ from os import environ
env = self._environ.copy() env = self._environ.copy()
for k, v in env.iteritems(): for k, v in env.items():
logger.info( logger.info(
'Environment %r set to %r' if k in environ else 'Environment %r set to %r' if k in environ else
'Environment %r added with %r', k, v) 'Environment %r added with %r', k, v)
for kw in environ.iteritems(): for kw in environ.items():
env.setdefault(*kw) env.setdefault(*kw)
return env return env
...@@ -249,7 +249,7 @@ class Script(EnvironMixin): ...@@ -249,7 +249,7 @@ class Script(EnvironMixin):
# Cleanup in case of failure # Cleanup in case of failure
try: try:
shutil.rmtree(destination, ignore_errors=True) shutil.rmtree(destination, ignore_errors=True)
except (shutil.Error, OSError), strerror: except (shutil.Error, OSError) as strerror:
self.logger.error("Error occurred when cleaning after error: %s", self.logger.error("Error occurred when cleaning after error: %s",
strerror) strerror)
raise error raise error
...@@ -293,7 +293,7 @@ class Script(EnvironMixin): ...@@ -293,7 +293,7 @@ class Script(EnvironMixin):
# env is used in script exec'ed below # env is used in script exec'ed below
env = self.environ env = self.environ
try: try:
exec self.script exec(self.script)
self._checkPromise('slapos_promise', location) self._checkPromise('slapos_promise', location)
except: except:
self.cleanup_list.append(location) self.cleanup_list.append(location)
......
...@@ -34,7 +34,7 @@ class GitCloneNonInformativeTests(unittest.TestCase): ...@@ -34,7 +34,7 @@ class GitCloneNonInformativeTests(unittest.TestCase):
def tearDown(self): def tearDown(self):
shutil.rmtree(self.dir) shutil.rmtree(self.dir)
for var in os.environ.keys(): for var in list(os.environ):
if var.startswith('SRB_'): if var.startswith('SRB_'):
del os.environ[var] del os.environ[var]
...@@ -68,8 +68,8 @@ class GitCloneNonInformativeTests(unittest.TestCase): ...@@ -68,8 +68,8 @@ class GitCloneNonInformativeTests(unittest.TestCase):
recipe.install() recipe.install()
# Should have raised before. # Should have raised before.
self.assertTrue(False) self.assertTrue(False)
except zc.buildout.UserError, e: except zc.buildout.UserError as e:
self.assertEquals(e.message, GIT_CLONE_CACHE_ERROR_MESSAGE) self.assertEqual(e.message, GIT_CLONE_CACHE_ERROR_MESSAGE)
def test_not_using_download_cache_if_forbidden(self): def test_not_using_download_cache_if_forbidden(self):
recipe = self.makeGitCloneRecipe({"repository": BAD_GIT_REPOSITORY}) recipe = self.makeGitCloneRecipe({"repository": BAD_GIT_REPOSITORY})
...@@ -78,8 +78,8 @@ class GitCloneNonInformativeTests(unittest.TestCase): ...@@ -78,8 +78,8 @@ class GitCloneNonInformativeTests(unittest.TestCase):
recipe.install() recipe.install()
# Should have raised before. # Should have raised before.
self.assertTrue(False) self.assertTrue(False)
except zc.buildout.UserError, e: except zc.buildout.UserError as e:
self.assertEquals(e.message, GIT_CLONE_ERROR_MESSAGE) self.assertEqual(e.message, GIT_CLONE_ERROR_MESSAGE)
def test_cleanup_of_pyc_files(self): def test_cleanup_of_pyc_files(self):
recipe = self.makeGitCloneRecipe({}) recipe = self.makeGitCloneRecipe({})
......
...@@ -29,7 +29,7 @@ import os ...@@ -29,7 +29,7 @@ import os
import subprocess import subprocess
import zc.buildout import zc.buildout
def createExecutable(name, content, mode=0755): def createExecutable(name, content, mode=0o755):
"""Create an executable with content """Create an executable with content
The parent directory should exists, else it would raise IOError""" The parent directory should exists, else it would raise IOError"""
......
...@@ -91,8 +91,8 @@ class Recipe: ...@@ -91,8 +91,8 @@ class Recipe:
patch_archive_util() patch_archive_util()
# ad-hoc support for .xz and .lz archive # ad-hoc support for .xz and .lz archive
hdr = open(path, 'rb').read(6) hdr = open(path, 'rb').read(6)
for magic, cmd in (('\xfd7zXZ\x00', ('xzcat',)), for magic, cmd in ((b'\xfd7zXZ\x00', ('xzcat',)),
('LZIP', ('lunzip', '-c'))): (b'LZIP', ('lunzip', '-c'))):
if hdr.startswith(magic): if hdr.startswith(magic):
new_path = os.path.join(extract_dir, os.path.basename(path)) new_path = os.path.join(extract_dir, os.path.basename(path))
with open(new_path, 'wb') as stdout: with open(new_path, 'wb') as stdout:
......
...@@ -47,10 +47,10 @@ try: ...@@ -47,10 +47,10 @@ try:
else: else:
LIBNETWORKCACHE_ENABLED = True LIBNETWORKCACHE_ENABLED = True
except: except:
print 'There was problem while trying to import slapos.libnetworkcache:'\ print('There was problem while trying to import slapos.libnetworkcache:\n%s'
'\n%s' % traceback.format_exc() % traceback.format_exc())
LIBNETWORKCACHE_ENABLED = False LIBNETWORKCACHE_ENABLED = False
print 'Networkcache forced to be disabled.' print('Networkcache forced to be disabled.')
GIT_DEFAULT_REMOTE_NAME = 'origin' GIT_DEFAULT_REMOTE_NAME = 'origin'
GIT_DEFAULT_BRANCH_NAME = 'master' GIT_DEFAULT_BRANCH_NAME = 'master'
...@@ -68,7 +68,7 @@ def upload_network_cached(path, name, revision, networkcache_options): ...@@ -68,7 +68,7 @@ def upload_network_cached(path, name, revision, networkcache_options):
'upload-dir-url')): 'upload-dir-url')):
return False return False
try: try:
print 'Uploading git repository to cache...' print('Uploading git repository to cache...')
metadata_dict = { metadata_dict = {
'revision':revision, 'revision':revision,
# XXX: we set date from client side. It can be potentially dangerous # XXX: we set date from client side. It can be potentially dangerous
...@@ -89,9 +89,9 @@ def upload_network_cached(path, name, revision, networkcache_options): ...@@ -89,9 +89,9 @@ def upload_network_cached(path, name, revision, networkcache_options):
shadir_cert_file=networkcache_options.get('shadir-cert-file'), shadir_cert_file=networkcache_options.get('shadir-cert-file'),
shadir_key_file=networkcache_options.get('shadir-key-file'), shadir_key_file=networkcache_options.get('shadir-key-file'),
) )
print 'Uploaded git repository to cache.' print('Uploaded git repository to cache.')
except Exception: except Exception:
print 'Unable to upload to cache:\n%s.' % traceback.format_exc() print('Unable to upload to cache:\n%s.' % traceback.format_exc())
def download_network_cached(path, name, revision, networkcache_options): def download_network_cached(path, name, revision, networkcache_options):
...@@ -177,9 +177,9 @@ class Recipe(object): ...@@ -177,9 +177,9 @@ class Recipe(object):
""" """
# If directory already exist: delete it. # If directory already exist: delete it.
if os.path.exists(self.location): if os.path.exists(self.location):
print 'destination directory already exists.' print('destination directory already exists.')
if not self.develop: if not self.develop:
print 'Deleting it.' print('Deleting it.')
shutil.rmtree(self.location) shutil.rmtree(self.location)
else: else:
# If develop is set, assume that this is a valid working copy # If develop is set, assume that this is a valid working copy
...@@ -226,8 +226,8 @@ class Recipe(object): ...@@ -226,8 +226,8 @@ class Recipe(object):
upload_network_cached(os.path.join(self.location, '.git'), upload_network_cached(os.path.join(self.location, '.git'),
self.repository, self.revision, self.networkcache) self.repository, self.revision, self.networkcache)
except CalledProcessError: except CalledProcessError:
print ("Unable to download from git repository. Trying from network " print("Unable to download from git repository."
"cache...") " Trying from network cache...")
if os.path.exists(self.location): if os.path.exists(self.location):
shutil.rmtree(self.location) shutil.rmtree(self.location)
if not self.use_cache: if not self.use_cache:
...@@ -248,7 +248,7 @@ class Recipe(object): ...@@ -248,7 +248,7 @@ class Recipe(object):
# allow several processes clean the same folder at the same time # allow several processes clean the same folder at the same time
try: try:
os.remove(os.path.join(path, file)) os.remove(os.path.join(path, file))
except OSError, e: except OSError as e:
if e.errno != errno.ENOENT: if e.errno != errno.ENOENT:
raise raise
...@@ -284,7 +284,7 @@ class Recipe(object): ...@@ -284,7 +284,7 @@ class Recipe(object):
# Buildout will remove the installed location and mark the part as not # Buildout will remove the installed location and mark the part as not
# installed if an error occurs during update. If we are developping this # installed if an error occurs during update. If we are developping this
# repository we do not want this to happen. # repository we do not want this to happen.
print 'Unable to update:\n%s' % traceback.format_exc() print('Unable to update:\n%s' % traceback.format_exc())
def uninstall(name, options): def uninstall(name, options):
"""Keep the working copy, unless develop is set to false. """Keep the working copy, unless develop is set to false.
...@@ -299,8 +299,8 @@ def uninstall(name, options): ...@@ -299,8 +299,8 @@ def uninstall(name, options):
cwd=options['location'], cwd=options['location'],
stdout=subprocess.PIPE) stdout=subprocess.PIPE)
if p.communicate()[0].strip(): if p.communicate()[0].strip():
print "You have uncommited changes in %s. "\ print("You have uncommited changes in %s."
"This folder will be left as is." % options['location'] " This folder will be left as is." % options['location'])
force_keep = True force_keep = True
p = subprocess.Popen([git_path, p = subprocess.Popen([git_path,
...@@ -308,12 +308,12 @@ def uninstall(name, options): ...@@ -308,12 +308,12 @@ def uninstall(name, options):
cwd=options['location'], cwd=options['location'],
stdout=subprocess.PIPE) stdout=subprocess.PIPE)
if p.communicate()[0].strip(): if p.communicate()[0].strip():
print "You have commits not pushed upstream in %s. "\ print("You have commits not pushed upstream in %s."
"This folder will be left as is." % options['location'] " This folder will be left as is." % options['location'])
force_keep = True force_keep = True
else: else:
print "Cannot check if there are unpushed/uncommitted changes in %s. "\ print("Cannot check if there are unpushed/uncommitted changes in %s."
"This folder will be left as is." % options['location'] " This folder will be left as is." % options['location'])
force_keep = True force_keep = True
if force_keep: if force_keep:
......
...@@ -29,7 +29,7 @@ import os ...@@ -29,7 +29,7 @@ import os
import subprocess import subprocess
import zc.buildout import zc.buildout
def createExecutable(name, content, mode=0755): def createExecutable(name, content, mode=0o755):
"""Create an executable with content """Create an executable with content
The parent directory should exists, else it would raise IOError""" The parent directory should exists, else it would raise IOError"""
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
import gzip, os, select, shutil, socket, stat import gzip, os, select, shutil, socket, stat
import subprocess, sys, tempfile, threading, time import subprocess, sys, tempfile, threading, time
from cStringIO import StringIO from io import BytesIO
from collections import defaultdict from collections import defaultdict
from contextlib import contextmanager from contextlib import contextmanager
from os.path import join from os.path import join
...@@ -68,7 +68,7 @@ class CPIO(object): ...@@ -68,7 +68,7 @@ class CPIO(object):
ino = 1 ino = 1
def __init__(self): def __init__(self):
self.buf = StringIO() self.buf = BytesIO()
self.mtime = int(time.time()) self.mtime = int(time.time())
def _add(self, path, mode, data='', def _add(self, path, mode, data='',
...@@ -82,7 +82,7 @@ class CPIO(object): ...@@ -82,7 +82,7 @@ class CPIO(object):
write(data + '\0' * ((4 - size) % 4)) write(data + '\0' * ((4 - size) % 4))
self.ino += 1 self.ino += 1
def add_file(self, path, data, mode=0644): def add_file(self, path, data, mode=0o644):
self._add(path, mode | stat.S_IFREG, data) self._add(path, mode | stat.S_IFREG, data)
def close(self): def close(self):
...@@ -218,7 +218,7 @@ class InstallDebianRecipe(BaseRecipe): ...@@ -218,7 +218,7 @@ class InstallDebianRecipe(BaseRecipe):
if p and p[0] != '#': if p and p[0] != '#':
k, v = p.split('=', 1) k, v = p.split('=', 1)
common[self._alias(k.strip())] = v.strip() common[self._alias(k.strip())] = v.strip()
for k, v in options.iteritems(): for k, v in options.items():
try: try:
p, k = k.split('.', 1) p, k = k.split('.', 1)
p = p.rsplit('/', 1) p = p.rsplit('/', 1)
...@@ -290,16 +290,16 @@ class InstallDebianRecipe(BaseRecipe): ...@@ -290,16 +290,16 @@ class InstallDebianRecipe(BaseRecipe):
' cd /target; cp /late-command .; exec chroot . /late-command') ' cd /target; cp /late-command .; exec chroot . /late-command')
cpio.add_file('late-command', '#!/bin/sh -e\nrm $0\n' cpio.add_file('late-command', '#!/bin/sh -e\nrm $0\n'
'export HOME=/root; DIST=%s\n%s\n' 'export HOME=/root; DIST=%s\n%s\n'
% (dist, '\n'.join(self.late_command)), 0755) % (dist, '\n'.join(self.late_command)), 0o755)
cpio.add_file('preseed.cfg', ''.join(sorted( cpio.add_file('preseed.cfg', ''.join(sorted(
"%s string %s\n" % ('%s %s' % k if type(k) is tuple else "%s string %s\n" % ('%s %s' % k if type(k) is tuple else
'd-i ' + k, v) 'd-i ' + k, v)
for k, v in p.iteritems()))) for k, v in p.items())))
vm = join(location, dist + '.img') vm = join(location, dist + '.img')
args = self.getQemuBasicArgs(dist, 256, unsafe=True) args = self.getQemuBasicArgs(dist, 256, unsafe=True)
open_flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY open_flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY
fd = os.open(vm, open_flags, 0666) fd = os.open(vm, open_flags, 0o666)
try: try:
os.ftruncate(fd, self.size) os.ftruncate(fd, self.size)
finally: finally:
...@@ -324,7 +324,7 @@ class InstallDebianRecipe(BaseRecipe): ...@@ -324,7 +324,7 @@ class InstallDebianRecipe(BaseRecipe):
raise Exception('non bootable image') raise Exception('non bootable image')
if generated: if generated:
fd = os.open(join(location, 'passwd'), open_flags, 0600) fd = os.open(join(location, 'passwd'), open_flags, 0o600)
try: try:
for generated in generated: for generated in generated:
os.write(fd, "%s:%s\n" % generated) os.write(fd, "%s:%s\n" % generated)
...@@ -361,7 +361,7 @@ PARTDIR=`map %s` ...@@ -361,7 +361,7 @@ PARTDIR=`map %s`
BaseRecipe.__init__(self, buildout, name, options, False) BaseRecipe.__init__(self, buildout, name, options, False)
self.vm = options['vm'] self.vm = options['vm']
self.mount_dict = {'buildout': buildout['buildout']['directory']} self.mount_dict = {'buildout': buildout['buildout']['directory']}
for k, v in options.iteritems(): for k, v in options.items():
if k == 'mount.buildout': if k == 'mount.buildout':
raise UserError('option %r can not be overridden' % k) raise UserError('option %r can not be overridden' % k)
v = v.strip() v = v.strip()
...@@ -373,7 +373,7 @@ PARTDIR=`map %s` ...@@ -373,7 +373,7 @@ PARTDIR=`map %s`
options = self.options options = self.options
location = options['location'] location = options['location']
mount_args = [] mount_args = []
for i, (tag, path) in enumerate(self.mount_dict.iteritems()): for i, (tag, path) in enumerate(self.mount_dict.items()):
mount_args += ( mount_args += (
'-fsdev', 'local,security_model=none,id=fsdev%s,path=%s' '-fsdev', 'local,security_model=none,id=fsdev%s,path=%s'
% (i, path), % (i, path),
...@@ -402,8 +402,7 @@ cd /etc/sudoers.d ...@@ -402,8 +402,7 @@ cd /etc/sudoers.d
header = self.command % ( header = self.command % (
sudo, options.get('stop-ssh', 'systemctl stop ssh'), sudo, sudo, options.get('stop-ssh', 'systemctl stop ssh'), sudo,
self.buildout['buildout']['directory'], location) self.buildout['buildout']['directory'], location)
commands = map(options.__getitem__, commands = [options[k] for k in options.get('commands', 'command').split()]
options.get('commands', 'command').split())
hostfwd_retries = 9 hostfwd_retries = 9
wait_ssh = int(options.get('wait-ssh') or 60) wait_ssh = int(options.get('wait-ssh') or 60)
with building_directory(location): with building_directory(location):
......
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