156 lines
5.0 KiB
Python
156 lines
5.0 KiB
Python
# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
from rackclient.lib import RACK_CTX
|
|
from rackclient import exceptions
|
|
from swiftclient import client as swift_client
|
|
from swiftclient import exceptions as swift_exc
|
|
|
|
import json
|
|
import logging
|
|
import tempfile
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
SWIFT_PORT = 8080
|
|
|
|
|
|
def _get_swift_client():
|
|
if RACK_CTX.fs_endpoint:
|
|
try:
|
|
d = json.loads(RACK_CTX.fs_endpoint)
|
|
credentials = {
|
|
"user": d["os_username"],
|
|
"key": d["os_password"],
|
|
"tenant_name": d["os_tenant_name"],
|
|
"authurl": d["os_auth_url"],
|
|
"auth_version": "2"
|
|
}
|
|
return swift_client.Connection(**credentials)
|
|
except (ValueError, KeyError):
|
|
msg = "The format of fs_endpoint is invalid."
|
|
raise exceptions.InvalidFSEndpointError(msg)
|
|
else:
|
|
authurl = "http://%s:%d/auth/v1.0" % (RACK_CTX.proxy_ip, SWIFT_PORT)
|
|
|
|
credentials = {
|
|
"user": "rack:admin",
|
|
"key": "admin",
|
|
"authurl": authurl
|
|
}
|
|
swift = swift_client.Connection(**credentials)
|
|
authurl, token = swift.get_auth()
|
|
|
|
return swift_client.Connection(preauthurl=authurl, preauthtoken=token)
|
|
|
|
|
|
def listdir(directory):
|
|
swift = _get_swift_client()
|
|
directory = directory.strip('/')
|
|
|
|
files = []
|
|
try:
|
|
objects = swift.get_container(directory)[1]
|
|
for o in objects:
|
|
file_path = '/' + directory + '/' + o['name']
|
|
files.append(File(file_path))
|
|
except swift_exc.ClientException as e:
|
|
if e.http_status == 404:
|
|
msg = "Directory '%s' does not exist." % directory
|
|
raise exceptions.InvalidDirectoryError(msg)
|
|
else:
|
|
raise exceptions.FileSystemAccessError()
|
|
|
|
return files
|
|
|
|
|
|
class File(object):
|
|
|
|
def __init__(self, file_path, mode="r"):
|
|
self.path = file_path
|
|
self.file = None
|
|
if mode not in ('r', 'w'):
|
|
raise ValueError(
|
|
"mode must be 'r' or 'w', not %s" % mode)
|
|
else:
|
|
self.mode = mode
|
|
|
|
def get_name(self):
|
|
return self.path.strip('/').split('/', 1)[1]
|
|
|
|
def get_directory(self):
|
|
return self.path.strip('/').split('/', 1)[0]
|
|
|
|
def load(self, chunk_size=None):
|
|
if self.file:
|
|
return
|
|
|
|
if self.mode == 'r':
|
|
self.file = tempfile.TemporaryFile()
|
|
swift = _get_swift_client()
|
|
|
|
try:
|
|
_, contents = swift.get_object(self.get_directory(),
|
|
self.get_name(), chunk_size)
|
|
if chunk_size:
|
|
for c in contents:
|
|
self.file.write(c)
|
|
else:
|
|
self.file.write(contents)
|
|
self.file.flush()
|
|
self.file.seek(0)
|
|
except swift_exc.ClientException as e:
|
|
if e.http_status == 404:
|
|
msg = "File '%s' does not exist." % self.path
|
|
raise exceptions.InvalidFilePathError(msg)
|
|
else:
|
|
raise exceptions.FileSystemAccessError()
|
|
|
|
def write(self, *args, **kwargs):
|
|
if not self.file:
|
|
self.file = tempfile.TemporaryFile()
|
|
|
|
self.file.write(*args, **kwargs)
|
|
|
|
def close(self):
|
|
if self.mode == 'w':
|
|
swift = _get_swift_client()
|
|
|
|
try:
|
|
swift.put_container(self.get_directory())
|
|
self.file.seek(0)
|
|
swift.put_object(self.get_directory(), self.get_name(),
|
|
self.file)
|
|
except swift_exc.ClientException as e:
|
|
if e.http_status == 404:
|
|
msg = ("Directory '%s' does not exist. "
|
|
"The file object will be closed."
|
|
% self.get_directory())
|
|
raise exceptions.InvalidDirectoryError(msg)
|
|
else:
|
|
msg = ("Could not save the file to the file system. "
|
|
"The file object will be closed.")
|
|
raise exceptions.FileSystemAccessError(msg)
|
|
finally:
|
|
self.file.close()
|
|
|
|
self.file.close()
|
|
|
|
def __getattr__(self, name):
|
|
if self.file:
|
|
return getattr(self.file, name)
|
|
else:
|
|
raise AttributeError("%s instance has no attribute '%s'",
|
|
self.__class__.__name__, name)
|