Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
05a4e60
python3: use six.string_types not version-dependant types
ydirson Jul 18, 2022
84d172a
python3: use "six.ensure_binary" and "six.ensure_text" for str/bytes …
ydirson Jul 18, 2022
7ac16be
Remove direct call's to file's constructor and replace them with call…
brettcannon May 25, 2007
520d419
python3: xcp.net.mac: use six.python_2_unicode_compatible for stringi…
ydirson Jul 18, 2022
a59c3ba
xcp.net.ifrename.logic: use "logger.warning", "logger.warn" is deprec…
ydirson Jul 18, 2022
0832486
python3: use raw strings for regexps, fixes insufficient quoting
ydirson Jul 18, 2022
7e14499
test_dom0: mock "open()" in a python3-compatible way
ydirson Jul 19, 2022
9c64243
ifrename: don't rely on dict ordering in tests
ydirson Jul 19, 2022
ae79078
test_cpio: ensure paths are handled as text
ydirson Jul 20, 2022
346ebc0
cpiofile: migrate last "list.sort()" call still using a "cmp" argument
ydirson Jul 26, 2022
e008ff1
xcp.repository: switch from md5 to hashlib.md5
bernhardkaindl Apr 25, 2023
b70c48b
Pylint complements: honor len-as-condition convention
ydirson Jul 20, 2022
976b684
Pylint complements: whitespace in expressions
ydirson Jul 15, 2022
80fe22f
Pylint complements: test_ifrename_logic: disable "no-member" warning
ydirson Aug 8, 2022
2eb6f54
Pylint complements: avoid no-else-raise "refactor" issues
ydirson Aug 8, 2022
770a244
WIP xcp.repository: switch from ConfigParser to configparser
ydirson Jul 26, 2022
58a301c
xcp.xmlunwrap: encode() only if type is unicode (only for Py2)
bernhardkaindl Apr 24, 2023
c9dec5b
accessor: Add mode and kwargs parameters and default to binary mode
bernhardkaindl Apr 25, 2023
4d8fd63
test_accessor.py: Test reading binary data from http and file
bernhardkaindl Apr 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ diff_cover
mock
pytest
pytest-cov
parameterized
# dependencies also in setup.py until they can be used
six
future

# python-2.7 only
configparser ; python_version < "3.0"
Binary file added tests/data/repo/boot/isolinux/mboot.c32
Binary file not shown.
47 changes: 36 additions & 11 deletions tests/test_accessor.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,46 @@
import unittest
import hashlib
from tempfile import NamedTemporaryFile

from parameterized import parameterized_class

import xcp.accessor

@parameterized_class([{"url": "file://tests/data/repo/"},
{"url": "https://updates.xcp-ng.org/netinstall/8.2.1"}])
class TestAccessor(unittest.TestCase):
def test_http(self):
raise unittest.SkipTest("comment out if you really mean it")
a = xcp.accessor.createAccessor("https://updates.xcp-ng.org/netinstall/8.2.1", True)
a.start()
self.assertTrue(a.access('.treeinfo'))
url = ""

def setup_accessor(self, arg0):
result = xcp.accessor.createAccessor(self.url, True)
result.start()
self.assertTrue(result.access(arg0))
return result

def test_access(self):
a = self.setup_accessor('.treeinfo')
self.assertFalse(a.access('no_such_file'))
self.assertEqual(a.lastError, 404)
a.finish()

def test_file(self):
a = xcp.accessor.createAccessor("file://tests/data/repo/", True)
a.start()
self.assertTrue(a.access('.treeinfo'))
self.assertFalse(a.access('no_such_file'))
self.assertEqual(a.lastError, 404)
def test_file_binfile(self):
binary_file_in_repo = "boot/isolinux/mboot.c32"
a = self.setup_accessor(binary_file_in_repo)
inf = a.openAddress(binary_file_in_repo)
with NamedTemporaryFile("wb") as outf:
while True:
data = inf.read()
if not data: # EOF
break
outf.write(data)
outf.flush()
hasher = hashlib.md5()
with open(outf.name, "rb") as bincontents:
while True:
data = bincontents.read()
if not data: # EOF
break
hasher.update(data)
csum = hasher.hexdigest()
self.assertEqual(csum, "eab52cebc3723863432dc672360f6dac")
a.finish()
4 changes: 2 additions & 2 deletions tests/test_cpio.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ def writeRandomFile(fn, size, start=b'', add=b'a'):
with open(fn, 'wb') as f:
m = md5()
m.update(start)
assert(len(add) != 0)
assert add
while size > 0:
d = m.digest()
if size < len(d):
d=d[:size]
d = d[:size]
f.write(d)
size -= len(d)
m.update(add)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_dom0.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def mock_version(open_mock, version):
(2*1024, 4*1024, 8*1024), # Above max
]

with patch("__builtin__.open") as open_mock:
with patch("xcp.dom0.open") as open_mock:
for host_gib, dom0_mib, _ in test_values:
mock_version(open_mock, '2.8.0')
expected = dom0_mib * 1024;
Expand All @@ -39,7 +39,7 @@ def mock_version(open_mock, version):

open_mock.assert_called_with("/etc/xensource-inventory")

with patch("__builtin__.open") as open_mock:
with patch("xcp.dom0.open") as open_mock:
for host_gib, _, dom0_mib in test_values:
mock_version(open_mock, '2.9.0')
expected = dom0_mib * 1024;
Expand Down
4 changes: 2 additions & 2 deletions tests/test_ifrename_dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ def test_pci_matching_invert(self):
MACPCI("c8:cb:b8:d3:0c:cf", "0000:04:00.0", kname="eth1",
ppn="", label="")])

self.assertEqual(dr.rules,[
self.assertEqual(set(dr.rules), set([
MACPCI("c8:cb:b8:d3:0c:ce", "0000:04:00.0", tname="eth1"),
MACPCI("c8:cb:b8:d3:0c:cf", "0000:04:00.0", tname="eth0")
])
]))

def test_pci_missing(self):

Expand Down
1 change: 1 addition & 0 deletions tests/test_ifrename_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ def test_ibft_nic_to_ibft(self):


class TestInputSanitisation(unittest.TestCase):
# pylint: disable=no-member

def setUp(self):
"""
Expand Down
24 changes: 12 additions & 12 deletions tests/test_ifrename_static.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,10 @@ def test_pci_matching(self):

sr.generate(self.state)

self.assertEqual(sr.rules,[
MACPCI("c8:cb:b8:d3:0c:cf", "0000:04:00.0", tname="eth1"),
MACPCI("c8:cb:b8:d3:0c:ce", "0000:04:00.0", tname="eth0")
])
self.assertEqual(set(sr.rules), set([
MACPCI("c8:cb:b8:d3:0c:cf", "0000:04:00.0", tname="eth1"),
MACPCI("c8:cb:b8:d3:0c:ce", "0000:04:00.0", tname="eth0")
]))

def test_pci_matching_invert(self):

Expand All @@ -389,10 +389,10 @@ def test_pci_matching_invert(self):

sr.generate(self.state)

self.assertEqual(sr.rules,[
MACPCI("c8:cb:b8:d3:0c:ce", "0000:04:00.0", tname="eth1"),
MACPCI("c8:cb:b8:d3:0c:cf", "0000:04:00.0", tname="eth0")
])
self.assertEqual(set(sr.rules), set([
MACPCI("c8:cb:b8:d3:0c:ce", "0000:04:00.0", tname="eth1"),
MACPCI("c8:cb:b8:d3:0c:cf", "0000:04:00.0", tname="eth0")
]))

def test_pci_matching_mixed(self):

Expand All @@ -403,10 +403,10 @@ def test_pci_matching_mixed(self):

sr.generate(self.state)

self.assertEqual(sr.rules,[
MACPCI("c8:cb:b8:d3:0c:cf", "0000:04:00.0", tname="eth0"),
MACPCI("c8:cb:b8:d3:0c:ce", "0000:04:00.0", tname="eth1")
])
self.assertEqual(set(sr.rules), set([
MACPCI("c8:cb:b8:d3:0c:cf", "0000:04:00.0", tname="eth0"),
MACPCI("c8:cb:b8:d3:0c:ce", "0000:04:00.0", tname="eth1")
]))

def test_pci_missing(self):

Expand Down
2 changes: 1 addition & 1 deletion tests/test_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class TestRepository(unittest.TestCase):
def test_http(self):
raise unittest.SkipTest("comment out if you really mean it")
#raise unittest.SkipTest("comment out if you really mean it")
a = xcp.accessor.createAccessor("https://updates.xcp-ng.org/netinstall/8.2.1", True)
repo_ver = repository.BaseRepository.getRepoVer(a)
self.assertEqual(repo_ver, Version([3, 2, 1]))
Expand Down
22 changes: 11 additions & 11 deletions xcp/accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def access(self, name):

return True

def openAddress(self, address):
def openAddress(self, address, mode="", **kwargs):
"""should be overloaded"""
pass

Expand Down Expand Up @@ -99,9 +99,9 @@ def __init__(self, location, ro):
super(FilesystemAccessor, self).__init__(ro)
self.location = location

def openAddress(self, address):
def openAddress(self, address, mode="rb", **kwargs):
try:
filehandle = open(os.path.join(self.location, address), 'r')
filehandle = open(os.path.join(self.location, address), mode, **kwargs)
except OSError as e:
if e.errno == errno.EIO:
self.lastError = 5
Expand Down Expand Up @@ -165,9 +165,9 @@ def finish(self):
os.rmdir(self.location)
self.location = None

def writeFile(self, in_fh, out_name):
def writeFile(self, in_fh, out_name, mode="wb", **kwargs):
logger.info("Copying to %s" % os.path.join(self.location, out_name))
out_fh = open(os.path.join(self.location, out_name), 'w')
out_fh = open(os.path.join(self.location, out_name), mode, **kwargs)
return self._writeFile(in_fh, out_fh)

def __del__(self):
Expand Down Expand Up @@ -220,9 +220,9 @@ def __init__(self, baseAddress, ro):
super(FileAccessor, self).__init__(ro)
self.baseAddress = baseAddress

def openAddress(self, address):
def openAddress(self, address, mode="rb", **kwargs):
try:
file = open(os.path.join(self.baseAddress, address))
file = open(os.path.join(self.baseAddress, address), mode, **kwargs)
except IOError as e:
if e.errno == errno.EIO:
self.lastError = 5
Expand All @@ -240,9 +240,9 @@ def openAddress(self, address):
return False
return file

def writeFile(self, in_fh, out_name):
def writeFile(self, in_fh, out_name, mode="wb", **kwargs):
logger.info("Copying to %s" % os.path.join(self.baseAddress, out_name))
out_fh = open(os.path.join(self.baseAddress, out_name), 'w')
out_fh = open(os.path.join(self.baseAddress, out_name), mode, **kwargs)
return self._writeFile(in_fh, out_fh)

def __repr__(self):
Expand Down Expand Up @@ -331,13 +331,13 @@ def access(self, path):
self.lastError = 500
return False

def openAddress(self, address):
def openAddress(self, address, mode="rb", **kwargs):
logger.debug("Opening "+address)
self._cleanup()
url = urllib.parse.unquote(address)

self.ftp.voidcmd('TYPE I')
s = self.ftp.transfercmd('RETR ' + url).makefile('rb')
s = self.ftp.transfercmd('RETR ' + url).makefile(mode, **kwargs)
self.cleanup = True
return s

Expand Down
6 changes: 3 additions & 3 deletions xcp/bootloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,19 +336,19 @@ def create_label(title):
try:
for line in fh:
l = line.strip()
menu_match = re.match("menuentry ['\"]([^']*)['\"](.*){", l)
menu_match = re.match(r"menuentry ['\"]([^']*)['\"](.*){", l)

# Only parse unindented default and timeout lines to prevent
# changing these lines in if statements.
if l.startswith('set default=') and l == line.rstrip():
default = l.split('=')[1]
match = re.match("['\"](.*)['\"]$", default)
match = re.match(r"['\"](.*)['\"]$", default)
if match:
default = match.group(1)
elif l.startswith('set timeout=') and l == line.rstrip():
timeout = int(l.split('=')[1]) * 10
elif l.startswith('serial'):
match = re.match("serial --unit=(\d+) --speed=(\d+)", l)
match = re.match(r"serial --unit=(\d+) --speed=(\d+)", l)
if match:
serial = {
'port': int(match.group(1)),
Expand Down
11 changes: 6 additions & 5 deletions xcp/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@
"""Command processing"""

import subprocess
import six

import xcp.logger as logger

def runCmd(command, with_stdout = False, with_stderr = False, inputtext = None):
cmd = subprocess.Popen(command, bufsize = 1,
stdin = (inputtext and subprocess.PIPE or None),
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
shell = isinstance(command, str))
cmd = subprocess.Popen(command, bufsize=1,
stdin=(inputtext and subprocess.PIPE or None),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=isinstance(command, six.string_types))

(out, err) = cmd.communicate(inputtext)
rv = cmd.returncode
Expand Down
22 changes: 11 additions & 11 deletions xcp/cpiofile.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ def _init_write_gz(self):
self.__write(b"\037\213\010\010%s\002\377" % timestamp)
if self.name.endswith(".gz"):
self.name = self.name[:-3]
self.__write(self.name + NUL)
self.__write(six.ensure_binary(self.name) + NUL)

def write(self, s):
"""Write string s to the stream.
Expand Down Expand Up @@ -951,7 +951,7 @@ def __init__(self, name=None, mode="r", fileobj=None):
self.mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]

if not fileobj:
fileobj = file(name, self.mode)
fileobj = bltn_open(name, self.mode)
self._extfileobj = False
else:
if name is None and hasattr(fileobj, "name"):
Expand Down Expand Up @@ -1109,7 +1109,7 @@ def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9):
raise CompressionError("gzip module is not available")

if fileobj is None:
fileobj = file(name, mode + "b")
fileobj = bltn_open(name, mode + "b")

try:
t = cls.cpioopen(name, mode, gzip.GzipFile(name, mode, compresslevel, fileobj))
Expand Down Expand Up @@ -1354,7 +1354,7 @@ def add(self, name, arcname=None, recursive=True):

# Append the cpio header and data to the archive.
if cpioinfo.isreg():
f = file(name, "rb")
f = bltn_open(name, "rb")
self.addfile(cpioinfo, f)
f.close()

Expand Down Expand Up @@ -1420,20 +1420,20 @@ def extractall(self, path=".", members=None):
# Extract directory with a safe mode, so that
# all files below can be extracted as well.
try:
os.makedirs(os.path.join(path, cpioinfo.name), 0o777)
os.makedirs(os.path.join(path, six.ensure_text(cpioinfo.name)), 0o777)
except EnvironmentError:
pass
directories.append(cpioinfo)
else:
self.extract(cpioinfo, path)

# Reverse sort directories.
directories.sort(lambda a, b: cmp(a.name, b.name))
directories.sort(key=lambda x: x.name)
directories.reverse()

# Set correct owner, mtime and filemode on directories.
for cpioinfo in directories:
path = os.path.join(path, cpioinfo.name)
path = os.path.join(path, six.ensure_text(cpioinfo.name))
try:
self.chown(cpioinfo, path)
self.utime(cpioinfo, path)
Expand Down Expand Up @@ -1462,7 +1462,7 @@ def extract(self, member, path=""):
cpioinfo._link_path = path

try:
self._extract_member(cpioinfo, os.path.join(path, cpioinfo.name))
self._extract_member(cpioinfo, os.path.join(path, six.ensure_text(cpioinfo.name)))
except EnvironmentError as e:
if self.errorlevel > 0:
raise
Expand Down Expand Up @@ -1594,7 +1594,7 @@ def makefile(self, cpioinfo, targetpath):

if extractinfo:
source = self.extractfile(extractinfo)
target = file(targetpath, "wb")
target = bltn_open(targetpath, "wb")
copyfileobj(source, target)
source.close()
target.close()
Expand Down Expand Up @@ -1926,5 +1926,5 @@ def is_cpiofile(name):
except CpioError:
return False

def cpioOpen(*al, **ad):
return CpioFile.open(*al, **ad)
bltn_open = open
open = CpioFile.open
2 changes: 1 addition & 1 deletion xcp/dom0.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def default_memory(host_mem_kib):
return default_memory_for_version(host_mem_kib, platform_version)


_size_and_unit_re = re.compile("^(-?\d+)([bkmg]?)$", re.IGNORECASE)
_size_and_unit_re = re.compile(r"^(-?\d+)([bkmg]?)$", re.IGNORECASE)

def _parse_size_and_unit(s):
m = _size_and_unit_re.match(s)
Expand Down
Loading