示例#1
0
文件: nfs.py 项目: Jchuan/cinder
    def migrate_volume(self, ctxt, volume, host):
        """Migrate if volume and host are managed by Nexenta appliance.

        :param ctxt: context
        :param volume: a dictionary describing the volume to migrate
        :param host: a dictionary describing the host to migrate to
        """
        LOG.debug('Enter: migrate_volume: id=%(id)s, host=%(host)s',
                  {'id': volume['id'], 'host': host})

        false_ret = (False, None)

        if volume['status'] not in ('available', 'retyping'):
            LOG.warning(_LW("Volume status must be 'available' or 'retyping'."
                            " Current volume status: %s"), volume['status'])
            return false_ret

        if 'capabilities' not in host:
            LOG.warning(_LW("Unsupported host. No capabilities found"))
            return false_ret

        capabilities = host['capabilities']
        ns_shares = capabilities['ns_shares']
        dst_parts = capabilities['location_info'].split(':')
        dst_host, dst_volume = dst_parts[1:]

        if (capabilities.get('vendor_name') != 'Nexenta' or
                dst_parts[0] != self.__class__.__name__ or
                capabilities['free_capacity_gb'] < volume['size']):
            return false_ret

        nms = self.share2nms[volume['provider_location']]
        ssh_bindings = nms.appliance.ssh_list_bindings()
        shares = []
        for bind in ssh_bindings:
            for share in ns_shares:
                if (share.startswith(ssh_bindings[bind][3]) and
                        ns_shares[share] >= volume['size']):
                    shares.append(share)
        if len(shares) == 0:
            LOG.warning(_LW("Remote NexentaStor appliance at %s should be "
                            "SSH-bound."), share)
            return false_ret
        share = sorted(shares, key=ns_shares.get, reverse=True)[0]
        snapshot = {
            'volume_name': volume['name'],
            'volume_id': volume['id'],
            'name': utils.get_migrate_snapshot_name(volume)
        }
        self.create_snapshot(snapshot)
        location = volume['provider_location']
        src = '%(share)s/%(volume)s@%(snapshot)s' % {
            'share': location.split(':')[1].split('volumes/')[1],
            'volume': volume['name'],
            'snapshot': snapshot['name']
        }
        dst = ':'.join([dst_host, dst_volume.split('/volumes/')[1]])
        try:
            nms.appliance.execute(self._get_zfs_send_recv_cmd(src, dst))
        except exception.NexentaException as exc:
            LOG.warning(_LW("Cannot send source snapshot %(src)s to "
                            "destination %(dst)s. Reason: %(exc)s"),
                        {'src': src, 'dst': dst, 'exc': exc})
            return false_ret
        finally:
            try:
                self.delete_snapshot(snapshot)
            except exception.NexentaException as exc:
                LOG.warning(_LW("Cannot delete temporary source snapshot "
                                "%(src)s on NexentaStor Appliance: %(exc)s"),
                            {'src': src, 'exc': exc})
        try:
            self.delete_volume(volume)
        except exception.NexentaException as exc:
            LOG.warning(_LW("Cannot delete source volume %(volume)s on "
                            "NexentaStor Appliance: %(exc)s"),
                        {'volume': volume['name'], 'exc': exc})

        dst_nms = self._get_nms_for_url(capabilities['nms_url'])
        dst_snapshot = '%s/%s@%s' % (dst_volume.split('volumes/')[1],
                                     volume['name'], snapshot['name'])
        try:
            dst_nms.snapshot.destroy(dst_snapshot, '')
        except exception.NexentaException as exc:
            LOG.warning(_LW("Cannot delete temporary destination snapshot "
                            "%(dst)s on NexentaStor Appliance: %(exc)s"),
                        {'dst': dst_snapshot, 'exc': exc})
        return True, {'provider_location': share}
示例#2
0
文件: iscsi.py 项目: mahak/cinder
    def migrate_volume(self, ctxt, volume, host):
        """Migrate if volume and host are managed by Nexenta appliance.

        :param ctxt: context
        :param volume: a dictionary describing the volume to migrate
        :param host: a dictionary describing the host to migrate to
        """
        LOG.debug('Enter: migrate_volume: id=%(id)s, host=%(host)s',
                  {'id': volume['id'], 'host': host})
        false_ret = (False, None)

        if volume['status'] not in ('available', 'retyping'):
            return false_ret

        if 'capabilities' not in host:
            return false_ret

        capabilities = host['capabilities']

        if ('location_info' not in capabilities or
                'iscsi_target_portal_port' not in capabilities or
                'nms_url' not in capabilities):
            return false_ret

        nms_url = capabilities['nms_url']
        dst_parts = capabilities['location_info'].split(':')

        if (capabilities.get('vendor_name') != 'Nexenta' or
                dst_parts[0] != self.__class__.__name__ or
                capabilities['free_capacity_gb'] < volume['size']):
            return false_ret

        dst_host, dst_volume = dst_parts[1:]

        ssh_bound = False
        ssh_bindings = self.nms.appliance.ssh_list_bindings()
        for bind in ssh_bindings:
            if dst_host.startswith(ssh_bindings[bind][3]):
                ssh_bound = True
                break
        if not ssh_bound:
            LOG.warning("Remote NexentaStor appliance at %s should be "
                        "SSH-bound.", dst_host)

        # Create temporary snapshot of volume on NexentaStor Appliance.
        snapshot = {
            'volume_name': volume['name'],
            'name': utils.get_migrate_snapshot_name(volume)
        }
        self.create_snapshot(snapshot)

        src = '%(volume)s/%(zvol)s@%(snapshot)s' % {
            'volume': self.volume,
            'zvol': volume['name'],
            'snapshot': snapshot['name']
        }
        dst = ':'.join([dst_host, dst_volume])

        try:
            self.nms.appliance.execute(self._get_zfs_send_recv_cmd(src, dst))
        except utils.NexentaException as exc:
            LOG.warning("Cannot send source snapshot %(src)s to "
                        "destination %(dst)s. Reason: %(exc)s",
                        {'src': src, 'dst': dst, 'exc': exc})
            return false_ret
        finally:
            try:
                self.delete_snapshot(snapshot)
            except utils.NexentaException as exc:
                LOG.warning("Cannot delete temporary source snapshot "
                            "%(src)s on NexentaStor Appliance: %(exc)s",
                            {'src': src, 'exc': exc})
        try:
            self.delete_volume(volume)
        except utils.NexentaException as exc:
            LOG.warning("Cannot delete source volume %(volume)s on "
                        "NexentaStor Appliance: %(exc)s",
                        {'volume': volume['name'], 'exc': exc})

        dst_nms = self.get_nms_for_url(nms_url)
        dst_snapshot = '%s/%s@%s' % (dst_volume, volume['name'],
                                     snapshot['name'])
        try:
            dst_nms.snapshot.destroy(dst_snapshot, '')
        except utils.NexentaException as exc:
            LOG.warning("Cannot delete temporary destination snapshot "
                        "%(dst)s on NexentaStor Appliance: %(exc)s",
                        {'dst': dst_snapshot, 'exc': exc})
        return True, None
示例#3
0
文件: nfs.py 项目: bergwolf/cinder
    def migrate_volume(self, ctxt, volume, host):
        """Migrate if volume and host are managed by Nexenta appliance.

        :param ctxt: context
        :param volume: a dictionary describing the volume to migrate
        :param host: a dictionary describing the host to migrate to
        """
        LOG.debug('Enter: migrate_volume: id=%(id)s, host=%(host)s',
                  {'id': volume['id'], 'host': host})

        false_ret = (False, None)

        if volume['status'] not in ('available', 'retyping'):
            LOG.warning(_LW("Volume status must be 'available' or 'retyping'."
                            " Current volume status: %s"), volume['status'])
            return false_ret

        if 'capabilities' not in host:
            LOG.warning(_LW("Unsupported host. No capabilities found"))
            return false_ret

        capabilities = host['capabilities']
        ns_shares = capabilities['ns_shares']
        dst_parts = capabilities['location_info'].split(':')
        dst_host, dst_volume = dst_parts[1:]

        if (capabilities.get('vendor_name') != 'Nexenta' or
                dst_parts[0] != self.__class__.__name__ or
                capabilities['free_capacity_gb'] < volume['size']):
            return false_ret

        nms = self.share2nms[volume['provider_location']]
        ssh_bindings = nms.appliance.ssh_list_bindings()
        shares = []
        for bind in ssh_bindings:
            for share in ns_shares:
                if (share.startswith(ssh_bindings[bind][3]) and
                        ns_shares[share] >= volume['size']):
                    shares.append(share)
        if len(shares) == 0:
            LOG.warning(_LW("Remote NexentaStor appliance at %s should be "
                            "SSH-bound."), share)
            return false_ret
        share = sorted(shares, key=ns_shares.get, reverse=True)[0]
        snapshot = {
            'volume_name': volume['name'],
            'volume_id': volume['id'],
            'name': utils.get_migrate_snapshot_name(volume)
        }
        self.create_snapshot(snapshot)
        location = volume['provider_location']
        src = '%(share)s/%(volume)s@%(snapshot)s' % {
            'share': location.split(':')[1].split('volumes/')[1],
            'volume': volume['name'],
            'snapshot': snapshot['name']
        }
        dst = ':'.join([dst_host, dst_volume.split('/volumes/')[1]])
        try:
            nms.appliance.execute(self._get_zfs_send_recv_cmd(src, dst))
        except exception.NexentaException as exc:
            LOG.warning(_LW("Cannot send source snapshot %(src)s to "
                            "destination %(dst)s. Reason: %(exc)s"),
                        {'src': src, 'dst': dst, 'exc': exc})
            return false_ret
        finally:
            try:
                self.delete_snapshot(snapshot)
            except exception.NexentaException as exc:
                LOG.warning(_LW("Cannot delete temporary source snapshot "
                                "%(src)s on NexentaStor Appliance: %(exc)s"),
                            {'src': src, 'exc': exc})
        try:
            self.delete_volume(volume)
        except exception.NexentaException as exc:
            LOG.warning(_LW("Cannot delete source volume %(volume)s on "
                            "NexentaStor Appliance: %(exc)s"),
                        {'volume': volume['name'], 'exc': exc})

        dst_nms = self._get_nms_for_url(capabilities['nms_url'])
        dst_snapshot = '%s/%s@%s' % (dst_volume.split('volumes/')[1],
                                     volume['name'], snapshot['name'])
        try:
            dst_nms.snapshot.destroy(dst_snapshot, '')
        except exception.NexentaException as exc:
            LOG.warning(_LW("Cannot delete temporary destination snapshot "
                            "%(dst)s on NexentaStor Appliance: %(exc)s"),
                        {'dst': dst_snapshot, 'exc': exc})
        return True, {'provider_location': share}
示例#4
0
    def migrate_volume(self, ctxt, volume, host):
        """Migrate if volume and host are managed by Nexenta appliance.

        :param ctxt: context
        :param volume: a dictionary describing the volume to migrate
        :param host: a dictionary describing the host to migrate to
        """
        LOG.debug('Enter: migrate_volume: id=%(id)s, host=%(host)s', {
            'id': volume['id'],
            'host': host
        })
        false_ret = (False, None)

        if volume['status'] not in ('available', 'retyping'):
            return false_ret

        if 'capabilities' not in host:
            return false_ret

        capabilities = host['capabilities']

        if ('location_info' not in capabilities
                or 'iscsi_target_portal_port' not in capabilities
                or 'nms_url' not in capabilities):
            return false_ret

        nms_url = capabilities['nms_url']
        dst_parts = capabilities['location_info'].split(':')

        if (capabilities.get('vendor_name') != 'Nexenta'
                or dst_parts[0] != self.__class__.__name__
                or capabilities['free_capacity_gb'] < volume['size']):
            return false_ret

        dst_host, dst_volume = dst_parts[1:]

        ssh_bound = False
        ssh_bindings = self.nms.appliance.ssh_list_bindings()
        for bind in ssh_bindings:
            if dst_host.startswith(bind.split('@')[1].split(':')[0]):
                ssh_bound = True
                break
        if not ssh_bound:
            LOG.warning(
                "Remote NexentaStor appliance at %s should be "
                "SSH-bound.", dst_host)

        # Create temporary snapshot of volume on NexentaStor Appliance.
        snapshot = {
            'volume_name': volume['name'],
            'name': utils.get_migrate_snapshot_name(volume)
        }
        self.create_snapshot(snapshot)

        src = '%(volume)s/%(zvol)s@%(snapshot)s' % {
            'volume': self.volume,
            'zvol': volume['name'],
            'snapshot': snapshot['name']
        }
        dst = ':'.join([dst_host, dst_volume])

        try:
            self.nms.appliance.execute(self._get_zfs_send_recv_cmd(src, dst))
        except exception.NexentaException as exc:
            LOG.warning(
                "Cannot send source snapshot %(src)s to "
                "destination %(dst)s. Reason: %(exc)s", {
                    'src': src,
                    'dst': dst,
                    'exc': exc
                })
            return false_ret
        finally:
            try:
                self.delete_snapshot(snapshot)
            except exception.NexentaException as exc:
                LOG.warning(
                    "Cannot delete temporary source snapshot "
                    "%(src)s on NexentaStor Appliance: %(exc)s", {
                        'src': src,
                        'exc': exc
                    })
        try:
            self.delete_volume(volume)
        except exception.NexentaException as exc:
            LOG.warning(
                "Cannot delete source volume %(volume)s on "
                "NexentaStor Appliance: %(exc)s", {
                    'volume': volume['name'],
                    'exc': exc
                })

        dst_nms = self.get_nms_for_url(nms_url)
        dst_snapshot = '%s/%s@%s' % (dst_volume, volume['name'],
                                     snapshot['name'])
        try:
            dst_nms.snapshot.destroy(dst_snapshot, '')
        except exception.NexentaException as exc:
            LOG.warning(
                "Cannot delete temporary destination snapshot "
                "%(dst)s on NexentaStor Appliance: %(exc)s", {
                    'dst': dst_snapshot,
                    'exc': exc
                })
        return True, None
示例#5
0
文件: nfs.py 项目: 10171121/cinder
    def migrate_volume(self, ctxt, volume, host):
        """Migrate if volume and host are managed by Nexenta appliance.

        :param ctxt: context
        :param volume: a dictionary describing the volume to migrate
        :param host: a dictionary describing the host to migrate to
        """
        LOG.debug("Enter: migrate_volume: id=%(id)s, host=%(host)s", {"id": volume["id"], "host": host})

        false_ret = (False, None)

        if volume["status"] not in ("available", "retyping"):
            LOG.warning(
                _LW("Volume status must be 'available' or 'retyping'." " Current volume status: %s"), volume["status"]
            )
            return false_ret

        if "capabilities" not in host:
            LOG.warning(_LW("Unsupported host. No capabilities found"))
            return false_ret

        capabilities = host["capabilities"]
        ns_shares = capabilities["ns_shares"]
        dst_parts = capabilities["location_info"].split(":")
        dst_host, dst_volume = dst_parts[1:]

        if (
            capabilities.get("vendor_name") != "Nexenta"
            or dst_parts[0] != self.__class__.__name__
            or capabilities["free_capacity_gb"] < volume["size"]
        ):
            return false_ret

        nms = self.share2nms[volume["provider_location"]]
        ssh_bindings = nms.appliance.ssh_list_bindings()
        shares = []
        for bind in ssh_bindings:
            for share in ns_shares:
                if share.startswith(ssh_bindings[bind][3]) and ns_shares[share] >= volume["size"]:
                    shares.append(share)
        if len(shares) == 0:
            LOG.warning(_LW("Remote NexentaStor appliance at %s should be " "SSH-bound."), share)
            return false_ret
        share = sorted(shares, key=ns_shares.get, reverse=True)[0]
        snapshot = {
            "volume_name": volume["name"],
            "volume_id": volume["id"],
            "name": utils.get_migrate_snapshot_name(volume),
        }
        self.create_snapshot(snapshot)
        location = volume["provider_location"]
        src = "%(share)s/%(volume)s@%(snapshot)s" % {
            "share": location.split(":")[1].split("volumes/")[1],
            "volume": volume["name"],
            "snapshot": snapshot["name"],
        }
        dst = ":".join([dst_host, dst_volume.split("/volumes/")[1]])
        try:
            nms.appliance.execute(self._get_zfs_send_recv_cmd(src, dst))
        except exception.NexentaException as exc:
            LOG.warning(
                _LW("Cannot send source snapshot %(src)s to " "destination %(dst)s. Reason: %(exc)s"),
                {"src": src, "dst": dst, "exc": exc},
            )
            return false_ret
        finally:
            try:
                self.delete_snapshot(snapshot)
            except exception.NexentaException as exc:
                LOG.warning(
                    _LW("Cannot delete temporary source snapshot " "%(src)s on NexentaStor Appliance: %(exc)s"),
                    {"src": src, "exc": exc},
                )
        try:
            self.delete_volume(volume)
        except exception.NexentaException as exc:
            LOG.warning(
                _LW("Cannot delete source volume %(volume)s on " "NexentaStor Appliance: %(exc)s"),
                {"volume": volume["name"], "exc": exc},
            )

        dst_nms = self._get_nms_for_url(capabilities["nms_url"])
        dst_snapshot = "%s/%s@%s" % (dst_volume.split("volumes/")[1], volume["name"], snapshot["name"])
        try:
            dst_nms.snapshot.destroy(dst_snapshot, "")
        except exception.NexentaException as exc:
            LOG.warning(
                _LW("Cannot delete temporary destination snapshot " "%(dst)s on NexentaStor Appliance: %(exc)s"),
                {"dst": dst_snapshot, "exc": exc},
            )
        return True, {"provider_location": share}