mirror of
https://github.com/kevingruesser/bootstrap-vz.git
synced 2025-08-24 15:36:27 +00:00
131 lines
3.5 KiB
Python
131 lines
3.5 KiB
Python
![]() |
import hashlib
|
||
|
import logging
|
||
|
import os
|
||
|
import requests
|
||
|
|
||
|
|
||
|
class OracleStorageAPIClient:
|
||
|
MEGABYTE = 1024**2
|
||
|
|
||
|
def __init__(self, username, password, identity_domain, container):
|
||
|
self.username = username
|
||
|
self.password = password
|
||
|
self.identity_domain = identity_domain
|
||
|
self.container = container
|
||
|
self.base_url = 'https://' + identity_domain + '.storage.oraclecloud.com'
|
||
|
self.log = logging.getLogger(__name__)
|
||
|
|
||
|
def _fail(self, error):
|
||
|
raise RuntimeError('Oracle Storage Cloud API - ' + error)
|
||
|
|
||
|
@property
|
||
|
def auth_token(self):
|
||
|
headers = {
|
||
|
'X-Storage-User': 'Storage-{id_domain}:{user}'.format(
|
||
|
id_domain=self.identity_domain,
|
||
|
user=self.username,
|
||
|
),
|
||
|
'X-Storage-Pass': self.password,
|
||
|
}
|
||
|
url = self.base_url + '/auth/v1.0'
|
||
|
response = requests.get(url, headers=headers)
|
||
|
if response.status_code == 200:
|
||
|
return response.headers.get('x-auth-token')
|
||
|
else:
|
||
|
self._fail(response.text)
|
||
|
|
||
|
@property
|
||
|
def chunk_size(self):
|
||
|
file_size = os.path.getsize(self.file_path)
|
||
|
if file_size > (300 * self.MEGABYTE):
|
||
|
chunk_size = 100 * self.MEGABYTE
|
||
|
else:
|
||
|
chunk_size = 50 * self.MEGABYTE
|
||
|
return chunk_size
|
||
|
|
||
|
def compare_files(self):
|
||
|
uploaded_file_md5 = hashlib.md5()
|
||
|
downloaded_file_md5 = hashlib.md5()
|
||
|
files = [self.file_path, self.target_file_path]
|
||
|
hashes = [uploaded_file_md5, downloaded_file_md5]
|
||
|
for f, h in zip(files, hashes):
|
||
|
with open(f, 'rb') as current_file:
|
||
|
while True:
|
||
|
data = current_file.read(self.MEGABYTE)
|
||
|
if not data:
|
||
|
break
|
||
|
h.update(data)
|
||
|
if uploaded_file_md5.hexdigest() != downloaded_file_md5.hexdigest():
|
||
|
self.log.error('File hashes mismatch')
|
||
|
else:
|
||
|
self.log.info('Both files have the same hash')
|
||
|
|
||
|
def create_manifest(self):
|
||
|
headers = {
|
||
|
'X-Auth-Token': self.auth_token,
|
||
|
'X-Object-Manifest': '{container}/{object_name}-'.format(
|
||
|
container=self.container,
|
||
|
object_name=self.file_name,
|
||
|
),
|
||
|
'Content-Length': '0',
|
||
|
}
|
||
|
url = self.object_url
|
||
|
self.log.info('Creating remote manifest to join chunks')
|
||
|
response = requests.put(url, headers=headers)
|
||
|
if response.status_code != 201:
|
||
|
self._fail(response.text)
|
||
|
|
||
|
def download_file(self):
|
||
|
headers = {
|
||
|
'X-Auth-Token': self.auth_token,
|
||
|
}
|
||
|
url = self.object_url
|
||
|
response = requests.get(url, headers=headers, stream=True)
|
||
|
if response.status_code != 200:
|
||
|
self._fail(response.text)
|
||
|
with open(self.target_file_path, 'wb') as f:
|
||
|
for chunk in response.iter_content(chunk_size=self.MEGABYTE):
|
||
|
if chunk:
|
||
|
f.write(chunk)
|
||
|
|
||
|
@property
|
||
|
def file_name(self):
|
||
|
return os.path.basename(self.file_path)
|
||
|
|
||
|
@property
|
||
|
def object_url(self):
|
||
|
url = '{base}/v1/Storage-{id_domain}/{container}/{object_name}'.format(
|
||
|
base=self.base_url,
|
||
|
id_domain=self.identity_domain,
|
||
|
container=self.container,
|
||
|
object_name=self.file_name,
|
||
|
)
|
||
|
return url
|
||
|
|
||
|
def upload_file(self):
|
||
|
f = open(self.file_path, 'rb')
|
||
|
n = 1
|
||
|
while True:
|
||
|
chunk = f.read(self.chunk_size)
|
||
|
if not chunk:
|
||
|
break
|
||
|
chunk_name = '{name}-{number}'.format(
|
||
|
name=self.file_name,
|
||
|
number='{0:04d}'.format(n),
|
||
|
)
|
||
|
headers = {
|
||
|
'X-Auth-Token': self.auth_token,
|
||
|
}
|
||
|
url = '{base}/v1/Storage-{id_domain}/{container}/{object_chunk_name}'.format(
|
||
|
base=self.base_url,
|
||
|
id_domain=self.identity_domain,
|
||
|
container=self.container,
|
||
|
object_chunk_name=chunk_name,
|
||
|
)
|
||
|
self.log.info('Uploading chunk ' + chunk_name)
|
||
|
response = requests.put(url, data=chunk, headers=headers)
|
||
|
if response.status_code != 201:
|
||
|
self._fail(response.text)
|
||
|
n += 1
|
||
|
self.create_manifest()
|