osi-dump 0.1.4__py3-none-any.whl → 0.1.5__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.
@@ -31,7 +31,6 @@ class RoleAssignmentBatchHandler:
31
31
  def process(self):
32
32
  for importer, exporter in self._importer_exporter_list:
33
33
  try:
34
- # importer to exporter
35
34
  exporter.export_role_assignments(importer=importer)
36
35
  except Exception as e:
37
36
  logger.warning(e)
@@ -12,22 +12,14 @@ class ExcelRoleAssignmentExporter(RoleAssignmentExporter):
12
12
  self.output_file = output_file
13
13
 
14
14
  def export_role_assignments(self, importer: RoleAssignmentImporter):
15
- # Sheet 1: User Effective Roles
16
- df_effective = pd.json_normalize(
17
- (role.model_dump() for role in importer.calculate_effective_roles())
18
- )
19
- if not df_effective.empty:
20
- df_effective.sort_values(by=['user_name', 'role_name'], inplace=True)
21
- self._export_to_sheet(df_effective, f"{self.sheet_name_prefix}-effective")
22
-
23
- # Sheet 2: Raw User Roles
15
+ # Sheet 1: Raw User Role Assignments
24
16
  df_user = pd.json_normalize(
25
17
  (role.model_dump() for role in importer.get_user_roles())
26
18
  )
27
19
  if not df_user.empty:
28
20
  self._export_to_sheet(df_user, f"{self.sheet_name_prefix}-user")
29
21
 
30
- # Sheet 3: Raw Group Roles
22
+ # Sheet 2: Raw Group Role Assignments
31
23
  df_group = pd.json_normalize(
32
24
  (role.model_dump() for role in importer.get_group_roles())
33
25
  )
@@ -1,10 +1,7 @@
1
1
  import logging
2
-
3
- import concurrent
4
-
2
+ from typing import Generator
5
3
  from openstack.connection import Connection
6
4
  from openstack.compute.v2.server import Server
7
-
8
5
  from openstack.compute.v2.flavor import Flavor as OSFlavor
9
6
 
10
7
  from osi_dump.importer.instance.instance_importer import InstanceImporter
@@ -17,63 +14,45 @@ class OpenStackInstanceImporter(InstanceImporter):
17
14
  def __init__(self, connection: Connection):
18
15
  self.connection = connection
19
16
 
20
- def import_instances(self) -> list[Instance]:
21
- """Import instances information from Openstack
22
-
23
- Raises:
24
- Exception: Raises exception if fetching server failed
25
-
26
- Returns:
27
- list[Instance]: _description_
28
- """
17
+ def import_instances(self) -> Generator[Instance, None, None]:
18
+ """Import instances information from Openstack as a generator."""
29
19
 
30
20
  logger.info(f"Importing instances for {self.connection.auth['auth_url']}")
31
-
32
21
  try:
33
- servers: list[Server] = list(
34
- self.connection.compute.servers(details=True, all_projects=True)
35
- )
36
- except Exception as e:
37
- raise Exception(
38
- f"Can not fetch instances for {self.connection.auth['auth_url']}: {e}"
39
- ) from e
40
-
41
- instances: list[Instance] = []
42
-
43
- with concurrent.futures.ThreadPoolExecutor() as executor:
44
- futures = [
45
- executor.submit(self._get_instance_info, server) for server in servers
46
- ]
47
- for future in concurrent.futures.as_completed(futures):
48
- instances.append(future.result())
22
+ server_iterator = self.connection.compute.servers(details=True, all_projects=True)
23
+
24
+ for server in server_iterator:
25
+ yield self._get_instance_info(server)
49
26
 
50
- logger.info(f"Imported instances for {self.connection.auth['auth_url']}")
51
-
52
- return instances
27
+ except Exception as e:
28
+ logger.error(f"Cannot fetch instances for {self.connection.auth['auth_url']}: {e}")
29
+ return
30
+
31
+ logger.info(f"Finished importing instances for {self.connection.auth['auth_url']}")
53
32
 
54
33
  def _get_instance_info(self, server: Server) -> Instance:
55
-
56
34
  project_name = None
57
35
  project_id = None
36
+ project = None
58
37
  try:
59
38
  project = self.connection.identity.get_project(server.project_id)
60
39
  project_name = project.name
61
40
  project_id = project.id
62
41
  except Exception as e:
63
- logger.warn(
42
+ logger.warning(
64
43
  f"Unable to obtain project name for instance: {server.name}: {e}"
65
44
  )
66
45
 
67
46
  domain_name = None
68
- try:
69
- domain = self.connection.identity.get_domain(project.domain_id)
70
- domain_name = domain.name
71
- except Exception as e:
72
- logger.warning(
73
- f"Unable to obtain domain name for instance {server.name}: {e}"
74
- )
47
+ if project:
48
+ try:
49
+ domain = self.connection.identity.get_domain(project.domain_id)
50
+ domain_name = domain.name
51
+ except Exception as e:
52
+ logger.warning(
53
+ f"Unable to obtain domain name for instance {server.name}: {e}"
54
+ )
75
55
 
76
- # Lấy thông tin IPv4 private
77
56
  private_v4_ips = []
78
57
  floating_ip = None
79
58
 
@@ -91,28 +70,25 @@ class OpenStackInstanceImporter(InstanceImporter):
91
70
 
92
71
  vgpus = None
93
72
  vgpu_type = None
94
-
95
73
  vgpu_metadata_property = "pci_passthrough:alias"
96
74
 
97
75
  try:
98
76
  flavor: OSFlavor = self.connection.get_flavor(
99
77
  name_or_id=server.flavor["id"]
100
78
  )
101
-
102
- vgpu_prop: str = flavor.extra_specs[vgpu_metadata_property]
103
-
104
- vgpu_props = vgpu_prop.split(":")
105
-
106
- vgpu_type = vgpu_props[0]
107
- vgpus = int(vgpu_props[1])
108
-
109
- except Exception as e:
79
+ if flavor and flavor.extra_specs:
80
+ vgpu_prop: str = flavor.extra_specs.get(vgpu_metadata_property)
81
+ if vgpu_prop:
82
+ vgpu_props = vgpu_prop.split(":")
83
+ vgpu_type = vgpu_props[0]
84
+ vgpus = int(vgpu_props[1])
85
+ except Exception:
110
86
  pass
111
87
 
112
- image_id = server.image["id"]
113
- flavor_id = server.flavor["id"]
88
+ image_id = server.image.get("id") if server.image else None
89
+ flavor_id = server.flavor.get("id") if server.flavor else None
114
90
 
115
- instance = Instance(
91
+ return Instance(
116
92
  instance_id=server.id,
117
93
  instance_name=server.name,
118
94
  project_id=project_id,
@@ -131,6 +107,4 @@ class OpenStackInstanceImporter(InstanceImporter):
131
107
  vgpu_type=vgpu_type,
132
108
  image_id=image_id,
133
109
  flavor_id=flavor_id
134
- )
135
-
136
- return instance
110
+ )
@@ -4,7 +4,7 @@ from openstack.identity.v3.role_assignment import RoleAssignment as OSRoleAssign
4
4
  from typing import Generator
5
5
 
6
6
  from .role_assignment_importer import RoleAssignmentImporter
7
- from osi_dump.model.role_assignment import UserRoleAssignment, GroupRoleAssignment, EffectiveUserRole
7
+ from osi_dump.model.role_assignment import UserRoleAssignment, GroupRoleAssignment
8
8
  from osi_dump.api.keystone import get_users
9
9
 
10
10
  logger = logging.getLogger(__name__)
@@ -15,15 +15,14 @@ class OpenStackRoleAssignmentImporter(RoleAssignmentImporter):
15
15
  self.users = {}
16
16
  self.roles = {}
17
17
  self.groups = {}
18
- self.group_members = {} # group_id -> [user_id_1, user_id_2]
19
- self._raw_assignments = None # Cache
18
+ self._raw_assignments = None
20
19
 
21
- def _fetch_all_data(self):
22
- """pre-cache for metadata."""
20
+ def _fetch_metadata(self):
21
+ """cache metadata"""
23
22
  if self._raw_assignments is not None:
24
- return
23
+ return
25
24
 
26
- logger.info(f"Pre-caching all role assignment metadata for {self.connection.auth['auth_url']}")
25
+ logger.info(f"Pre-caching metadata for role assignments on {self.connection.auth['auth_url']}")
27
26
 
28
27
  try:
29
28
  os_users = get_users(self.connection)
@@ -39,14 +38,7 @@ class OpenStackRoleAssignmentImporter(RoleAssignmentImporter):
39
38
 
40
39
  try:
41
40
  os_groups = list(self.connection.identity.groups())
42
- for group in os_groups:
43
- self.groups[group.id] = group.name
44
- try:
45
- members = list(self.connection.identity.group_users(group))
46
- self.group_members[group.id] = [user.id for user in members]
47
- except Exception as e:
48
- logger.warning(f"Could not fetch members for group {group.name}: {e}")
49
- self.group_members[group.id] = []
41
+ for group in os_groups: self.groups[group.id] = group.name
50
42
  except Exception as e:
51
43
  logger.error(f"Could not fetch groups: {e}")
52
44
 
@@ -57,7 +49,7 @@ class OpenStackRoleAssignmentImporter(RoleAssignmentImporter):
57
49
  self._raw_assignments = []
58
50
 
59
51
  def get_user_roles(self) -> Generator[UserRoleAssignment, None, None]:
60
- self._fetch_all_data()
52
+ self._fetch_metadata()
61
53
  for assignment in self._raw_assignments:
62
54
  if assignment.user:
63
55
  user_id = assignment.user.get('id')
@@ -75,7 +67,7 @@ class OpenStackRoleAssignmentImporter(RoleAssignmentImporter):
75
67
  )
76
68
 
77
69
  def get_group_roles(self) -> Generator[GroupRoleAssignment, None, None]:
78
- self._fetch_all_data()
70
+ self._fetch_metadata()
79
71
  for assignment in self._raw_assignments:
80
72
  if assignment.group:
81
73
  group_id = assignment.group.get('id')
@@ -86,32 +78,4 @@ class OpenStackRoleAssignmentImporter(RoleAssignmentImporter):
86
78
  role_id=role_id,
87
79
  role_name=self.roles.get(role_id),
88
80
  scope=assignment.scope
89
- )
90
-
91
- def calculate_effective_roles(self) -> Generator[EffectiveUserRole, None, None]:
92
- # generator
93
- # direct role
94
- for user_role in self.get_user_roles():
95
- yield EffectiveUserRole(
96
- user_id=user_role.user_id,
97
- user_name=user_role.user_name,
98
- role_id=user_role.role_id,
99
- role_name=user_role.role_name,
100
- scope=user_role.scope,
101
- inherited_from_group='[Direct]'
102
- )
103
-
104
- # inherited_from_group
105
- for group_role in self.get_group_roles():
106
- group_id = group_role.group_id
107
- if group_id in self.group_members:
108
- for user_id in self.group_members[group_id]:
109
- user_info = self.users.get(user_id, {})
110
- yield EffectiveUserRole(
111
- user_id=user_id,
112
- user_name=user_info.get('name'),
113
- role_id=group_role.role_id,
114
- role_name=group_role.role_name,
115
- scope=group_role.scope,
116
- inherited_from_group=group_role.group_name
117
- )
81
+ )
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from typing import Generator
3
- from osi_dump.model.role_assignment import UserRoleAssignment, GroupRoleAssignment, EffectiveUserRole
3
+ from osi_dump.model.role_assignment import UserRoleAssignment, GroupRoleAssignment
4
4
 
5
5
  class RoleAssignmentImporter(ABC):
6
6
  @abstractmethod
@@ -10,7 +10,7 @@ class RoleAssignmentImporter(ABC):
10
10
  @abstractmethod
11
11
  def get_group_roles(self) -> Generator[GroupRoleAssignment, None, None]:
12
12
  pass
13
-
14
- @abstractmethod
15
- def calculate_effective_roles(self) -> Generator[EffectiveUserRole, None, None]:
16
- pass
13
+
14
+ # @abstractmethod
15
+ # def calculate_effective_roles(self) -> Generator[EffectiveUserRole, None, None]:
16
+ # pass
@@ -20,11 +20,11 @@ class GroupRoleAssignment(BaseModel):
20
20
  role_name: Optional[str]
21
21
  scope: dict
22
22
 
23
- class EffectiveUserRole(BaseModel):
24
- model_config = ConfigDict(strict=True)
25
- user_id: str
26
- user_name: Optional[str]
27
- role_id: str
28
- role_name: Optional[str]
29
- scope: dict
30
- inherited_from_group: Optional[str]
23
+ #class EffectiveUserRole(BaseModel):
24
+ # model_config = ConfigDict(strict=True)
25
+ # user_id: str
26
+ # user_name: Optional[str]
27
+ # role_id: str
28
+ # role_name: Optional[str]
29
+ # scope: dict
30
+ # inherited_from_group: Optional[str]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: osi-dump
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: OpenStack information dump tool
5
5
  Author: TVKain
6
6
  License: Apache-2.0
@@ -16,7 +16,7 @@ osi_dump/batch_handler/instance_batch_handler.py,sha256=9Q6T7qLGgxVWGMWX9Re7rW0U
16
16
  osi_dump/batch_handler/load_balancer_batch_handler.py,sha256=57M8umBGPGkzJfES8Ge7NyW2PPkURTIH-jo5TfNKvhE,1855
17
17
  osi_dump/batch_handler/network_batch_handler.py,sha256=k-WLnz5UCiX70fGjLywRV_ufEMySSP8UZbdlI0W1DSM,1665
18
18
  osi_dump/batch_handler/project_batch_handler.py,sha256=8tpF3_yJMXXvOogX2iN1C4xx5_IKt_xIP71ZFwOzNPI,1677
19
- osi_dump/batch_handler/role_assignment_batch_handler.py,sha256=LBaPY7rD34sJSXznCx8_R4W4VZMOP3x45oHZrsKjYFM,1787
19
+ osi_dump/batch_handler/role_assignment_batch_handler.py,sha256=Ms1BkmoBqAeVlLOlb6lR-gj9rymI-xSdXIRiGSxK5T0,1747
20
20
  osi_dump/batch_handler/router_batch_handler.py,sha256=cjccPBF7nBzLMxaMgPYa7yNU6YLWz6Wcsbur7o9Jwa4,1636
21
21
  osi_dump/batch_handler/security_group_batch_handler.py,sha256=iI5s-Lup9masy1s0TNtdKTCYpbQ1Hznwqc3edfRsPyo,1747
22
22
  osi_dump/batch_handler/volume_batch_handler.py,sha256=Lqd5CHsdRZzr7dxCy0jiXKatTHFdqU4H7AdO0OFHiYU,1614
@@ -49,7 +49,7 @@ osi_dump/exporter/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
49
49
  osi_dump/exporter/project/excel_project_exporter.py,sha256=mr0QKYxkTt8ilFLyIjBZ9SFIFBOKV5hEaq5D0enam6A,946
50
50
  osi_dump/exporter/project/project_exporter.py,sha256=iD0TfkhNCGzu6GXDoK5amabPWNwbio8n16I68ezNWfc,165
51
51
  osi_dump/exporter/role_assignment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- osi_dump/exporter/role_assignment/excel_role_assignment_exporter.py,sha256=XPYcINXWZ1SLiYmo2DG3DSMd286rkxNigWvddHawNsc,1888
52
+ osi_dump/exporter/role_assignment/excel_role_assignment_exporter.py,sha256=nj4wCKHsQ39FtVLik93vs47f4YN78xPSTKGICJimp2Y,1524
53
53
  osi_dump/exporter/role_assignment/role_assignment_exporter.py,sha256=7PJuwTTkSolSWalbKY5iydniPGPUS5eoB3kf1mMFlNQ,277
54
54
  osi_dump/exporter/router/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  osi_dump/exporter/router/excel_router_exporter.py,sha256=rckGg5SMCK6Y1gbXjasWpkOnkBEWSj6c1jrtt0Pd-wU,930
@@ -76,7 +76,7 @@ osi_dump/importer/image/image_importer.py,sha256=-S4zjWvnEONK_G_D8cJaK7txDgICgmd
76
76
  osi_dump/importer/image/openstack_image_importer.py,sha256=jf0bE6SNV8vMInGsrMNWrtAt1U7cJqbRLMEPNpGQLGg,2666
77
77
  osi_dump/importer/instance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
78
  osi_dump/importer/instance/instance_importer.py,sha256=PaTGNBzMtIht624LGTumlXEZVdcLS2WkXvzeAtDNAHA,246
79
- osi_dump/importer/instance/openstack_instance_importer.py,sha256=PWckeP7o1QWdgGvfJ4sn2E7seEtK-J-wTf68gwv_f4Q,4385
79
+ osi_dump/importer/instance/openstack_instance_importer.py,sha256=aQIbIL_ftgW-sMYXBK65ZQ1cFsoFMN3ICX9m67pAo24,4100
80
80
  osi_dump/importer/load_balancer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
81
  osi_dump/importer/load_balancer/load_balancer_importer.py,sha256=8QPbe0DmaLEOcRcr82IcCuB1gRc0ZG-vIuSXiO_QfhQ,227
82
82
  osi_dump/importer/load_balancer/openstack_load_balancer_importer.py,sha256=U1DyAc_ca0fXR1n27sMk14R_X_vI2rQESOGBEpdlR4I,4146
@@ -87,8 +87,8 @@ osi_dump/importer/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
87
87
  osi_dump/importer/project/openstack_project_importer.py,sha256=wlPPGEi1uOBDCU0eoxsof6KjIs2lVy3laXiRvt53QyQ,5105
88
88
  osi_dump/importer/project/project_importer.py,sha256=DYQFTIPsROt0BYgPWI8NNRwyvnjmaTNThXoCB415xe8,200
89
89
  osi_dump/importer/role_assignment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
- osi_dump/importer/role_assignment/openstack_role_assignment_importer.py,sha256=uIdnvebqXcH8E_039ltQ-7LpCcqWAs-7dgZVLf0eJdw,5094
91
- osi_dump/importer/role_assignment/role_assignment_importer.py,sha256=5KerMFUQ8cXHXnn1RQORydNihL_21vkn8WFTpiYXtO0,555
90
+ osi_dump/importer/role_assignment/openstack_role_assignment_importer.py,sha256=ezUFhMIMNvRH-4Wbz8PtBkmmA5AqEvDO-9hm01mlQBo,3388
91
+ osi_dump/importer/role_assignment/role_assignment_importer.py,sha256=fNHhTufpopzUo-0j3HlHVa2pQSCxAxcS68Z16P7TW9w,543
92
92
  osi_dump/importer/router/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
93
93
  osi_dump/importer/router/openstack_router_importer.py,sha256=cV-R4qUFUYlAIVLFxxozlD6howOfjZ-O4vgU4mL5UhE,2868
94
94
  osi_dump/importer/router/router_importer.py,sha256=4tEbkMPErSrFiW648fSRwnd80DtSKbz70et-gzzRJMA,195
@@ -108,7 +108,7 @@ osi_dump/model/instance.py,sha256=UjJagGoD86sSEkAC4vS0j4VFoHTGZvns-TV45KynOtU,66
108
108
  osi_dump/model/load_balancer.py,sha256=uPYqzoh2vbPeAhKPHdM2TGhh5-ZpGC0u2fhX6IZxdKk,597
109
109
  osi_dump/model/network.py,sha256=HJmRIrVPCu4FLEPVY3Q0W05CE42qFhiEpMId2gclSRs,565
110
110
  osi_dump/model/project.py,sha256=nTVswIdfhLH-vvtvrcHvxc31Wol_jPCKopGVMhEN2XE,782
111
- osi_dump/model/role_assignment.py,sha256=X_-GeBLwTlwjzOlLKIMPrazCQBsnBLuUDGocaCOmH1g,803
111
+ osi_dump/model/role_assignment.py,sha256=tv9h4HqNrXI-WV8deBm8d-onpy6-wJtHy6V6Hu7FmTY,811
112
112
  osi_dump/model/router.py,sha256=CORkRw5AuU_A8eGY1t2FJSFX0l0nExzjZTGl3I0hGLs,440
113
113
  osi_dump/model/security_group.py,sha256=MJjmgSM8WOuGW2h4PxMv6PwlwLrZzRiToR-5JFUDbBc,642
114
114
  osi_dump/model/volume.py,sha256=cHbIVmG1Cs08AkQGE167Ih3hYCIWRjdKHSwD3SDb4js,448
@@ -123,8 +123,8 @@ osi_dump/util/extract_hostname.py,sha256=NdpF2tYt-Gl1Wx4nVZA0FkBzh-IbPfid_dLGQrA
123
123
  osi_dump/util/openstack_util.py,sha256=m8Xcp2KNNf3jzo-J7BYj_SdnoNymRN-1DJeQcOwygDg,1347
124
124
  osi_dump/util/panda_excel.py,sha256=db53jqLsBhSE1oM14GbeKJZpF7RAUA7bHBjDh9Be8H4,760
125
125
  osi_dump/util/validate_dir_path.py,sha256=JHjZBsQIT5ubw8rnsHbw2hkKDBFzYMjmjQ_oJT8EtJc,527
126
- osi_dump-0.1.4.dist-info/METADATA,sha256=gLvhzT2bIRdlKkndUGA3iUcQ1TT-laKX3HO1hXPXRaQ,719
127
- osi_dump-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
128
- osi_dump-0.1.4.dist-info/entry_points.txt,sha256=ozm5sIBtXzLv6_FiUe26v1BgA3_xUReGLPhKQKZ56wQ,46
129
- osi_dump-0.1.4.dist-info/top_level.txt,sha256=OtAAwmJfcoPvlw_Cemo_H1aXIGV_7w0O2941KQt6faQ,9
130
- osi_dump-0.1.4.dist-info/RECORD,,
126
+ osi_dump-0.1.5.dist-info/METADATA,sha256=K1Em-pKBquQWRPhuIMAqMfuqJJZwzkJrqKYFFjA9PVc,719
127
+ osi_dump-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
128
+ osi_dump-0.1.5.dist-info/entry_points.txt,sha256=ozm5sIBtXzLv6_FiUe26v1BgA3_xUReGLPhKQKZ56wQ,46
129
+ osi_dump-0.1.5.dist-info/top_level.txt,sha256=OtAAwmJfcoPvlw_Cemo_H1aXIGV_7w0O2941KQt6faQ,9
130
+ osi_dump-0.1.5.dist-info/RECORD,,