osi-dump 0.1.3.3.4.3__py3-none-any.whl → 0.1.4__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.
- osi_dump/__main__.py +4 -4
- osi_dump/api/keystone.py +70 -70
- osi_dump/api/neutron.py +65 -65
- osi_dump/api/octavia.py +94 -94
- osi_dump/api/placement.py +41 -41
- osi_dump/batch_handler/__init__.py +6 -5
- osi_dump/batch_handler/external_port_batch_handler.py +55 -55
- osi_dump/batch_handler/flavor_batch_handler.py +51 -51
- osi_dump/batch_handler/floating_ip_batch_handler.py +57 -57
- osi_dump/batch_handler/hypervisor_batch_handler.py +55 -55
- osi_dump/batch_handler/image_batch_handler.py +51 -51
- osi_dump/batch_handler/instance_batch_handler.py +46 -54
- osi_dump/batch_handler/load_balancer_batch_handler.py +59 -59
- osi_dump/batch_handler/network_batch_handler.py +51 -51
- osi_dump/batch_handler/project_batch_handler.py +51 -51
- osi_dump/batch_handler/role_assignment_batch_handler.py +38 -61
- osi_dump/batch_handler/router_batch_handler.py +49 -49
- osi_dump/batch_handler/security_group_batch_handler.py +37 -0
- osi_dump/batch_handler/volume_batch_handler.py +45 -45
- osi_dump/cli.py +267 -257
- osi_dump/exporter/external_port/excel_external_port_exporter.py +34 -34
- osi_dump/exporter/external_port/external_port_exporter.py +7 -7
- osi_dump/exporter/flavor/excel_flavor_exporter.py +30 -30
- osi_dump/exporter/flavor/flavor_exporter.py +7 -7
- osi_dump/exporter/floating_ip/excel_floating_ip_exporter.py +30 -30
- osi_dump/exporter/floating_ip/floating_ip_exporter.py +7 -7
- osi_dump/exporter/hypervisor/excel_hypervisor_exporter.py +32 -32
- osi_dump/exporter/hypervisor/hypervisor_exporter.py +7 -7
- osi_dump/exporter/image/excel_image_exporter.py +28 -28
- osi_dump/exporter/image/image_exporter.py +7 -7
- osi_dump/exporter/instance/excel_instance_exporter.py +29 -29
- osi_dump/exporter/instance/instance_exporter.py +8 -7
- osi_dump/exporter/load_balancer/excel_load_balancer_exporter.py +36 -36
- osi_dump/exporter/load_balancer/load_balancer_exporter.py +7 -7
- osi_dump/exporter/network/excel_network_exporter.py +32 -32
- osi_dump/exporter/network/network_exporter.py +7 -7
- osi_dump/exporter/project/excel_project_exporter.py +30 -30
- osi_dump/exporter/project/project_exporter.py +7 -7
- osi_dump/exporter/role_assignment/excel_role_assignment_exporter.py +43 -35
- osi_dump/exporter/role_assignment/role_assignment_exporter.py +7 -7
- osi_dump/exporter/router/excel_router_exporter.py +30 -30
- osi_dump/exporter/router/router_exporter.py +7 -7
- osi_dump/exporter/security_group/excel_security_group_exporter.py +35 -0
- osi_dump/exporter/security_group/security_group_exporter.py +8 -0
- osi_dump/exporter/volume/excel_volume_exporter.py +29 -29
- osi_dump/exporter/volume/volume_exporter.py +7 -7
- osi_dump/importer/external_port/external_port_importer.py +9 -9
- osi_dump/importer/external_port/openstack_external_port_importer.py +177 -177
- osi_dump/importer/flavor/flavor_importer.py +9 -9
- osi_dump/importer/flavor/openstack_flavor_importer.py +64 -64
- osi_dump/importer/floating_ip/floating_ip_importer.py +9 -9
- osi_dump/importer/floating_ip/openstack_floating_ip_importer.py +68 -68
- osi_dump/importer/hypervisor/hypervisor_importer.py +9 -9
- osi_dump/importer/hypervisor/openstack_hypervisor_importer.py +137 -137
- osi_dump/importer/image/image_importer.py +9 -9
- osi_dump/importer/image/openstack_image_importer.py +81 -81
- osi_dump/importer/instance/instance_importer.py +8 -9
- osi_dump/importer/instance/openstack_instance_importer.py +136 -136
- osi_dump/importer/load_balancer/load_balancer_importer.py +9 -9
- osi_dump/importer/load_balancer/openstack_load_balancer_importer.py +113 -113
- osi_dump/importer/network/network_importer.py +9 -9
- osi_dump/importer/network/openstack_network_importer.py +93 -93
- osi_dump/importer/project/openstack_project_importer.py +141 -141
- osi_dump/importer/project/project_importer.py +9 -9
- osi_dump/importer/role_assignment/openstack_role_assignment_importer.py +117 -147
- osi_dump/importer/role_assignment/role_assignment_importer.py +16 -9
- osi_dump/importer/router/openstack_router_importer.py +87 -87
- osi_dump/importer/router/router_importer.py +9 -9
- osi_dump/importer/security_group/openstack_security_group_importer.py +54 -0
- osi_dump/importer/security_group/security_group_importer.py +8 -0
- osi_dump/importer/volume/openstack_volume_importer.py +81 -81
- osi_dump/importer/volume/volume_importer.py +9 -9
- osi_dump/model/authentication_info.py +15 -15
- osi_dump/model/external_port.py +30 -30
- osi_dump/model/flavor.py +20 -20
- osi_dump/model/floating_ip.py +24 -24
- osi_dump/model/hypervisor.py +24 -24
- osi_dump/model/image.py +27 -27
- osi_dump/model/instance.py +29 -29
- osi_dump/model/load_balancer.py +26 -26
- osi_dump/model/network.py +25 -25
- osi_dump/model/project.py +33 -33
- osi_dump/model/role_assignment.py +30 -23
- osi_dump/model/router.py +23 -23
- osi_dump/model/security_group.py +22 -0
- osi_dump/model/volume.py +25 -25
- osi_dump/os_connection/get_connections.py +67 -67
- osi_dump/util/__init__.py +7 -7
- osi_dump/util/create_file.py +11 -11
- osi_dump/util/excel_autosize_column.py +39 -39
- osi_dump/util/excel_sort_sheet.py +35 -35
- osi_dump/util/export_data_excel.py +36 -36
- osi_dump/util/extract_hostname.py +5 -5
- osi_dump/util/openstack_util.py +48 -48
- osi_dump/util/panda_excel.py +26 -26
- osi_dump/util/validate_dir_path.py +20 -20
- {osi_dump-0.1.3.3.4.3.dist-info → osi_dump-0.1.4.dist-info}/METADATA +40 -40
- osi_dump-0.1.4.dist-info/RECORD +130 -0
- osi_dump-0.1.3.3.4.3.dist-info/RECORD +0 -124
- {osi_dump-0.1.3.3.4.3.dist-info → osi_dump-0.1.4.dist-info}/WHEEL +0 -0
- {osi_dump-0.1.3.3.4.3.dist-info → osi_dump-0.1.4.dist-info}/entry_points.txt +0 -0
- {osi_dump-0.1.3.3.4.3.dist-info → osi_dump-0.1.4.dist-info}/top_level.txt +0 -0
@@ -1,64 +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
|
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
|
@@ -1,9 +1,9 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
|
3
|
-
from osi_dump.model.floating_ip import FloatingIP
|
4
|
-
|
5
|
-
|
6
|
-
class FloatingIPImporter(ABC):
|
7
|
-
@abstractmethod
|
8
|
-
def import_floating_ips(self) -> list[FloatingIP]:
|
9
|
-
pass
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
from osi_dump.model.floating_ip import FloatingIP
|
4
|
+
|
5
|
+
|
6
|
+
class FloatingIPImporter(ABC):
|
7
|
+
@abstractmethod
|
8
|
+
def import_floating_ips(self) -> list[FloatingIP]:
|
9
|
+
pass
|
@@ -1,68 +1,68 @@
|
|
1
|
-
import logging
|
2
|
-
|
3
|
-
import concurrent
|
4
|
-
|
5
|
-
from openstack.connection import Connection
|
6
|
-
from openstack.network.v2.floating_ip import FloatingIP as OSFloatingIP
|
7
|
-
|
8
|
-
from osi_dump.importer.floating_ip.floating_ip_importer import FloatingIPImporter
|
9
|
-
from osi_dump.model.floating_ip import FloatingIP
|
10
|
-
|
11
|
-
logger = logging.getLogger(__name__)
|
12
|
-
|
13
|
-
|
14
|
-
class OpenStackFloatingIPImporter(FloatingIPImporter):
|
15
|
-
def __init__(self, connection: Connection):
|
16
|
-
self.connection = connection
|
17
|
-
|
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
|
-
|
28
|
-
logger.info(f"Importing floating ips for {self.connection.auth['auth_url']}")
|
29
|
-
|
30
|
-
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())
|
48
|
-
|
49
|
-
logger.info(f"Imported floating ips for {self.connection.auth['auth_url']}")
|
50
|
-
|
51
|
-
return floating_ips
|
52
|
-
|
53
|
-
def _get_floating_ip_info(self, floating_ip: OSFloatingIP) -> FloatingIP:
|
54
|
-
|
55
|
-
ret_floating_ip = FloatingIP(
|
56
|
-
floating_ip_id=floating_ip.id,
|
57
|
-
project_id=floating_ip.project_id,
|
58
|
-
floating_ip_address=floating_ip.floating_ip_address,
|
59
|
-
floating_network=floating_ip.floating_network_id,
|
60
|
-
fixed_ip_address=floating_ip.fixed_ip_address,
|
61
|
-
router_id=floating_ip.router_id,
|
62
|
-
port_id=floating_ip.port_id,
|
63
|
-
status=floating_ip.status,
|
64
|
-
created_at=floating_ip.created_at,
|
65
|
-
updated_at=floating_ip.updated_at,
|
66
|
-
)
|
67
|
-
|
68
|
-
return ret_floating_ip
|
1
|
+
import logging
|
2
|
+
|
3
|
+
import concurrent
|
4
|
+
|
5
|
+
from openstack.connection import Connection
|
6
|
+
from openstack.network.v2.floating_ip import FloatingIP as OSFloatingIP
|
7
|
+
|
8
|
+
from osi_dump.importer.floating_ip.floating_ip_importer import FloatingIPImporter
|
9
|
+
from osi_dump.model.floating_ip import FloatingIP
|
10
|
+
|
11
|
+
logger = logging.getLogger(__name__)
|
12
|
+
|
13
|
+
|
14
|
+
class OpenStackFloatingIPImporter(FloatingIPImporter):
|
15
|
+
def __init__(self, connection: Connection):
|
16
|
+
self.connection = connection
|
17
|
+
|
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
|
+
|
28
|
+
logger.info(f"Importing floating ips for {self.connection.auth['auth_url']}")
|
29
|
+
|
30
|
+
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())
|
48
|
+
|
49
|
+
logger.info(f"Imported floating ips for {self.connection.auth['auth_url']}")
|
50
|
+
|
51
|
+
return floating_ips
|
52
|
+
|
53
|
+
def _get_floating_ip_info(self, floating_ip: OSFloatingIP) -> FloatingIP:
|
54
|
+
|
55
|
+
ret_floating_ip = FloatingIP(
|
56
|
+
floating_ip_id=floating_ip.id,
|
57
|
+
project_id=floating_ip.project_id,
|
58
|
+
floating_ip_address=floating_ip.floating_ip_address,
|
59
|
+
floating_network=floating_ip.floating_network_id,
|
60
|
+
fixed_ip_address=floating_ip.fixed_ip_address,
|
61
|
+
router_id=floating_ip.router_id,
|
62
|
+
port_id=floating_ip.port_id,
|
63
|
+
status=floating_ip.status,
|
64
|
+
created_at=floating_ip.created_at,
|
65
|
+
updated_at=floating_ip.updated_at,
|
66
|
+
)
|
67
|
+
|
68
|
+
return ret_floating_ip
|
@@ -1,9 +1,9 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
|
3
|
-
from osi_dump.model.hypervisor import Hypervisor
|
4
|
-
|
5
|
-
|
6
|
-
class HypervisorImporter(ABC):
|
7
|
-
@abstractmethod
|
8
|
-
def import_hypervisors(self) -> list[Hypervisor]:
|
9
|
-
pass
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
from osi_dump.model.hypervisor import Hypervisor
|
4
|
+
|
5
|
+
|
6
|
+
class HypervisorImporter(ABC):
|
7
|
+
@abstractmethod
|
8
|
+
def import_hypervisors(self) -> list[Hypervisor]:
|
9
|
+
pass
|
@@ -1,137 +1,137 @@
|
|
1
|
-
import logging
|
2
|
-
|
3
|
-
import concurrent
|
4
|
-
|
5
|
-
from openstack.connection import Connection
|
6
|
-
from openstack.compute.v2.hypervisor import Hypervisor as OSHypervisor
|
7
|
-
from openstack.compute.v2.aggregate import Aggregate as OSAggregate
|
8
|
-
|
9
|
-
from openstack.placement.v1._proxy import Proxy as PlacementProxy
|
10
|
-
from openstack.placement.v1.resource_provider_inventory import ResourceProviderInventory
|
11
|
-
|
12
|
-
from osi_dump.importer.hypervisor.hypervisor_importer import HypervisorImporter
|
13
|
-
from osi_dump.model.hypervisor import Hypervisor
|
14
|
-
|
15
|
-
from osi_dump.api.placement import get_usage
|
16
|
-
|
17
|
-
logger = logging.getLogger(__name__)
|
18
|
-
|
19
|
-
|
20
|
-
class OpenStackHypervisorImporter(HypervisorImporter):
|
21
|
-
def __init__(self, connection: Connection):
|
22
|
-
self.connection = connection
|
23
|
-
|
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
|
-
|
35
|
-
try:
|
36
|
-
oshypervisors: list[OSHypervisor] = list(
|
37
|
-
self.connection.compute.hypervisors(details=True, with_servers=True)
|
38
|
-
)
|
39
|
-
|
40
|
-
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]] = [
|
67
|
-
|
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]
|
75
|
-
|
76
|
-
def _get_hypervisor_info(
|
77
|
-
self, hypervisor: OSHypervisor, aggregates: list[OSAggregate]
|
78
|
-
) -> Hypervisor:
|
79
|
-
aggregate_list, az = self._get_aggregates(hypervisor=hypervisor)
|
80
|
-
|
81
|
-
placement_proxy: PlacementProxy = self.connection.placement
|
82
|
-
|
83
|
-
rpi: ResourceProviderInventory = list(
|
84
|
-
placement_proxy.resource_provider_inventories(
|
85
|
-
resource_provider=hypervisor.id
|
86
|
-
)
|
87
|
-
)
|
88
|
-
|
89
|
-
usage_data = get_usage(self.connection, resource_provider_id=hypervisor.id)
|
90
|
-
|
91
|
-
vcpu = rpi[0]
|
92
|
-
memory = rpi[1]
|
93
|
-
disk = rpi[2]
|
94
|
-
|
95
|
-
ret_hypervisor = Hypervisor(
|
96
|
-
hypervisor_id=hypervisor.id,
|
97
|
-
hypervisor_type=hypervisor.hypervisor_type,
|
98
|
-
name=hypervisor.name,
|
99
|
-
state=hypervisor.state,
|
100
|
-
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"],
|
107
|
-
vm_count=len(hypervisor.servers),
|
108
|
-
aggregates=aggregate_list,
|
109
|
-
availability_zone=az,
|
110
|
-
)
|
111
|
-
|
112
|
-
return ret_hypervisor
|
113
|
-
|
114
|
-
def _get_aggregates(self, hypervisor: OSHypervisor):
|
115
|
-
aggregates_ret = []
|
116
|
-
|
117
|
-
aggregates: OSAggregate = list(self.connection.list_aggregates())
|
118
|
-
|
119
|
-
az = None
|
120
|
-
|
121
|
-
for aggregate in aggregates:
|
122
|
-
if hypervisor.name in aggregate.hosts:
|
123
|
-
aggregates_ret.append(
|
124
|
-
{
|
125
|
-
"id": aggregate.id,
|
126
|
-
"name": aggregate.name,
|
127
|
-
}
|
128
|
-
)
|
129
|
-
|
130
|
-
if aggregate.availability_zone != None:
|
131
|
-
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
|
1
|
+
import logging
|
2
|
+
|
3
|
+
import concurrent
|
4
|
+
|
5
|
+
from openstack.connection import Connection
|
6
|
+
from openstack.compute.v2.hypervisor import Hypervisor as OSHypervisor
|
7
|
+
from openstack.compute.v2.aggregate import Aggregate as OSAggregate
|
8
|
+
|
9
|
+
from openstack.placement.v1._proxy import Proxy as PlacementProxy
|
10
|
+
from openstack.placement.v1.resource_provider_inventory import ResourceProviderInventory
|
11
|
+
|
12
|
+
from osi_dump.importer.hypervisor.hypervisor_importer import HypervisorImporter
|
13
|
+
from osi_dump.model.hypervisor import Hypervisor
|
14
|
+
|
15
|
+
from osi_dump.api.placement import get_usage
|
16
|
+
|
17
|
+
logger = logging.getLogger(__name__)
|
18
|
+
|
19
|
+
|
20
|
+
class OpenStackHypervisorImporter(HypervisorImporter):
|
21
|
+
def __init__(self, connection: Connection):
|
22
|
+
self.connection = connection
|
23
|
+
|
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
|
+
|
35
|
+
try:
|
36
|
+
oshypervisors: list[OSHypervisor] = list(
|
37
|
+
self.connection.compute.hypervisors(details=True, with_servers=True)
|
38
|
+
)
|
39
|
+
|
40
|
+
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]] = [
|
67
|
+
|
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]
|
75
|
+
|
76
|
+
def _get_hypervisor_info(
|
77
|
+
self, hypervisor: OSHypervisor, aggregates: list[OSAggregate]
|
78
|
+
) -> Hypervisor:
|
79
|
+
aggregate_list, az = self._get_aggregates(hypervisor=hypervisor)
|
80
|
+
|
81
|
+
placement_proxy: PlacementProxy = self.connection.placement
|
82
|
+
|
83
|
+
rpi: ResourceProviderInventory = list(
|
84
|
+
placement_proxy.resource_provider_inventories(
|
85
|
+
resource_provider=hypervisor.id
|
86
|
+
)
|
87
|
+
)
|
88
|
+
|
89
|
+
usage_data = get_usage(self.connection, resource_provider_id=hypervisor.id)
|
90
|
+
|
91
|
+
vcpu = rpi[0]
|
92
|
+
memory = rpi[1]
|
93
|
+
disk = rpi[2]
|
94
|
+
|
95
|
+
ret_hypervisor = Hypervisor(
|
96
|
+
hypervisor_id=hypervisor.id,
|
97
|
+
hypervisor_type=hypervisor.hypervisor_type,
|
98
|
+
name=hypervisor.name,
|
99
|
+
state=hypervisor.state,
|
100
|
+
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"],
|
107
|
+
vm_count=len(hypervisor.servers),
|
108
|
+
aggregates=aggregate_list,
|
109
|
+
availability_zone=az,
|
110
|
+
)
|
111
|
+
|
112
|
+
return ret_hypervisor
|
113
|
+
|
114
|
+
def _get_aggregates(self, hypervisor: OSHypervisor):
|
115
|
+
aggregates_ret = []
|
116
|
+
|
117
|
+
aggregates: OSAggregate = list(self.connection.list_aggregates())
|
118
|
+
|
119
|
+
az = None
|
120
|
+
|
121
|
+
for aggregate in aggregates:
|
122
|
+
if hypervisor.name in aggregate.hosts:
|
123
|
+
aggregates_ret.append(
|
124
|
+
{
|
125
|
+
"id": aggregate.id,
|
126
|
+
"name": aggregate.name,
|
127
|
+
}
|
128
|
+
)
|
129
|
+
|
130
|
+
if aggregate.availability_zone != None:
|
131
|
+
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
|
@@ -1,9 +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
|
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
|