osi-dump 0.1.2__py3-none-any.whl → 0.1.2.1__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 (42) hide show
  1. osi_dump/api/octavia.py +17 -0
  2. osi_dump/batch_handler/flavor_batch_handler.py +51 -0
  3. osi_dump/batch_handler/image_batch_handler.py +51 -0
  4. osi_dump/batch_handler/load_balancer_batch_handler.py +61 -0
  5. osi_dump/batch_handler/role_assignment_batch_handler.py +61 -0
  6. osi_dump/cli.py +57 -0
  7. osi_dump/exporter/flavor/__init__.py +0 -0
  8. osi_dump/exporter/flavor/excel_flavor_exporter.py +30 -0
  9. osi_dump/exporter/flavor/flavor_exporter.py +7 -0
  10. osi_dump/exporter/image/__init__.py +0 -0
  11. osi_dump/exporter/image/excel_image_exporter.py +28 -0
  12. osi_dump/exporter/image/image_exporter.py +7 -0
  13. osi_dump/exporter/load_balancer/__init__.py +0 -0
  14. osi_dump/exporter/load_balancer/excel_load_balancer_exporter.py +33 -0
  15. osi_dump/exporter/load_balancer/load_balancer_exporter.py +7 -0
  16. osi_dump/exporter/role_assignment/__init__.py +0 -0
  17. osi_dump/exporter/role_assignment/excel_role_assignment_exporter.py +35 -0
  18. osi_dump/exporter/role_assignment/role_assignment_exporter.py +7 -0
  19. osi_dump/importer/flavor/__init__.py +0 -0
  20. osi_dump/importer/flavor/flavor_importer.py +9 -0
  21. osi_dump/importer/flavor/openstack_flavor_importer.py +64 -0
  22. osi_dump/importer/hypervisor/openstack_hypervisor_importer.py +10 -1
  23. osi_dump/importer/image/__init__.py +0 -0
  24. osi_dump/importer/image/image_importer.py +9 -0
  25. osi_dump/importer/image/openstack_image_importer.py +77 -0
  26. osi_dump/importer/load_balancer/__init__.py +0 -0
  27. osi_dump/importer/load_balancer/load_balancer_importer.py +9 -0
  28. osi_dump/importer/load_balancer/openstack_load_balancer_importer.py +65 -0
  29. osi_dump/importer/project/openstack_project_importer.py +6 -6
  30. osi_dump/importer/role_assignment/__init__.py +0 -0
  31. osi_dump/importer/role_assignment/openstack_role_assignment_importer.py +83 -0
  32. osi_dump/importer/role_assignment/role_assignment_importer.py +9 -0
  33. osi_dump/model/flavor.py +20 -0
  34. osi_dump/model/hypervisor.py +2 -0
  35. osi_dump/model/image.py +26 -0
  36. osi_dump/model/load_balancer.py +17 -0
  37. osi_dump/model/role_assignment.py +17 -0
  38. {osi_dump-0.1.2.dist-info → osi_dump-0.1.2.1.dist-info}/METADATA +1 -1
  39. {osi_dump-0.1.2.dist-info → osi_dump-0.1.2.1.dist-info}/RECORD +42 -9
  40. {osi_dump-0.1.2.dist-info → osi_dump-0.1.2.1.dist-info}/WHEEL +1 -1
  41. {osi_dump-0.1.2.dist-info → osi_dump-0.1.2.1.dist-info}/entry_points.txt +0 -0
  42. {osi_dump-0.1.2.dist-info → osi_dump-0.1.2.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,17 @@
1
+ from openstack.connection import Connection
2
+ from openstack.identity.v3.service import Service
3
+
4
+
5
+ def get_amphorae(connection: Connection, load_balancer_id: str) -> str | None:
6
+
7
+ octavia_endpoint = connection.endpoint_for(
8
+ service_type="octavia", interface="public"
9
+ )
10
+
11
+ url = f"{octavia_endpoint}/v2/octavia/amphorae"
12
+
13
+ response = connection.session.get(url)
14
+
15
+ data = response.json()
16
+
17
+ return data["usages"]
@@ -0,0 +1,51 @@
1
+ import logging
2
+
3
+ from openstack.connection import Connection
4
+
5
+ from osi_dump.exporter.flavor.flavor_exporter import FlavorExporter
6
+ from osi_dump.exporter.flavor.excel_flavor_exporter import (
7
+ ExcelFlavorExporter,
8
+ )
9
+
10
+ from osi_dump.importer.flavor.flavor_importer import FlavorImporter
11
+ from osi_dump.importer.flavor.openstack_flavor_importer import (
12
+ OpenStackFlavorImporter,
13
+ )
14
+
15
+
16
+ from osi_dump import util
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class FlavorBatchHandler:
22
+ def __init__(self):
23
+ self._importer_exporter_list: list[tuple[FlavorImporter, FlavorExporter]] = []
24
+
25
+ def add_importer_exporter_from_openstack_connections(
26
+ self, connections: list[Connection], output_file: str
27
+ ):
28
+ for connection in connections:
29
+ importer = OpenStackFlavorImporter(connection)
30
+
31
+ sheet_name = f"{util.extract_hostname(connection.auth['auth_url'])}-flavor"
32
+ exporter = ExcelFlavorExporter(
33
+ sheet_name=sheet_name, output_file=output_file
34
+ )
35
+
36
+ self.add_importer_exporter(importer=importer, exporter=exporter)
37
+
38
+ def add_importer_exporter(self, importer: FlavorImporter, exporter: FlavorExporter):
39
+ self._importer_exporter_list.append((importer, exporter))
40
+
41
+ def process(self):
42
+
43
+ for importer, exporter in self._importer_exporter_list:
44
+ try:
45
+
46
+ flavors = importer.import_flavors()
47
+
48
+ exporter.export_flavors(flavors=flavors)
49
+ except Exception as e:
50
+ logger.warning(e)
51
+ logger.warning("Skipping...")
@@ -0,0 +1,51 @@
1
+ import logging
2
+
3
+ from openstack.connection import Connection
4
+
5
+ from osi_dump.exporter.image.image_exporter import ImageExporter
6
+ from osi_dump.exporter.image.excel_image_exporter import (
7
+ ExcelImageExporter,
8
+ )
9
+
10
+ from osi_dump.importer.image.image_importer import ImageImporter
11
+ from osi_dump.importer.image.openstack_image_importer import (
12
+ OpenStackImageImporter,
13
+ )
14
+
15
+
16
+ from osi_dump import util
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class ImageBatchHandler:
22
+ def __init__(self):
23
+ self._importer_exporter_list: list[tuple[ImageImporter, ImageExporter]] = []
24
+
25
+ def add_importer_exporter_from_openstack_connections(
26
+ self, connections: list[Connection], output_file: str
27
+ ):
28
+ for connection in connections:
29
+ importer = OpenStackImageImporter(connection)
30
+
31
+ sheet_name = f"{util.extract_hostname(connection.auth['auth_url'])}-image"
32
+ exporter = ExcelImageExporter(
33
+ sheet_name=sheet_name, output_file=output_file
34
+ )
35
+
36
+ self.add_importer_exporter(importer=importer, exporter=exporter)
37
+
38
+ def add_importer_exporter(self, importer: ImageImporter, exporter: ImageExporter):
39
+ self._importer_exporter_list.append((importer, exporter))
40
+
41
+ def process(self):
42
+
43
+ for importer, exporter in self._importer_exporter_list:
44
+ try:
45
+
46
+ images = importer.import_images()
47
+
48
+ exporter.export_images(images=images)
49
+ except Exception as e:
50
+ logger.warning(e)
51
+ logger.warning("Skipping...")
@@ -0,0 +1,61 @@
1
+ import logging
2
+
3
+ from openstack.connection import Connection
4
+
5
+ from osi_dump.exporter.load_balancer.load_balancer_exporter import (
6
+ LoadBalancerExporter,
7
+ )
8
+ from osi_dump.exporter.load_balancer.excel_load_balancer_exporter import (
9
+ ExcelLoadBalancerExporter,
10
+ )
11
+
12
+ from osi_dump.importer.load_balancer.load_balancer_importer import (
13
+ LoadBalancerImporter,
14
+ )
15
+ from osi_dump.importer.load_balancer.openstack_load_balancer_importer import (
16
+ OpenStackLoadBalancerImporter,
17
+ )
18
+
19
+
20
+ from osi_dump import util
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ class LoadBalancerBatchHandler:
26
+ def __init__(self):
27
+ self._importer_exporter_list: list[
28
+ tuple[LoadBalancerImporter, LoadBalancerExporter]
29
+ ] = []
30
+
31
+ def add_importer_exporter_from_openstack_connections(
32
+ self, connections: list[Connection], output_file: str
33
+ ):
34
+ for connection in connections:
35
+ importer = OpenStackLoadBalancerImporter(connection)
36
+
37
+ sheet_name = (
38
+ f"{util.extract_hostname(connection.auth['auth_url'])}-load_balancer"
39
+ )
40
+ exporter = ExcelLoadBalancerExporter(
41
+ sheet_name=sheet_name, output_file=output_file
42
+ )
43
+
44
+ self.add_importer_exporter(importer=importer, exporter=exporter)
45
+
46
+ def add_importer_exporter(
47
+ self, importer: LoadBalancerImporter, exporter: LoadBalancerExporter
48
+ ):
49
+ self._importer_exporter_list.append((importer, exporter))
50
+
51
+ def process(self):
52
+
53
+ for importer, exporter in self._importer_exporter_list:
54
+ try:
55
+
56
+ load_balancers = importer.import_load_balancers()
57
+
58
+ exporter.export_load_balancers(load_balancers=load_balancers)
59
+ except Exception as e:
60
+ logger.warning(e)
61
+ logger.warning("Skipping...")
@@ -0,0 +1,61 @@
1
+ import logging
2
+
3
+ from openstack.connection import Connection
4
+
5
+ from osi_dump.exporter.role_assignment.role_assignment_exporter import (
6
+ RoleAssignmentExporter,
7
+ )
8
+ from osi_dump.exporter.role_assignment.excel_role_assignment_exporter import (
9
+ ExcelRoleAssignmentExporter,
10
+ )
11
+
12
+ from osi_dump.importer.role_assignment.role_assignment_importer import (
13
+ RoleAssignmentImporter,
14
+ )
15
+ from osi_dump.importer.role_assignment.openstack_role_assignment_importer import (
16
+ OpenStackRoleAssignmentImporter,
17
+ )
18
+
19
+
20
+ from osi_dump import util
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ class RoleAssignmentBatchHandler:
26
+ def __init__(self):
27
+ self._importer_exporter_list: list[
28
+ tuple[RoleAssignmentImporter, RoleAssignmentExporter]
29
+ ] = []
30
+
31
+ def add_importer_exporter_from_openstack_connections(
32
+ self, connections: list[Connection], output_file: str
33
+ ):
34
+ for connection in connections:
35
+ importer = OpenStackRoleAssignmentImporter(connection)
36
+
37
+ sheet_name = (
38
+ f"{util.extract_hostname(connection.auth['auth_url'])}-role_assignment"
39
+ )
40
+ exporter = ExcelRoleAssignmentExporter(
41
+ sheet_name=sheet_name, output_file=output_file
42
+ )
43
+
44
+ self.add_importer_exporter(importer=importer, exporter=exporter)
45
+
46
+ def add_importer_exporter(
47
+ self, importer: RoleAssignmentImporter, exporter: RoleAssignmentExporter
48
+ ):
49
+ self._importer_exporter_list.append((importer, exporter))
50
+
51
+ def process(self):
52
+
53
+ for importer, exporter in self._importer_exporter_list:
54
+ try:
55
+
56
+ role_assignments = importer.import_role_assignments()
57
+
58
+ exporter.export_role_assignments(role_assignments=role_assignments)
59
+ except Exception as e:
60
+ logger.warning(e)
61
+ logger.warning("Skipping...")
osi_dump/cli.py CHANGED
@@ -8,9 +8,16 @@ import typer
8
8
 
9
9
  from typing_extensions import Annotated
10
10
 
11
+ from osi_dump.batch_handler.load_balancer_batch_handler import LoadBalancerBatchHandler
12
+ from osi_dump.batch_handler.role_assignment_batch_handler import (
13
+ RoleAssignmentBatchHandler,
14
+ )
15
+
11
16
  app = typer.Typer()
12
17
 
13
18
 
19
+ from osi_dump.batch_handler.flavor_batch_handler import FlavorBatchHandler
20
+ from osi_dump.batch_handler.image_batch_handler import ImageBatchHandler
14
21
  from osi_dump.batch_handler.volume_batch_handler import VolumeBatchHandler
15
22
  from osi_dump.os_connection.get_connections import get_connections
16
23
 
@@ -76,6 +83,46 @@ def _hypervisor(connections, output_path: str):
76
83
  hypervisor_batch_handler.process()
77
84
 
78
85
 
86
+ def _image(connections, output_path: str):
87
+ image_batch_handler = ImageBatchHandler()
88
+
89
+ image_batch_handler.add_importer_exporter_from_openstack_connections(
90
+ connections, output_file=output_path
91
+ )
92
+
93
+ image_batch_handler.process()
94
+
95
+
96
+ def _flavor(connections, output_path: str):
97
+ flavor_batch_handler = FlavorBatchHandler()
98
+
99
+ flavor_batch_handler.add_importer_exporter_from_openstack_connections(
100
+ connections, output_file=output_path
101
+ )
102
+
103
+ flavor_batch_handler.process()
104
+
105
+
106
+ def _role_assignment(connections, output_path: str):
107
+ _role_assignment_batch_handler = RoleAssignmentBatchHandler()
108
+
109
+ _role_assignment_batch_handler.add_importer_exporter_from_openstack_connections(
110
+ connections, output_file=output_path
111
+ )
112
+
113
+ _role_assignment_batch_handler.process()
114
+
115
+
116
+ def _load_balancer(connections, output_path: str):
117
+ _load_balancer_batch_handler = LoadBalancerBatchHandler()
118
+
119
+ _load_balancer_batch_handler.add_importer_exporter_from_openstack_connections(
120
+ connections, output_file=output_path
121
+ )
122
+
123
+ _load_balancer_batch_handler.process()
124
+
125
+
79
126
  def inner_main(file_path: str, output_path: str):
80
127
 
81
128
  logger = logging.getLogger(__name__)
@@ -92,6 +139,13 @@ def inner_main(file_path: str, output_path: str):
92
139
 
93
140
  _project(connections=connections, output_path=output_path)
94
141
 
142
+ _image(connections=connections, output_path=output_path)
143
+
144
+ _flavor(connections=connections, output_path=output_path)
145
+
146
+ _role_assignment(connections=connections, output_path=output_path)
147
+
148
+ _load_balancer(connections=connections, output_path=output_path)
95
149
  util.excel_autosize_column(output_path)
96
150
 
97
151
  util.excel_sort_sheet(output_path)
@@ -141,6 +195,9 @@ Path of the output file, will override if file already exists
141
195
  level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
142
196
  )
143
197
 
198
+ # Suppress pool limit warning will investigate later
199
+ logging.getLogger("urllib3").propagate = False
200
+
144
201
  logger = logging.getLogger(__name__)
145
202
 
146
203
  if util.validate_dir_path(file_path=output_path) is False:
File without changes
@@ -0,0 +1,30 @@
1
+ import logging
2
+
3
+
4
+ import pandas as pd
5
+
6
+
7
+ from osi_dump.exporter.flavor.flavor_exporter import FlavorExporter
8
+
9
+ from osi_dump.model.flavor import Flavor
10
+
11
+ from osi_dump import util
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class ExcelFlavorExporter(FlavorExporter):
17
+ def __init__(self, sheet_name: str, output_file: str):
18
+ self.sheet_name = sheet_name
19
+ self.output_file = output_file
20
+
21
+ def export_flavors(self, flavors: list[Flavor]):
22
+ df = pd.json_normalize([flavor.model_dump() for flavor in flavors])
23
+
24
+ logger.info(f"Exporting flavors for {self.sheet_name}")
25
+ try:
26
+ util.export_data_excel(self.output_file, sheet_name=self.sheet_name, df=df)
27
+
28
+ logger.info(f"Exported flavors for {self.sheet_name}")
29
+ except Exception as e:
30
+ logger.warning(f"Exporting floating ips for {self.sheet_name} error: {e}")
@@ -0,0 +1,7 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class FlavorExporter(ABC):
5
+ @abstractmethod
6
+ def export_flavors(self, flavors, output_file: str):
7
+ pass
File without changes
@@ -0,0 +1,28 @@
1
+ import pandas as pd
2
+
3
+ import logging
4
+
5
+
6
+ from osi_dump import util
7
+ from osi_dump.exporter.image.image_exporter import ImageExporter
8
+
9
+ from osi_dump.model.image import Image
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class ExcelImageExporter(ImageExporter):
15
+ def __init__(self, sheet_name: str, output_file: str):
16
+ self.sheet_name = sheet_name
17
+ self.output_file = output_file
18
+
19
+ def export_images(self, images: list[Image]):
20
+ df = pd.json_normalize([image.model_dump() for image in images])
21
+
22
+ logger.info(f"Exporting images for {self.sheet_name}")
23
+ try:
24
+ util.export_data_excel(self.output_file, sheet_name=self.sheet_name, df=df)
25
+
26
+ logger.info(f"Exported images for {self.sheet_name}")
27
+ except Exception as e:
28
+ logger.warning(f"Exporting images for {self.sheet_name} error: {e}")
@@ -0,0 +1,7 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class ImageExporter(ABC):
5
+ @abstractmethod
6
+ def export_images(self, images, output_file: str):
7
+ pass
File without changes
@@ -0,0 +1,33 @@
1
+ import pandas as pd
2
+
3
+ import logging
4
+
5
+
6
+ from osi_dump import util
7
+
8
+ from osi_dump.exporter.load_balancer.load_balancer_exporter import (
9
+ LoadBalancerExporter,
10
+ )
11
+
12
+ from osi_dump.model.load_balancer import LoadBalancer
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class ExcelLoadBalancerExporter(LoadBalancerExporter):
18
+ def __init__(self, sheet_name: str, output_file: str):
19
+ self.sheet_name = sheet_name
20
+ self.output_file = output_file
21
+
22
+ def export_load_balancers(self, load_balancers: list[LoadBalancer]):
23
+ df = pd.json_normalize(
24
+ [load_balancer.model_dump() for load_balancer in load_balancers]
25
+ )
26
+
27
+ logger.info(f"Exporting load_balancers for {self.sheet_name}")
28
+ try:
29
+ util.export_data_excel(self.output_file, sheet_name=self.sheet_name, df=df)
30
+
31
+ logger.info(f"Exported load_balancers for {self.sheet_name}")
32
+ except Exception as e:
33
+ logger.warning(f"Exporting load_balancers for {self.sheet_name} error: {e}")
@@ -0,0 +1,7 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class LoadBalancerExporter(ABC):
5
+ @abstractmethod
6
+ def export_load_balancers(self, load_balancers, output_file: str):
7
+ pass
File without changes
@@ -0,0 +1,35 @@
1
+ import pandas as pd
2
+
3
+ import logging
4
+
5
+
6
+ from osi_dump import util
7
+
8
+ from osi_dump.exporter.role_assignment.role_assignment_exporter import (
9
+ RoleAssignmentExporter,
10
+ )
11
+
12
+ from osi_dump.model.role_assignment import RoleAssignment
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class ExcelRoleAssignmentExporter(RoleAssignmentExporter):
18
+ def __init__(self, sheet_name: str, output_file: str):
19
+ self.sheet_name = sheet_name
20
+ self.output_file = output_file
21
+
22
+ def export_role_assignments(self, role_assignments: list[RoleAssignment]):
23
+ df = pd.json_normalize(
24
+ [role_assignment.model_dump() for role_assignment in role_assignments]
25
+ )
26
+
27
+ logger.info(f"Exporting role_assignments for {self.sheet_name}")
28
+ try:
29
+ util.export_data_excel(self.output_file, sheet_name=self.sheet_name, df=df)
30
+
31
+ logger.info(f"Exported role_assignments for {self.sheet_name}")
32
+ except Exception as e:
33
+ logger.warning(
34
+ f"Exporting role_assignments for {self.sheet_name} error: {e}"
35
+ )
@@ -0,0 +1,7 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class RoleAssignmentExporter(ABC):
5
+ @abstractmethod
6
+ def export_role_assignments(self, role_assignments, output_file: str):
7
+ pass
File without changes
@@ -0,0 +1,9 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from osi_dump.model.flavor import Flavor
4
+
5
+
6
+ class FlavorImporter(ABC):
7
+ @abstractmethod
8
+ def import_flavors(self) -> list[Flavor]:
9
+ pass
@@ -0,0 +1,64 @@
1
+ import logging
2
+
3
+ import concurrent
4
+
5
+ from openstack.connection import Connection
6
+ from openstack.compute.v2.flavor import Flavor as OSFlavor
7
+
8
+ from osi_dump.importer.flavor.flavor_importer import FlavorImporter
9
+ from osi_dump.model.flavor import Flavor
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class OpenStackFlavorImporter(FlavorImporter):
15
+ def __init__(self, connection: Connection):
16
+ self.connection = connection
17
+
18
+ def import_flavors(self) -> list[Flavor]:
19
+ """Import flavors information from Openstack
20
+
21
+ Raises:
22
+ Exception: Raises exception if fetching flavor failed
23
+
24
+ Returns:
25
+ list[Instance]: _description_
26
+ """
27
+
28
+ logger.info(f"Importing flavors for {self.connection.auth['auth_url']}")
29
+
30
+ try:
31
+ osflavors: list[OSFlavor] = list(self.connection.list_flavors())
32
+ except Exception as e:
33
+ raise Exception(
34
+ f"Can not fetch flavors for {self.connection.auth['auth_url']}"
35
+ ) from e
36
+
37
+ flavors: list[Flavor] = []
38
+
39
+ with concurrent.futures.ThreadPoolExecutor() as executor:
40
+ futures = [
41
+ executor.submit(self._get_flavor_info, osflavor)
42
+ for osflavor in osflavors
43
+ ]
44
+ for future in concurrent.futures.as_completed(futures):
45
+ flavors.append(future.result())
46
+
47
+ logger.info(f"Imported flavors for {self.connection.auth['auth_url']}")
48
+
49
+ return flavors
50
+
51
+ def _get_flavor_info(self, flavor: OSFlavor) -> Flavor:
52
+
53
+ ret_flavor = Flavor(
54
+ flavor_id=flavor.id,
55
+ flavor_name=flavor.name,
56
+ ram=flavor.ram,
57
+ vcpus=flavor.vcpus,
58
+ disk=flavor.disk,
59
+ swap=flavor.swap,
60
+ public=flavor.is_public,
61
+ properties=flavor.extra_specs,
62
+ )
63
+
64
+ return ret_flavor
@@ -33,7 +33,9 @@ class OpenStackHypervisorImporter(HypervisorImporter):
33
33
  logger.info(f"Importing hypervisors for {self.connection.auth['auth_url']}")
34
34
 
35
35
  try:
36
- oshypervisors: list[OSHypervisor] = list(self.connection.list_hypervisors())
36
+ oshypervisors: list[OSHypervisor] = list(
37
+ self.connection.compute.hypervisors(details=True)
38
+ )
37
39
  except Exception as e:
38
40
  raise Exception(
39
41
  f"Can not fetch hypervisor for {self.connection.auth['auth_url']}"
@@ -63,6 +65,12 @@ class OpenStackHypervisorImporter(HypervisorImporter):
63
65
  )
64
66
  )
65
67
 
68
+ servers = list(
69
+ self.connection.compute.servers(
70
+ details=False, all_project=True, hypervisor=hypervisor.id
71
+ )
72
+ )
73
+
66
74
  usage_data = get_usage(self.connection, resource_provider_id=hypervisor.id)
67
75
 
68
76
  vcpu = rpi[0]
@@ -81,6 +89,7 @@ class OpenStackHypervisorImporter(HypervisorImporter):
81
89
  vcpus_usage=usage_data["VCPU"],
82
90
  memory_usage=usage_data["MEMORY_MB"],
83
91
  local_disk_usage=usage_data["DISK_GB"],
92
+ vm_count=len(servers),
84
93
  )
85
94
 
86
95
  return ret_hypervisor
File without changes
@@ -0,0 +1,9 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from osi_dump.model.image import Image
4
+
5
+
6
+ class ImageImporter(ABC):
7
+ @abstractmethod
8
+ def import_images(self) -> list[Image]:
9
+ pass
@@ -0,0 +1,77 @@
1
+ import logging
2
+
3
+ import concurrent
4
+
5
+ from openstack.connection import Connection
6
+ from openstack.image.v2.image import Image as OSImage
7
+
8
+ from osi_dump.importer.image.image_importer import ImageImporter
9
+ from osi_dump.model.image import Image
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class OpenStackImageImporter(ImageImporter):
15
+ def __init__(self, connection: Connection):
16
+ self.connection = connection
17
+
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
+
28
+ logger.info(f"Importing images for {self.connection.auth['auth_url']}")
29
+
30
+ try:
31
+
32
+ os_images: list[OSImage] = list(self.connection.list_images(show_all=True))
33
+ except Exception as e:
34
+ raise Exception(
35
+ f"Can not fetch images for {self.connection.auth['auth_url']}"
36
+ ) from e
37
+
38
+ images: list[OSImage] = []
39
+
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
+
51
+ def _get_image_info(self, os_image: OSImage) -> Image:
52
+
53
+ properties: dict = os_image.properties
54
+
55
+ properties.pop("owner_specified.openstack.md5", None)
56
+ properties.pop("owner_specified.openstack.sha256", None)
57
+ properties.pop("owner_specified.openstack.object", None)
58
+ properties.pop("stores", None)
59
+
60
+ image = Image(
61
+ image_id=os_image.id,
62
+ disk_format=os_image.disk_format,
63
+ min_disk=os_image.min_disk,
64
+ min_ram=os_image.min_ram,
65
+ image_name=os_image.name,
66
+ owner=os_image.owner,
67
+ properties=os_image.properties,
68
+ protected=os_image.is_protected,
69
+ status=os_image.status,
70
+ size=os_image.size,
71
+ virtual_size=os_image.virtual_size,
72
+ visibility=os_image.visibility,
73
+ created_at=os_image.created_at,
74
+ updated_at=os_image.updated_at,
75
+ )
76
+
77
+ return image
File without changes
@@ -0,0 +1,9 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from osi_dump.model.load_balancer import LoadBalancer
4
+
5
+
6
+ class LoadBalancerImporter(ABC):
7
+ @abstractmethod
8
+ def import_load_balancers(self) -> list[LoadBalancer]:
9
+ pass
@@ -0,0 +1,65 @@
1
+ import logging
2
+
3
+ import concurrent
4
+
5
+ from openstack.connection import Connection
6
+
7
+ from openstack.load_balancer.v2.load_balancer import LoadBalancer as OSLoadBalancer
8
+
9
+ from osi_dump.importer.load_balancer.load_balancer_importer import (
10
+ LoadBalancerImporter,
11
+ )
12
+ from osi_dump.model.load_balancer import LoadBalancer
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class OpenStackLoadBalancerImporter(LoadBalancerImporter):
18
+ def __init__(self, connection: Connection):
19
+ self.connection = connection
20
+
21
+ def import_load_balancers(self) -> list[LoadBalancer]:
22
+ """Import load_balancers information from Openstack
23
+
24
+ Raises:
25
+ Exception: Raises exception if fetching load_balancer failed
26
+
27
+ Returns:
28
+ list[LoadBalancer]: _description_
29
+ """
30
+
31
+ logger.info(f"Importing load_balancers for {self.connection.auth['auth_url']}")
32
+
33
+ try:
34
+ osload_balancers: list[OSLoadBalancer] = list(
35
+ self.connection.network.load_balancers()
36
+ )
37
+ except Exception as e:
38
+ raise Exception(
39
+ f"Can not fetch load_balancers for {self.connection.auth['auth_url']}"
40
+ ) from e
41
+
42
+ load_balancers: list[LoadBalancer] = []
43
+
44
+ with concurrent.futures.ThreadPoolExecutor() as executor:
45
+ futures = [
46
+ executor.submit(self._get_load_balancer_info, load_balancer)
47
+ for load_balancer in osload_balancers
48
+ ]
49
+ for future in concurrent.futures.as_completed(futures):
50
+ load_balancers.append(future.result())
51
+
52
+ logger.info(f"Imported load_balancers for {self.connection.auth['auth_url']}")
53
+
54
+ return load_balancers
55
+
56
+ def _get_load_balancer_info(self, load_balancer: OSLoadBalancer) -> LoadBalancer:
57
+
58
+ load_balancer_ret = LoadBalancer(
59
+ id=load_balancer.id,
60
+ load_balancer_name=load_balancer.name,
61
+ status=load_balancer.operating_status,
62
+ project_id=load_balancer.project_id,
63
+ )
64
+
65
+ return load_balancer_ret
@@ -76,12 +76,12 @@ class OpenStackProjectImporter(ProjectImporter):
76
76
  quota_ram=compute_quotas.ram,
77
77
  usage_vcpu=compute_quotas.usage["cores"],
78
78
  quota_vcpu=compute_quotas.cores,
79
- usage_volume=storage_quotas.volumes,
80
- quota_volume=storage_quotas.usage["volumes"],
81
- usage_snapshot=storage_quotas.snapshots,
82
- quota_snapshot=storage_quotas.usage["snapshots"],
83
- usage_storage=storage_quotas.gigabytes,
84
- quota_storage=storage_quotas.usage["gigabytes"],
79
+ usage_volume=storage_quotas.usage["volumes"],
80
+ quota_volume=storage_quotas.volumes,
81
+ usage_snapshot=storage_quotas.usage["snapshots"],
82
+ quota_snapshot=storage_quotas.snapshots,
83
+ usage_storage=storage_quotas.usage["gigabytes"],
84
+ quota_storage=storage_quotas.gigabytes,
85
85
  )
86
86
 
87
87
  return project_ret
File without changes
@@ -0,0 +1,83 @@
1
+ import logging
2
+
3
+ import concurrent
4
+
5
+ from openstack.connection import Connection
6
+ from openstack.identity.v3.role_assignment import RoleAssignment as OSRoleAssignment
7
+
8
+ from osi_dump.importer.role_assignment.role_assignment_importer import (
9
+ RoleAssignmentImporter,
10
+ )
11
+ from osi_dump.model.role_assignment import RoleAssignment
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class OpenStackRoleAssignmentImporter(RoleAssignmentImporter):
17
+ def __init__(self, connection: Connection):
18
+ self.connection = connection
19
+
20
+ def import_role_assignments(self) -> list[RoleAssignment]:
21
+ """Import role_assignments information from Openstack
22
+
23
+ Raises:
24
+ Exception: Raises exception if fetching role_assignment failed
25
+
26
+ Returns:
27
+ list[RoleAssignment]: _description_
28
+ """
29
+
30
+ logger.info(
31
+ f"Importing role_assignments for {self.connection.auth['auth_url']}"
32
+ )
33
+
34
+ try:
35
+ osrole_assignments: list[OSRoleAssignment] = list(
36
+ self.connection.identity.role_assignments()
37
+ )
38
+ except Exception as e:
39
+ raise Exception(
40
+ f"Can not fetch role_assignments for {self.connection.auth['auth_url']}"
41
+ ) from e
42
+
43
+ role_assignments: list[RoleAssignment] = []
44
+
45
+ with concurrent.futures.ThreadPoolExecutor() as executor:
46
+ futures = [
47
+ executor.submit(self._get_role_assignment_info, role_assignment)
48
+ for role_assignment in osrole_assignments
49
+ ]
50
+ for future in concurrent.futures.as_completed(futures):
51
+ role_assignments.append(future.result())
52
+
53
+ logger.info(f"Imported role_assignments for {self.connection.auth['auth_url']}")
54
+
55
+ return role_assignments
56
+
57
+ def _get_role_assignment_info(
58
+ self, role_assignment: OSRoleAssignment
59
+ ) -> RoleAssignment:
60
+
61
+ user_name = None
62
+ role_name = None
63
+
64
+ try:
65
+ role_name = self.connection.identity.get_role(
66
+ role_assignment.role["id"]
67
+ ).name
68
+ user_name = self.connection.identity.get_user(
69
+ role_assignment.user["id"]
70
+ ).name
71
+
72
+ except Exception as e:
73
+ logger.warning("Can not get role name or user name")
74
+
75
+ role_assignment_ret = RoleAssignment(
76
+ user_id=role_assignment.user["id"],
77
+ user_name=user_name,
78
+ role_id=role_assignment.role["id"],
79
+ role_name=role_name,
80
+ scope=role_assignment.scope,
81
+ )
82
+
83
+ return role_assignment_ret
@@ -0,0 +1,9 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from osi_dump.model.role_assignment import RoleAssignment
4
+
5
+
6
+ class RoleAssignmentImporter(ABC):
7
+ @abstractmethod
8
+ def import_role_assignments(self) -> list[RoleAssignment]:
9
+ pass
@@ -0,0 +1,20 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict, ValidationError
4
+
5
+
6
+ class Flavor(BaseModel):
7
+ model_config = ConfigDict(strict=True)
8
+
9
+ flavor_id: str
10
+
11
+ flavor_name: str
12
+
13
+ properties: Optional[dict]
14
+
15
+ ram: int
16
+ vcpus: int
17
+ disk: int
18
+ swap: Optional[int]
19
+
20
+ public: bool
@@ -16,3 +16,5 @@ class Hypervisor(BaseModel):
16
16
 
17
17
  local_disk_usage: int
18
18
  local_disk_size: int
19
+
20
+ vm_count: int
@@ -0,0 +1,26 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict, ValidationError
4
+
5
+
6
+ class Image(BaseModel):
7
+ model_config = ConfigDict(strict=True)
8
+
9
+ image_id: str
10
+
11
+ disk_format: str
12
+ min_disk: int
13
+ min_ram: int
14
+ image_name: Optional[str]
15
+ owner: str
16
+
17
+ properties: Optional[dict]
18
+
19
+ protected: bool
20
+ status: str
21
+ size: int
22
+ virtual_size: int
23
+ visibility: str
24
+
25
+ created_at: str
26
+ updated_at: str
@@ -0,0 +1,17 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict, ValidationError
4
+
5
+
6
+ class LoadBalancer(BaseModel):
7
+ model_config = ConfigDict(strict=True)
8
+
9
+ id: str
10
+
11
+ load_balancer_name: Optional[str]
12
+
13
+ status: str
14
+
15
+ # amphora_id: Optional[str]
16
+
17
+ project_id: Optional[str]
@@ -0,0 +1,17 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict, ValidationError
4
+
5
+
6
+ class RoleAssignment(BaseModel):
7
+ model_config = ConfigDict(strict=True)
8
+
9
+ user_id: str
10
+
11
+ user_name: Optional[str]
12
+
13
+ role_id: str
14
+
15
+ role_name: Optional[str]
16
+
17
+ scope: Optional[dict]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: osi-dump
3
- Version: 0.1.2
3
+ Version: 0.1.2.1
4
4
  Summary: OpenStack instances information dump tool
5
5
  Author: TVKain
6
6
  License: Apache-2.0
@@ -1,51 +1,84 @@
1
1
  osi_dump/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  osi_dump/__main__.py,sha256=fCVTLFipB-P0872_4j7iOJNNosOMBj3YdHr8TH_fhRY,71
3
- osi_dump/cli.py,sha256=cTOQA_thCt1ON5eQ-gTA_hFUSN5uPgFPDoOttpyuTNg,3605
3
+ osi_dump/cli.py,sha256=5sFtsS91Em26PmziWybKFW7bxnfRompH-1UTnWIKGkc,5425
4
4
  osi_dump/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ osi_dump/api/octavia.py,sha256=rT6d10OCQRdMnqvZTlW1gRMe1vOk8Rgct58oUIvDoyg,433
5
6
  osi_dump/api/placement.py,sha256=9yADLulo1HfUnPLE7IJt4ZY8e2jRTaoeV4J4MMiKCew,455
6
7
  osi_dump/batch_handler/__init__.py,sha256=wsiE42GCjbKgXBzpiahWEDF_-IXCKzr6PyrLn0oEKSc,288
8
+ osi_dump/batch_handler/flavor_batch_handler.py,sha256=Cxf-rkuW5MrrOyiKi9N3InsdDGku7Bf0CAaPNhhM0hE,1589
7
9
  osi_dump/batch_handler/floating_ip_batch_handler.py,sha256=bEkT4BRi85qir-a1i7eEI_arA0LENq1gD6xHj8IdXu0,1771
8
10
  osi_dump/batch_handler/hypervisor_batch_handler.py,sha256=vkv6SAx1arPNVvFJ6RyvbJjC2F2Hes9km7dwhL4NJDY,1755
11
+ osi_dump/batch_handler/image_batch_handler.py,sha256=aGF_jnHXuBc7IRFoLLCrSFD8h4TP0g98T_NtBXkZjd4,1564
9
12
  osi_dump/batch_handler/instance_batch_handler.py,sha256=tiHAdhH76BT9-ymnTmTr962cMUTqpPpAQyPSePKEgSM,1761
13
+ osi_dump/batch_handler/load_balancer_batch_handler.py,sha256=Y8K5raUPX-ZtIRE9G0rgVBP9WsxKpqN3wv6eDYmXau4,1839
10
14
  osi_dump/batch_handler/project_batch_handler.py,sha256=uMHx_s-Z4tO1MBah5X-T5d6tLr0qUJuPIR_7RHJ64ck,1626
15
+ osi_dump/batch_handler/role_assignment_batch_handler.py,sha256=x0LuRIyaBQq17aDznXqLxtZOPj79ufGz7TKFSM63vMA,1889
11
16
  osi_dump/batch_handler/volume_batch_handler.py,sha256=UAU34FZD8XkJkmlr4Idk4NgFBzjD52PxekJDgV1ekG0,1569
12
17
  osi_dump/exporter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ osi_dump/exporter/flavor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ osi_dump/exporter/flavor/excel_flavor_exporter.py,sha256=_wNVToj0FsIkaLbqn7-TWETrtUftBM1Pjr-0WaBJtBI,876
20
+ osi_dump/exporter/flavor/flavor_exporter.py,sha256=-zQ8776yk7vHpiZUOcX61V8KxA40AAq8foV7fD0i1g0,155
13
21
  osi_dump/exporter/floating_ip/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
22
  osi_dump/exporter/floating_ip/excel_floating_ip_exporter.py,sha256=Bn1yZTvZ8dP3EhVHW-Pr4O9TC2Cz2RbJaz_vRE66xTQ,975
15
23
  osi_dump/exporter/floating_ip/floating_ip_exporter.py,sha256=5qh4xS6m1Gfu2N3WcfkEu6U38qtc6oLWAsnNhSwXTCo,169
16
24
  osi_dump/exporter/hypervisor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
25
  osi_dump/exporter/hypervisor/excel_hypervisor_exporter.py,sha256=VhZoVjqCky5Sxvx0R9kxj-7O4tLTaPZKVqxyvqe1YLY,964
18
26
  osi_dump/exporter/hypervisor/hypervisor_exporter.py,sha256=HS3U-M-iv-ixNLfkGoaGdjdgHXXTBAjgtWQ_OhVY2xQ,167
27
+ osi_dump/exporter/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ osi_dump/exporter/image/excel_image_exporter.py,sha256=S_9UScZKI4N8xe8oXjNfnV2Eh7_llg7tOPR7H0hGVnA,853
29
+ osi_dump/exporter/image/image_exporter.py,sha256=7sNugBJDIDHjW_J9DCPgonIIGvD7xrjb5ofK195xNfM,152
19
30
  osi_dump/exporter/instance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
31
  osi_dump/exporter/instance/excel_instance_exporter.py,sha256=8WTv3RDOdUkumyWzwUK4KAZCnnq9P2yKi5TC091I9fs,931
21
32
  osi_dump/exporter/instance/instance_exporter.py,sha256=5CuKKvTa5S2_Ds7fap6tle4go9pOFmQ5VEf6O7tjwBo,161
33
+ osi_dump/exporter/load_balancer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ osi_dump/exporter/load_balancer/excel_load_balancer_exporter.py,sha256=BM3dzGL7UAug1v3Re04RBowOLGvHwc6mc0gsTfRJJwo,1008
35
+ osi_dump/exporter/load_balancer/load_balancer_exporter.py,sha256=Z5uvEKz1UG_dpAw5KVh-IX5PWLzlPt7pV9773bkgjXs,175
22
36
  osi_dump/exporter/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
37
  osi_dump/exporter/project/excel_project_exporter.py,sha256=2U3Tvn_Bk4xEQk3Tmh-oj5WXAG1bfxI6m7WVPF1upQw,916
24
38
  osi_dump/exporter/project/project_exporter.py,sha256=q3VAmtmBP4iq9YEW9Eescm3vjAVM4Ev3BDjzkGz9Pgo,158
39
+ osi_dump/exporter/role_assignment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
+ osi_dump/exporter/role_assignment/excel_role_assignment_exporter.py,sha256=CvMmueVclc22A7BPx8qR2-zXyr6FptI31bMHtyih2CA,1070
41
+ osi_dump/exporter/role_assignment/role_assignment_exporter.py,sha256=MmqFhhF7HWFoULNdDPt8yuW0GZmDxV262iEnLkLKw1s,181
25
42
  osi_dump/exporter/volume/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
43
  osi_dump/exporter/volume/excel_volume_exporter.py,sha256=BhesTGXMQF3BAwHgJMYfnxFgHxZo7TKPePG8q9T8ONI,865
27
44
  osi_dump/exporter/volume/volume_exporter.py,sha256=YoPvytC0ctWeWwVcG6pb0XwkF4N0QcGAoUHa3QldkEg,155
45
+ osi_dump/importer/flavor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
+ osi_dump/importer/flavor/flavor_importer.py,sha256=IfU2L8N8EO4eESnEDirwe9U-GXSTuTcsdrlDxD95tcQ,186
47
+ osi_dump/importer/flavor/openstack_flavor_importer.py,sha256=y3uFCls7H-l1tu11T_PaEoWghhdxINsf7baRAShXC1w,1876
28
48
  osi_dump/importer/floating_ip/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
49
  osi_dump/importer/floating_ip/floating_ip_importer.py,sha256=2_lCZYF-r2dgdL4YzwsJPudDLbRBsSPi7Wt4jS0INiI,208
30
50
  osi_dump/importer/floating_ip/openstack_floating_ip_importer.py,sha256=xuALHyiyb4LdRgFN0hZvOx0pImKpGsLUtPWW_1q52gc,2286
31
51
  osi_dump/importer/hypervisor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
52
  osi_dump/importer/hypervisor/hypervisor_importer.py,sha256=JuoJBltqFYhH-Ql9TLUPHX2YurS0JFV7Augrc6bDJ5Q,206
33
- osi_dump/importer/hypervisor/openstack_hypervisor_importer.py,sha256=OerUSzh4Ns7gXm5JwiLKIEGmLzXFqU7RZ5hbzIi1J3Q,2845
53
+ osi_dump/importer/hypervisor/openstack_hypervisor_importer.py,sha256=8EP99VPMrm4RUSHDbMmiuZeDOnwY17RLtJGotHd6ETs,3093
54
+ osi_dump/importer/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
+ osi_dump/importer/image/image_importer.py,sha256=6zwAMnS58S2HGwARwebqf4VE9IBQBv5Ot6nmcn9H4fY,181
56
+ osi_dump/importer/image/openstack_image_importer.py,sha256=Tc2eZ4fU_2S-fp_vuDWutqPcyV6Erz17nDLjzjusihY,2413
34
57
  osi_dump/importer/instance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
58
  osi_dump/importer/instance/instance_importer.py,sha256=TaaPgEFVVMRT3mSXrzQkSaSIBPBwwANpEaWCgRsgImc,196
36
59
  osi_dump/importer/instance/openstack_instance_importer.py,sha256=b1OB-8_7DlwvOo7TX5zUG64XXtUufKhgCc3lhgNqxaY,3394
60
+ osi_dump/importer/load_balancer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ osi_dump/importer/load_balancer/load_balancer_importer.py,sha256=fzInBlkscqlbhCATeQYXvufc-WHq2pbofTJJifN0zaY,218
62
+ osi_dump/importer/load_balancer/openstack_load_balancer_importer.py,sha256=Uh94UJLeKCSmDAuPORf-TJbl3nVYzkB4lDxt2J6-d88,2072
37
63
  osi_dump/importer/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- osi_dump/importer/project/openstack_project_importer.py,sha256=OXL9KB2yOgN-8hsb0RJZDT3p8wK4fLcTeqFogdtF944,2988
64
+ osi_dump/importer/project/openstack_project_importer.py,sha256=K8Si2uaC88L2CxXi68A4ML9mlWKwnZp1ABDiufFUZ8g,2988
39
65
  osi_dump/importer/project/project_importer.py,sha256=jwEvxteFbSwyWMV8hKAtf5Lo2bZysWkQ1L_NVUE8XOQ,191
66
+ osi_dump/importer/role_assignment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
+ osi_dump/importer/role_assignment/openstack_role_assignment_importer.py,sha256=nESax2gka0BpKUA2phmk1-wx0IjFLA1xGf-mORHZgFg,2598
68
+ osi_dump/importer/role_assignment/role_assignment_importer.py,sha256=Faorx0qsgdXjv5y2t-7obpV3wFfbmByx_-8b9yBr7L8,228
40
69
  osi_dump/importer/volume/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
70
  osi_dump/importer/volume/openstack_volume_importer.py,sha256=Tte9fX91oxEoRcUZPJd7g6oH6izcWy8WwFCapg_ZY1M,2454
42
71
  osi_dump/importer/volume/volume_importer.py,sha256=tmDTE9L9vtl75GR79blSxa_MVsRU6LDCbR0yJk0xKwo,186
43
72
  osi_dump/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
73
  osi_dump/model/authentication_info.py,sha256=02kXxtILfjh8t45_-bPM8rtyRk2cQcJK6l2d1bPih7k,257
74
+ osi_dump/model/flavor.py,sha256=-G8FaH_qiVrgtRxAWhdpC1c9FRdXLRroG-WJ03-DRZ4,318
45
75
  osi_dump/model/floating_ip.py,sha256=CRJufC5ZaxxcbGvdot7Af-sO8uyKbyQK9zHljfBnyFA,427
46
- osi_dump/model/hypervisor.py,sha256=zFJkLf4Z_vaMBnLmWR06Qaq0DjNTMCWP0sV3DEtpueU,317
76
+ osi_dump/model/hypervisor.py,sha256=pToa-rg7LldKd-h3aNZDJQPy5dhYDIXehq-tr8_xv1I,336
77
+ osi_dump/model/image.py,sha256=ahW0rRb2mgqoPqYhRzn_qnyShKvCvNZPlcDs_bnyt6g,445
47
78
  osi_dump/model/instance.py,sha256=flNywojuBj7ZyFTnWvl2rpvzL3Ju-QtuUY69DSPfPs8,464
79
+ osi_dump/model/load_balancer.py,sha256=ve0vEbIAZLR7RBCbEk_MGR8wrfKQ9dI21Jx6V7nFoR4,298
48
80
  osi_dump/model/project.py,sha256=3fNsDcWxuRVBS96W98C_Fia82qt14InjUM7n7rBCX6E,679
81
+ osi_dump/model/role_assignment.py,sha256=dwuXVxgHJ8pIu8_i_w9kZ0r0uaQQXAMDTYnLrDY3O9U,290
49
82
  osi_dump/model/volume.py,sha256=1p5Xw0LPxfroJwSYtE-n_Gv4MsRDA_sSvc7SQY_Uo8I,371
50
83
  osi_dump/os_connection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
84
  osi_dump/os_connection/get_connections.py,sha256=1zeir4cEtzJOUOn53zUmlD9lWMvYXhuRr0IhI5U1DAw,1753
@@ -56,8 +89,8 @@ osi_dump/util/excel_sort_sheet.py,sha256=o4jXtP1ZFYtAGzkAP5S8Tym4h-SEoFBAI3j24y-
56
89
  osi_dump/util/export_data_excel.py,sha256=VYSxDBZ7dgSbTj3n_8RRPqe183tILNh6wJW-UnFvJUU,882
57
90
  osi_dump/util/extract_hostname.py,sha256=IpdklGHevmtRu67xeSRE_5n2mvWGI1sDsnJwExo_AR0,111
58
91
  osi_dump/util/validate_dir_path.py,sha256=pL_OrY8JnNwk3vj6Zp6bsZtgHXhszSGRoqIt-1G5S90,507
59
- osi_dump-0.1.2.dist-info/METADATA,sha256=PjwOdiifp-ygU1NKMtVcEQ2PUOOqyFRCUqY8mYkpj9E,662
60
- osi_dump-0.1.2.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
61
- osi_dump-0.1.2.dist-info/entry_points.txt,sha256=ozm5sIBtXzLv6_FiUe26v1BgA3_xUReGLPhKQKZ56wQ,46
62
- osi_dump-0.1.2.dist-info/top_level.txt,sha256=OtAAwmJfcoPvlw_Cemo_H1aXIGV_7w0O2941KQt6faQ,9
63
- osi_dump-0.1.2.dist-info/RECORD,,
92
+ osi_dump-0.1.2.1.dist-info/METADATA,sha256=DCMaAo3uYHiZeiyqjcWStEokaKxFKuzgYH-_-JIDBnE,664
93
+ osi_dump-0.1.2.1.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
94
+ osi_dump-0.1.2.1.dist-info/entry_points.txt,sha256=ozm5sIBtXzLv6_FiUe26v1BgA3_xUReGLPhKQKZ56wQ,46
95
+ osi_dump-0.1.2.1.dist-info/top_level.txt,sha256=OtAAwmJfcoPvlw_Cemo_H1aXIGV_7w0O2941KQt6faQ,9
96
+ osi_dump-0.1.2.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (72.1.0)
2
+ Generator: setuptools (72.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5