diff --git a/oz/Fedora.py b/oz/Fedora.py
index 89ecca8c..c6152f14 100644
--- a/oz/Fedora.py
+++ b/oz/Fedora.py
@@ -298,11 +298,11 @@ def _modify_iso(self):
initrdline += " inst.nosave=output_ks"
self._modify_isolinux(initrdline)
- def generate_diskimage(self, size=10, force=False):
+ def generate_diskimage(self, size=10*1024*1024*1024, force=False):
"""
Method to generate a diskimage. By default, a blank diskimage of
- 10GB will be created; the caller can override this with the size
- parameter, specified in GB. If force is False (the default), then
+ 10 GiB will be created; the caller can override this with the size
+ parameter, specified in bytes. If force is False (the default), then
a diskimage will not be created if a cached JEOS is found. If
force is True, a diskimage will be created regardless of whether a
cached JEOS exists. See the oz-install man page for more
diff --git a/oz/Guest.py b/oz/Guest.py
index 249cce04..8a4e4858 100644
--- a/oz/Guest.py
+++ b/oz/Guest.py
@@ -571,7 +571,7 @@ def _generate_xml(self, bootdev, installdev, kernel=None, initrd=None,
return xml
- def _internal_generate_diskimage(self, size=10, force=False,
+ def _internal_generate_diskimage(self, size=10*1024*1024*1024, force=False,
create_partition=False,
image_filename=None,
backing_filename=None):
@@ -587,7 +587,7 @@ def _internal_generate_diskimage(self, size=10, force=False,
# we'll copy the JEOS itself later on
return
- self.log.info("Generating %dGB diskimage for %s", size, self.tdl.name)
+ self.log.info("Generating %s diskimage for %s", oz.ozutil.sizeof_fmt(int(size)), self.tdl.name)
diskimage = self.diskimage
if image_filename:
@@ -628,17 +628,17 @@ def _internal_generate_diskimage(self, size=10, force=False,
# allows creation without an explicit capacity element.
qcow_size = oz.ozutil.check_qcow_size(backing_filename)
if qcow_size:
- capacity = qcow_size / 1024 / 1024 / 1024
+ capacity = qcow_size
backing_format = 'qcow2'
else:
- capacity = os.path.getsize(backing_filename) / 1024 / 1024 / 1024
+ capacity = os.path.getsize(backing_filename)
backing_format = 'raw'
backing = oz.ozutil.lxml_subelement(vol, "backingStore")
oz.ozutil.lxml_subelement(backing, "path", backing_filename)
oz.ozutil.lxml_subelement(backing, "format", None,
{"type": backing_format})
- oz.ozutil.lxml_subelement(vol, "capacity", str(int(capacity)), {'unit': 'G'})
+ oz.ozutil.lxml_subelement(vol, "capacity", str(int(capacity)), {'unit': 'B'})
vol_xml = lxml.etree.tostring(vol, pretty_print=True, encoding="unicode")
# sigh. Yes, this is racy; if a pool is defined during this loop, we
@@ -718,11 +718,11 @@ def _vol_create_cb(args):
g_handle.create_msdos_partition_table()
g_handle.cleanup()
- def generate_diskimage(self, size=10, force=False):
+ def generate_diskimage(self, size=10*1024*1024*1024, force=False):
"""
Method to generate a diskimage. By default, a blank diskimage of
- 10GB will be created; the caller can override this with the size
- parameter, specified in GB. If force is False (the default), then
+ 10 GiB will be created; the caller can override this with the size
+ parameter, specified in bytes. If force is False (the default), then
a diskimage will not be created if a cached JEOS is found. If
force is True, a diskimage will be created regardless of whether a
cached JEOS exists. See the oz-install man page for more
diff --git a/oz/TDL.py b/oz/TDL.py
index cb373cb3..aee74a3d 100644
--- a/oz/TDL.py
+++ b/oz/TDL.py
@@ -327,20 +327,39 @@ def _parse_disksize(self):
# a sensible default
return None
- match = re.match(r'([0-9]*) *([GT]?)$', size)
- if not match or len(match.groups()) != 2:
- raise oz.OzException.OzException("Invalid disk size; it must be specified as a size in gigabytes, optionally suffixed with 'G' or 'T'")
-
- number = match.group(1)
- suffix = match.group(2)
-
- if not suffix or suffix == 'G':
- # for backwards compatibility, we assume G when there is no suffix
- size = number
- elif suffix == 'T':
- size = str(int(number) * 1024)
-
- return size
+ # drop spaces and downcase
+ size = size.replace(" ", "").lower()
+ # isolate digits
+ number = ""
+ suffix = ""
+ for (idx, char) in enumerate(size):
+ if char.isdigit():
+ number += char
+ else:
+ suffix = size[idx:]
+ break
+
+ if not suffix:
+ # for backwards compatibility, we assume GiB when there is no suffix
+ suffix = "gib"
+
+ # also for backwards compatibility with an earlier attempt to support
+ # suffixes, treat "T" and "G" as "TiB" and "GiB"
+ units = {"b": 1, "g": 2**30, "t": 2**40}
+ tenscale = 3
+ twoscale = 10
+ for (i, pref) in enumerate(("k", "m", "g", "t", "p", "e", "z", "y"), start=1):
+ # this is giving us {"gib": 2 ** 30, "gb": 10 ** 9}, etc
+ units[pref + "b"] = (10 ** (i*tenscale))
+ units[pref + "ib"] = (2 ** (i*twoscale))
+
+ factor = units.get(suffix)
+ if not number or not factor:
+ raise oz.OzException.OzException(
+ "Invalid disk size; it must be specified as an integer size with an optional SI or IEC unit suffix, e.g. '10TB' or '16GiB'"
+ )
+
+ return str(int(number) * factor)
def _parse_commands(self, xpath):
"""
diff --git a/oz/Windows.py b/oz/Windows.py
index 78948ac0..777a3068 100644
--- a/oz/Windows.py
+++ b/oz/Windows.py
@@ -78,12 +78,12 @@ def _generate_new_iso(self):
self.iso_contents],
printfn=self.log.debug)
- def generate_diskimage(self, size=10, force=False):
+ def generate_diskimage(self, size=10*1024*1024*1024, force=False):
"""
Method to generate a diskimage. By default, a blank diskimage of
- 10GB will be created; the caller can override this with the size
- parameter, specified in GB. If force is False (the default), then
- a diskimage will not be created if a cached JEOS is found. If
+ 10 GiB will be created; the caller can override this with the size
+ parameter, specified in bytes. If force is False (the default),
+ then a diskimage will not be created if a cached JEOS is found. If
force is True, a diskimage will be created regardless of whether a
cached JEOS exists. See the oz-install man page for more
information about JEOS caching.
diff --git a/oz/ozutil.py b/oz/ozutil.py
index 689559f3..be27d3f0 100644
--- a/oz/ozutil.py
+++ b/oz/ozutil.py
@@ -1178,3 +1178,20 @@ def get_free_port():
sock.close()
return listen_port
+
+
+def sizeof_fmt(num, suffix="B"):
+ """
+ Give a convenient human-readable representation of a large size in
+ bytes. Initially by Fred Cirera:
+ https://web.archive.org/web/20111010015624/http://blogmag.net/blog/read/38/Print_human_readable_file_size
+ edited by multiple contributors at:
+ https://stackoverflow.com/questions/1094841
+ Per Richard Fontana this is too trivial to be copyrightable, so
+ there are no licensing concerns
+ """
+ for unit in ("", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"):
+ if abs(num) < 1024.0:
+ return "%3.1f%s%s" % (num, unit, suffix)
+ num /= 1024.0
+ return "%.1f%s%s" % (num, 'Yi', suffix)
diff --git a/tests/guest/test_guest.py b/tests/guest/test_guest.py
index 625eb678..85f6b03a 100644
--- a/tests/guest/test_guest.py
+++ b/tests/guest/test_guest.py
@@ -352,7 +352,8 @@ def test_geteltorito_bogus_bootp(tmpdir):
def test_init_guest():
guest = setup_guest(tdlxml2)
- assert guest.disksize == 20
+ # size without units is taken to be GiB
+ assert guest.disksize == 20*(2**30)
assert guest.image_name() == 'tester'
assert guest.output_image_path() in (
# user's image storage
diff --git a/tests/tdl/test-58-disk-size-terabyte.tdl b/tests/tdl/test-58-disk-size-tebibyte-compat.tdl
similarity index 100%
rename from tests/tdl/test-58-disk-size-terabyte.tdl
rename to tests/tdl/test-58-disk-size-tebibyte-compat.tdl
diff --git a/tests/tdl/test-63-disk-size-exbibyte.tdl b/tests/tdl/test-63-disk-size-exbibyte.tdl
new file mode 100644
index 00000000..e3f6b123
--- /dev/null
+++ b/tests/tdl/test-63-disk-size-exbibyte.tdl
@@ -0,0 +1,15 @@
+
+ help
+
+ Fedora
+ 12
+ i386
+
+ http://download.fedoraproject.org/pub/fedora/linux/releases/12/Fedora/x86_64/os/
+
+
+ My Fedora 12 JEOS image
+
+ 2EiB
+
+
diff --git a/tests/tdl/test-64-disk-size-zettabyte.tdl b/tests/tdl/test-64-disk-size-zettabyte.tdl
new file mode 100644
index 00000000..26b71055
--- /dev/null
+++ b/tests/tdl/test-64-disk-size-zettabyte.tdl
@@ -0,0 +1,15 @@
+
+ help
+
+ Fedora
+ 12
+ i386
+
+ http://download.fedoraproject.org/pub/fedora/linux/releases/12/Fedora/x86_64/os/
+
+
+ My Fedora 12 JEOS image
+
+ 10ZB
+
+
diff --git a/tests/tdl/test-65-disk-size-byte.tdl b/tests/tdl/test-65-disk-size-byte.tdl
new file mode 100644
index 00000000..b6e07744
--- /dev/null
+++ b/tests/tdl/test-65-disk-size-byte.tdl
@@ -0,0 +1,15 @@
+
+ help
+
+ Fedora
+ 12
+ i386
+
+ http://download.fedoraproject.org/pub/fedora/linux/releases/12/Fedora/x86_64/os/
+
+
+ My Fedora 12 JEOS image
+
+ 10000000 B
+
+
diff --git a/tests/tdl/test_tdl.py b/tests/tdl/test_tdl.py
index a94b2c18..366f1bc1 100644
--- a/tests/tdl/test_tdl.py
+++ b/tests/tdl/test_tdl.py
@@ -92,8 +92,11 @@
"test-55-files-http-url.tdl": True,
"test-56-invalid-disk-size.tdl": False,
"test-57-invalid-disk-size.tdl": False,
- "test-58-disk-size-terabyte.tdl": True,
+ "test-58-disk-size-tebibyte-compat.tdl": True,
"test-59-command-sorting.tdl": True,
+ "test-63-disk-size-exbibyte.tdl": True,
+ "test-64-disk-size-zettabyte.tdl": True,
+ "test-65-disk-size-byte.tdl": True,
}
# Test that iterates over all .tdl files