gns3-qemu-config - QEMU config disk
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
4.5KB

  1. From 7b3d9e3f5b4352d8d611e29799b00f206bfd48a3 Mon Sep 17 00:00:00 2001
  2. From: Bernhard Ehlers <none@bernhard-ehlers.de>
  3. Date: Tue, 7 Apr 2020 14:11:00 +0200
  4. Subject: [PATCH 2/4] QEMU config disk - preserve file timestamp on zip unpack
  5. ---
  6. gns3server/compute/qemu/qemu_vm.py | 9 +++---
  7. gns3server/compute/qemu/utils/ziputils.py | 53 +++++++++++++++++++++++++++++++
  8. 2 files changed, 58 insertions(+), 4 deletions(-)
  9. create mode 100644 gns3server/compute/qemu/utils/ziputils.py
  10. diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py
  11. index 88698ed4..0b08df7e 100644
  12. --- a/gns3server/compute/qemu/qemu_vm.py
  13. +++ b/gns3server/compute/qemu/qemu_vm.py
  14. @@ -37,6 +37,7 @@ from gns3server.utils import parse_version, shlex_quote
  15. from gns3server.utils.asyncio import subprocess_check_output, cancellable_wait_run_in_executor
  16. from .qemu_error import QemuError
  17. from .utils.qcow2 import Qcow2, Qcow2Error
  18. +from .utils.ziputils import pack_zip, unpack_zip
  19. from ..adapters.ethernet_adapter import EthernetAdapter
  20. from ..error import NodeError, ImageMissingError
  21. from ..nios.nio_udp import NIOUDP
  22. @@ -1626,8 +1627,8 @@ class QemuVM(BaseNode):
  23. os.mkdir(config_dir)
  24. if os.path.exists(zip_file):
  25. os.remove(zip_file)
  26. - if await self._mcopy("-s", "-m", "x:/", config_dir) == 0:
  27. - shutil.make_archive(zip_file[:-4], "zip", config_dir)
  28. + if await self._mcopy("-s", "-m", "-n", "--", "x:/", config_dir) == 0:
  29. + pack_zip(zip_file, config_dir)
  30. except OSError as e:
  31. log.error("Can't export config: {}".format(e))
  32. finally:
  33. @@ -1643,12 +1644,12 @@ class QemuVM(BaseNode):
  34. try:
  35. shutil.rmtree(config_dir, ignore_errors=True)
  36. os.mkdir(config_dir)
  37. - shutil.unpack_archive(zip_file, config_dir)
  38. + unpack_zip(zip_file, config_dir)
  39. shutil.copyfile(getattr(self, "config_disk_image"), disk)
  40. config_files = [os.path.join(config_dir, fname)
  41. for fname in os.listdir(config_dir)]
  42. if config_files:
  43. - if await self._mcopy("-s", "-m", *config_files, "x:/") != 0:
  44. + if await self._mcopy("-s", "-m", "-o", "--", *config_files, "x:/") != 0:
  45. os.remove(disk)
  46. os.remove(zip_file)
  47. except OSError as e:
  48. diff --git a/gns3server/compute/qemu/utils/ziputils.py b/gns3server/compute/qemu/utils/ziputils.py
  49. new file mode 100644
  50. index 00000000..3ff8c999
  51. --- /dev/null
  52. +++ b/gns3server/compute/qemu/utils/ziputils.py
  53. @@ -0,0 +1,53 @@
  54. +#!/usr/bin/env python3
  55. +#
  56. +# Copyright (C) 2020 GNS3 Technologies Inc.
  57. +#
  58. +# This program is free software: you can redistribute it and/or modify
  59. +# it under the terms of the GNU General Public License as published by
  60. +# the Free Software Foundation, either version 3 of the License, or
  61. +# (at your option) any later version.
  62. +#
  63. +# This program is distributed in the hope that it will be useful,
  64. +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  65. +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  66. +# GNU General Public License for more details.
  67. +#
  68. +# You should have received a copy of the GNU General Public License
  69. +# along with this program. If not, see <http://www.gnu.org/licenses/>.
  70. +
  71. +import os
  72. +import time
  73. +import shutil
  74. +import zipfile
  75. +
  76. +def pack_zip(filename, root_dir=None, base_dir=None):
  77. + """Create a zip archive"""
  78. +
  79. + if filename[-4:].lower() == ".zip":
  80. + filename = filename[:-4]
  81. + shutil.make_archive(filename, 'zip', root_dir, base_dir)
  82. +
  83. +def unpack_zip(filename, extract_dir=None):
  84. + """Unpack a zip archive"""
  85. +
  86. + dirs = []
  87. + if not extract_dir:
  88. + extract_dir = os.getcwd()
  89. +
  90. + try:
  91. + with zipfile.ZipFile(filename, 'r') as zfile:
  92. + for zinfo in zfile.infolist():
  93. + fname = os.path.join(extract_dir, zinfo.filename)
  94. + date_time = time.mktime(zinfo.date_time + (0, 0, -1))
  95. + zfile.extract(zinfo, extract_dir)
  96. +
  97. + # update timestamp
  98. + if zinfo.is_dir():
  99. + dirs.append((fname, date_time))
  100. + else:
  101. + os.utime(fname, (date_time, date_time))
  102. + # update timestamp of directories
  103. + for fname, date_time in reversed(dirs):
  104. + os.utime(fname, (date_time, date_time))
  105. + except zipfile.BadZipFile:
  106. + raise shutil.ReadError("%s is not a zip file" % filename)
  107. --
  108. 2.15.1 (Apple Git-101)