testcloud 0.11.0__tar.gz → 0.11.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {testcloud-0.11.0/testcloud.egg-info → testcloud-0.11.2}/PKG-INFO +1 -1
  2. {testcloud-0.11.0 → testcloud-0.11.2}/docs/source/conf.py +1 -1
  3. {testcloud-0.11.0 → testcloud-0.11.2}/test/test_config.py +1 -1
  4. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/__init__.py +1 -1
  5. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/config.py +28 -4
  6. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/instance.py +35 -11
  7. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/sql.py +7 -1
  8. {testcloud-0.11.0 → testcloud-0.11.2/testcloud.egg-info}/PKG-INFO +1 -1
  9. {testcloud-0.11.0 → testcloud-0.11.2}/.gitignore +0 -0
  10. {testcloud-0.11.0 → testcloud-0.11.2}/LICENSE +0 -0
  11. {testcloud-0.11.0 → testcloud-0.11.2}/README.md +0 -0
  12. {testcloud-0.11.0 → testcloud-0.11.2}/conf/99-testcloud-nonroot-libvirt-access.rules +0 -0
  13. {testcloud-0.11.0 → testcloud-0.11.2}/conf/settings-example.py +0 -0
  14. {testcloud-0.11.0 → testcloud-0.11.2}/conf/testcloud +0 -0
  15. {testcloud-0.11.0 → testcloud-0.11.2}/docs/LICENSE +0 -0
  16. {testcloud-0.11.0 → testcloud-0.11.2}/docs/Makefile +0 -0
  17. {testcloud-0.11.0 → testcloud-0.11.2}/docs/source/api.rst +0 -0
  18. {testcloud-0.11.0 → testcloud-0.11.2}/docs/source/indepth.rst +0 -0
  19. {testcloud-0.11.0 → testcloud-0.11.2}/docs/source/index.rst +0 -0
  20. {testcloud-0.11.0 → testcloud-0.11.2}/manpages/testcloud.1 +0 -0
  21. {testcloud-0.11.0 → testcloud-0.11.2}/pyproject.toml +0 -0
  22. {testcloud-0.11.0 → testcloud-0.11.2}/requirements.txt +0 -0
  23. {testcloud-0.11.0 → testcloud-0.11.2}/run_testcloud.py +0 -0
  24. {testcloud-0.11.0 → testcloud-0.11.2}/setup.cfg +0 -0
  25. {testcloud-0.11.0 → testcloud-0.11.2}/setup.py +0 -0
  26. {testcloud-0.11.0 → testcloud-0.11.2}/test/__init__.py +0 -0
  27. {testcloud-0.11.0 → testcloud-0.11.2}/test/test_cli.py +0 -0
  28. {testcloud-0.11.0 → testcloud-0.11.2}/test/test_image.py +0 -0
  29. {testcloud-0.11.0 → testcloud-0.11.2}/test/test_instance.py +0 -0
  30. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/cli.py +0 -0
  31. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/distro_utils/__init__.py +0 -0
  32. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/distro_utils/alma.py +0 -0
  33. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/distro_utils/centos.py +0 -0
  34. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/distro_utils/debian.py +0 -0
  35. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/distro_utils/fedora.py +0 -0
  36. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/distro_utils/misc.py +0 -0
  37. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/distro_utils/oracle.py +0 -0
  38. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/distro_utils/rocky.py +0 -0
  39. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/distro_utils/ubuntu.py +0 -0
  40. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/domain_configuration.py +0 -0
  41. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/exceptions.py +0 -0
  42. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/image.py +0 -0
  43. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/util.py +0 -0
  44. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud/workarounds.py +0 -0
  45. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud.egg-info/SOURCES.txt +0 -0
  46. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud.egg-info/dependency_links.txt +0 -0
  47. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud.egg-info/entry_points.txt +0 -0
  48. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud.egg-info/requires.txt +0 -0
  49. {testcloud-0.11.0 → testcloud-0.11.2}/testcloud.egg-info/top_level.txt +0 -0
  50. {testcloud-0.11.0 → testcloud-0.11.2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: testcloud
3
- Version: 0.11.0
3
+ Version: 0.11.2
4
4
  Summary: A tool to download and boot cloud images locally, with an easy to use API.
5
5
  Home-page: https://pagure.io/testcloud
6
6
  Author: Mike Ruckman
@@ -55,7 +55,7 @@ copyright = "2016-2024, testCloud devs"
55
55
  # built documents.
56
56
  #
57
57
  # The short X.Y version.
58
- version = "0.11.0"
58
+ version = "0.11.2"
59
59
  # The full version, including alpha/beta/rc tags.
60
60
  release = version
61
61
 
@@ -66,7 +66,7 @@ class TestConfig(object):
66
66
  test_config = config.ConfigData()
67
67
  assert test_config.DATA_DIR != REF_DATA_DIR
68
68
 
69
- test_config.merge_object(test_config_obj)
69
+ test_config._merge_object(test_config_obj)
70
70
  assert test_config.DATA_DIR == REF_DATA_DIR
71
71
 
72
72
  def test_load_merge_config_file(self, tmpdir, monkeypatch):
@@ -1,5 +1,5 @@
1
1
  # NOTE: if you update version, *make sure* to also update `docs/source/conf.py`
2
- __version__ = "0.11.0"
2
+ __version__ = "0.11.2"
3
3
 
4
4
  import signal
5
5
  import sys
@@ -45,7 +45,7 @@ def _parse_config():
45
45
 
46
46
  if config_filename is not None:
47
47
  loaded_config = _load_config(config_filename)
48
- config.merge_object(loaded_config)
48
+ config._merge_object(loaded_config)
49
49
 
50
50
  return config
51
51
 
@@ -98,7 +98,20 @@ class ConfigData(object):
98
98
 
99
99
  # Directories testcloud cares about
100
100
 
101
- DATA_DIR = "/var/lib/testcloud"
101
+ __DATA_DIR = "/var/lib/testcloud"
102
+
103
+ @property
104
+ def DATA_DIR(self):
105
+ return self.__DATA_DIR
106
+
107
+ @DATA_DIR.setter
108
+ def DATA_DIR(self, value):
109
+ if self.__DATA_DIR == value:
110
+ return
111
+ from testcloud import sql
112
+ sql.data_dir_changed(value)
113
+ self.__DATA_DIR = value
114
+
102
115
  STORE_DIR = "/var/lib/testcloud/backingstores"
103
116
 
104
117
  # Data for cloud-init
@@ -263,7 +276,7 @@ storage:
263
276
  UBUNTU_RELEASES_API = "https://api.launchpad.net/devel/ubuntu/series"
264
277
  UBUNTU_IMG_URL = "https://cloud-images.ubuntu.com/%s/current/%s-server-cloudimg-%s.img"
265
278
 
266
- def merge_object(self, obj):
279
+ def _merge_object(self, obj):
267
280
  """Overwrites default values with values from a python object which have
268
281
  names containing all upper case letters.
269
282
 
@@ -273,4 +286,15 @@ storage:
273
286
 
274
287
  for key in dir(obj):
275
288
  if key.isupper():
276
- setattr(self, key, getattr(obj, key))
289
+ if key != "DATA_DIR":
290
+ setattr(self, key, getattr(obj, key))
291
+ else:
292
+ # I hate life... but since we want to "automagically" work around TMT's
293
+ # way of changing the DATA_DIR on the fly, I don't see another way.
294
+ try:
295
+ self.DATA_DIR = getattr(obj, key)
296
+ except AttributeError as e:
297
+ if 'partially initialized module' in str(e):
298
+ self.__DATA_DIR = getattr(obj, key)
299
+ else:
300
+ raise
@@ -429,9 +429,9 @@ class Instance(object):
429
429
  key_content = None
430
430
  # We need this weird code until the way of objects sharing with tmt gets refactored
431
431
  try:
432
- bu_data = config_data.COREOS_DATA % key_content
432
+ bu_data = coreos_data_tpl % key_content
433
433
  except TypeError:
434
- bu_data = config_data.COREOS_DATA
434
+ bu_data = coreos_data_tpl
435
435
  with open(self.bu_path, "w") as user_file:
436
436
  user_file.write(bu_data)
437
437
 
@@ -571,13 +571,14 @@ class Instance(object):
571
571
  "qemu:///system and qemu:///session")
572
572
 
573
573
  excs = []
574
- for _ in range(max(1, retries + 1)):
574
+ for i in range(max(1, retries + 1)):
575
575
  try:
576
576
  self._start(timeout=timeout)
577
577
  break
578
578
  except TestcloudInstanceError as exc:
579
579
  excs.append(exc)
580
- log.debug("Retrying instance creation due to hang...")
580
+ if i != range(max(1, retries + 1)):
581
+ log.debug("Retrying instance creation due to hang...")
581
582
  else:
582
583
  raise excs[-1]
583
584
 
@@ -601,7 +602,7 @@ class Instance(object):
601
602
  poll_tick = 0.5
602
603
  timeout_ticks = timeout / poll_tick
603
604
  count = 0
604
- port_open = -1
605
+ port_open = False
605
606
  domif = {}
606
607
  port = self.get_instance_port()
607
608
 
@@ -609,22 +610,45 @@ class Instance(object):
609
610
  # found, indicating that the boot process is post-cloud-init
610
611
  while count <= timeout_ticks:
611
612
  if self.connection == "qemu:///system":
613
+ log.debug("Checking if ssh is up on: %s" % self.name)
612
614
  domif = dom.interfaceAddresses(libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE)
613
615
  elif self.connection == "qemu:///session" and not self.coreos:
614
616
  try:
615
- log.debug("Checking if cloud-init has finished its job for: " + self.name)
617
+ log.debug("Checking if cloud-init has finished its job for: %s" % self.name)
616
618
  requests.head("http://127.0.0.1:%d" % (port - 1000), timeout=1).raise_for_status()
617
- port_open = 0
619
+ port_open = True
618
620
  except Exception:
619
621
  time.sleep(poll_tick * 4) # Larger value to prevent SYN flood
620
622
  count += 4
621
623
  continue
622
624
  elif self.connection == "qemu:///session" and self.coreos:
623
625
  domif = {}
624
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
625
- port_open = sock.connect_ex(("127.0.0.1", self.get_instance_port()))
626
-
627
- if len(domif) > 0 or port_open == 0:
626
+ log.debug("Checking if ssh is up on: %s" % self.name)
627
+ try:
628
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
629
+ sock.settimeout(poll_tick * 4)
630
+ sock.connect(("127.0.0.1", self.get_instance_port()))
631
+ resp = sock.recv(1024)
632
+ assert resp is not None
633
+ assert "ssh" in resp.decode("utf-8").lower()
634
+ port_open = True
635
+ except ConnectionRefusedError:
636
+ # To support old behavior where sock.connect fails before vm startup
637
+ # We didn't wait for timeout in this branch
638
+ domain_state = _find_domain(self.name, self.connection)
639
+ if domain_state != "running":
640
+ break
641
+ time.sleep(poll_tick * 4)
642
+ except (TimeoutError, AssertionError):
643
+ # AssertionError To break on abrupt libvirt domain shutoff
644
+ # TimeoutError Expected while waiting for ssh in VM
645
+ domain_state = _find_domain(self.name, self.connection)
646
+ if domain_state != "running":
647
+ break
648
+ finally:
649
+ sock.close()
650
+
651
+ if len(domif) > 0 or port_open:
628
652
  log.info("Successfully booted instance {}".format(self.name))
629
653
  return
630
654
 
@@ -15,7 +15,7 @@ logger.setLevel(logging.ERROR)
15
15
 
16
16
 
17
17
  cfg = config.get_config()
18
- if os.path.exists(cfg.DATA_DIR):
18
+ if os.path.exists(cfg.DATA_DIR) and os.access(cfg.DATA_DIR, os.W_OK):
19
19
  DB = pw.SqliteDatabase(os.path.join(cfg.DATA_DIR, "testcloud.sqlite"))
20
20
  else:
21
21
  DB = pw.SqliteDatabase(":memory:")
@@ -51,5 +51,11 @@ class DBImage(pw.Model):
51
51
  table_name = "image"
52
52
 
53
53
 
54
+ def data_dir_changed(pth):
55
+ global DB
56
+ DB = pw.SqliteDatabase(os.path.join(pth, "testcloud.sqlite"))
57
+ DB.connect()
58
+ DB.create_tables([DBImage])
59
+
54
60
  DB.connect()
55
61
  DB.create_tables([DBImage])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: testcloud
3
- Version: 0.11.0
3
+ Version: 0.11.2
4
4
  Summary: A tool to download and boot cloud images locally, with an easy to use API.
5
5
  Home-page: https://pagure.io/testcloud
6
6
  Author: Mike Ruckman
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes