Exemple #1
0
 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)
Exemple #2
0
 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))
Exemple #3
0
 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)
Exemple #4
0
    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)
Exemple #5
0
 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)
Exemple #6
0
    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)
Exemple #7
0
    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)
Exemple #8
0
 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
Exemple #9
0
    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)
Exemple #10
0
 def api_status(self):
     raise ServiceUnavailable('node is not configured')
Exemple #11
0
 def status(self):
     raise ServiceUnavailable('volumes are not configured')
Exemple #12
0
 def status(self):
     raise ServiceUnavailable('exports are not configured')
Exemple #13
0
 def mock_do_create(*args, **kwargs):
     raise ServiceUnavailable("Kaboom, out of space!")
Exemple #14
0
 def export_create(*args, **kwargs):
     raise ServiceUnavailable("no export for you")
Exemple #15
0
                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,