Skip to content

Commit 6f5d956

Browse files
authored
VM verification and Logs (#896)
1 parent 4bda8b8 commit 6f5d956

File tree

8 files changed

+450
-50
lines changed

8 files changed

+450
-50
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ terraform.tfstate
221221
/benchmark_runner/main/perf_key.txt
222222
/venv.sh
223223

224+
# Google drive credentials
225+
/benchmark_runner/main/credentials.json
226+
/benchmark_runner/main/token.json
227+
224228
# Emacs autosave and backup files
225229
*~
226230
**/#*#

benchmark_runner/common/clouds/BareMetal/bare_metal_operations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def _wait_for_upgrade_complete(self, oc: OC, sleep_time: int = SHORT_TIMEOUT):
101101
"""
102102
current_wait_time = 0
103103
logger.info(f'Waiting until the upgrade to version {self._upgrade_ocp_version} starts...')
104-
oc.wait_for_upgrade_start(upgrade_version=self._upgrade_ocp_version)
104+
oc.wait_for_ocp_upgrade_start(upgrade_version=self._upgrade_ocp_version)
105105
while self._provision_timeout <= 0 or current_wait_time <= self._provision_timeout and oc.upgrade_in_progress():
106106
logger.info(f'Waiting till OCP upgrade complete, waiting {int(current_wait_time / 60)} minutes')
107107
# sleep for x seconds

benchmark_runner/common/google_drive/google_drive_operations.py

Lines changed: 235 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11

22
import os
33
import logging
4+
45
from googleapiclient.discovery import build
56
from google.oauth2.credentials import Credentials
67
from googleapiclient.http import MediaFileUpload
78
from google.auth.transport.requests import Request
89
from google_auth_oauthlib.flow import InstalledAppFlow
910
from benchmark_runner.common.logger.logger_time_stamp import logger # Added logger import
1011

11-
# Configure logging
12-
logging.basicConfig(level=logging.INFO)
13-
logger = logging.getLogger(__name__)
14-
1512
# Define the scope
1613
SCOPES = ['https://www.googleapis.com/auth/drive']
1714

@@ -23,31 +20,232 @@ class GoogleDriveOperations:
2320
1. credentials.json - Obtain from the "Google Cloud Console" under "APIs & Services" > "Credentials" > "Create Credentials" and select "OAuth 2.0 Client ID".
2421
2. token.json - This is generated automatically. If a browser is not available, copy the token from a machine with a browser.
2522
"""
26-
def __init__(self):
23+
def __init__(self, google_drive_path: str, credentials_path: str, token_path: str, shared_drive_id: str):
2724
"""
2825
Initializes GoogleDriveOperations with authentication.
2926
"""
27+
self._google_drive_path = google_drive_path
28+
self._credentials_path = credentials_path
29+
self._token_path = token_path
30+
self._shared_drive_id = shared_drive_id
3031
self.creds = self.authenticate()
3132
self.service = build('drive', 'v3', credentials=self.creds)
3233

3334
def authenticate(self):
3435
"""
35-
Authenticates and returns credentials using token.json or interactive login.
36+
Authenticates and returns credentials using token or interactive login.
3637
:return: Credentials object
3738
"""
3839
creds = None
39-
if os.path.exists('token.json'):
40-
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
40+
if os.path.exists(self._token_path):
41+
creds = Credentials.from_authorized_user_file(self._token_path, SCOPES)
4142
if not creds or not creds.valid:
4243
if creds and creds.expired and creds.refresh_token:
4344
creds.refresh(Request())
4445
else:
45-
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
46+
flow = InstalledAppFlow.from_client_secrets_file(self._credentials_path, SCOPES)
4647
creds = flow.run_local_server(port=0)
47-
with open('token.json', 'w') as token_file:
48+
with open(self._token_path, 'w') as token_file:
4849
token_file.write(creds.to_json())
4950
return creds
5051

52+
def list_folders_and_files_in_shared_drive(self, shared_drive_id):
53+
"""
54+
Lists all folders and files within a specified Google Drive shared drive.
55+
:param shared_drive_id: The ID of the shared drive to list.
56+
"""
57+
try:
58+
logger.info(f'Folders and Files in shared drive with ID {shared_drive_id}:')
59+
self.list_files_in_folder(shared_drive_id)
60+
logger.info("Folder and file listing successful!")
61+
except Exception as e:
62+
logger.error(f"An error occurred: {e}")
63+
64+
def get_folder_id(self, folder_names, shared_drive_id):
65+
"""
66+
Finds the ID of a nested folder structure in the specified shared drive.
67+
:param folder_names: A list of folder names to traverse.
68+
:param shared_drive_id: The ID of the shared drive.
69+
:return: The ID of the innermost folder if the full path exists, else None.
70+
"""
71+
parent_id = shared_drive_id
72+
73+
for folder_name in folder_names:
74+
query = f"'{parent_id}' in parents and mimeType='application/vnd.google-apps.folder' and name='{folder_name}'"
75+
response = self.service.files().list(
76+
q=query,
77+
supportsAllDrives=True,
78+
fields='files(id)',
79+
spaces='drive'
80+
).execute()
81+
82+
folders = response.get('files', [])
83+
if folders:
84+
# Folder exists, move to the next level
85+
parent_id = folders[0]['id']
86+
else:
87+
# If any folder in the path doesn't exist, return None
88+
return None
89+
90+
return parent_id
91+
92+
def create_folder_at_path(self, folder_path, parent_folder_id):
93+
"""
94+
Creates folders along a specified path in Google Drive and returns the ID of the last folder.
95+
:param folder_path: The path of folders to create, e.g., '2024/09/15/10'.
96+
:param parent_folder_id: The ID of the parent folder where the path starts.
97+
:return: The ID of the last folder in the path if successful, otherwise None.
98+
"""
99+
for folder_name in folder_path.split('/'):
100+
parent_folder_id = self._find_or_create_folder(folder_name, parent_folder_id)
101+
if not parent_folder_id:
102+
return None
103+
return parent_folder_id
104+
105+
def _find_or_create_folder(self, folder_name, parent_folder_id):
106+
"""
107+
Finds a folder by name within a specified parent folder or creates it if not found.
108+
:param folder_name: The name of the folder to find or create.
109+
:param parent_folder_id: The ID of the parent folder to search within.
110+
:return: The ID of the found or newly created folder.
111+
"""
112+
folder_id = self._find_folder_id(parent_folder_id, folder_name)
113+
if folder_id:
114+
return folder_id
115+
116+
# Folder does not exist, create it
117+
return self.create_folder(folder_name, parent_folder_id)
118+
119+
def create_folder(self, folder_name, parent_folder_id):
120+
"""
121+
Creates a new folder in the specified parent folder.
122+
:param folder_name: The name of the new folder to create.
123+
:param parent_folder_id: The ID of the parent folder where the new folder will be created.
124+
:return: The ID of the newly created folder if successful, otherwise None.
125+
"""
126+
try:
127+
folder_metadata = {
128+
'name': folder_name,
129+
'mimeType': 'application/vnd.google-apps.folder',
130+
'parents': [parent_folder_id]
131+
}
132+
folder = self.service.files().create(
133+
body=folder_metadata,
134+
fields='id',
135+
supportsAllDrives=True
136+
).execute()
137+
return folder.get('id')
138+
except Exception as e:
139+
logger.error(f"Error creating folder '{folder_name}': {e}")
140+
return None
141+
142+
def _find_folder_id(self, parent_folder_id, folder_name):
143+
"""
144+
Helper method to find the folder ID by name within a specified parent folder.
145+
:param parent_folder_id: The ID of the parent folder to search within.
146+
:param folder_name: The name of the folder to find.
147+
:return: The ID of the folder if found, otherwise None.
148+
"""
149+
page_token = None
150+
while True:
151+
results = self.service.files().list(
152+
q=f"'{parent_folder_id}' in parents and trashed = false and mimeType = 'application/vnd.google-apps.folder'",
153+
includeItemsFromAllDrives=True,
154+
supportsAllDrives=True,
155+
pageSize=100,
156+
fields="nextPageToken, files(id, name)",
157+
pageToken=page_token
158+
).execute()
159+
160+
items = results.get('files', [])
161+
for item in items:
162+
if item['name'] == folder_name:
163+
return item['id']
164+
165+
page_token = results.get('nextPageToken', None)
166+
if page_token is None:
167+
break
168+
169+
return None
170+
171+
def get_folder_id_by_path(self, folder_path, parent_folder_id):
172+
"""
173+
Checks if a folder path exists in Google Drive and returns the ID of the last folder in the path.
174+
:param folder_path: The path of folders to check, e.g., '2024/09/15'.
175+
:param parent_folder_id: The ID of the parent folder where the search starts.
176+
:return: The ID of the last folder in the path if it exists, otherwise None.
177+
"""
178+
folder_names = folder_path.split('/')
179+
current_parent_id = parent_folder_id
180+
181+
for folder_name in folder_names:
182+
folder_id = self._find_folder_id(current_parent_id, folder_name)
183+
if folder_id:
184+
current_parent_id = folder_id
185+
else:
186+
# Folder in path does not exist
187+
return None
188+
189+
return current_parent_id
190+
191+
def is_folder_name_exists(self, folder_id, target_folder_name):
192+
"""
193+
Recursively checks if a folder with the specified name exists in a given Google Drive folder.
194+
:param folder_id: The ID of the folder to start the search.
195+
:param target_folder_name: The name of the folder to find.
196+
:return: True if the folder exists, otherwise False.
197+
"""
198+
page_token = None
199+
while True:
200+
results = self.service.files().list(
201+
q=f"'{folder_id}' in parents and trashed = false",
202+
includeItemsFromAllDrives=True,
203+
supportsAllDrives=True,
204+
pageSize=100,
205+
fields="nextPageToken, files(id, name, mimeType)",
206+
pageToken=page_token
207+
).execute()
208+
209+
items = results.get('files', [])
210+
for item in items:
211+
if item['mimeType'] == 'application/vnd.google-apps.folder':
212+
if item['name'] == target_folder_name:
213+
return item['id']
214+
# Recursively check in the subfolders
215+
if self.is_folder_name_exists(item['id'], target_folder_name):
216+
return item['id']
217+
218+
page_token = results.get('nextPageToken', None)
219+
if page_token is None:
220+
break
221+
222+
return False
223+
224+
def get_drive_folder_url(self, folder_path, parent_folder_id):
225+
"""
226+
Retrieves the Google Drive folder URL based on the folder path without uploading a file.
227+
:param folder_path: The folder path to retrieve or create.
228+
:param parent_folder_id: The parent folder ID where the folder path begins.
229+
:return: The Google Drive URL for the folder.
230+
"""
231+
# Check if the folder exists in the specified path
232+
folder_id = self.get_folder_id_by_path(folder_path, parent_folder_id)
233+
234+
if folder_id:
235+
# Folder exists, return the folder URL
236+
folder_url = f"{self._google_drive_path}/{folder_id}"
237+
return folder_url
238+
else:
239+
# If folder does not exist, create it along the path
240+
folder_id = self.create_folder_at_path(folder_path, parent_folder_id)
241+
if folder_id:
242+
# Return the newly created folder's URL
243+
folder_url = f"{self._google_drive_path}/{folder_id}"
244+
return folder_url
245+
else:
246+
logger.error(f"Unable to create or find the folder path: {folder_path}")
247+
return None
248+
51249
def list_files_in_folder(self, folder_id, level=0):
52250
"""
53251
Recursively lists files and folders in a specified Google Drive folder.
@@ -82,18 +280,6 @@ def list_files_in_folder(self, folder_id, level=0):
82280

83281
return items
84282

85-
def list_folders_and_files_in_shared_drive(self, shared_drive_id):
86-
"""
87-
Lists all folders and files within a specified Google Drive shared drive.
88-
:param shared_drive_id: The ID of the shared drive to list.
89-
"""
90-
try:
91-
logger.info(f'Folders and Files in shared drive with ID {shared_drive_id}:')
92-
self.list_files_in_folder(shared_drive_id)
93-
logger.info("Folder and file listing successful!")
94-
except Exception as e:
95-
logger.error(f"An error occurred: {e}")
96-
97283
def find_existing_file(self, file_name, shared_drive_id):
98284
"""
99285
Finds an existing file in a specified Google Drive shared drive.
@@ -113,9 +299,10 @@ def find_existing_file(self, file_name, shared_drive_id):
113299

114300
def upload_file(self, file_path, shared_drive_id):
115301
"""
116-
Uploads a file to a specified Google Drive shared drive and override if exist
302+
Uploads a file to a specified Google Drive shared drive and returns the Google Drive folder URL.
117303
:param file_path: The local path of the file to upload.
118304
:param shared_drive_id: The ID of the shared drive to upload the file to.
305+
:return: The Google Drive URL for the folder containing the uploaded file.
119306
"""
120307
try:
121308
file_name = os.path.basename(file_path)
@@ -124,7 +311,7 @@ def upload_file(self, file_path, shared_drive_id):
124311

125312
if existing_file:
126313
file_id = existing_file['id']
127-
file = self.service.files().update(
314+
self.service.files().update(
128315
fileId=file_id,
129316
media_body=media,
130317
supportsAllDrives=True,
@@ -142,7 +329,31 @@ def upload_file(self, file_path, shared_drive_id):
142329
supportsAllDrives=True,
143330
fields='id'
144331
).execute()
332+
file_id = file.get('id')
145333
logger.info(f"File '{file_name}' uploaded successfully to shared drive with ID: {shared_drive_id}")
146334

335+
# Return the Google Drive URL for the folder containing the uploaded file
336+
folder_url = f"{self._google_drive_path}/{shared_drive_id}"
337+
return folder_url
338+
147339
except Exception as e:
148340
logger.error(f"An error occurred: {e}")
341+
return None
342+
343+
def upload_file_to_folder(self, file_path: str, folder_path: str, parent_folder_id: str):
344+
"""
345+
This method uploads file into google drive folder_path and return the folder url
346+
@param file_path: the file path to upload to google drive
347+
@param folder_path: google drive folder path
348+
@param parent_folder_id: the base drive folder
349+
@return:the folder url
350+
"""
351+
folder_id = self.get_folder_id_by_path(
352+
folder_path=folder_path,
353+
parent_folder_id=parent_folder_id)
354+
# new path
355+
if not folder_id:
356+
folder_id = self.create_folder_at_path(
357+
folder_path=folder_path,
358+
parent_folder_id=parent_folder_id)
359+
return self.upload_file(file_path=file_path, shared_drive_id=folder_id)

0 commit comments

Comments
 (0)