def ietadm(self, *args, **kwargs): try: return ietadm(*args, **kwargs) except ConnectionRefused, e: if not os.path.exists(self.proc_iet_volume): raise ServiceUnavailable("'%s' does not exist, ietd is not " "running." % self.proc_iet_volume) msg = 'Unexpected ConnectionRefused: %s' % e logger.exception(msg) raise ServiceUnavailable(msg)
def status(self): options = ('vg_size', 'vg_free', 'lv_count') try: out = execute('vgs', self.volume_group, noheadings=None, unit='b', options=','.join(options), separator=':') except ProcessError, e: if e.errcode == 5 and 'not found' in e.err: raise ServiceUnavailable("Volume group '%s' not found." % self.volume_group) logger.exception("Unknown error trying to query status of " "volume group '%s'" % self.volume_group) raise ServiceUnavailable("[Errno %d] %s" % (e.errcode, e.err))
def status(self): conn = get_conn(self.conf) status = {'client': conn.__module__.rsplit('.', 1)[-1]} try: status.update(conn.head_account()) except conn.ClientException, e: raise ServiceUnavailable(e)
def delete(self, volume_id, callback=None, lock=None): volume = self.get(volume_id) # If origin exists, this volume is a snapshot if volume['origin']: # scrub and remove snapshots synchronously self.remove_lvm_snapshot(volume) return # This is a normal volume delete if 'zero' not in volume['id']: # Does this volume have a snapshot? if self._get_snapshot(volume['id']): raise ServiceUnavailable("Refusing to delete volume '%s' " "with an active backup" % volume['id']) try: self.update_tags(volume, {'zero': True}) except NotFound: pass volume = self.get(volume_id) spawn(lock, self.remove_lvm_volume, volume, callback=callback, skip_fork=self.skip_fork)
def _do_create(self, volume_id, size_str, tag, backup_source_volume_id=None): try: out = execute('lvcreate', self.volume_group, name=volume_id, size=size_str, addtag=tag) except ProcessError, e: if not e.errcode == 5 and 'already exists' not in e.err: raise # We ran out of space on the storage node! if "Insufficient free extents" in e.err \ or "insufficient free space" in e.err: logger.error(e.err) raise ServiceUnavailable("LVM reports insufficient " "free space on drive") # If we are requesting a restore, and the existing volume is this # same failed restore, it's not an error. if backup_source_volume_id and backup_source_volume_id == \ self.get(volume_id).get('backup_source_volume_id', False): logger.info("Restarting failed restore on '%s'" % volume_id) else: raise AlreadyExists("Unable to create a new volume named " "'%s' because one already exists." % volume_id)
def _scan_file(self, file): """ Scans IET files in the form tid:1 name:iqn.2010-11.com.rackspace:volume-00000001.uuid \tsid:562950527844864 initiator:iqn.1993-08.org.debian:01:47441681ba44 \t\tcid:0 ip:127.0.0.1 state:active hd:none dd:none \tsid:281474997486080 initiator:iqn.1993-08.org.debian:01:669c9c15f124 \t\tcid:0 ip:192.168.56.1 state:active hd:none dd:none and returns an array of key:value dicts for each entry it finds in the file """ # TODO(clayg): this needs a refactor, it's really hard to follow, sry records = [] try: with open(file) as f: record = {} for line in f: if not line.strip(): continue # new record, get it in the list and update via ref if not line.startswith('\t'): record = {} records.append(record) subrecord = self.parse_export_line(line) if not record: base_record = dict(subrecord) if any(k in record for k in subrecord): # this is a second entry record = dict(base_record) records.append(record) record.update(subrecord) except IOError, e: if e.errno == errno.ENOENT: raise ServiceUnavailable("'%s' does not exist, iscsitarget" "is not running." % file) else: msg = "Unexpected error trying to read '%s'", file logger.exception(msg) raise ServiceUnavailable(msg)
def create(self, id, ip=None): with lock.ResourceFile(self._build_lock_path(id)): try: # see if an export was created while we were locking self.get(id) except NotFound: pass else: raise AlreadyExists("An export already exists for " "volume '%s'" % id) # create target params = {'Name': self._generate_target_name(id)} try: out = self.ietadm(op='new', tid='auto', params=params) except InvalidArgument: logger.exception("Unable to create target for '%s'" % id) raise ServiceUnavailable("Invalid argument while trying to " "create export for '%s'" % id) # lookup tid tid = self._get_tid(id) # add lun path = self._lun_path(id) params = {'Path': path, 'Type': 'blockio'} try: out += self.ietadm(op='new', tid=tid, lun=0, params=params) except (NoSuchFile, NotPermitted): # clean up the target self.delete(id) if not os.path.exists(path): raise NotFound("No volume named '%s'" % id) logger.exception('Unable to create export for %s' % id) raise ServiceUnavailable("Invalid param trying to create " "export for '%s'" % id) # Write the new exports to the iet config exports = self.rewrite_config() if ip: self.add_initiator_allow(id, ip) return self.get(id, exports=exports)
def api_status(self): resp = self.make_api_request('nodes?name=%s' % self.name) data = loads(resp.read()) if not data: raise NotRegistered("Unable to find node entry for name '%s'" % self.name) elif len(data) > 1: raise ServiceUnavailable("Duplicate node entry for name '%s'" % self.name) else: node_resp = self.make_api_request('nodes', data[0]['id']) node = loads(node_resp.read()) return node
def create_clone(self, volume_id, clone_id, iqn, iscsi_ip, iscsi_port, callback=None, lock=None, cinder=None): volume = self.get(volume_id) size = volume['size'] / 1024 / 1024 / 1024 logger.info("Cloning source '%s' to volume '%s'" % (volume_id, clone_id)) snapshot_name = uuid.uuid4() snapshot = self.create_snapshot(volume_id, snapshot_name, clone_id=clone_id, type_='clone') logger.info("Snapshot to clone id: '%s'" % snapshot['id']) try: new_volume = ISCSIDevice(iqn, iscsi_ip, iscsi_port) new_volume.connect() except (ISCSILoginFailed, ISCSINotConnected): msg = "Unable to open iscsi connection to %s:%s - %s" % \ (iscsi_ip, iscsi_port, iqn) logger.error(msg) self.delete(snapshot['id']) raise ServiceUnavailable(msg) spawn(lock, self._copy_clone, snapshot, clone_id, size, new_volume, cinder, callback=callback, skip_fork=self.skip_fork)
def api_status(self): raise ServiceUnavailable('node is not configured')
def status(self): raise ServiceUnavailable('volumes are not configured')
def status(self): raise ServiceUnavailable('exports are not configured')
def mock_do_create(*args, **kwargs): raise ServiceUnavailable("Kaboom, out of space!")
def export_create(*args, **kwargs): raise ServiceUnavailable("no export for you")
logger.warning("Error updating clone-progress metadata: %s" % e) op_start = time() logger.rename('lunr.storage.helper.volume._copy_clone') setproctitle("lunr-clone: %s %s" % (snapshot['origin'], clone_id)) try: iscsi_device.copy_file_out(snapshot['path'], callback=progress_callback) except (ISCSINotConnected, ISCSICopyFailed), e: logger.error("copy_file_out failed: %s" % str(e)) raise try: iscsi_device.disconnect() except ISCSILogoutFailed: raise ServiceUnavailable("Unable to disconnect") duration = time() - op_start logger.info('STAT: Clone %r to %r. ' 'Size: %r GB Time: %r s Speed: %r MB/s' % (snapshot['origin'], clone_id, size, duration, size * 1024 / duration)) self.delete(snapshot['id']) def create_clone(self, volume_id, clone_id, iqn, iscsi_ip, iscsi_port, callback=None, lock=None,