def __init__(self, config): self._metadata_dict = {} self._data_dict = {} self._config = config self._node_error_state_set = UKAINodeErrorStateSet() self._open_image_set = set() self._rpc_trans = UKAIXMLRPCTranslation()
def __init__(self, config): self._metadata_dict = {} self._data_dict = {} self._config = config self._node_error_state_set = UKAINodeErrorStateSet() self._rpc_trans = UKAIXMLRPCTranslation() self._writers = UKAIWriters() self._open_count = UKAIOpenImageCount() self._fh = 0 ukai_db_client.connect(self._config)
class UKAICore(object): ''' UKAI core processing. ''' def __init__(self, config): self._metadata_dict = {} self._data_dict = {} self._config = config self._node_error_state_set = UKAINodeErrorStateSet() self._open_image_set = set() self._rpc_trans = UKAIXMLRPCTranslation() @property def metadata_server(self): return self._config.get('metadata_server') @property def core_server(self): return self._config.get('core_server') @property def core_port(self): return self._config.get('core_port') ''' Filesystem I/O processing. ''' def getattr(self, path): ret = 0 st = None if path == '/': st = dict(st_mode=(stat.S_IFDIR | 0755), st_ctime=0, st_mtime=0, st_atime=0, st_nlink=2) else: image_name = path[1:] if self._exists(image_name): st = dict(st_mode=(stat.S_IFREG | 0644), st_ctime=0, st_mtime=0, st_atime=0, st_nlink=1, st_size=self._metadata_dict[image_name].size) else: ret = errno.ENOENT return ret, st def open(self, path, flags): ret = 0 image_name = path[1:] if not self._exists(image_name): return errno.ENOENT if image_name in self._open_image_set: return errno.EBUSY else: self._open_image_set.add(image_name) return 0 def release(self, path): image_name = path[1:] if image_name in self._open_image_set: self._open_image_set.remove(image_name) return 0 def read(self, path, size, offset): image_name = path[1:] if not self._exists(image_name): return errno.ENOENT, None image_data = self._data_dict[image_name] data = image_data.read(size, offset) return 0, self._rpc_trans.encode(data) def readdir(self, path): return ['.', '..'] + self._metadata_dict.keys() def statfs(self, path): ''' TODO: the values are fake right now. ''' return dict(f_bsize=512, f_blocks=4096, f_bavail=2048) def truncate(self, path, length): return errno.EPERM def unlink(self, path): return errno.EPERM def write(self, path, encoded_data, offset): image_name = path[1:] if not self._exists(image_name): return errno.ENOENT, None image_data = self._data_dict[image_name] return 0, image_data.write(self._rpc_trans.decode(encoded_data), offset) def _exists(self, image_name): if image_name not in self._metadata_dict: return False if image_name not in self._data_dict: return False return True ''' Proxy server processing. ''' def proxy_read(self, image_name, block_size, block_index, offset, size): data = ukai_local_read(image_name, block_size, block_index, offset, size, self._config) return self._rpc_trans.encode(zlib.compress(data)) def proxy_write(self, image_name, block_size, block_index, offset, encoded_data): data = zlib.decompress(self._rpc_trans.decode(encoded_data)) return ukai_local_write(image_name, block_size, block_index, offset, data, self._config) def proxy_allocate_dataspace(self, image_name, block_size, block_index): return ukai_local_allocate_dataspace(image_name, block_size, block_index, self._config) def proxy_update_metadata(self, image_name, encoded_metadata): metadata_raw = json.loads(zlib.decompress(self._rpc_trans.decode( encoded_metadata))) if image_name in self._metadata_dict: self._metadata_dict[image_name].metadata = metadata_raw else: metadata = UKAIMetadata(image_name, self._config, metadata_raw) self._metadata_dict[image_name] = metadata self._data_dict[image_name] = UKAIData(metadata, self._node_error_state_set, self._config) UKAIStatistics[image_name] = UKAIImageStatistics() return 0 ''' Controll processing. ''' def ctl_create_image(self, image_name, size, block_size=None, location=None, hypervisor=None): assert image_name is not None assert size > 0 if block_size is None: defaults = self._config.get('create_default') block_size = defaults['block_size'] assert block_size > 0 assert size > block_size assert size % block_size == 0 block_count = size / block_size if location is None: location = self._config.get('core_server') if hypervisor is None: hypervisor = self._config.get('core_server') ukai_metadata_create(image_name, size, block_size, location, hypervisor, self._config) def ctl_add_image(self, image_name): if image_name in self._metadata_dict: return errno.EEXIST metadata = UKAIMetadata(image_name, self._config) self._metadata_dict[image_name] = metadata data = UKAIData(metadata=metadata, node_error_state_set=self._node_error_state_set, config=self._config) self._data_dict[image_name] = data UKAIStatistics[image_name] = UKAIImageStatistics() return 0 def ctl_remove_image(self, image_name): if image_name not in self._metadata_dict: return errno.ENOENT del self._metadata_dict[image_name] del self._data_dict[image_name] del UKAIStatistics[image_name] return 0 def ctl_get_metadata(self, image_name): if image_name not in self._metadata_dict: return errno.ENOENT, None return 0, json.dumps(self._metadata_dict[image_name].metadata) def ctl_add_location(self, image_name, location, start_index=0, end_index=-1, sync_status=UKAI_OUT_OF_SYNC): if image_name not in self._metadata_dict: return errno.ENOENT metadata = self._metadata_dict[image_name] metadata.add_location(location, start_index, end_index, sync_status) return 0 def ctl_remove_location(self, image_name, location, start_index=0, end_index=-1): if image_name not in self._metadata_dict: return errno.ENOENT metadata = self._metadata_dict[image_name] metadata.remove_location(location, start_index, end_index) return 0 def ctl_add_hypervisor(self, image_name, hypervisor): if image_name not in self._metadata_dict: return errno.ENOENT metadata = self._metadata_dict[image_name] metadata.add_hypervisor(hypervisor) return 0 def ctl_remove_hypervisor(self, image_name, hypervisor): if image_name not in self._metadata_dict: return errno.ENOENT metadata = self._metadata_dict[image_name] metadata.remove_hypervisor(hypervisor) return 0 def ctl_synchronize(self, image_name, start_index=0, end_index=-1, verbose=False): if image_name not in self._metadata_dict: return errno.ENOENT metadata = self._metadata_dict[image_name] data = self._data_dict[image_name] if end_index == -1: end_index = (metadata.size / metadata.block_size) - 1 for block_index in range(start_index, end_index + 1): if verbose is True: print 'Syncing block %d (from %d to %d)' % (block_index, start_index, end_index) if data.synchronize_block(block_index) is True: metadata.flush() return 0 def ctl_get_node_error_state_set(self): return self._node_error_state_set.get_list()
class UKAICore(object): ''' The UKAICore class implements core processing of the UKAI filesystem. ''' def __init__(self, config): self._metadata_dict = {} self._data_dict = {} self._config = config self._node_error_state_set = UKAINodeErrorStateSet() self._rpc_trans = UKAIXMLRPCTranslation() self._writers = UKAIWriters() self._open_count = UKAIOpenImageCount() self._fh = 0 ukai_db_client.connect(self._config) ''' Filesystem I/O processing. ''' def getattr(self, path): ret = 0 st = None if path == '/': st = dict(st_mode=(stat.S_IFDIR | 0755), st_ctime=0, st_mtime=0, st_atime=0, st_nlink=2) else: image_name = path[1:] metadata = self._get_metadata(image_name) if metadata is not None: st = dict(st_mode=(stat.S_IFREG | 0644), st_ctime=0, st_mtime=0, st_atime=0, st_nlink=1, st_size=metadata['used_size']) else: ret = errno.ENOENT return ret, json.dumps(st) def open(self, path, flags): try: lock.acquire() ret = 0 image_name = path[1:] metadata = self._get_metadata(image_name) if metadata is None: return errno.ENOENT, None self._fh += 1 if (flags & 3) != os.O_RDONLY: if self._writers.add_writer(image_name, self._fh) == errno.EBUSY: return errno.EBUSY, None if self._open_count.increment(image_name) == 1: self._add_image(image_name) return 0, self._fh finally: lock.release() def release(self, path, fh): try: lock.acquire() image_name = path[1:] self._writers.remove_writer(image_name, fh) if self._open_count.decrement(image_name) == 0: self._remove_image(image_name) return 0 finally: lock.release() def read(self, path, str_size, str_offset): image_name = path[1:] size = int(str_size) offset = int(str_offset) if not self._exists(image_name): return errno.ENOENT, None image_data = self._data_dict[image_name] data = image_data.read(size, offset) return 0, self._rpc_trans.encode(data) def readdir(self, path): return ['.', '..'] + self._metadata_dict.keys() def statfs(self, path): ''' TODO: the values are fake right now. ''' return dict(f_bsize=512, f_blocks=4096, f_bavail=2048) def truncate(self, path, str_length): image_name = path[1:] length = int(str_length) if not self._exists(image_name): return errno.ENOENT image_metadata = self._metadata_dict[image_name] if image_metadata.size < length: return errno.EINVAL image_metadata.used_size = length image_metadata.flush() return 0 def unlink(self, path): return errno.EPERM def write(self, path, encoded_data, str_offset): image_name = path[1:] offset = int(str_offset) if not self._exists(image_name): return errno.ENOENT, None image_data = self._data_dict[image_name] return 0, image_data.write(self._rpc_trans.decode(encoded_data), offset) def _get_metadata(self, image_name): return ukai_db_client.get_metadata(image_name) def _add_image(self, image_name): assert image_name not in self._metadata_dict metadata = UKAIMetadata(image_name, self._config) ukai_db_client.join_reader(image_name, self._config.get('id')) self._metadata_dict[image_name] = metadata data = UKAIData(metadata=metadata, node_error_state_set=self._node_error_state_set, config=self._config) self._data_dict[image_name] = data UKAIStatistics[image_name] = UKAIImageStatistics() def _remove_image(self, image_name): assert image_name in self._metadata_dict ukai_db_client.leave_reader(image_name, self._config.get('id')) del self._metadata_dict[image_name] del self._data_dict[image_name] del UKAIStatistics[image_name] def _exists(self, image_name): if image_name not in self._metadata_dict: return False if image_name not in self._data_dict: return False return True ''' Proxy server processing. ''' def proxy_read(self, image_name, str_block_size, str_block_index, str_offset, str_size): block_size = int(str_block_size) block_index = int(str_block_index) offset = int(str_offset) size = int(str_size) data = ukai_local_read(image_name, block_size, block_index, offset, size, self._config) return self._rpc_trans.encode(zlib.compress(data)) def proxy_write(self, image_name, str_block_size, str_block_index, str_offset, encoded_data): block_size = int(str_block_size) block_index = int(str_block_index) offset = int(str_offset) data = zlib.decompress(self._rpc_trans.decode(encoded_data)) return ukai_local_write(image_name, block_size, block_index, offset, data, self._config) def proxy_allocate_dataspace(self, image_name, block_size, block_index): return ukai_local_allocate_dataspace(image_name, block_size, block_index, self._config) def proxy_deallocate_dataspace(self, image_name, block_index): return ukai_local_deallocate_dataspace(image_name, block_index, self._config) def proxy_update_metadata(self, image_name, encoded_metadata): metadata_raw = json.loads(zlib.decompress(self._rpc_trans.decode( encoded_metadata))) if image_name in self._metadata_dict: self._metadata_dict[image_name].metadata = metadata_raw else: metadata = UKAIMetadata(image_name, self._config, metadata_raw) self._metadata_dict[image_name] = metadata self._data_dict[image_name] = UKAIData(metadata, self._node_error_state_set, self._config) UKAIStatistics[image_name] = UKAIImageStatistics() return 0 def proxy_destroy_image(self, image_name): return ukai_local_destroy_image(image_name, self._config) ''' Controll processing. ''' def ctl_create_image(self, image_name, str_size, block_size=None, location=None): assert image_name is not None size = int(str_size) assert size > 0 if block_size is None: defaults = self._config.get('create_default') block_size = defaults['block_size'] assert block_size > 0 assert size > block_size assert size % block_size == 0 block_count = size / block_size if location is None: location = self._config.get('core_server') ukai_metadata_create(image_name, size, block_size, location, self._config) def ctl_destroy_image(self, image_name): assert image_name is not None ukai_data_destroy(image_name, self._config) ukai_metadata_destroy(image_name, self._config) def ctl_get_metadata(self, image_name): metadata = self._get_metadata(image_name) if metadata is None: return errno.ENOENT, None return 0, json.dumps(metadata) def ctl_add_location(self, image_name, location, start_index=0, end_index=-1, sync_status=UKAI_OUT_OF_SYNC): metadata = None if image_name in self._metadata_dict: # the image is in use on this node. metadata = self._metadata_dict[image_name] else: # XXX need to check if no one is using this image. metadata_raw = self._get_metadata(image_name) if metadata_raw is None: return errno.ENOENT metadata = UKAIMetadata(image_name, self._config, metadata_raw) metadata.add_location(location, start_index, end_index, sync_status) return 0 def ctl_remove_location(self, image_name, location, start_index=0, end_index=-1): metadata = None if image_name in self._metadata_dict: # the image is in use on this node. metadata = self._metadata_dict[image_name] else: # XXX need to check if no one is using this image. metadata_raw = self._get_metadata(image_name) if metadata_raw is None: return errno.ENOENT metadata = UKAIMetadata(image_name, self._config, metadata_raw) metadata.remove_location(location, start_index, end_index) ukai_data_location_destroy(image_name, location, self._config) return 0 def ctl_add_hypervisor(self, image_name, hypervisor): metadata = None if image_name in self._metadata_dict: # the image is in use on this node. metadata = self._metadata_dict[image_name] else: # XXX need to check if no one is using this image. metadata_raw = self._get_metadata(image_name) if metadata_raw is None: return errno.ENOENT metadata = UKAIMetadata(image_name, self._config, metadata_raw) metadata.add_hypervisor(hypervisor) return 0 def ctl_remove_hypervisor(self, image_name, hypervisor): metadata = None if image_name in self._metadata_dict: # the image is in use on this node. metadata = self._metadata_dict[image_name] else: # XXX need to check if no one is using this image. metadata_raw = self._get_metadata(image_name) if metadata_raw is None: return errno.ENOENT metadata = UKAIMetadata(image_name, self._config, metadata_raw) metadata.remove_hypervisor(hypervisor) return 0 def ctl_synchronize(self, image_name, start_index=0, end_index=-1, verbose=False): metadata = None if image_name in self._metadata_dict: # the image is in use on this node. metadata = self._metadata_dict[image_name] data = self._data_dict[image_name] else: # XXX need to check if no one is using this image. metadata_raw = self._get_metadata(image_name) if metadata_raw is None: return errno.ENOENT metadata = UKAIMetadata(image_name, self._config, metadata_raw) data = UKAIData(metadata, self._node_error_state_set, self._config) if end_index == -1: end_index = (metadata.size / metadata.block_size) - 1 for block_index in range(start_index, end_index + 1): if verbose is True: print 'Syncing block %d (from %d to %d)' % (block_index, start_index, end_index) if data.synchronize_block(block_index) is True: metadata.flush() return 0 def ctl_get_node_error_state_set(self): return self._node_error_state_set.get_list() def ctl_get_image_names(self): return ukai_db_client.get_image_names() def ctl_diag(self): print self._open_count._images print self._writers._images print self._metadata_dict return 0
fh.seek(self._metadata.block_size - 1) fh.write('\0') fh.close() else: remote = xmlrpclib.ServerProxy( 'http://%s:%d/' % (node, self._config.get('core_port'))) remote.proxy_allocate_dataspace(self._metadata.name, self._metadata.block_size, blk_idx) if __name__ == '__main__': from ukai_node_error_state import UKAINodeErrorStateSet ukai_config.set('data_root', './test/local/data') ukai_config.set('metadata_root', './test/local/metadata') ness = UKAINodeErrorStateSet() meta = UKAIMetadata('./test/local/metadata/test') fh = UKAIData(meta, ness) data = 'Hello World!' offset = 0 print 'offset %d' % offset fh.write(data, offset) ver = fh.read(len(data), offset) if ver != data: print 'error at offset %d' % offset offset = meta.block_size - (len(data) / 2) print 'offset %d' % offset fh.write(data, offset) ver = fh.read(len(data), offset)