osi-dump 0.1.5__py3-none-any.whl → 0.1.6__py3-none-any.whl

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 (49) hide show
  1. osi_dump/batch_handler/external_port_batch_handler.py +8 -26
  2. osi_dump/batch_handler/flavor_batch_handler.py +4 -18
  3. osi_dump/batch_handler/hypervisor_batch_handler.py +5 -17
  4. osi_dump/batch_handler/image_batch_handler.py +4 -18
  5. osi_dump/batch_handler/network_batch_handler.py +5 -19
  6. osi_dump/batch_handler/project_batch_handler.py +5 -17
  7. osi_dump/batch_handler/router_batch_handler.py +4 -16
  8. osi_dump/batch_handler/volume_batch_handler.py +4 -10
  9. osi_dump/exporter/external_port/excel_external_port_exporter.py +16 -11
  10. osi_dump/exporter/external_port/external_port_exporter.py +4 -3
  11. osi_dump/exporter/flavor/excel_flavor_exporter.py +10 -9
  12. osi_dump/exporter/flavor/flavor_exporter.py +4 -2
  13. osi_dump/exporter/floating_ip/excel_floating_ip_exporter.py +17 -11
  14. osi_dump/exporter/floating_ip/floating_ip_exporter.py +4 -2
  15. osi_dump/exporter/hypervisor/excel_hypervisor_exporter.py +14 -13
  16. osi_dump/exporter/hypervisor/hypervisor_exporter.py +4 -3
  17. osi_dump/exporter/image/excel_image_exporter.py +10 -7
  18. osi_dump/exporter/image/image_exporter.py +4 -2
  19. osi_dump/exporter/network/excel_network_exporter.py +13 -11
  20. osi_dump/exporter/network/network_exporter.py +4 -3
  21. osi_dump/exporter/project/excel_project_exporter.py +11 -11
  22. osi_dump/exporter/project/project_exporter.py +4 -3
  23. osi_dump/exporter/router/excel_router_exporter.py +9 -8
  24. osi_dump/exporter/router/router_exporter.py +3 -2
  25. osi_dump/exporter/volume/excel_volume_exporter.py +10 -8
  26. osi_dump/exporter/volume/volume_exporter.py +4 -2
  27. osi_dump/importer/external_port/external_port_importer.py +3 -4
  28. osi_dump/importer/external_port/openstack_external_port_importer.py +44 -131
  29. osi_dump/importer/flavor/flavor_importer.py +3 -3
  30. osi_dump/importer/flavor/openstack_flavor_importer.py +13 -35
  31. osi_dump/importer/floating_ip/floating_ip_importer.py +3 -3
  32. osi_dump/importer/floating_ip/openstack_floating_ip_importer.py +11 -38
  33. osi_dump/importer/hypervisor/hypervisor_importer.py +3 -4
  34. osi_dump/importer/hypervisor/openstack_hypervisor_importer.py +44 -88
  35. osi_dump/importer/image/image_importer.py +3 -3
  36. osi_dump/importer/image/openstack_image_importer.py +16 -44
  37. osi_dump/importer/network/network_importer.py +3 -4
  38. osi_dump/importer/network/openstack_network_importer.py +23 -52
  39. osi_dump/importer/project/openstack_project_importer.py +45 -83
  40. osi_dump/importer/project/project_importer.py +3 -4
  41. osi_dump/importer/router/openstack_router_importer.py +18 -53
  42. osi_dump/importer/router/router_importer.py +2 -3
  43. osi_dump/importer/volume/openstack_volume_importer.py +15 -45
  44. osi_dump/importer/volume/volume_importer.py +3 -4
  45. {osi_dump-0.1.5.dist-info → osi_dump-0.1.6.dist-info}/METADATA +1 -1
  46. {osi_dump-0.1.5.dist-info → osi_dump-0.1.6.dist-info}/RECORD +49 -49
  47. {osi_dump-0.1.5.dist-info → osi_dump-0.1.6.dist-info}/WHEEL +0 -0
  48. {osi_dump-0.1.5.dist-info → osi_dump-0.1.6.dist-info}/entry_points.txt +0 -0
  49. {osi_dump-0.1.5.dist-info → osi_dump-0.1.6.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,5 @@
1
1
  import logging
2
-
3
- import concurrent
4
-
2
+ from typing import Generator
5
3
  from openstack.connection import Connection
6
4
  from openstack.network.v2.floating_ip import FloatingIP as OSFloatingIP
7
5
 
@@ -10,49 +8,26 @@ from osi_dump.model.floating_ip import FloatingIP
10
8
 
11
9
  logger = logging.getLogger(__name__)
12
10
 
13
-
14
11
  class OpenStackFloatingIPImporter(FloatingIPImporter):
15
12
  def __init__(self, connection: Connection):
16
13
  self.connection = connection
17
14
 
18
- def import_floating_ips(self) -> list[FloatingIP]:
19
- """Import instances information from Openstack
20
-
21
- Raises:
22
- Exception: Raises exception if fetching server failed
23
-
24
- Returns:
25
- list[Instance]: _description_
26
- """
27
-
15
+ def import_floating_ips(self) -> Generator[FloatingIP, None, None]:
28
16
  logger.info(f"Importing floating ips for {self.connection.auth['auth_url']}")
29
-
30
17
  try:
31
- osfloating_ips: list[OSFloatingIP] = list(
32
- self.connection.list_floating_ips()
33
- )
34
- except Exception as e:
35
- raise Exception(
36
- f"Can not fetch floating IPs for {self.connection.auth['auth_url']}"
37
- ) from e
38
-
39
- floating_ips: list[FloatingIP] = []
40
-
41
- with concurrent.futures.ThreadPoolExecutor() as executor:
42
- futures = [
43
- executor.submit(self._get_floating_ip_info, osfloating_ip)
44
- for osfloating_ip in osfloating_ips
45
- ]
46
- for future in concurrent.futures.as_completed(futures):
47
- floating_ips.append(future.result())
18
+ osfloating_ip_iterator = self.connection.list_floating_ips()
19
+
20
+ for floating_ip in osfloating_ip_iterator:
21
+ yield self._get_floating_ip_info(floating_ip)
48
22
 
49
- logger.info(f"Imported floating ips for {self.connection.auth['auth_url']}")
23
+ except Exception as e:
24
+ logger.error(f"Cannot fetch floating IPs for {self.connection.auth['auth_url']}: {e}")
25
+ return
50
26
 
51
- return floating_ips
27
+ logger.info(f"Finished importing floating ips for {self.connection.auth['auth_url']}")
52
28
 
53
29
  def _get_floating_ip_info(self, floating_ip: OSFloatingIP) -> FloatingIP:
54
-
55
- ret_floating_ip = FloatingIP(
30
+ return FloatingIP(
56
31
  floating_ip_id=floating_ip.id,
57
32
  project_id=floating_ip.project_id,
58
33
  floating_ip_address=floating_ip.floating_ip_address,
@@ -64,5 +39,3 @@ class OpenStackFloatingIPImporter(FloatingIPImporter):
64
39
  created_at=floating_ip.created_at,
65
40
  updated_at=floating_ip.updated_at,
66
41
  )
67
-
68
- return ret_floating_ip
@@ -1,9 +1,8 @@
1
1
  from abc import ABC, abstractmethod
2
-
2
+ from typing import Generator
3
3
  from osi_dump.model.hypervisor import Hypervisor
4
4
 
5
-
6
5
  class HypervisorImporter(ABC):
7
6
  @abstractmethod
8
- def import_hypervisors(self) -> list[Hypervisor]:
9
- pass
7
+ def import_hypervisors(self) -> Generator[Hypervisor, None, None]:
8
+ pass
@@ -1,124 +1,84 @@
1
1
  import logging
2
-
3
- import concurrent
4
-
2
+ from typing import Generator
5
3
  from openstack.connection import Connection
6
4
  from openstack.compute.v2.hypervisor import Hypervisor as OSHypervisor
7
5
  from openstack.compute.v2.aggregate import Aggregate as OSAggregate
8
-
9
6
  from openstack.placement.v1._proxy import Proxy as PlacementProxy
10
7
  from openstack.placement.v1.resource_provider_inventory import ResourceProviderInventory
11
8
 
12
9
  from osi_dump.importer.hypervisor.hypervisor_importer import HypervisorImporter
13
10
  from osi_dump.model.hypervisor import Hypervisor
14
-
15
11
  from osi_dump.api.placement import get_usage
16
12
 
17
13
  logger = logging.getLogger(__name__)
18
14
 
19
-
20
15
  class OpenStackHypervisorImporter(HypervisorImporter):
21
16
  def __init__(self, connection: Connection):
22
17
  self.connection = connection
23
18
 
24
- def import_hypervisors(self) -> list[Hypervisor]:
25
- """Import hypervisors information from Openstack
26
-
27
- Raises:
28
- Exception: Raises exception if fetching hypervisor failed
29
-
30
- Returns:
31
- list[Hypervisor]: _description_
32
- """
33
- aggregates = list(self.connection.list_aggregates())
34
-
19
+ def import_hypervisors(self) -> Generator[Hypervisor, None, None]:
20
+ logger.info("Pre-caching aggregates...")
35
21
  try:
36
- oshypervisors: list[OSHypervisor] = list(
37
- self.connection.compute.hypervisors(details=True, with_servers=True)
38
- )
39
-
22
+ aggregates = list(self.connection.list_aggregates())
40
23
  except Exception as e:
41
- raise Exception(
42
- f"Can not fetch hypervisor for {self.connection.auth['auth_url']}"
43
- ) from e
44
-
45
- hypervisors: list[Hypervisor] = []
46
-
47
- with concurrent.futures.ThreadPoolExecutor() as executor:
48
- futures = [
49
- executor.submit(self._get_hypervisor_info, hypervisor, aggregates)
50
- for hypervisor in oshypervisors
51
- ]
52
- for future in concurrent.futures.as_completed(futures):
53
- hypervisors.append(future.result())
54
-
55
- logger.info(f"Imported hypervisors for {self.connection.auth['auth_url']}")
56
-
57
- return hypervisors
58
-
59
-
60
- def _normalize_hypervisor_aggregate(self, hypervisors: list[Hypervisor]):
61
-
62
- aggregate_id_map = {
63
-
64
- }
65
-
66
- aggregates: list[list[dict]] = [
24
+ logger.warning(f"Could not pre-cache aggregates: {e}")
25
+ aggregates = []
67
26
 
68
- ]
69
-
70
- for hypervisor in hypervisors:
71
- aggregates.append(hypervisor.aggregates)
72
-
73
- def _swap_element(array, i, j):
74
- array[i], array[j] = array[j], array[i]
27
+ logger.info(f"Importing hypervisors for {self.connection.auth['auth_url']}")
28
+ try:
29
+ hypervisor_iterator = self.connection.compute.hypervisors(details=True, with_servers=True)
30
+ for hypervisor in hypervisor_iterator:
31
+ yield self._get_hypervisor_info(hypervisor, aggregates)
32
+ except Exception as e:
33
+ logger.error(f"Cannot fetch hypervisors for {self.connection.auth['auth_url']}: {e}")
34
+ return
35
+
36
+ logger.info(f"Finished importing hypervisors for {self.connection.auth['auth_url']}")
75
37
 
76
38
  def _get_hypervisor_info(
77
39
  self, hypervisor: OSHypervisor, aggregates: list[OSAggregate]
78
40
  ) -> Hypervisor:
79
- aggregate_list, az = self._get_aggregates(hypervisor=hypervisor)
41
+ aggregate_list, az = self._get_aggregates(hypervisor=hypervisor, all_aggregates=aggregates)
80
42
 
81
43
  placement_proxy: PlacementProxy = self.connection.placement
82
-
83
- rpi: ResourceProviderInventory = list(
84
- placement_proxy.resource_provider_inventories(
85
- resource_provider=hypervisor.id
44
+ rpi: list[ResourceProviderInventory] = []
45
+ usage_data = {}
46
+
47
+ try:
48
+ rpi = list(
49
+ placement_proxy.resource_provider_inventories(
50
+ resource_provider=hypervisor.id
51
+ )
86
52
  )
87
- )
88
-
89
- usage_data = get_usage(self.connection, resource_provider_id=hypervisor.id)
53
+ usage_data = get_usage(self.connection, resource_provider_id=hypervisor.id)
54
+ except Exception as e:
55
+ logger.warning(f"Could not get placement data for hypervisor {hypervisor.name}: {e}")
90
56
 
91
- vcpu = rpi[0]
92
- memory = rpi[1]
93
- disk = rpi[2]
57
+ vcpu = rpi[0] if len(rpi) > 0 else {}
58
+ memory = rpi[1] if len(rpi) > 1 else {}
59
+ disk = rpi[2] if len(rpi) > 2 else {}
94
60
 
95
- ret_hypervisor = Hypervisor(
61
+ return Hypervisor(
96
62
  hypervisor_id=hypervisor.id,
97
63
  hypervisor_type=hypervisor.hypervisor_type,
98
64
  name=hypervisor.name,
99
65
  state=hypervisor.state,
100
66
  status=hypervisor.status,
101
- local_disk_size=disk["max_unit"],
102
- memory_size=memory["max_unit"] + memory["reserved"],
103
- vcpus=vcpu["max_unit"],
104
- vcpus_usage=usage_data["VCPU"],
105
- memory_usage=usage_data["MEMORY_MB"],
106
- local_disk_usage=usage_data["DISK_GB"],
67
+ local_disk_size=disk.get("max_unit", 0),
68
+ memory_size=memory.get("max_unit", 0) + memory.get("reserved", 0),
69
+ vcpus=vcpu.get("max_unit", 0),
70
+ vcpus_usage=usage_data.get("VCPU", 0),
71
+ memory_usage=usage_data.get("MEMORY_MB", 0),
72
+ local_disk_usage=usage_data.get("DISK_GB", 0),
107
73
  vm_count=len(hypervisor.servers),
108
74
  aggregates=aggregate_list,
109
75
  availability_zone=az,
110
76
  )
111
77
 
112
- return ret_hypervisor
113
-
114
- def _get_aggregates(self, hypervisor: OSHypervisor):
78
+ def _get_aggregates(self, hypervisor: OSHypervisor, all_aggregates: list[OSAggregate]):
115
79
  aggregates_ret = []
116
-
117
- aggregates: OSAggregate = list(self.connection.list_aggregates())
118
-
119
80
  az = None
120
-
121
- for aggregate in aggregates:
81
+ for aggregate in all_aggregates:
122
82
  if hypervisor.name in aggregate.hosts:
123
83
  aggregates_ret.append(
124
84
  {
@@ -126,12 +86,8 @@ class OpenStackHypervisorImporter(HypervisorImporter):
126
86
  "name": aggregate.name,
127
87
  }
128
88
  )
129
-
130
- if aggregate.availability_zone != None:
89
+ if aggregate.availability_zone is not None:
131
90
  az = aggregate.availability_zone
132
-
133
- aggregates_ret = [
134
- dict(sorted(aggregate.items())) for aggregate in aggregates_ret
135
- ]
136
-
137
- return aggregates_ret, az
91
+
92
+ aggregates_ret = sorted(aggregates_ret, key=lambda x: x['name'])
93
+ return aggregates_ret, az
@@ -1,9 +1,9 @@
1
1
  from abc import ABC, abstractmethod
2
-
2
+ from typing import Generator
3
3
  from osi_dump.model.image import Image
4
4
 
5
-
6
5
  class ImageImporter(ABC):
7
6
  @abstractmethod
8
- def import_images(self) -> list[Image]:
7
+ def import_images(self) -> Generator[Image, None, None]:
9
8
  pass
9
+
@@ -1,7 +1,5 @@
1
1
  import logging
2
-
3
- import concurrent
4
-
2
+ from typing import Generator
5
3
  from openstack.connection import Connection
6
4
  from openstack.image.v2.image import Image as OSImage
7
5
 
@@ -10,64 +8,40 @@ from osi_dump.model.image import Image
10
8
 
11
9
  logger = logging.getLogger(__name__)
12
10
 
13
-
14
11
  class OpenStackImageImporter(ImageImporter):
15
12
  def __init__(self, connection: Connection):
16
13
  self.connection = connection
17
14
 
18
- def import_images(self) -> list[Image]:
19
- """Import instances information from Openstack
20
-
21
- Raises:
22
- Exception: Raises exception if fetching server failed
23
-
24
- Returns:
25
- list[Instance]: _description_
26
- """
27
-
15
+ def import_images(self) -> Generator[Image, None, None]:
28
16
  logger.info(f"Importing images for {self.connection.auth['auth_url']}")
29
-
30
17
  try:
18
+ os_image_iterator = self.connection.list_images(show_all=True)
19
+
20
+ for os_image in os_image_iterator:
21
+ yield self._get_image_info(os_image)
31
22
 
32
- os_images: list[OSImage] = list(self.connection.list_images(show_all=True))
33
23
  except Exception as e:
34
- raise Exception(
35
- f"Can not fetch images for {self.connection.auth['auth_url']}"
36
- ) from e
24
+ logger.error(f"Cannot fetch images for {self.connection.auth['auth_url']}: {e}")
25
+ return
37
26
 
38
- images: list[OSImage] = []
27
+ logger.info(f"Finished importing images for {self.connection.auth['auth_url']}")
39
28
 
40
- with concurrent.futures.ThreadPoolExecutor() as executor:
41
- futures = [
42
- executor.submit(self._get_image_info, image) for image in os_images
43
- ]
44
- for future in concurrent.futures.as_completed(futures):
45
- images.append(future.result())
46
-
47
- logger.info(f"Imported images for {self.connection.auth['auth_url']}")
48
-
49
- return images
50
29
 
51
30
  def _get_image_info(self, os_image: OSImage) -> Image:
31
+ properties = os_image.properties or {}
32
+ properties.pop("owner_specified.openstack.md5", None)
33
+ properties.pop("owner_specified.openstack.sha256", None)
34
+ properties.pop("owner_specified.openstack.object", None)
35
+ properties.pop("stores", None)
52
36
 
53
- try:
54
- properties: dict = os_image.properties
55
-
56
- properties.pop("owner_specified.openstack.md5", None)
57
- properties.pop("owner_specified.openstack.sha256", None)
58
- properties.pop("owner_specified.openstack.object", None)
59
- properties.pop("stores", None)
60
- except Exception as e:
61
- logger.warn(f"properties for {os_image.id} is None")
62
-
63
- image = Image(
37
+ return Image(
64
38
  image_id=os_image.id,
65
39
  disk_format=os_image.disk_format,
66
40
  min_disk=os_image.min_disk,
67
41
  min_ram=os_image.min_ram,
68
42
  image_name=os_image.name,
69
43
  owner=os_image.owner,
70
- properties=os_image.properties,
44
+ properties=properties,
71
45
  protected=os_image.is_protected,
72
46
  status=os_image.status,
73
47
  os_distro=os_image.os_distro,
@@ -77,5 +51,3 @@ class OpenStackImageImporter(ImageImporter):
77
51
  created_at=os_image.created_at,
78
52
  updated_at=os_image.updated_at,
79
53
  )
80
-
81
- return image
@@ -1,9 +1,8 @@
1
1
  from abc import ABC, abstractmethod
2
-
2
+ from typing import Generator
3
3
  from osi_dump.model.network import Network
4
4
 
5
-
6
5
  class NetworkImporter(ABC):
7
6
  @abstractmethod
8
- def import_networks(self) -> list[Network]:
9
- pass
7
+ def import_networks(self) -> Generator[Network, None, None]:
8
+ pass
@@ -1,59 +1,33 @@
1
1
  import logging
2
-
3
- import concurrent
4
-
2
+ from typing import Generator
5
3
  from openstack.network.v2.network import Network as OSNetwork
6
4
  from openstack.network.v2.subnet import Subnet as OSSubnet
7
-
8
5
  from openstack.connection import Connection
9
6
 
10
7
  from osi_dump.importer.network.network_importer import NetworkImporter
11
8
  from osi_dump.model.network import Network
12
9
 
13
-
14
10
  logger = logging.getLogger(__name__)
15
11
 
16
-
17
12
  class OpenStackNetworkImporter(NetworkImporter):
18
13
  def __init__(self, connection: Connection):
19
14
  self.connection = connection
20
15
 
21
- def import_networks(self) -> list[Network]:
22
- """Import networks information from Openstack
23
-
24
- Raises:
25
- Exception: Raises exception if fetching networks failed
26
-
27
- Returns:
28
- list[Network]: _description_
29
- """
30
-
16
+ def import_networks(self) -> Generator[Network, None, None]:
17
+ logger.info(f"Importing networks for {self.connection.auth['auth_url']}")
31
18
  try:
32
- os_networks: list[OSNetwork] = list(self.connection.list_networks())
33
- except Exception as e:
34
- raise Exception(
35
- f"Can not fetch hypervisor for {self.connection.auth['auth_url']}"
36
- ) from e
37
-
38
- networks: list[Network] = []
19
+ network_iterator = self.connection.list_networks()
39
20
 
40
- with concurrent.futures.ThreadPoolExecutor() as executor:
41
- futures = [
42
- executor.submit(self._get_network_info, network)
43
- for network in os_networks
44
- ]
45
- for future in concurrent.futures.as_completed(futures):
46
- networks.append(future.result())
47
-
48
- logger.info(f"Imported networks for {self.connection.auth['auth_url']}")
49
-
50
- return networks
21
+ for network in network_iterator:
22
+ yield self._get_network_info(network)
51
23
 
24
+ except Exception as e:
25
+ logger.error(f"Cannot fetch networks for {self.connection.auth['auth_url']}: {e}")
26
+ return
52
27
 
53
- def _get_network_info(
54
- self, network: OSNetwork,
55
- ) -> Network:
28
+ logger.info(f"Finished importing networks for {self.connection.auth['auth_url']}")
56
29
 
30
+ def _get_network_info(self, network: OSNetwork) -> Network:
57
31
  subnets = self._get_subnets_info(subnet_ids=network.subnet_ids)
58
32
 
59
33
  return Network(
@@ -72,23 +46,20 @@ class OpenStackNetworkImporter(NetworkImporter):
72
46
  subnets=subnets
73
47
  )
74
48
 
75
-
76
49
  def _get_subnets_info(self, subnet_ids: list[str]) -> list[dict]:
77
50
  subnets = []
51
+ if not subnet_ids:
52
+ return subnets
78
53
 
79
54
  for subnet_id in subnet_ids:
80
- os_subnet: OSSubnet = self.connection.get_subnet(name_or_id=subnet_id)
81
-
82
- if not os_subnet:
83
- continue
55
+ try:
56
+ os_subnet: OSSubnet = self.connection.get_subnet(subnet_id)
57
+ if os_subnet:
58
+ subnets.append({
59
+ "id": os_subnet.id,
60
+ "cidr": os_subnet.cidr
61
+ })
62
+ except Exception as e:
63
+ logger.warning(f"Could not get info for subnet {subnet_id}: {e}")
84
64
 
85
- subnets.append({
86
- "id": os_subnet.id,
87
- "cidr": os_subnet.cidr
88
- })
89
-
90
- return subnets
91
-
92
-
93
-
94
-
65
+ return subnets
@@ -1,7 +1,5 @@
1
1
  import logging
2
-
3
- import concurrent
4
-
2
+ from typing import Generator
5
3
  from openstack.connection import Connection
6
4
  from openstack.identity.v3.project import Project as OSProject
7
5
  from openstack.load_balancer.v2.load_balancer import LoadBalancer as OSLoadBalancer
@@ -9,101 +7,67 @@ from openstack.load_balancer.v2.load_balancer import LoadBalancer as OSLoadBalan
9
7
  from osi_dump.importer.project.project_importer import ProjectImporter
10
8
  from osi_dump.model.project import Project
11
9
  import osi_dump.api.octavia as octavia_api
12
- logger = logging.getLogger(__name__)
13
10
 
11
+ logger = logging.getLogger(__name__)
14
12
 
15
13
  class OpenStackProjectImporter(ProjectImporter):
16
14
  def __init__(self, connection: Connection):
17
15
  self.connection = connection
18
16
 
19
- def import_projects(self) -> list[Project]:
20
- """Import projects information from Openstack
21
-
22
- Raises:
23
- Exception: Raises exception if fetching project failed
24
-
25
- Returns:
26
- list[Instance]: _description_
27
- """
28
-
29
- logger.info(f"Importing projects for {self.connection.auth['auth_url']}")
17
+ def import_projects(self) -> Generator[Project, None, None]:
18
+ project_lb_dict = {}
19
+ logger.info(f"Pre-caching load balancers for project count on {self.connection.auth['auth_url']}")
30
20
  try:
31
- osload_balancers: list[OSLoadBalancer] = octavia_api.get_load_balancers(
32
- connection=self.connection
33
- )
21
+ osload_balancers = octavia_api.get_load_balancers(connection=self.connection)
22
+ if osload_balancers:
23
+ for lb in osload_balancers:
24
+ project_id = lb.get("project_id")
25
+ if project_id:
26
+ project_lb_dict[project_id] = project_lb_dict.get(project_id, 0) + 1
34
27
  except Exception as e:
35
- raise Exception(
36
- f"Can not fetch load_balancers for {self.connection.auth['auth_url']} {e}"
37
- ) from e
38
-
39
- project_lb_dict = {}
40
-
41
- for osload_balancer in osload_balancers:
42
- if project_lb_dict.get(osload_balancer["project_id"]):
43
- project_lb_dict[osload_balancer["project_id"]] += 1
44
- else:
45
- project_lb_dict[osload_balancer["project_id"]] = 1
28
+ logger.warning(f"Could not pre-cache load balancers for project count: {e}")
46
29
 
30
+ logger.info(f"Importing projects for {self.connection.auth['auth_url']}")
47
31
  try:
48
- osprojects: list[OSProject] = list(self.connection.identity.projects())
32
+ project_iterator = self.connection.identity.projects()
33
+ for project in project_iterator:
34
+ yield self._get_project_info(project, project_lb_dict)
49
35
  except Exception as e:
50
- raise Exception(
51
- f"Can not fetch projects for {self.connection.auth['auth_url']}"
52
- ) from e
53
-
54
- projects: list[Project] = []
55
-
56
- with concurrent.futures.ThreadPoolExecutor() as executor:
57
- futures = [
58
- executor.submit(self._get_project_info, project, project_lb_dict)
59
- for project in osprojects
60
- ]
61
- for future in concurrent.futures.as_completed(futures):
62
- projects.append(future.result())
63
-
64
- logger.info(f"Imported projects for {self.connection.auth['auth_url']}")
65
-
66
- return projects
36
+ logger.error(f"Cannot fetch projects for {self.connection.auth['auth_url']}: {e}")
37
+ return
38
+
39
+ logger.info(f"Finished importing projects for {self.connection.auth['auth_url']}")
67
40
 
68
41
  def _get_project_info(self, project: OSProject, project_lb_dict: dict) -> Project:
69
-
70
- usage_instance=None
71
- quota_instance=None
72
- usage_ram=None
73
- quota_ram=None
74
- usage_vcpu=None
75
- quota_vcpu=None
42
+ usage_instance, quota_instance = None, None
43
+ usage_ram, quota_ram = None, None
44
+ usage_vcpu, quota_vcpu = None, None
45
+ usage_volume, quota_volume = None, None
46
+ usage_snapshot, quota_snapshot = None, None
47
+ usage_storage, quota_storage = None, None
76
48
 
77
49
  try:
78
- compute_quotas = self.connection.compute.get_quota_set(
79
- project.id, usage=True
80
- )
81
-
82
- usage_instance=compute_quotas.usage["instances"]
83
- quota_instance=compute_quotas.instances
84
- usage_ram=compute_quotas.usage["ram"]
85
- quota_ram=compute_quotas.ram
86
- usage_vcpu=compute_quotas.usage["cores"]
87
- quota_vcpu=compute_quotas.cores
50
+ compute_quotas = self.connection.compute.get_quota_set(project.id, usage=True)
51
+ if compute_quotas and compute_quotas.usage:
52
+ usage_instance = compute_quotas.usage.get("instances")
53
+ quota_instance = compute_quotas.instances
54
+ usage_ram = compute_quotas.usage.get("ram")
55
+ quota_ram = compute_quotas.ram
56
+ usage_vcpu = compute_quotas.usage.get("cores")
57
+ quota_vcpu = compute_quotas.cores
88
58
  except Exception as e:
89
59
  logger.warning(f"Get compute quotas failed for {project.id} error: {e}")
90
60
 
91
- usage_volume=None
92
- quota_volume=None
93
- usage_snapshot=None
94
- quota_snapshot=None
95
- usage_storage=None
96
- quota_storage=None
61
+ # Lấy thông tin storage quotas
97
62
  try:
98
- storage_quotas = self.connection.block_storage.get_quota_set(
99
- project.id, usage=True
100
- )
101
- usage_volume=storage_quotas.usage["volumes"]
102
- quota_volume=storage_quotas.volumes
103
- usage_snapshot=storage_quotas.usage["snapshots"]
104
- quota_snapshot=storage_quotas.snapshots
105
- usage_storage=storage_quotas.usage["gigabytes"]
106
- quota_storage=storage_quotas.gigabytes
63
+ storage_quotas = self.connection.block_storage.get_quota_set(project.id, usage=True)
64
+ if storage_quotas and storage_quotas.usage:
65
+ usage_volume = storage_quotas.usage.get("volumes")
66
+ quota_volume = storage_quotas.volumes
67
+ usage_snapshot = storage_quotas.usage.get("snapshots")
68
+ quota_snapshot = storage_quotas.snapshots
69
+ usage_storage = storage_quotas.usage.get("gigabytes")
70
+ quota_storage = storage_quotas.gigabytes
107
71
  except Exception as e:
108
72
  logger.warning(f"Get storage quotas failed for {project.id} error: {e}")
109
73
 
@@ -116,7 +80,7 @@ class OpenStackProjectImporter(ProjectImporter):
116
80
 
117
81
  lb_count = project_lb_dict.get(project.id)
118
82
 
119
- project_ret = Project(
83
+ return Project(
120
84
  project_id=project.id,
121
85
  project_name=project.name,
122
86
  domain_id=project.domain_id,
@@ -136,6 +100,4 @@ class OpenStackProjectImporter(ProjectImporter):
136
100
  usage_storage=usage_storage,
137
101
  quota_storage=quota_storage,
138
102
  load_balancer_count=lb_count
139
- )
140
-
141
- return project_ret
103
+ )