Mohammed Junaid e625cc40ff swift: Passing account name in container_update.
This patch also contains fixes to bugs
  * 811501
  * 812498
  * 821310

Also, removed the default set of users in the proxy-server.conf file.

Change-Id: Ief83905d10ff7bf7c43685ada4d7f05959cee9d1
BUG: 821310
Signed-off-by: Mohammed Junaid <junaid@redhat.com>
Reviewed-on: http://review.gluster.com/3390
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vijay@gluster.com>
2013-04-29 16:35:54 -04:00

485 lines
17 KiB
Python

# Copyright (c) 2011 Red Hat, Inc.
#
# 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.
import os
from swift.plugins.utils import clean_metadata, dir_empty, rmdirs, mkdirs, \
validate_account, validate_container, check_valid_account, is_marker, \
get_container_details, get_account_details, create_container_metadata, \
create_account_metadata, DEFAULT_GID, DEFAULT_UID, get_account_details, \
validate_object, create_object_metadata, read_metadata, write_metadata
from swift.common.constraints import CONTAINER_LISTING_LIMIT, \
check_mount
from swift.plugins.utils import X_CONTENT_TYPE, X_CONTENT_LENGTH, X_TIMESTAMP,\
X_PUT_TIMESTAMP, X_TYPE, X_ETAG, X_OBJECTS_COUNT, X_BYTES_USED, \
X_CONTAINER_COUNT, CONTAINER
from swift import plugins
def strip_obj_storage_path(path, string='/mnt/gluster-object'):
"""
strip /mnt/gluster-object
"""
return path.replace(string, '').strip('/')
DATADIR = 'containers'
class DiskCommon(object):
def is_deleted(self):
return not os.path.exists(self.datadir)
def filter_prefix(self, objects, prefix):
"""
Accept sorted list.
"""
found = 0
filtered_objs = []
for object_name in objects:
if object_name.startswith(prefix):
filtered_objs.append(object_name)
found = 1
else:
if found:
break
return filtered_objs
def filter_delimiter(self, objects, delimiter, prefix):
"""
Accept sorted list.
Objects should start with prefix.
"""
filtered_objs=[]
for object_name in objects:
tmp_obj = object_name.replace(prefix, '', 1)
sufix = tmp_obj.split(delimiter, 1)
new_obj = prefix + sufix[0]
if new_obj and new_obj not in filtered_objs:
filtered_objs.append(new_obj)
return filtered_objs
def filter_marker(self, objects, marker):
"""
TODO: We can traverse in reverse order to optimize.
Accept sorted list.
"""
filtered_objs=[]
found = 0
if objects[-1] < marker:
return filtered_objs
for object_name in objects:
if object_name > marker:
filtered_objs.append(object_name)
return filtered_objs
def filter_end_marker(self, objects, end_marker):
"""
Accept sorted list.
"""
filtered_objs=[]
for object_name in objects:
if object_name < end_marker:
filtered_objs.append(object_name)
else:
break
return filtered_objs
def filter_limit(self, objects, limit):
filtered_objs=[]
for i in range(0, limit):
filtered_objs.append(objects[i])
return filtered_objs
def update_account(self, metadata):
acc_path = self.datadir
write_metadata(acc_path, metadata)
self.metadata = metadata
class DiskDir(DiskCommon):
"""
Manage object files on disk.
:param path: path to devices on the node
:param device: device name
:param partition: partition on the device the object lives in
:param account: account name for the object
:param container: container name for the object
:param obj: object name for the object
:param keep_data_fp: if True, don't close the fp, otherwise close it
:param disk_chunk_Size: size of chunks on file reads
"""
def __init__(self, path, device, partition, account, container, logger,
uid=DEFAULT_UID, gid=DEFAULT_GID, fs_object=None):
self.root = path
device = account
if container:
self.name = container
else:
self.name = None
if self.name:
self.datadir = os.path.join(path, account, self.name)
else:
self.datadir = os.path.join(path, device)
self.account = account
self.device_path = os.path.join(path, device)
if not check_mount(path, device):
check_valid_account(account, fs_object)
self.logger = logger
self.metadata = {}
self.uid = int(uid)
self.gid = int(gid)
# Create a dummy db_file in /etc/swift
self.db_file = '/etc/swift/db_file.db'
if not os.path.exists(self.db_file):
file(self.db_file, 'w+')
self.dir_exists = os.path.exists(self.datadir)
if self.dir_exists:
try:
self.metadata = read_metadata(self.datadir)
except EOFError:
create_container_metadata(self.datadir)
else:
return
if container:
if not self.metadata:
create_container_metadata(self.datadir)
self.metadata = read_metadata(self.datadir)
else:
if not validate_container(self.metadata):
create_container_metadata(self.datadir)
self.metadata = read_metadata(self.datadir)
else:
if not self.metadata:
create_account_metadata(self.datadir)
self.metadata = read_metadata(self.datadir)
else:
if not validate_account(self.metadata):
create_account_metadata(self.datadir)
self.metadata = read_metadata(self.datadir)
def empty(self):
return dir_empty(self.datadir)
def delete(self):
if self.empty():
#For delete account.
if os.path.ismount(self.datadir):
clean_metadata(self.datadir)
else:
rmdirs(self.datadir)
self.dir_exists = False
def put_metadata(self, metadata):
"""
Write metadata to directory/container.
"""
write_metadata(self.datadir, metadata)
self.metadata = metadata
def put(self, metadata):
"""
Create and write metatdata to directory/container.
:param metadata: Metadata to write.
"""
if not self.dir_exists:
mkdirs(self.datadir)
os.chown(self.datadir, self.uid, self.gid)
write_metadata(self.datadir, metadata)
self.metadata = metadata
self.dir_exists = True
def put_obj(self, content_length, timestamp):
self.metadata[X_OBJECTS_COUNT] = int(self.metadata[X_OBJECTS_COUNT]) + 1
self.metadata[X_PUT_TIMESTAMP] = timestamp
self.metadata[X_BYTES_USED] = int(self.metadata[X_BYTES_USED]) + int(content_length)
#TODO: define update_metadata instad of writing whole metadata again.
self.put_metadata(self.metadata)
def delete_obj(self, content_length):
self.metadata[X_OBJECTS_COUNT] = int(self.metadata[X_OBJECTS_COUNT]) - 1
self.metadata[X_BYTES_USED] = int(self.metadata[X_BYTES_USED]) - int(content_length)
self.put_metadata(self.metadata)
def put_container(self, container, put_timestamp, del_timestamp, object_count, bytes_used):
"""
For account server.
"""
self.metadata[X_OBJECTS_COUNT] = 0
self.metadata[X_BYTES_USED] = 0
self.metadata[X_CONTAINER_COUNT] = int(self.metadata[X_CONTAINER_COUNT]) + 1
self.metadata[X_PUT_TIMESTAMP] = 1
self.put_metadata(self.metadata)
def delete_container(self, object_count, bytes_used):
"""
For account server.
"""
self.metadata[X_OBJECTS_COUNT] = 0
self.metadata[X_BYTES_USED] = 0
self.metadata[X_CONTAINER_COUNT] = int(self.metadata[X_CONTAINER_COUNT]) - 1
self.put_metadata(self.metadata)
def unlink(self):
"""
Remove directory/container if empty.
"""
if dir_empty(self.datadir):
rmdirs(self.datadir)
def list_objects_iter(self, limit, marker, end_marker,
prefix, delimiter, path):
"""
Returns tuple of name, created_at, size, content_type, etag.
"""
if path:
prefix = path = path.rstrip('/') + '/'
delimiter = '/'
if delimiter and not prefix:
prefix = ''
objects = []
object_count = 0
bytes_used = 0
container_list = []
objects, object_count, bytes_used = get_container_details(self.datadir)
if int(self.metadata[X_OBJECTS_COUNT]) != object_count or \
int(self.metadata[X_BYTES_USED]) != bytes_used:
self.metadata[X_OBJECTS_COUNT] = object_count
self.metadata[X_BYTES_USED] = bytes_used
self.update_container(self.metadata)
if objects:
objects.sort()
if objects and prefix:
objects = self.filter_prefix(objects, prefix)
if objects and delimiter:
objects = self.filter_delimiter(objects, delimiter, prefix)
if objects and marker:
objects = self.filter_marker(objects, marker)
if objects and end_marker:
objects = self.filter_end_marker(objects, end_marker)
if objects and limit:
if len(objects) > limit:
objects = self.filter_limit(objects, limit)
if objects:
for obj in objects:
list_item = []
list_item.append(obj)
metadata = read_metadata(self.datadir + '/' + obj)
if not metadata or not validate_object(metadata):
metadata = create_object_metadata(self.datadir + '/' + obj)
if metadata:
list_item.append(metadata[X_TIMESTAMP])
list_item.append(int(metadata[X_CONTENT_LENGTH]))
list_item.append(metadata[X_CONTENT_TYPE])
list_item.append(metadata[X_ETAG])
container_list.append(list_item)
return container_list
def update_container(self, metadata):
cont_path = self.datadir
write_metadata(cont_path, metadata)
self.metadata = metadata
def update_object_count(self):
objects = []
object_count = 0
bytes_used = 0
objects, object_count, bytes_used = get_container_details(self.datadir)
if int(self.metadata[X_OBJECTS_COUNT]) != object_count or \
int(self.metadata[X_BYTES_USED]) != bytes_used:
self.metadata[X_OBJECTS_COUNT] = object_count
self.metadata[X_BYTES_USED] = bytes_used
self.update_container(self.metadata)
def update_container_count(self):
containers = []
container_count = 0
containers, container_count = get_account_details(self.datadir)
if int(self.metadata[X_CONTAINER_COUNT]) != container_count:
self.metadata[X_CONTAINER_COUNT] = container_count
self.update_account(self.metadata)
def get_info(self, include_metadata=False):
"""
Get global data for the container.
:returns: dict with keys: account, container, created_at,
put_timestamp, delete_timestamp, object_count, bytes_used,
reported_put_timestamp, reported_delete_timestamp,
reported_object_count, reported_bytes_used, hash, id,
x_container_sync_point1, and x_container_sync_point2.
If include_metadata is set, metadata is included as a key
pointing to a dict of tuples of the metadata
"""
# TODO: delete_timestamp, reported_put_timestamp
# reported_delete_timestamp, reported_object_count,
# reported_bytes_used, created_at
metadata = {}
if os.path.exists(self.datadir):
metadata = read_metadata(self.datadir)
data = {'account' : self.account, 'container' : self.name,
'object_count' : metadata.get(X_OBJECTS_COUNT, '0'),
'bytes_used' : metadata.get(X_BYTES_USED, '0'),
'hash': '', 'id' : '', 'created_at' : '1',
'put_timestamp' : metadata.get(X_PUT_TIMESTAMP, '0'),
'delete_timestamp' : '1',
'reported_put_timestamp' : '1', 'reported_delete_timestamp' : '1',
'reported_object_count' : '1', 'reported_bytes_used' : '1'}
if include_metadata:
data['metadata'] = metadata
return data
def put_object(self, name, timestamp, size, content_type,
etag, deleted=0):
# TODO: Implement the specifics of this func.
pass
def initialize(self, timestamp):
pass
def update_put_timestamp(self, timestamp):
"""
Create the container if it doesn't exist and update the timestamp
"""
if not os.path.exists(self.datadir):
self.put(self.metadata)
def delete_object(self, name, timestamp):
# TODO: Implement the delete object
pass
def delete_db(self, timestamp):
"""
Delete the container
"""
self.unlink()
def update_metadata(self, metadata):
self.metadata.update(metadata)
write_metadata(self.datadir, self.metadata)
class DiskAccount(DiskDir):
def __init__(self, root, account, fs_object = None):
self.root = root
self.account = account
self.datadir = os.path.join(self.root, self.account)
if not check_mount(root, account):
check_valid_account(account, fs_object)
self.metadata = read_metadata(self.datadir)
if not self.metadata or not validate_account(self.metadata):
self.metadata = create_account_metadata(self.datadir)
def list_containers_iter(self, limit, marker, end_marker,
prefix, delimiter):
"""
Return tuple of name, object_count, bytes_used, 0(is_subdir).
Used by account server.
"""
if delimiter and not prefix:
prefix = ''
containers = []
container_count = 0
account_list = []
containers, container_count = get_account_details(self.datadir)
if int(self.metadata[X_CONTAINER_COUNT]) != container_count:
self.metadata[X_CONTAINER_COUNT] = container_count
self.update_account(self.metadata)
if containers:
containers.sort()
if containers and prefix:
containers = self.filter_prefix(containers, prefix)
if containers and delimiter:
containers = self.filter_delimiter(containers, delimiter, prefix)
if containers and marker:
containers = self.filter_marker(containers, marker)
if containers and end_marker:
containers = self.filter_end_marker(containers, end_marker)
if containers and limit:
if len(containers) > limit:
containers = self.filter_limit(containers, limit)
if containers:
for cont in containers:
list_item = []
metadata = None
list_item.append(cont)
metadata = read_metadata(self.datadir + '/' + cont)
if not metadata or not validate_container(metadata):
metadata = create_container_metadata(self.datadir + '/' + cont)
if metadata:
list_item.append(metadata[X_OBJECTS_COUNT])
list_item.append(metadata[X_BYTES_USED])
list_item.append(0)
account_list.append(list_item)
return account_list
def get_info(self, include_metadata=False):
"""
Get global data for the account.
:returns: dict with keys: account, created_at, put_timestamp,
delete_timestamp, container_count, object_count,
bytes_used, hash, id
"""
metadata = {}
if (os.path.exists(self.datadir)):
metadata = read_metadata(self.datadir)
if not metadata:
metadata = create_account_metadata(self.datadir)
data = {'account' : self.account, 'created_at' : '1',
'put_timestamp' : '1', 'delete_timestamp' : '1',
'container_count' : metadata.get(X_CONTAINER_COUNT, 0),
'object_count' : metadata.get(X_OBJECTS_COUNT, 0),
'bytes_used' : metadata.get(X_BYTES_USED, 0),
'hash' : '', 'id' : ''}
if include_metadata:
data['metadata'] = metadata
return data