CEPH存储操作(Python代码)

10 篇文章 1 订阅

CEPH STORAGE CLUSTER OPERATION

ceph的python_api文档: http://docs.ceph.com/docs/master/rados/api/python/

#!/usr/bin/env python
# -*-coding: utf-8-*-

import json
import os

import rados
import rbd

from utils.constant import CSTOR_LOG_PATH
from utils.exception import ExecuteException
from utils.logger import set_logger

cstor_logger = set_logger(os.path.basename(__file__), CSTOR_LOG_PATH)

CEPH_RBD_ERROR = 'CEPH ERROR'


class CLUSTEROperation(object):

    def __init__(self, conf):
        if not conf:
            raise ExecuteException(CEPH_RBD_ERROR, 'conf is none.')
        if not os.path.exists(conf):
            raise ExecuteException(CEPH_RBD_ERROR, 'conf file not exits.')

        self.conf = conf

        self.cluster = self._get_cluster()
        self._connect_cluster()

    def _get_cluster(self):
        """
        获取ceph集群
        :return:
        """
        try:
            return rados.Rados(conffile=self.conf)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get cluster failed.')

    def _connect_cluster(self):
        """
        连接ceph集群
        :return:
        """
        try:
            self.cluster.connect()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'connect cluster failed.')

    def close_cluster(self):
        """
        断开ceph集群
        :return:
        """
        try:
            self.cluster.shutdown()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'close cluster failed.')

    def get_fsid(self):
        """
        获取ceph集群fsid值
        :return: 7c9c2ba8-dcec-42b0-8231-a2149988b913
        """
        try:
            return self.cluster.get_fsid().encode()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get fsid failed.')

    def get_cluster_stats(self):
        """
        获取ceph集群统计数据
        :return: {'kb': 3221213184L, 'num_objects': 35390L, 'kb_avail': 2876726592L, 'kb_used': 344486592L}
        """
        try:
            return self.cluster.get_cluster_stats()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'close cluster failed.')

    def get_conf(self, var):
        """
        获取ceph集群配置文件(ceph.conf)的中的内容(即使文件中没记载的配置,也可以获取)
        :param var: 配置项名称,如:fsid, osd pool default size等
        :return:
        """
        try:
            return self.cluster.conf_get(var).encode()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'close cluster failed.')

    def mon_command(self, **kwargs):
        """
        执行 ceph 命令
        :param kwargs: ceph 命令拼接:如:
        ceph df: 即为 prefix='df', format='json',拼接过程中去除ceph,以接送格式输出
        ceph status: 即为 prefix='status', format='json',拼接过程中去除ceph,以接送格式输出
        ceph mon_status: 即为 prefix='mon_status', format='json',拼接过程中去除ceph,以接送格式输出
        ceph osd pool ls detail: 即为 prefix='osd pool ls', detail='detail', format='json',拼接过程中去除ceph,以接送格式输出
        :return: code: 执行结果(0成功,其余失败), buf:执行结果, err:错误原因
        """
        cmd = json.dumps(kwargs)
        try:
            code, buf, error = self.cluster.mon_command(cmd, "", timeout=10)
            return {"code": code,
                    "buf": json.loads(buf, encoding="utf-8") if buf else '',
                    "err": error.encode("utf-8")}
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'execute cmd: %s failed.' % cmd)


class POOLOperation(object):

    def __init__(self, cluster):
        """
        :param cluster: ceph集群
        """
        if not cluster:
            raise ExecuteException(CEPH_RBD_ERROR, 'cluster is none.')

        self.cluster = cluster

    def get_ioctx(self, pool):
        """
        获取存储池上下文连接
        :param pool: 存储池名称
        :return:
        """
        try:
            return self.cluster.open_ioctx(pool)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get ioctx failed.')

    @staticmethod
    def close_ioctx(ioctx):
        """
        断开存储池上下文连接
        :param ioctx: 存储池上下文连接
        :return:
        """
        try:
            ioctx.close()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'close ioctx failed.')

    def get_pools(self):
        """
        获取存储池列表
        :return:
        """
        try:
            return [i.encode() for i in self.cluster.list_pools()]
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get pool failed.')

    def is_pool_exists(self, pool):
        """
        检查存储池是否存在
        :param pool: 存储池名称
        :return: 布尔值
        """
        try:
            return self.cluster.pool_exists(pool)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'check pool exists failed.')

    def create_pool(self, pool):
        """
        创建存储池
        :param pool: 存储池名称
        :return:
        """
        try:
            if self.is_pool_exists(pool):
                raise ExecuteException(CEPH_RBD_ERROR, 'pool already exists.')
            self.cluster.create_pool(pool)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'create pool failed.')

    def delete_pool(self, pool):
        """
        删除存储池(慎用,存储池中若还存有镜像,则会连同数据一起删除)
        :param pool: 存储池名称
        :return:
        """
        try:
            self.cluster.delete_pool(pool)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'delete pool failed.')


class IMAGEOperation(object):

    def __init__(self, ioctx):
        """
        :param ioctx: 存储池上下文连接
        """
        if not ioctx:
            raise ExecuteException(CEPH_RBD_ERROR, 'ioctx is none.')

        self.ioctx = ioctx
        self.rbd_inst = self._get_rbd_inst()

    @staticmethod
    def _get_rbd_inst():
        """
        获取rbd对象
        :return:
        """
        try:
            return rbd.RBD()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get rbd object failed.')

    def get_images(self):
        """
        获取存储池中镜像列表
        :return:
        """
        try:
            return [i.encode() for i in self.rbd_inst.list(self.ioctx)]
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get images failed.')

    def is_image_exists(self, name):
        """
        检查镜像是否存在
        :param name: 镜像名称
        :return: 布尔值
        """
        try:
            flag = False
            if name in self.get_images():
                flag = True
            return flag
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'check images exists failed.')

    def create_image(self, name, size):
        """
        创建镜像
        :param name: 镜像名称
        :param size: 镜像大小(bytes)
        :return:
        """
        try:
            if self.is_image_exists(name):
                raise ExecuteException(CEPH_RBD_ERROR, 'image already exists.')
            self.rbd_inst.create(self.ioctx, name, size)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'create images failed.')

    def rename_image(self, name, new_name):
        """
        重命名镜像
        :param name: 镜像名称
        :param new_name: 镜像新名称
        :return:
        """
        if self.is_image_exists(new_name):
            raise ExecuteException(CEPH_RBD_ERROR, 'images %s exits.' % new_name)
        try:
            self.rbd_inst.rename(self.ioctx, name, new_name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'rename images failed.')

    def remove_image(self, name):
        """
        删除镜像
        :param name: 镜像名称
        :return:
        """
        try:
            self.rbd_inst.remove(self.ioctx, name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'remove images failed.')

    def get_mirror_image_status_list(self):
        """
        获取镜像状态列表
        :return:
        """
        try:
            return self.rbd_inst.mirror_image_status_list(self.ioctx)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get images status list failed.')

    def get_mirror_image_status_summary(self):
        """
        获取镜像状态摘要
        :return:
        """
        try:
            return self.rbd_inst.mirror_image_status_summary(self.ioctx)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get images status summary failed.')

    def get_mirror_mode_get(self):
        """
        获取镜像模式
        :return: 返回数字,如:0
        """
        try:
            return self.rbd_inst.mirror_mode_get(self.ioctx)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get images mode failed.')

    def _get_image(self, name):
        """
        获取镜像对象
        :param name: 镜像名称
        :return:
        """
        try:
            return rbd.Image(self.ioctx, name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get image object failed.')

    @staticmethod
    def _close_image(image):
        """
        关闭镜像对象
        :param image: 镜像对象
        :return:
        """
        try:
            if image:
                image.close()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'close image object failed.')

    def get_stat(self, name):
        """
        获取镜像统计数据
        :param name: 镜像名称
        :return: {'parent_name': '',
                  'parent_pool': 18446744073709551615 L,
                  'num_objs': 1 L,
                  'block_name_prefix': 'rbd_data.69687e2ae8944a',
                  'obj_size': 4194304 L,
                  'order': 22,
                  'size': 20480 L
                }
        """
        image = None
        try:
            image = self._get_image(name)
            stat = image.stat()
            for k, v in stat.items():
                stat[k] = v.encode() if type(v) == unicode else v
            return stat
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get image stat failed.')
        finally:
            self._close_image(image)

    def get_size(self, name):
        """
        获取镜像大小
        :param name: 镜像名称
        :return:
        """
        image = None
        try:
            image = self._get_image(name)
            return image.size()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get image size failed.')
        finally:
            self._close_image(image)

    def resize(self, name, size):
        """
        扩容镜像
        :param name: 镜像名称
        :param size: 大小
        :return:
        """
        image = None
        try:
            image = self._get_image(name)
            image.resize(size)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'resize image failed.')
        finally:
            self._close_image(image)

    def copy(self, name, dest_ioctx, dest_name):
        """
        拷贝镜像(将镜像拷贝,形成新的镜像),此举是浅拷贝,不会拷贝原镜像的快照
        :param name: 镜像名称
        :param dest_ioctx: 目标存储池上下文连接
        :param dest_name: 拷贝后生成的镜像名称
        :return:
        """
        image = None
        try:
            image = self._get_image(name)
            image.copy(dest_ioctx, dest_name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'copy image failed.')
        finally:
            self._close_image(image)


class SNAPOperation(object):
    def __init__(self, ioctx, name):
        """

        :param ioctx: 存储池上下文连接
        :param name: 镜像名称
        """
        if not ioctx:
            raise ExecuteException(CEPH_RBD_ERROR, 'ioctx is none.')
        if not name:
            raise ExecuteException(CEPH_RBD_ERROR, 'image is none.')

        self.ioctx = ioctx
        self.name = name

    def _get_image(self):
        """
        获取镜像对象
        :return:
        """
        try:
            return rbd.Image(self.ioctx, self.name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get image object failed.')

    @staticmethod
    def _close_image(image):
        try:
            if image:
                image.close()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'close image object failed.')

    def get_snaps(self):
        """
        获取镜像快照列表
        :return:
        """
        image = None
        try:
            image = self._get_image()
            # <rbd.SnapIterator object at 0x7fe7451ad650>
            snapIterator = image.list_snaps()
            # <generator object at 0x7fe7451d0d70>
            snapGenerator = snapIterator.__iter__()
            snaps = []
            while True:
                try:
                    snaps.append(next(snapGenerator))
                except StopIteration:
                    break
                except Exception as e:
                    cstor_logger.error(e.message)
                    raise ExecuteException(CEPH_RBD_ERROR, 'get snap list error.')
            for j in snaps:
                for k, v in j.items():
                    j[k] = v.encode() if type(v) == unicode else v
            return snaps
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get snaps failed.')
        finally:
            self._close_image(image)

    def is_snap_exits(self, name):
        """
        检查镜像快照是否存在
        :param name: 快照名称
        :return:
        """
        try:
            flag = False
            if name in [i['name'].encode() for i in self.get_snaps()]:
                flag = True
            return flag
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'check snap exits failed.')

    def create_snap(self, name):
        """
        创建快照
        :param name: 快照名称
        :return:
        """
        image = None
        try:
            if self.is_snap_exits(name):
                raise ExecuteException(CEPH_RBD_ERROR, 'snap already exists.')
            image = self._get_image()
            image.create_snap(name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'create snap failed.')
        finally:
            self._close_image(image)

    @staticmethod
    def _get_rbd_inst():
        """
        获取rbd对象
        :return:
        """
        try:
            return rbd.RBD()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get rbd object failed.')

    def clone(self, name, dest_ioctx, dest_name):
        """
        克隆(此处是对快照(快照需要被保护)进行克隆,生成新的镜像)
        :param name: 快照名称
        :param dest_ioctx: 目标存储池上下文连接
        :param dest_name: 克隆后生成的镜像名称
        :return:
        """
        try:
            if not self.is_snap_exits(name):
                raise ExecuteException(CEPH_RBD_ERROR, 'snap not exists.')
            # 被克隆的快照需要被保护
            if not self.is_snap_protected(name):
                raise ExecuteException(CEPH_RBD_ERROR, 'snap should be protected.')
            rbd_inst = self._get_rbd_inst()
            rbd_inst.clone(self.ioctx, self.name, name, dest_ioctx, dest_name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'clone snap failed.')

    def get_children_list(self, name):
        """
        获取快照的儿子列表(即由快照克隆出来的镜像),注意,跨集群的无法显示
        :param name: 快照名称
        :return: [{'pool': 'xx', 'image': '1'}, {'pool': 'xx', 'image': '2'}]
        """
        image = None
        try:
            children = []
            image = self._get_image()
            image.set_snap(name)
            # [(u'bb', u'1')]
            list_children = image.list_children()
            for i in list_children:
                children.append(
                    {'pool': i[0].encode() if type(i[0]) == unicode else i[0],
                     'image': i[1].encode() if type(i[1]) == unicode else i[1]})
            return children
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get children failed.')
        finally:
            self._close_image(image)

    def delete_snap(self, name):
        """
        删除快照
        :param name: 快照名称
        :return:
        """
        image = None
        try:
            # 被保护的快照无法删除,需要先取消保护才可以删除
            if self.is_snap_protected(name):
                raise ExecuteException(CEPH_RBD_ERROR, 'cannot unprotect: snap has at least one children.')
            image = self._get_image()
            image.remove_snap(name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'delete snap failed.')
        finally:
            self._close_image(image)

    def is_snap_protected(self, name):
        """
        查看快照是否被保护
        :param name: 快照名称
        :return: 布尔值
        """
        image = None
        try:
            image = self._get_image()
            return image.is_protected_snap(name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'check snap protected failed.')
        finally:
            self._close_image(image)

    def protect_snap(self, name):
        """
        保护快照
        :param name: 快照名称
        :return: 布尔值
        """
        image = None
        try:
            if not self.is_snap_protected(name):
                image = self._get_image()
                image.protect_snap(name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'protect snap failed.')
        finally:
            self._close_image(image)

    def unprotect_snap(self, name):
        """
        取消快照保护
        :param name: 快照名称
        :return: 布尔值
        """
        image = None
        try:
            # 若此快照克隆出了新镜像(儿子),此时无法取消取消保护,需先删除儿子才可以进行操作
            if self.get_children_list(name):
                raise ExecuteException(CEPH_RBD_ERROR, 'cannot unprotect: snap has at least one children.')
            if self.is_snap_protected(name):
                image = self._get_image()
                image.unprotect_snap(name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'unprotect snap failed.')
        finally:
            self._close_image(image)

    def rollback_snap(self, name):
        """
        回滚快照
        :param name: 快照名称
        :return:
        """
        image = None
        try:
            if not self.is_snap_exits(name):
                raise ExecuteException(CEPH_RBD_ERROR, 'snap not exists.')
            image = self._get_image()
            image.rollback_to_snap(name)
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'rollback snap failed.')
        finally:
            self._close_image(image)

    def get_stripe_count(self):
        image = None
        try:
            image = self._get_image()
            return image.stripe_count()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get snap stripe count failed.')
        finally:
            self._close_image(image)

    def get_stripe_unit(self):
        image = None
        try:
            image = self._get_image()
            return image.stripe_unit()
        except Exception as err:
            cstor_logger.error(err.message)
            raise ExecuteException(CEPH_RBD_ERROR, 'get snap stripe unit failed.')
        finally:
            self._close_image(image)


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值