osi-dump 0.1.3.3.4.2__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 -141
- 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 -21
- 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.2.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.2.dist-info → osi_dump-0.1.4.dist-info}/WHEEL +1 -1
- osi_dump-0.1.3.3.4.2.dist-info/RECORD +0 -124
- {osi_dump-0.1.3.3.4.2.dist-info → osi_dump-0.1.4.dist-info}/entry_points.txt +0 -0
- {osi_dump-0.1.3.3.4.2.dist-info → osi_dump-0.1.4.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
|
3
|
-
|
4
|
-
class RoleAssignmentExporter(ABC):
|
5
|
-
@abstractmethod
|
6
|
-
def export_role_assignments(self,
|
7
|
-
pass
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from osi_dump.importer.role_assignment.role_assignment_importer import RoleAssignmentImporter
|
3
|
+
|
4
|
+
class RoleAssignmentExporter(ABC):
|
5
|
+
@abstractmethod
|
6
|
+
def export_role_assignments(self, importer: RoleAssignmentImporter):
|
7
|
+
pass
|
@@ -1,30 +1,30 @@
|
|
1
|
-
import pandas as pd
|
2
|
-
|
3
|
-
import logging
|
4
|
-
|
5
|
-
from openpyxl import load_workbook
|
6
|
-
|
7
|
-
from osi_dump import util
|
8
|
-
from osi_dump.exporter.router.router_exporter import RouterExporter
|
9
|
-
|
10
|
-
from osi_dump.model.router import Router
|
11
|
-
|
12
|
-
logger = logging.getLogger(__name__)
|
13
|
-
|
14
|
-
|
15
|
-
class ExcelRouterExporter(RouterExporter):
|
16
|
-
def __init__(self, sheet_name: str, output_file: str):
|
17
|
-
self.sheet_name = sheet_name
|
18
|
-
self.output_file = output_file
|
19
|
-
|
20
|
-
def export_routers(self, routers: list[Router]):
|
21
|
-
|
22
|
-
df = pd.DataFrame([router.model_dump() for router in routers])
|
23
|
-
|
24
|
-
logger.info(f"Exporting routers 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 routers for {self.sheet_name}")
|
29
|
-
except Exception as e:
|
30
|
-
logger.warning(f"Exporting routers for {self.sheet_name} error: {e}")
|
1
|
+
import pandas as pd
|
2
|
+
|
3
|
+
import logging
|
4
|
+
|
5
|
+
from openpyxl import load_workbook
|
6
|
+
|
7
|
+
from osi_dump import util
|
8
|
+
from osi_dump.exporter.router.router_exporter import RouterExporter
|
9
|
+
|
10
|
+
from osi_dump.model.router import Router
|
11
|
+
|
12
|
+
logger = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
|
15
|
+
class ExcelRouterExporter(RouterExporter):
|
16
|
+
def __init__(self, sheet_name: str, output_file: str):
|
17
|
+
self.sheet_name = sheet_name
|
18
|
+
self.output_file = output_file
|
19
|
+
|
20
|
+
def export_routers(self, routers: list[Router]):
|
21
|
+
|
22
|
+
df = pd.DataFrame([router.model_dump() for router in routers])
|
23
|
+
|
24
|
+
logger.info(f"Exporting routers 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 routers for {self.sheet_name}")
|
29
|
+
except Exception as e:
|
30
|
+
logger.warning(f"Exporting routers for {self.sheet_name} error: {e}")
|
@@ -1,7 +1,7 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
|
3
|
-
|
4
|
-
class RouterExporter(ABC):
|
5
|
-
@abstractmethod
|
6
|
-
def export_routers(self, routers, output_file: str):
|
7
|
-
pass
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
|
4
|
+
class RouterExporter(ABC):
|
5
|
+
@abstractmethod
|
6
|
+
def export_routers(self, routers, output_file: str):
|
7
|
+
pass
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import logging
|
2
|
+
import pandas as pd
|
3
|
+
from typing import Generator
|
4
|
+
from osi_dump import util
|
5
|
+
from osi_dump.exporter.security_group.security_group_exporter import SecurityGroupExporter
|
6
|
+
from osi_dump.model.security_group import SecurityGroup
|
7
|
+
|
8
|
+
logger = logging.getLogger(__name__)
|
9
|
+
|
10
|
+
class ExcelSecurityGroupExporter(SecurityGroupExporter):
|
11
|
+
def __init__(self, sheet_name: str, output_file: str):
|
12
|
+
self.sheet_name = sheet_name
|
13
|
+
self.output_file = output_file
|
14
|
+
|
15
|
+
def export_security_groups(self, security_groups: Generator[SecurityGroup, None, None]):
|
16
|
+
|
17
|
+
data_generator = (sg.model_dump() for sg in security_groups)
|
18
|
+
|
19
|
+
df = pd.json_normalize(
|
20
|
+
data_generator,
|
21
|
+
record_path='rules',
|
22
|
+
meta=['security_group_id', 'name', 'project_id', 'description'],
|
23
|
+
record_prefix='rule.'
|
24
|
+
)
|
25
|
+
|
26
|
+
if df.empty:
|
27
|
+
logger.info(f"No security groups to export for {self.sheet_name}")
|
28
|
+
return
|
29
|
+
|
30
|
+
logger.info(f"Exporting security groups for {self.sheet_name}")
|
31
|
+
try:
|
32
|
+
util.export_data_excel(self.output_file, sheet_name=self.sheet_name, df=df)
|
33
|
+
logger.info(f"Exported security groups for {self.sheet_name}")
|
34
|
+
except Exception as e:
|
35
|
+
logger.warning(f"Exporting security groups for {self.sheet_name} error: {e}")
|
@@ -0,0 +1,8 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from typing import Generator
|
3
|
+
from osi_dump.model.security_group import SecurityGroup
|
4
|
+
|
5
|
+
class SecurityGroupExporter(ABC):
|
6
|
+
@abstractmethod
|
7
|
+
def export_security_groups(self, security_groups: Generator[SecurityGroup, None, None]):
|
8
|
+
pass
|
@@ -1,29 +1,29 @@
|
|
1
|
-
import pandas as pd
|
2
|
-
|
3
|
-
import logging
|
4
|
-
|
5
|
-
|
6
|
-
from osi_dump import util
|
7
|
-
|
8
|
-
from osi_dump.exporter.volume.volume_exporter import VolumeExporter
|
9
|
-
|
10
|
-
from osi_dump.model.volume import Volume
|
11
|
-
|
12
|
-
logger = logging.getLogger(__name__)
|
13
|
-
|
14
|
-
|
15
|
-
class ExcelVolumeExporter(VolumeExporter):
|
16
|
-
def __init__(self, sheet_name: str, output_file: str):
|
17
|
-
self.sheet_name = sheet_name
|
18
|
-
self.output_file = output_file
|
19
|
-
|
20
|
-
def export_volumes(self, volumes: list[Volume]):
|
21
|
-
df = pd.DataFrame([volume.model_dump() for volume in volumes])
|
22
|
-
|
23
|
-
logger.info(f"Exporting volumes for {self.sheet_name}")
|
24
|
-
try:
|
25
|
-
util.export_data_excel(self.output_file, sheet_name=self.sheet_name, df=df)
|
26
|
-
|
27
|
-
logger.info(f"Exported volumes for {self.sheet_name}")
|
28
|
-
except Exception as e:
|
29
|
-
logger.warning(f"Exporting volumes for {self.sheet_name} error: {e}")
|
1
|
+
import pandas as pd
|
2
|
+
|
3
|
+
import logging
|
4
|
+
|
5
|
+
|
6
|
+
from osi_dump import util
|
7
|
+
|
8
|
+
from osi_dump.exporter.volume.volume_exporter import VolumeExporter
|
9
|
+
|
10
|
+
from osi_dump.model.volume import Volume
|
11
|
+
|
12
|
+
logger = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
|
15
|
+
class ExcelVolumeExporter(VolumeExporter):
|
16
|
+
def __init__(self, sheet_name: str, output_file: str):
|
17
|
+
self.sheet_name = sheet_name
|
18
|
+
self.output_file = output_file
|
19
|
+
|
20
|
+
def export_volumes(self, volumes: list[Volume]):
|
21
|
+
df = pd.DataFrame([volume.model_dump() for volume in volumes])
|
22
|
+
|
23
|
+
logger.info(f"Exporting volumes for {self.sheet_name}")
|
24
|
+
try:
|
25
|
+
util.export_data_excel(self.output_file, sheet_name=self.sheet_name, df=df)
|
26
|
+
|
27
|
+
logger.info(f"Exported volumes for {self.sheet_name}")
|
28
|
+
except Exception as e:
|
29
|
+
logger.warning(f"Exporting volumes for {self.sheet_name} error: {e}")
|
@@ -1,7 +1,7 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
|
3
|
-
|
4
|
-
class VolumeExporter(ABC):
|
5
|
-
@abstractmethod
|
6
|
-
def export_volumes(self, volumes, output_file: str):
|
7
|
-
pass
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
|
4
|
+
class VolumeExporter(ABC):
|
5
|
+
@abstractmethod
|
6
|
+
def export_volumes(self, volumes, output_file: str):
|
7
|
+
pass
|
@@ -1,9 +1,9 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
|
3
|
-
from osi_dump.model.external_port import ExternalPort
|
4
|
-
|
5
|
-
|
6
|
-
class ExternalPortImporter(ABC):
|
7
|
-
@abstractmethod
|
8
|
-
def import_external_ports(self) -> list[ExternalPort]:
|
9
|
-
pass
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
from osi_dump.model.external_port import ExternalPort
|
4
|
+
|
5
|
+
|
6
|
+
class ExternalPortImporter(ABC):
|
7
|
+
@abstractmethod
|
8
|
+
def import_external_ports(self) -> list[ExternalPort]:
|
9
|
+
pass
|
@@ -1,177 +1,177 @@
|
|
1
|
-
import logging
|
2
|
-
|
3
|
-
import ipaddress
|
4
|
-
|
5
|
-
import concurrent
|
6
|
-
|
7
|
-
import numpy as np
|
8
|
-
|
9
|
-
from openstack.connection import Connection
|
10
|
-
from openstack.network.v2.port import Port as OSPort
|
11
|
-
from openstack.network.v2.subnet import Subnet as OSSubnet
|
12
|
-
from openstack.network.v2.floating_ip import FloatingIP as OSFloatingIP
|
13
|
-
from openstack.network.v2.router import Router as OSRouter
|
14
|
-
from openstack.network.v2.network import Network as OSNetwork
|
15
|
-
|
16
|
-
from osi_dump.importer.external_port.external_port_importer import ExternalPortImporter
|
17
|
-
from osi_dump.model.external_port import ExternalPort
|
18
|
-
|
19
|
-
import osi_dump.api.neutron as osi_neutron
|
20
|
-
|
21
|
-
logger = logging.getLogger(__name__)
|
22
|
-
|
23
|
-
|
24
|
-
class OpenStackExternalPortImporter(ExternalPortImporter):
|
25
|
-
def __init__(self, connection: Connection):
|
26
|
-
self.connection = connection
|
27
|
-
|
28
|
-
def _get_external_ports(self) -> list[OSPort]:
|
29
|
-
|
30
|
-
# Get all external networks
|
31
|
-
networks = self.connection.network.networks(
|
32
|
-
is_router_external=True,
|
33
|
-
)
|
34
|
-
|
35
|
-
external_ports = []
|
36
|
-
|
37
|
-
for network in networks:
|
38
|
-
ex_ports = list(self.connection.network.ports(network_id=network.id))
|
39
|
-
|
40
|
-
for ex_port in ex_ports:
|
41
|
-
external_ports.append(ex_port)
|
42
|
-
|
43
|
-
# Get all port on those networks
|
44
|
-
|
45
|
-
return external_ports
|
46
|
-
|
47
|
-
def import_external_ports(self) -> list[ExternalPort]:
|
48
|
-
"""Import external_ports information from Openstack
|
49
|
-
|
50
|
-
|
51
|
-
Raises:
|
52
|
-
Exception: Raises exception if fetching external_port failed
|
53
|
-
|
54
|
-
Returns:
|
55
|
-
list[Instance]: _description_
|
56
|
-
"""
|
57
|
-
|
58
|
-
logger.info(f"Importing external_ports for {self.connection.auth['auth_url']}")
|
59
|
-
|
60
|
-
try:
|
61
|
-
os_ports: list[OSPort] = self._get_external_ports()
|
62
|
-
except Exception as e:
|
63
|
-
raise Exception(
|
64
|
-
f"Can not fetch external_ports for {self.connection.auth['auth_url']} {e}"
|
65
|
-
) from e
|
66
|
-
|
67
|
-
external_ports: list[ExternalPort] = []
|
68
|
-
|
69
|
-
with concurrent.futures.ThreadPoolExecutor() as executor:
|
70
|
-
futures = [
|
71
|
-
executor.submit(self._get_external_port_info, external_port)
|
72
|
-
for external_port in os_ports
|
73
|
-
]
|
74
|
-
for future in concurrent.futures.as_completed(futures):
|
75
|
-
external_ports.append(future.result())
|
76
|
-
|
77
|
-
logger.info(f"Imported external_ports for {self.connection.auth['auth_url']}")
|
78
|
-
|
79
|
-
external_ports = sorted(
|
80
|
-
external_ports,
|
81
|
-
key=lambda external_port: (
|
82
|
-
external_port.network_id,
|
83
|
-
(
|
84
|
-
ipaddress.ip_address(external_port.ip_address)
|
85
|
-
if external_port.ip_address
|
86
|
-
else ipaddress.ip_address("0.0.0.0")
|
87
|
-
),
|
88
|
-
),
|
89
|
-
)
|
90
|
-
|
91
|
-
return external_ports
|
92
|
-
|
93
|
-
def _get_external_port_info(self, external_port: OSPort) -> ExternalPort:
|
94
|
-
|
95
|
-
subnet_id = None
|
96
|
-
ip_address = None
|
97
|
-
subnet_cidr = None
|
98
|
-
|
99
|
-
try:
|
100
|
-
ip_address = external_port.fixed_ips[0]["ip_address"]
|
101
|
-
except Exception as e:
|
102
|
-
logger.warning(f"No IP address found for port {external_port.id}")
|
103
|
-
|
104
|
-
try:
|
105
|
-
subnet_id = external_port.fixed_ips[0]["subnet_id"]
|
106
|
-
except Exception as e:
|
107
|
-
logger.warning(f"No subnet ID found for {external_port.id}")
|
108
|
-
|
109
|
-
try:
|
110
|
-
subnet: OSSubnet = self.connection.get_subnet_by_id(subnet_id)
|
111
|
-
|
112
|
-
subnet_cidr = subnet.cidr
|
113
|
-
except Exception as e:
|
114
|
-
logger.warning(f"No subnet cidr found for port {external_port.id}")
|
115
|
-
|
116
|
-
mapped_device_project = ["network:floatingip", "network:router_gateway"]
|
117
|
-
|
118
|
-
project_id = (
|
119
|
-
external_port.project_id
|
120
|
-
if external_port.device_owner not in mapped_device_project
|
121
|
-
else self._map_project_id(
|
122
|
-
device_owner=external_port.device_owner,
|
123
|
-
device_id=external_port.device_id,
|
124
|
-
)
|
125
|
-
)
|
126
|
-
|
127
|
-
network: OSNetwork = self.connection.get_network(name_or_id=external_port.network_id)
|
128
|
-
|
129
|
-
vlan_id = None
|
130
|
-
|
131
|
-
try:
|
132
|
-
if not network.segments:
|
133
|
-
vlan_id = network.provider_segmentation_id
|
134
|
-
else:
|
135
|
-
logger.warning(f"Multiple segments mapped for net id {network.id}")
|
136
|
-
except Exception as e:
|
137
|
-
logger.warning(f"Can not get vlan ID for external port {external_port.id}, net id {network.id}")
|
138
|
-
|
139
|
-
external_port_ret = ExternalPort(
|
140
|
-
port_id=external_port.id,
|
141
|
-
project_id=project_id,
|
142
|
-
network_id=external_port.network_id,
|
143
|
-
network_name=network.name,
|
144
|
-
subnet_id=subnet_id,
|
145
|
-
subnet_cidr=subnet_cidr,
|
146
|
-
ip_address=ip_address,
|
147
|
-
allowed_address_pairs=external_port.allowed_address_pairs,
|
148
|
-
device_id=external_port.device_id,
|
149
|
-
device_owner=external_port.device_owner,
|
150
|
-
status=external_port.status,
|
151
|
-
vlan_id=vlan_id
|
152
|
-
)
|
153
|
-
|
154
|
-
return external_port_ret
|
155
|
-
|
156
|
-
def _map_project_id(self, device_owner: str, device_id: str) -> str:
|
157
|
-
|
158
|
-
if device_owner == "network:router_gateway":
|
159
|
-
return self._map_project_id_router(device_id=device_id)
|
160
|
-
elif device_owner == "network:floatingip":
|
161
|
-
return self._map_project_id_floating(device_id=device_id)
|
162
|
-
|
163
|
-
return ""
|
164
|
-
|
165
|
-
def _map_project_id_router(self, device_id: str) -> str:
|
166
|
-
project_id = osi_neutron.get_router_project(
|
167
|
-
self.connection, router_id=device_id
|
168
|
-
)
|
169
|
-
|
170
|
-
return project_id
|
171
|
-
|
172
|
-
def _map_project_id_floating(self, device_id: str) -> str:
|
173
|
-
project_id = osi_neutron.get_floating_ip_project(
|
174
|
-
self.connection, floating_ip_id=device_id
|
175
|
-
)
|
176
|
-
|
177
|
-
return project_id
|
1
|
+
import logging
|
2
|
+
|
3
|
+
import ipaddress
|
4
|
+
|
5
|
+
import concurrent
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
|
9
|
+
from openstack.connection import Connection
|
10
|
+
from openstack.network.v2.port import Port as OSPort
|
11
|
+
from openstack.network.v2.subnet import Subnet as OSSubnet
|
12
|
+
from openstack.network.v2.floating_ip import FloatingIP as OSFloatingIP
|
13
|
+
from openstack.network.v2.router import Router as OSRouter
|
14
|
+
from openstack.network.v2.network import Network as OSNetwork
|
15
|
+
|
16
|
+
from osi_dump.importer.external_port.external_port_importer import ExternalPortImporter
|
17
|
+
from osi_dump.model.external_port import ExternalPort
|
18
|
+
|
19
|
+
import osi_dump.api.neutron as osi_neutron
|
20
|
+
|
21
|
+
logger = logging.getLogger(__name__)
|
22
|
+
|
23
|
+
|
24
|
+
class OpenStackExternalPortImporter(ExternalPortImporter):
|
25
|
+
def __init__(self, connection: Connection):
|
26
|
+
self.connection = connection
|
27
|
+
|
28
|
+
def _get_external_ports(self) -> list[OSPort]:
|
29
|
+
|
30
|
+
# Get all external networks
|
31
|
+
networks = self.connection.network.networks(
|
32
|
+
is_router_external=True,
|
33
|
+
)
|
34
|
+
|
35
|
+
external_ports = []
|
36
|
+
|
37
|
+
for network in networks:
|
38
|
+
ex_ports = list(self.connection.network.ports(network_id=network.id))
|
39
|
+
|
40
|
+
for ex_port in ex_ports:
|
41
|
+
external_ports.append(ex_port)
|
42
|
+
|
43
|
+
# Get all port on those networks
|
44
|
+
|
45
|
+
return external_ports
|
46
|
+
|
47
|
+
def import_external_ports(self) -> list[ExternalPort]:
|
48
|
+
"""Import external_ports information from Openstack
|
49
|
+
|
50
|
+
|
51
|
+
Raises:
|
52
|
+
Exception: Raises exception if fetching external_port failed
|
53
|
+
|
54
|
+
Returns:
|
55
|
+
list[Instance]: _description_
|
56
|
+
"""
|
57
|
+
|
58
|
+
logger.info(f"Importing external_ports for {self.connection.auth['auth_url']}")
|
59
|
+
|
60
|
+
try:
|
61
|
+
os_ports: list[OSPort] = self._get_external_ports()
|
62
|
+
except Exception as e:
|
63
|
+
raise Exception(
|
64
|
+
f"Can not fetch external_ports for {self.connection.auth['auth_url']} {e}"
|
65
|
+
) from e
|
66
|
+
|
67
|
+
external_ports: list[ExternalPort] = []
|
68
|
+
|
69
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
70
|
+
futures = [
|
71
|
+
executor.submit(self._get_external_port_info, external_port)
|
72
|
+
for external_port in os_ports
|
73
|
+
]
|
74
|
+
for future in concurrent.futures.as_completed(futures):
|
75
|
+
external_ports.append(future.result())
|
76
|
+
|
77
|
+
logger.info(f"Imported external_ports for {self.connection.auth['auth_url']}")
|
78
|
+
|
79
|
+
external_ports = sorted(
|
80
|
+
external_ports,
|
81
|
+
key=lambda external_port: (
|
82
|
+
external_port.network_id,
|
83
|
+
(
|
84
|
+
ipaddress.ip_address(external_port.ip_address)
|
85
|
+
if external_port.ip_address
|
86
|
+
else ipaddress.ip_address("0.0.0.0")
|
87
|
+
),
|
88
|
+
),
|
89
|
+
)
|
90
|
+
|
91
|
+
return external_ports
|
92
|
+
|
93
|
+
def _get_external_port_info(self, external_port: OSPort) -> ExternalPort:
|
94
|
+
|
95
|
+
subnet_id = None
|
96
|
+
ip_address = None
|
97
|
+
subnet_cidr = None
|
98
|
+
|
99
|
+
try:
|
100
|
+
ip_address = external_port.fixed_ips[0]["ip_address"]
|
101
|
+
except Exception as e:
|
102
|
+
logger.warning(f"No IP address found for port {external_port.id}")
|
103
|
+
|
104
|
+
try:
|
105
|
+
subnet_id = external_port.fixed_ips[0]["subnet_id"]
|
106
|
+
except Exception as e:
|
107
|
+
logger.warning(f"No subnet ID found for {external_port.id}")
|
108
|
+
|
109
|
+
try:
|
110
|
+
subnet: OSSubnet = self.connection.get_subnet_by_id(subnet_id)
|
111
|
+
|
112
|
+
subnet_cidr = subnet.cidr
|
113
|
+
except Exception as e:
|
114
|
+
logger.warning(f"No subnet cidr found for port {external_port.id}")
|
115
|
+
|
116
|
+
mapped_device_project = ["network:floatingip", "network:router_gateway"]
|
117
|
+
|
118
|
+
project_id = (
|
119
|
+
external_port.project_id
|
120
|
+
if external_port.device_owner not in mapped_device_project
|
121
|
+
else self._map_project_id(
|
122
|
+
device_owner=external_port.device_owner,
|
123
|
+
device_id=external_port.device_id,
|
124
|
+
)
|
125
|
+
)
|
126
|
+
|
127
|
+
network: OSNetwork = self.connection.get_network(name_or_id=external_port.network_id)
|
128
|
+
|
129
|
+
vlan_id = None
|
130
|
+
|
131
|
+
try:
|
132
|
+
if not network.segments:
|
133
|
+
vlan_id = network.provider_segmentation_id
|
134
|
+
else:
|
135
|
+
logger.warning(f"Multiple segments mapped for net id {network.id}")
|
136
|
+
except Exception as e:
|
137
|
+
logger.warning(f"Can not get vlan ID for external port {external_port.id}, net id {network.id}")
|
138
|
+
|
139
|
+
external_port_ret = ExternalPort(
|
140
|
+
port_id=external_port.id,
|
141
|
+
project_id=project_id,
|
142
|
+
network_id=external_port.network_id,
|
143
|
+
network_name=network.name,
|
144
|
+
subnet_id=subnet_id,
|
145
|
+
subnet_cidr=subnet_cidr,
|
146
|
+
ip_address=ip_address,
|
147
|
+
allowed_address_pairs=external_port.allowed_address_pairs,
|
148
|
+
device_id=external_port.device_id,
|
149
|
+
device_owner=external_port.device_owner,
|
150
|
+
status=external_port.status,
|
151
|
+
vlan_id=vlan_id
|
152
|
+
)
|
153
|
+
|
154
|
+
return external_port_ret
|
155
|
+
|
156
|
+
def _map_project_id(self, device_owner: str, device_id: str) -> str:
|
157
|
+
|
158
|
+
if device_owner == "network:router_gateway":
|
159
|
+
return self._map_project_id_router(device_id=device_id)
|
160
|
+
elif device_owner == "network:floatingip":
|
161
|
+
return self._map_project_id_floating(device_id=device_id)
|
162
|
+
|
163
|
+
return ""
|
164
|
+
|
165
|
+
def _map_project_id_router(self, device_id: str) -> str:
|
166
|
+
project_id = osi_neutron.get_router_project(
|
167
|
+
self.connection, router_id=device_id
|
168
|
+
)
|
169
|
+
|
170
|
+
return project_id
|
171
|
+
|
172
|
+
def _map_project_id_floating(self, device_id: str) -> str:
|
173
|
+
project_id = osi_neutron.get_floating_ip_project(
|
174
|
+
self.connection, floating_ip_id=device_id
|
175
|
+
)
|
176
|
+
|
177
|
+
return project_id
|
@@ -1,9 +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
|
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
|