osi-dump 0.1.2.1__py3-none-any.whl → 0.1.2.3__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 (36) hide show
  1. osi_dump/api/octavia.py +21 -4
  2. osi_dump/batch_handler/external_port_batch_handler.py +57 -0
  3. osi_dump/batch_handler/load_balancer_batch_handler.py +1 -3
  4. osi_dump/batch_handler/role_assignment_batch_handler.py +1 -1
  5. osi_dump/batch_handler/router_batch_handler.py +49 -0
  6. osi_dump/cli.py +32 -0
  7. osi_dump/exporter/external_port/__init__.py +0 -0
  8. osi_dump/exporter/external_port/excel_external_port_exporter.py +34 -0
  9. osi_dump/exporter/external_port/external_port_exporter.py +7 -0
  10. osi_dump/exporter/load_balancer/excel_load_balancer_exporter.py +2 -0
  11. osi_dump/exporter/router/__init__.py +0 -0
  12. osi_dump/exporter/router/excel_router_exporter.py +30 -0
  13. osi_dump/exporter/router/router_exporter.py +7 -0
  14. osi_dump/importer/external_port/__init__.py +0 -0
  15. osi_dump/importer/external_port/external_port_importer.py +9 -0
  16. osi_dump/importer/external_port/openstack_external_port_importer.py +129 -0
  17. osi_dump/importer/hypervisor/openstack_hypervisor_importer.py +3 -10
  18. osi_dump/importer/instance/openstack_instance_importer.py +1 -0
  19. osi_dump/importer/load_balancer/openstack_load_balancer_importer.py +15 -7
  20. osi_dump/importer/role_assignment/openstack_role_assignment_importer.py +21 -4
  21. osi_dump/importer/router/__init__.py +0 -0
  22. osi_dump/importer/router/openstack_router_importer.py +86 -0
  23. osi_dump/importer/router/router_importer.py +9 -0
  24. osi_dump/model/external_port.py +27 -0
  25. osi_dump/model/image.py +2 -2
  26. osi_dump/model/instance.py +1 -0
  27. osi_dump/model/load_balancer.py +4 -2
  28. osi_dump/model/role_assignment.py +2 -2
  29. osi_dump/model/router.py +20 -0
  30. osi_dump/util/__init__.py +1 -0
  31. osi_dump/util/panda_excel.py +33 -0
  32. {osi_dump-0.1.2.1.dist-info → osi_dump-0.1.2.3.dist-info}/METADATA +3 -2
  33. {osi_dump-0.1.2.1.dist-info → osi_dump-0.1.2.3.dist-info}/RECORD +36 -19
  34. {osi_dump-0.1.2.1.dist-info → osi_dump-0.1.2.3.dist-info}/WHEEL +0 -0
  35. {osi_dump-0.1.2.1.dist-info → osi_dump-0.1.2.3.dist-info}/entry_points.txt +0 -0
  36. {osi_dump-0.1.2.1.dist-info → osi_dump-0.1.2.3.dist-info}/top_level.txt +0 -0
osi_dump/api/octavia.py CHANGED
@@ -1,17 +1,34 @@
1
1
  from openstack.connection import Connection
2
2
  from openstack.identity.v3.service import Service
3
+ from openstack.load_balancer.v2.load_balancer import LoadBalancer
3
4
 
4
5
 
5
- def get_amphorae(connection: Connection, load_balancer_id: str) -> str | None:
6
+ def get_load_balancers(connection: Connection) -> list[LoadBalancer]:
7
+ octavia_endpoint = connection.endpoint_for(
8
+ service_type="load-balancer", interface="public"
9
+ )
10
+
11
+ url = f"{octavia_endpoint}/v2.0/lbaas/loadbalancers"
12
+
13
+ response = connection.session.get(url)
14
+
15
+ data = response.json()
16
+
17
+ return data["loadbalancers"]
18
+
19
+
20
+ def get_amphoraes(connection: Connection, load_balancer_id: str) -> list[dict]:
6
21
 
7
22
  octavia_endpoint = connection.endpoint_for(
8
- service_type="octavia", interface="public"
23
+ service_type="load-balancer", interface="public"
9
24
  )
10
25
 
11
- url = f"{octavia_endpoint}/v2/octavia/amphorae"
26
+ url = f"{octavia_endpoint}/v2/octavia/amphorae?load_balancer_id={load_balancer_id}&fields=status&fields=compute_id"
12
27
 
13
28
  response = connection.session.get(url)
14
29
 
15
30
  data = response.json()
16
31
 
17
- return data["usages"]
32
+ amphoraes = data["amphorae"]
33
+
34
+ return amphoraes
@@ -0,0 +1,57 @@
1
+ import logging
2
+
3
+ from openstack.connection import Connection
4
+
5
+ from osi_dump.exporter.external_port.external_port_exporter import ExternalPortExporter
6
+ from osi_dump.exporter.external_port.excel_external_port_exporter import (
7
+ ExcelExternalPortExporter,
8
+ )
9
+
10
+ from osi_dump.importer.external_port.external_port_importer import ExternalPortImporter
11
+ from osi_dump.importer.external_port.openstack_external_port_importer import (
12
+ OpenStackExternalPortImporter,
13
+ )
14
+
15
+
16
+ from osi_dump import util
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class ExternalPortBatchHandler:
22
+ def __init__(self):
23
+ self._importer_exporter_list: list[
24
+ tuple[ExternalPortImporter, ExternalPortExporter]
25
+ ] = []
26
+
27
+ def add_importer_exporter_from_openstack_connections(
28
+ self, connections: list[Connection], output_file: str
29
+ ):
30
+ for connection in connections:
31
+ importer = OpenStackExternalPortImporter(connection)
32
+
33
+ sheet_name = (
34
+ f"{util.extract_hostname(connection.auth['auth_url'])}-external_port"
35
+ )
36
+ exporter = ExcelExternalPortExporter(
37
+ sheet_name=sheet_name, output_file=output_file
38
+ )
39
+
40
+ self.add_importer_exporter(importer=importer, exporter=exporter)
41
+
42
+ def add_importer_exporter(
43
+ self, importer: ExternalPortImporter, exporter: ExternalPortExporter
44
+ ):
45
+ self._importer_exporter_list.append((importer, exporter))
46
+
47
+ def process(self):
48
+
49
+ for importer, exporter in self._importer_exporter_list:
50
+ try:
51
+
52
+ external_ports = importer.import_external_ports()
53
+
54
+ exporter.export_external_ports(external_ports=external_ports)
55
+ except Exception as e:
56
+ logger.warning(e)
57
+ logger.warning("Skipping...")
@@ -34,9 +34,7 @@ class LoadBalancerBatchHandler:
34
34
  for connection in connections:
35
35
  importer = OpenStackLoadBalancerImporter(connection)
36
36
 
37
- sheet_name = (
38
- f"{util.extract_hostname(connection.auth['auth_url'])}-load_balancer"
39
- )
37
+ sheet_name = f"{util.extract_hostname(connection.auth['auth_url'])}-lb"
40
38
  exporter = ExcelLoadBalancerExporter(
41
39
  sheet_name=sheet_name, output_file=output_file
42
40
  )
@@ -35,7 +35,7 @@ class RoleAssignmentBatchHandler:
35
35
  importer = OpenStackRoleAssignmentImporter(connection)
36
36
 
37
37
  sheet_name = (
38
- f"{util.extract_hostname(connection.auth['auth_url'])}-role_assignment"
38
+ f"{util.extract_hostname(connection.auth['auth_url'])}-role_ass"
39
39
  )
40
40
  exporter = ExcelRoleAssignmentExporter(
41
41
  sheet_name=sheet_name, output_file=output_file
@@ -0,0 +1,49 @@
1
+ import logging
2
+
3
+ from openstack.connection import Connection
4
+
5
+ from osi_dump.exporter.router.router_exporter import (
6
+ RouterExporter,
7
+ )
8
+ from osi_dump.exporter.router.excel_router_exporter import ExcelRouterExporter
9
+
10
+ from osi_dump.importer.router.router_importer import RouterImporter
11
+ from osi_dump.importer.router.openstack_router_importer import (
12
+ OpenStackRouterImporter,
13
+ )
14
+
15
+
16
+ from osi_dump import util
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class RouterBatchHandler:
22
+ def __init__(self):
23
+ self._importer_exporter_list: list[tuple[RouterImporter, RouterExporter]] = []
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 = OpenStackRouterImporter(connection)
30
+
31
+ sheet_name = f"{util.extract_hostname(connection.auth['auth_url'])}-router"
32
+ exporter = ExcelRouterExporter(
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: RouterImporter, exporter: RouterExporter):
39
+ self._importer_exporter_list.append((importer, exporter))
40
+
41
+ def process(self):
42
+ for importer, exporter in self._importer_exporter_list:
43
+ try:
44
+ routers = importer.import_routers()
45
+
46
+ exporter.export_routers(routers=routers)
47
+ except Exception as e:
48
+ logger.warning(e)
49
+ logger.warning("Skipping...")
osi_dump/cli.py CHANGED
@@ -8,10 +8,12 @@ import typer
8
8
 
9
9
  from typing_extensions import Annotated
10
10
 
11
+ from osi_dump.batch_handler.external_port_batch_handler import ExternalPortBatchHandler
11
12
  from osi_dump.batch_handler.load_balancer_batch_handler import LoadBalancerBatchHandler
12
13
  from osi_dump.batch_handler.role_assignment_batch_handler import (
13
14
  RoleAssignmentBatchHandler,
14
15
  )
16
+ from osi_dump.batch_handler.router_batch_handler import RouterBatchHandler
15
17
 
16
18
  app = typer.Typer()
17
19
 
@@ -30,6 +32,11 @@ from osi_dump.batch_handler import (
30
32
  )
31
33
 
32
34
 
35
+ from osi_dump.importer.external_port.openstack_external_port_importer import (
36
+ OpenStackExternalPortImporter,
37
+ )
38
+
39
+
33
40
  from osi_dump import util
34
41
 
35
42
 
@@ -123,6 +130,26 @@ def _load_balancer(connections, output_path: str):
123
130
  _load_balancer_batch_handler.process()
124
131
 
125
132
 
133
+ def _router(connections, output_path: str):
134
+ _router_batch_handler = RouterBatchHandler()
135
+
136
+ _router_batch_handler.add_importer_exporter_from_openstack_connections(
137
+ connections, output_file=output_path
138
+ )
139
+
140
+ _router_batch_handler.process()
141
+
142
+
143
+ def _external_port(connections, output_path: str):
144
+ _external_batch_handler = ExternalPortBatchHandler()
145
+
146
+ _external_batch_handler.add_importer_exporter_from_openstack_connections(
147
+ connections, output_file=output_path
148
+ )
149
+
150
+ _external_batch_handler.process()
151
+
152
+
126
153
  def inner_main(file_path: str, output_path: str):
127
154
 
128
155
  logger = logging.getLogger(__name__)
@@ -146,6 +173,11 @@ def inner_main(file_path: str, output_path: str):
146
173
  _role_assignment(connections=connections, output_path=output_path)
147
174
 
148
175
  _load_balancer(connections=connections, output_path=output_path)
176
+
177
+ _router(connections=connections, output_path=output_path)
178
+
179
+ _external_port(connections=connections, output_path=output_path)
180
+
149
181
  util.excel_autosize_column(output_path)
150
182
 
151
183
  util.excel_sort_sheet(output_path)
File without changes
@@ -0,0 +1,34 @@
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.external_port.external_port_exporter import ExternalPortExporter
9
+
10
+ from osi_dump.model.external_port import ExternalPort
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class ExcelExternalPortExporter(ExternalPortExporter):
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_external_ports(self, external_ports: list[ExternalPort]):
21
+
22
+ df = pd.DataFrame(
23
+ [external_port.model_dump() for external_port in external_ports]
24
+ )
25
+
26
+ df = util.panda_excel.expand_list_column(df, "allowed_address_pairs")
27
+
28
+ logger.info(f"Exporting external_ports for {self.sheet_name}")
29
+ try:
30
+ util.export_data_excel(self.output_file, sheet_name=self.sheet_name, df=df)
31
+
32
+ logger.info(f"Exported external_ports for {self.sheet_name}")
33
+ except Exception as e:
34
+ logger.warning(f"Exporting external_ports for {self.sheet_name} error: {e}")
@@ -0,0 +1,7 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class ExternalPortExporter(ABC):
5
+ @abstractmethod
6
+ def export_external_ports(self, projects, output_file: str):
7
+ pass
@@ -24,6 +24,8 @@ class ExcelLoadBalancerExporter(LoadBalancerExporter):
24
24
  [load_balancer.model_dump() for load_balancer in load_balancers]
25
25
  )
26
26
 
27
+ df = util.expand_list_column(df, "amphoraes")
28
+
27
29
  logger.info(f"Exporting load_balancers for {self.sheet_name}")
28
30
  try:
29
31
  util.export_data_excel(self.output_file, sheet_name=self.sheet_name, df=df)
File without changes
@@ -0,0 +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}")
@@ -0,0 +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
File without changes
@@ -0,0 +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
@@ -0,0 +1,129 @@
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
+
13
+ from osi_dump.importer.external_port.external_port_importer import ExternalPortImporter
14
+ from osi_dump.model.external_port import ExternalPort
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class OpenStackExternalPortImporter(ExternalPortImporter):
20
+ def __init__(self, connection: Connection):
21
+ self.connection = connection
22
+
23
+ def _get_external_ports(self) -> list[OSPort]:
24
+
25
+ self.connection.list_networks()
26
+ # Get all external networks
27
+ networks = self.connection.network.networks(
28
+ is_router_external=True,
29
+ )
30
+
31
+ external_ports = []
32
+
33
+ for network in networks:
34
+ ex_ports = list(self.connection.network.ports(network_id=network.id))
35
+
36
+ for ex_port in ex_ports:
37
+ ex_port["segmentation_id"] = network.provider_segmentation_id
38
+
39
+ external_ports.append(ex_ports)
40
+
41
+ # Get all port on those networks
42
+
43
+ external_ports = list(np.array(external_ports).flatten())
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']}"
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
+ external_port_ret = ExternalPort(
117
+ port_id=external_port.id,
118
+ project_id=external_port.project_id,
119
+ network_id=external_port.network_id,
120
+ subnet_id=subnet_id,
121
+ subnet_cidr=subnet_cidr,
122
+ ip_address=ip_address,
123
+ allowed_address_pairs=external_port.allowed_address_pairs,
124
+ device_id=external_port.device_id,
125
+ device_owner=external_port.device_owner,
126
+ status=external_port.status,
127
+ )
128
+
129
+ return external_port_ret
@@ -30,12 +30,11 @@ class OpenStackHypervisorImporter(HypervisorImporter):
30
30
  list[Hypervisor]: _description_
31
31
  """
32
32
 
33
- logger.info(f"Importing hypervisors for {self.connection.auth['auth_url']}")
34
-
35
33
  try:
36
34
  oshypervisors: list[OSHypervisor] = list(
37
- self.connection.compute.hypervisors(details=True)
35
+ self.connection.compute.hypervisors(details=True, with_servers=True)
38
36
  )
37
+
39
38
  except Exception as e:
40
39
  raise Exception(
41
40
  f"Can not fetch hypervisor for {self.connection.auth['auth_url']}"
@@ -65,12 +64,6 @@ class OpenStackHypervisorImporter(HypervisorImporter):
65
64
  )
66
65
  )
67
66
 
68
- servers = list(
69
- self.connection.compute.servers(
70
- details=False, all_project=True, hypervisor=hypervisor.id
71
- )
72
- )
73
-
74
67
  usage_data = get_usage(self.connection, resource_provider_id=hypervisor.id)
75
68
 
76
69
  vcpu = rpi[0]
@@ -89,7 +82,7 @@ class OpenStackHypervisorImporter(HypervisorImporter):
89
82
  vcpus_usage=usage_data["VCPU"],
90
83
  memory_usage=usage_data["MEMORY_MB"],
91
84
  local_disk_usage=usage_data["DISK_GB"],
92
- vm_count=len(servers),
85
+ vm_count=len(hypervisor.servers),
93
86
  )
94
87
 
95
88
  return ret_hypervisor
@@ -96,6 +96,7 @@ class OpenStackInstanceImporter(InstanceImporter):
96
96
  private_v4_ips=private_v4_ips,
97
97
  floating_ip=floating_ip,
98
98
  status=server.status,
99
+ hypervisor=server.hypervisor_hostname,
99
100
  ram=server.flavor["ram"],
100
101
  vcpus=server.flavor["vcpus"],
101
102
  created_at=server.created_at,
@@ -11,6 +11,8 @@ from osi_dump.importer.load_balancer.load_balancer_importer import (
11
11
  )
12
12
  from osi_dump.model.load_balancer import LoadBalancer
13
13
 
14
+ import osi_dump.api.octavia as octavia_api
15
+
14
16
  logger = logging.getLogger(__name__)
15
17
 
16
18
 
@@ -31,12 +33,12 @@ class OpenStackLoadBalancerImporter(LoadBalancerImporter):
31
33
  logger.info(f"Importing load_balancers for {self.connection.auth['auth_url']}")
32
34
 
33
35
  try:
34
- osload_balancers: list[OSLoadBalancer] = list(
35
- self.connection.network.load_balancers()
36
+ osload_balancers: list[OSLoadBalancer] = octavia_api.get_load_balancers(
37
+ connection=self.connection
36
38
  )
37
39
  except Exception as e:
38
40
  raise Exception(
39
- f"Can not fetch load_balancers for {self.connection.auth['auth_url']}"
41
+ f"Can not fetch load_balancers for {self.connection.auth['auth_url']} {e}"
40
42
  ) from e
41
43
 
42
44
  load_balancers: list[LoadBalancer] = []
@@ -55,11 +57,17 @@ class OpenStackLoadBalancerImporter(LoadBalancerImporter):
55
57
 
56
58
  def _get_load_balancer_info(self, load_balancer: OSLoadBalancer) -> LoadBalancer:
57
59
 
60
+ amphoraes = octavia_api.get_amphoraes(
61
+ connection=self.connection, load_balancer_id=load_balancer["id"]
62
+ )
63
+
58
64
  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,
65
+ id=load_balancer["id"],
66
+ load_balancer_name=load_balancer["name"],
67
+ operating_status=load_balancer["operating_status"],
68
+ project_id=load_balancer["project_id"],
69
+ provisioning_status=load_balancer["provisioning_status"],
70
+ amphoraes=amphoraes,
63
71
  )
64
72
 
65
73
  return load_balancer_ret
@@ -58,6 +58,19 @@ class OpenStackRoleAssignmentImporter(RoleAssignmentImporter):
58
58
  self, role_assignment: OSRoleAssignment
59
59
  ) -> RoleAssignment:
60
60
 
61
+ user_id = None
62
+ role_id = None
63
+
64
+ try:
65
+ user_id = role_assignment.user["id"]
66
+ except Exception as e:
67
+ logger.warning(f"Can not get user id: {e}")
68
+
69
+ try:
70
+ role_id = role_assignment.role["id"]
71
+ except Exception as e:
72
+ logger.warning(f"Can not get role id: {e}")
73
+
61
74
  user_name = None
62
75
  role_name = None
63
76
 
@@ -65,17 +78,21 @@ class OpenStackRoleAssignmentImporter(RoleAssignmentImporter):
65
78
  role_name = self.connection.identity.get_role(
66
79
  role_assignment.role["id"]
67
80
  ).name
81
+
82
+ except Exception as e:
83
+ logger.warning(f"Can not get role name: {e}")
84
+
85
+ try:
68
86
  user_name = self.connection.identity.get_user(
69
87
  role_assignment.user["id"]
70
88
  ).name
71
-
72
89
  except Exception as e:
73
- logger.warning("Can not get role name or user name")
90
+ logger.warning(f"Can not get user name: {e}")
74
91
 
75
92
  role_assignment_ret = RoleAssignment(
76
- user_id=role_assignment.user["id"],
93
+ user_id=user_id,
77
94
  user_name=user_name,
78
- role_id=role_assignment.role["id"],
95
+ role_id=role_id,
79
96
  role_name=role_name,
80
97
  scope=role_assignment.scope,
81
98
  )
File without changes
@@ -0,0 +1,86 @@
1
+ import logging
2
+
3
+ import concurrent
4
+
5
+ from openstack.connection import Connection
6
+ from openstack.network.v2.router import Router as OSRouter
7
+
8
+ from osi_dump.importer.router.router_importer import (
9
+ RouterImporter,
10
+ )
11
+ from osi_dump.model.router import Router
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class OpenStackRouterImporter(RouterImporter):
17
+ def __init__(self, connection: Connection):
18
+ self.connection = connection
19
+
20
+ def import_routers(self) -> list[Router]:
21
+ """Import routers information from Openstack
22
+
23
+ Raises:
24
+ Exception: Raises exception if fetching router failed
25
+
26
+ Returns:
27
+ list[Router]: _description_
28
+ """
29
+
30
+ logger.info(f"Importing routers for {self.connection.auth['auth_url']}")
31
+
32
+ try:
33
+ osrouters: list[OSRouter] = list(self.connection.network.routers())
34
+ except Exception as e:
35
+ raise Exception(
36
+ f"Can not fetch routers for {self.connection.auth['auth_url']}"
37
+ ) from e
38
+
39
+ routers: list[Router] = []
40
+
41
+ with concurrent.futures.ThreadPoolExecutor() as executor:
42
+ futures = [
43
+ executor.submit(self._get_router_info, router) for router in osrouters
44
+ ]
45
+ for future in concurrent.futures.as_completed(futures):
46
+ routers.append(future.result())
47
+
48
+ logger.info(f"Imported routers for {self.connection.auth['auth_url']}")
49
+
50
+ return routers
51
+
52
+ def _get_router_info(self, router: OSRouter) -> Router:
53
+ """
54
+ {"network_id": "49760654-71d8-4967-8fdd-5a35d3ff78ef", "external_fixed_ips": [{"subnet_id": |
55
+ | | "c044a5c0-4b11-4d8d-ae5e-9ff4ce6c1be6", "ip_address": "10.0.2.188"}], "enable_snat": true}
56
+ """
57
+
58
+ external_net_id = None
59
+
60
+ try:
61
+ external_net_id = router.external_gateway_info["network_id"]
62
+ except Exception as e:
63
+ logger.warning(f"Could not get external net id for router: {router.id}")
64
+
65
+ external_net_ip = None
66
+
67
+ try:
68
+ external_net_ip = router.external_gateway_info["external_fixed_ips"][0][
69
+ "ip_address"
70
+ ]
71
+
72
+ except Exception as e:
73
+ logger.warning(f"Could not get external net ip for router {router.id}")
74
+
75
+ router_ret = Router(
76
+ router_id=router.id,
77
+ name=router.name,
78
+ external_net_id=external_net_id,
79
+ external_net_ip=external_net_ip,
80
+ status=router.status,
81
+ project_id=router.project_id,
82
+ created_at=router.created_at,
83
+ updated_at=router.updated_at,
84
+ )
85
+
86
+ return router_ret
@@ -0,0 +1,9 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from osi_dump.model.router import Router
4
+
5
+
6
+ class RouterImporter(ABC):
7
+ @abstractmethod
8
+ def import_routers(self) -> list[Router]:
9
+ pass
@@ -0,0 +1,27 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict, ValidationError
4
+
5
+
6
+ class ExternalPort(BaseModel):
7
+ model_config = ConfigDict(strict=True)
8
+
9
+ port_id: str
10
+
11
+ project_id: Optional[str]
12
+
13
+ subnet_id: Optional[str]
14
+
15
+ subnet_cidr: Optional[str]
16
+
17
+ ip_address: Optional[str]
18
+
19
+ network_id: Optional[str]
20
+
21
+ allowed_address_pairs: Optional[list[dict]]
22
+
23
+ device_id: Optional[str]
24
+
25
+ device_owner: Optional[str]
26
+
27
+ status: Optional[str]
osi_dump/model/image.py CHANGED
@@ -18,8 +18,8 @@ class Image(BaseModel):
18
18
 
19
19
  protected: bool
20
20
  status: str
21
- size: int
22
- virtual_size: int
21
+ size: Optional[int]
22
+ virtual_size: Optional[int]
23
23
  visibility: str
24
24
 
25
25
  created_at: str
@@ -16,5 +16,6 @@ class Instance(BaseModel):
16
16
  status: str
17
17
  ram: int
18
18
  vcpus: int
19
+ hypervisor: Optional[str]
19
20
  created_at: str
20
21
  updated_at: str
@@ -10,8 +10,10 @@ class LoadBalancer(BaseModel):
10
10
 
11
11
  load_balancer_name: Optional[str]
12
12
 
13
- status: str
13
+ provisioning_status: Optional[str]
14
14
 
15
- # amphora_id: Optional[str]
15
+ operating_status: Optional[str]
16
+
17
+ amphoraes: list[dict]
16
18
 
17
19
  project_id: Optional[str]
@@ -6,11 +6,11 @@ from pydantic import BaseModel, ConfigDict, ValidationError
6
6
  class RoleAssignment(BaseModel):
7
7
  model_config = ConfigDict(strict=True)
8
8
 
9
- user_id: str
9
+ user_id: Optional[str]
10
10
 
11
11
  user_name: Optional[str]
12
12
 
13
- role_id: str
13
+ role_id: Optional[str]
14
14
 
15
15
  role_name: Optional[str]
16
16
 
@@ -0,0 +1,20 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict, ValidationError
4
+
5
+
6
+ class Router(BaseModel):
7
+ model_config = ConfigDict(strict=True)
8
+
9
+ router_id: str
10
+
11
+ name: Optional[str]
12
+
13
+ external_net_id: Optional[str]
14
+ external_net_ip: Optional[str]
15
+
16
+ status: str
17
+ project_id: Optional[str]
18
+
19
+ created_at: str
20
+ updated_at: str
osi_dump/util/__init__.py CHANGED
@@ -4,3 +4,4 @@ from .create_file import create_file
4
4
  from .export_data_excel import export_data_excel
5
5
  from .excel_sort_sheet import excel_sort_sheet
6
6
  from .validate_dir_path import validate_dir_path
7
+ from .panda_excel import expand_list_column
@@ -0,0 +1,33 @@
1
+ import pandas as pd
2
+
3
+ from pandas import DataFrame
4
+
5
+
6
+ def expand_list_column(df, column):
7
+ # Find the maximum length of the list in the column
8
+ max_len = df[column].apply(len).max()
9
+
10
+ # Expand each dictionary in the list into columns
11
+ expanded_df = pd.DataFrame(
12
+ df[column]
13
+ .apply(lambda x: [{**item} for item in x] + [{}] * (max_len - len(x)))
14
+ .tolist(),
15
+ index=df.index,
16
+ )
17
+
18
+ # Flatten the nested dictionaries into separate columns
19
+ expanded_df = pd.json_normalize(expanded_df.to_dict(orient="records"))
20
+
21
+ new_columns = []
22
+ for i in range(max_len):
23
+ for key in expanded_df.columns[i::max_len]:
24
+ new_key = key.split(".")[-1] # Get the actual key name
25
+ new_columns.append(f"{column}_{i+1}.{new_key}")
26
+
27
+ # Rename the columns to reflect the nested structure
28
+ expanded_df.columns = new_columns
29
+
30
+ # Drop the original column and join the expanded columns
31
+ df = df.drop(column, axis=1).join(expanded_df)
32
+
33
+ return df
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: osi-dump
3
- Version: 0.1.2.1
4
- Summary: OpenStack instances information dump tool
3
+ Version: 0.1.2.3
4
+ Summary: OpenStack information dump tool
5
5
  Author: TVKain
6
6
  License: Apache-2.0
7
7
  Classifier: License :: OSI Approved :: Apache Software License
@@ -12,6 +12,7 @@ Requires-Dist: openstacksdk
12
12
  Requires-Dist: pydantic
13
13
  Requires-Dist: pandas
14
14
  Requires-Dist: openpyxl
15
+ Requires-Dist: numpy
15
16
  Provides-Extra: test
16
17
  Requires-Dist: pytest ; extra == 'test'
17
18
 
@@ -1,20 +1,25 @@
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=5sFtsS91Em26PmziWybKFW7bxnfRompH-1UTnWIKGkc,5425
3
+ osi_dump/cli.py,sha256=vLijmcrWieCVK4cSLN2sK9ltWlercw9Zg6yBEvZtPkg,6379
4
4
  osi_dump/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- osi_dump/api/octavia.py,sha256=rT6d10OCQRdMnqvZTlW1gRMe1vOk8Rgct58oUIvDoyg,433
5
+ osi_dump/api/octavia.py,sha256=_vuuZ-Pcj4oV1A3Sf_RSiuc_UxcHXKLty87HEyipPGg,950
6
6
  osi_dump/api/placement.py,sha256=9yADLulo1HfUnPLE7IJt4ZY8e2jRTaoeV4J4MMiKCew,455
7
7
  osi_dump/batch_handler/__init__.py,sha256=wsiE42GCjbKgXBzpiahWEDF_-IXCKzr6PyrLn0oEKSc,288
8
+ osi_dump/batch_handler/external_port_batch_handler.py,sha256=kWT7cKmcZZPY1mauYDB_qaCd42CzVbTof7lm7le4U6c,1821
8
9
  osi_dump/batch_handler/flavor_batch_handler.py,sha256=Cxf-rkuW5MrrOyiKi9N3InsdDGku7Bf0CAaPNhhM0hE,1589
9
10
  osi_dump/batch_handler/floating_ip_batch_handler.py,sha256=bEkT4BRi85qir-a1i7eEI_arA0LENq1gD6xHj8IdXu0,1771
10
11
  osi_dump/batch_handler/hypervisor_batch_handler.py,sha256=vkv6SAx1arPNVvFJ6RyvbJjC2F2Hes9km7dwhL4NJDY,1755
11
12
  osi_dump/batch_handler/image_batch_handler.py,sha256=aGF_jnHXuBc7IRFoLLCrSFD8h4TP0g98T_NtBXkZjd4,1564
12
13
  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
14
+ osi_dump/batch_handler/load_balancer_batch_handler.py,sha256=rpbi-n-KsYPGDmlRND5zqcVW6DYVgffmE5najUf2wT4,1796
14
15
  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
16
+ osi_dump/batch_handler/role_assignment_batch_handler.py,sha256=45TtVDDRjp9scpW9GCxbl-b6MoTm_kp0YHchEz630Zk,1882
17
+ osi_dump/batch_handler/router_batch_handler.py,sha256=XelVNw_2u00Rdnz20SI2HIPPJKwz3623BbceMGnDS8Q,1587
16
18
  osi_dump/batch_handler/volume_batch_handler.py,sha256=UAU34FZD8XkJkmlr4Idk4NgFBzjD52PxekJDgV1ekG0,1569
17
19
  osi_dump/exporter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ osi_dump/exporter/external_port/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ osi_dump/exporter/external_port/excel_external_port_exporter.py,sha256=FgLQersxmb-g2el02PxMFWSO0Chn5YdxEMXfDM_Jtn4,1108
22
+ osi_dump/exporter/external_port/external_port_exporter.py,sha256=LK7r_Do87ZONgmlH8FdtB-k1C_tT0ie3I0dCQyb6OUA,169
18
23
  osi_dump/exporter/flavor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
24
  osi_dump/exporter/flavor/excel_flavor_exporter.py,sha256=_wNVToj0FsIkaLbqn7-TWETrtUftBM1Pjr-0WaBJtBI,876
20
25
  osi_dump/exporter/flavor/flavor_exporter.py,sha256=-zQ8776yk7vHpiZUOcX61V8KxA40AAq8foV7fD0i1g0,155
@@ -31,7 +36,7 @@ osi_dump/exporter/instance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
31
36
  osi_dump/exporter/instance/excel_instance_exporter.py,sha256=8WTv3RDOdUkumyWzwUK4KAZCnnq9P2yKi5TC091I9fs,931
32
37
  osi_dump/exporter/instance/instance_exporter.py,sha256=5CuKKvTa5S2_Ds7fap6tle4go9pOFmQ5VEf6O7tjwBo,161
33
38
  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
39
+ osi_dump/exporter/load_balancer/excel_load_balancer_exporter.py,sha256=LX_4olvcHEfhTejTKoE_UStUpaRHslU_hcIBkk_9rnE,1063
35
40
  osi_dump/exporter/load_balancer/load_balancer_exporter.py,sha256=Z5uvEKz1UG_dpAw5KVh-IX5PWLzlPt7pV9773bkgjXs,175
36
41
  osi_dump/exporter/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
42
  osi_dump/exporter/project/excel_project_exporter.py,sha256=2U3Tvn_Bk4xEQk3Tmh-oj5WXAG1bfxI6m7WVPF1upQw,916
@@ -39,9 +44,15 @@ osi_dump/exporter/project/project_exporter.py,sha256=q3VAmtmBP4iq9YEW9Eescm3vjAV
39
44
  osi_dump/exporter/role_assignment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
45
  osi_dump/exporter/role_assignment/excel_role_assignment_exporter.py,sha256=CvMmueVclc22A7BPx8qR2-zXyr6FptI31bMHtyih2CA,1070
41
46
  osi_dump/exporter/role_assignment/role_assignment_exporter.py,sha256=MmqFhhF7HWFoULNdDPt8yuW0GZmDxV262iEnLkLKw1s,181
47
+ osi_dump/exporter/router/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ osi_dump/exporter/router/excel_router_exporter.py,sha256=RNvTWCDbp5NYvqPoh82FfLcVwvYa49MSG0pRC1d-Cgo,900
49
+ osi_dump/exporter/router/router_exporter.py,sha256=DZxDVnBnHZej3ZfMHO9gwsvonUWlRSAH1q9ShtFu_iM,155
42
50
  osi_dump/exporter/volume/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
51
  osi_dump/exporter/volume/excel_volume_exporter.py,sha256=BhesTGXMQF3BAwHgJMYfnxFgHxZo7TKPePG8q9T8ONI,865
44
52
  osi_dump/exporter/volume/volume_exporter.py,sha256=YoPvytC0ctWeWwVcG6pb0XwkF4N0QcGAoUHa3QldkEg,155
53
+ osi_dump/importer/external_port/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ osi_dump/importer/external_port/external_port_importer.py,sha256=mLFNwjaYiUNk3DO74GUCXC1eCaWbymGjKJKex3O2z-U,218
55
+ osi_dump/importer/external_port/openstack_external_port_importer.py,sha256=qnGTDVu-F7xNh7TSOmhyz8bV4fgMZm3WkcYRO1iTDZ8,4055
45
56
  osi_dump/importer/flavor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
57
  osi_dump/importer/flavor/flavor_importer.py,sha256=IfU2L8N8EO4eESnEDirwe9U-GXSTuTcsdrlDxD95tcQ,186
47
58
  osi_dump/importer/flavor/openstack_flavor_importer.py,sha256=y3uFCls7H-l1tu11T_PaEoWghhdxINsf7baRAShXC1w,1876
@@ -50,47 +61,53 @@ osi_dump/importer/floating_ip/floating_ip_importer.py,sha256=2_lCZYF-r2dgdL4Yzws
50
61
  osi_dump/importer/floating_ip/openstack_floating_ip_importer.py,sha256=xuALHyiyb4LdRgFN0hZvOx0pImKpGsLUtPWW_1q52gc,2286
51
62
  osi_dump/importer/hypervisor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
63
  osi_dump/importer/hypervisor/hypervisor_importer.py,sha256=JuoJBltqFYhH-Ql9TLUPHX2YurS0JFV7Augrc6bDJ5Q,206
53
- osi_dump/importer/hypervisor/openstack_hypervisor_importer.py,sha256=8EP99VPMrm4RUSHDbMmiuZeDOnwY17RLtJGotHd6ETs,3093
64
+ osi_dump/importer/hypervisor/openstack_hypervisor_importer.py,sha256=82lSo5cMdvMQ9snU_eIVNOsHp5cT5v8Sf9xSEGZfBzg,2870
54
65
  osi_dump/importer/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
66
  osi_dump/importer/image/image_importer.py,sha256=6zwAMnS58S2HGwARwebqf4VE9IBQBv5Ot6nmcn9H4fY,181
56
67
  osi_dump/importer/image/openstack_image_importer.py,sha256=Tc2eZ4fU_2S-fp_vuDWutqPcyV6Erz17nDLjzjusihY,2413
57
68
  osi_dump/importer/instance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
69
  osi_dump/importer/instance/instance_importer.py,sha256=TaaPgEFVVMRT3mSXrzQkSaSIBPBwwANpEaWCgRsgImc,196
59
- osi_dump/importer/instance/openstack_instance_importer.py,sha256=b1OB-8_7DlwvOo7TX5zUG64XXtUufKhgCc3lhgNqxaY,3394
70
+ osi_dump/importer/instance/openstack_instance_importer.py,sha256=hTCdrTvY-hsjXb15gDmpKaKTjJJACUVSRahvHsDOi38,3445
60
71
  osi_dump/importer/load_balancer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
72
  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
73
+ osi_dump/importer/load_balancer/openstack_load_balancer_importer.py,sha256=sX5ZMHT-QPIuAD4YBwitxj8l5fMvbOsA-BOQxLL84lU,2392
63
74
  osi_dump/importer/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
75
  osi_dump/importer/project/openstack_project_importer.py,sha256=K8Si2uaC88L2CxXi68A4ML9mlWKwnZp1ABDiufFUZ8g,2988
65
76
  osi_dump/importer/project/project_importer.py,sha256=jwEvxteFbSwyWMV8hKAtf5Lo2bZysWkQ1L_NVUE8XOQ,191
66
77
  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
78
+ osi_dump/importer/role_assignment/openstack_role_assignment_importer.py,sha256=bff9rutp2835KA0ibVsvtCZStNgtiTkc7IKUsCmaXRo,3003
68
79
  osi_dump/importer/role_assignment/role_assignment_importer.py,sha256=Faorx0qsgdXjv5y2t-7obpV3wFfbmByx_-8b9yBr7L8,228
80
+ osi_dump/importer/router/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
+ osi_dump/importer/router/openstack_router_importer.py,sha256=-8xJ9hV7Y9ZpUXIEl3PHsGvggp9r57-A9hL8Tm_lb7c,2731
82
+ osi_dump/importer/router/router_importer.py,sha256=L2i0Fnh3iZEsP_PFtx1j0yWTpkmgHsc6Pobii8lDRCo,186
69
83
  osi_dump/importer/volume/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
84
  osi_dump/importer/volume/openstack_volume_importer.py,sha256=Tte9fX91oxEoRcUZPJd7g6oH6izcWy8WwFCapg_ZY1M,2454
71
85
  osi_dump/importer/volume/volume_importer.py,sha256=tmDTE9L9vtl75GR79blSxa_MVsRU6LDCbR0yJk0xKwo,186
72
86
  osi_dump/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
87
  osi_dump/model/authentication_info.py,sha256=02kXxtILfjh8t45_-bPM8rtyRk2cQcJK6l2d1bPih7k,257
88
+ osi_dump/model/external_port.py,sha256=4FlyG8ZmQO7nNdavmRBhK8ZMsNogmhMqEBa03okvqXM,477
74
89
  osi_dump/model/flavor.py,sha256=-G8FaH_qiVrgtRxAWhdpC1c9FRdXLRroG-WJ03-DRZ4,318
75
90
  osi_dump/model/floating_ip.py,sha256=CRJufC5ZaxxcbGvdot7Af-sO8uyKbyQK9zHljfBnyFA,427
76
91
  osi_dump/model/hypervisor.py,sha256=pToa-rg7LldKd-h3aNZDJQPy5dhYDIXehq-tr8_xv1I,336
77
- osi_dump/model/image.py,sha256=ahW0rRb2mgqoPqYhRzn_qnyShKvCvNZPlcDs_bnyt6g,445
78
- osi_dump/model/instance.py,sha256=flNywojuBj7ZyFTnWvl2rpvzL3Ju-QtuUY69DSPfPs8,464
79
- osi_dump/model/load_balancer.py,sha256=ve0vEbIAZLR7RBCbEk_MGR8wrfKQ9dI21Jx6V7nFoR4,298
92
+ osi_dump/model/image.py,sha256=XidrVfSYEidgKP5Qh4auRAi1AgDagvTW-zMdhfwSenE,465
93
+ osi_dump/model/instance.py,sha256=DSQ0F0CTHL0f_GMZ4GwH2D-Q_KvRmrNyCWTpCzDlqBs,494
94
+ osi_dump/model/load_balancer.py,sha256=T5RU6gm36ePYCh3KQ_OYO44FHMfxTcSNaiuKP5E_9CY,352
80
95
  osi_dump/model/project.py,sha256=3fNsDcWxuRVBS96W98C_Fia82qt14InjUM7n7rBCX6E,679
81
- osi_dump/model/role_assignment.py,sha256=dwuXVxgHJ8pIu8_i_w9kZ0r0uaQQXAMDTYnLrDY3O9U,290
96
+ osi_dump/model/role_assignment.py,sha256=fNt05y4aFF6b71Yps_EHzWavv8wF-jYx7gd3WAhqy6Y,310
97
+ osi_dump/model/router.py,sha256=nO0XW0mpabr4ajM40Biuva63N8YWulZUrhH5kmPnKgI,363
82
98
  osi_dump/model/volume.py,sha256=1p5Xw0LPxfroJwSYtE-n_Gv4MsRDA_sSvc7SQY_Uo8I,371
83
99
  osi_dump/os_connection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
100
  osi_dump/os_connection/get_connections.py,sha256=1zeir4cEtzJOUOn53zUmlD9lWMvYXhuRr0IhI5U1DAw,1753
85
- osi_dump/util/__init__.py,sha256=GvhYTETVePJAsp0LfseMGtuRFWbbCc2xox-QSGQA3Us,286
101
+ osi_dump/util/__init__.py,sha256=obJLcem8iWbVC3NIk4GHBMwwAsW-FcrwRdfzphuDjpY,330
86
102
  osi_dump/util/create_file.py,sha256=hcEspFD0VZDtXCaG5QtMkV37GsbAHATdxYlClTszVK8,242
87
103
  osi_dump/util/excel_autosize_column.py,sha256=zzQ6uXkQhHAqVn9fUAgNjoCH_HiNEC9Dcj4OBqHd6rw,1102
88
104
  osi_dump/util/excel_sort_sheet.py,sha256=o4jXtP1ZFYtAGzkAP5S8Tym4h-SEoFBAI3j24y-24UM,1047
89
105
  osi_dump/util/export_data_excel.py,sha256=VYSxDBZ7dgSbTj3n_8RRPqe183tILNh6wJW-UnFvJUU,882
90
106
  osi_dump/util/extract_hostname.py,sha256=IpdklGHevmtRu67xeSRE_5n2mvWGI1sDsnJwExo_AR0,111
107
+ osi_dump/util/panda_excel.py,sha256=GHHLguKLMm1sq4FHTPHABTjx7IqpOcGF_3OJT-cJORE,1011
91
108
  osi_dump/util/validate_dir_path.py,sha256=pL_OrY8JnNwk3vj6Zp6bsZtgHXhszSGRoqIt-1G5S90,507
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,,
109
+ osi_dump-0.1.2.3.dist-info/METADATA,sha256=5XPQ1B8SqhBGn8zazSnh-eTjMceLCvp2gFNdoZrmBG4,675
110
+ osi_dump-0.1.2.3.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
111
+ osi_dump-0.1.2.3.dist-info/entry_points.txt,sha256=ozm5sIBtXzLv6_FiUe26v1BgA3_xUReGLPhKQKZ56wQ,46
112
+ osi_dump-0.1.2.3.dist-info/top_level.txt,sha256=OtAAwmJfcoPvlw_Cemo_H1aXIGV_7w0O2941KQt6faQ,9
113
+ osi_dump-0.1.2.3.dist-info/RECORD,,