@tony-yin
        
        2018-04-25T02:18:04.000000Z
        字数 3894
        阅读 7401
    Ceph Nas
最近公司有个集群一直在跑着,领导想要测测它上面NAS服务的稳定性,也就是看看正常持续的读写会不会导致NAS服务异常,这个其实通过fio或者cosbench这类的工具测试起来很容易,但是这样一是没有挑战性,二是比较机械,可扩展性低。比如并行测试、进程保护和异常通知等等这些是机械地运用工具测试所做不到的,所以我们尝试做了一套基于NAS稳定性测试的框架。
整个测试框架打包和发布都是通过RPM的方式,方便测试人员一键部署。部署之后测试工作由supervisor管理,实时监控后台进程的运行状态,发生异常时可以进行重启等自动化操作。所有读写操作都是通过python 连接NAS服务,无需做任何挂载工作。主要测试工作是通过celery实现任务调度,支持并行多个NAS服务的读写测试,broker和backend store都采用了rabbitmq。后端注册了register、nfs、cifs和ftp四个job,定时每10分钟执行一次,设置最大开启worker数为5个。Job注册进消息队列中后,celery worker会自动去消费,针对服务器中不同的NAS服务进行读写操作,每个任务的执行结果最后都会记录在日志中,出了异常通过邮件通知管理员。
整个项目的框架图如下:

由于每个NAS服务的测试方式是一致的,所以下面就以单个NAS服务的流程来介绍。首先client端向server的NAS服务端口发起连接,server端接收到client端的请求后建立连接。Client在/tmp目录下生成固定大小1G的文件,并且记录该文件的MD5值,然后将该文件上传至远端NAS服务目录(即对NAS服务进行写操作),上传完成后将该文件从本地删除。接着对之前上传至NAS服务目录的文件进行下载(即对NAS服务进行读操作),下载完成后再次记录文件MD5值,并删除掉远端NAS服务目录对应的文件。最后对两次记录的MD5值进行比较,判断上传和下载的文件是否一致,并将比较结果记录在日志中,再次删除本地下载的文件。NAS服务读写流程图如下:

通过pip安装:
pip install libnfs
一般会报这个错:
libnfs/libnfs_wrap.c:2969:25: fatal error: nfsc/libnfs.h: No such file or directory
这个错看起来是缺少这个头文件的包,但是通过yum search libnfs是找不到相关的包的,所以我们只能去官网下载rpm包然后在安装:
## 下载rpm
wget http://li.nux.ro/download/nux/dextop/el7/x86_64//libnfs-1.9.8-1.el7.nux.x86_64.rpm
wget http://li.nux.ro/download/nux/dextop/el7/x86_64//libnfs-devel-1.9.8-1.el7.nux.x86_64.rpm
## 安装rpm
yum localinstall libnfs-1.9.8-1.el7.nux.x86_64.rpm
yum localinstall libnfs-devel-1.9.8-1.el7.nux.x86_64.rpm
这个比较简单,直接pip安装就可以了,也没遇到什么问题。
pip install pysmb
这里只贴出部分python连接或者操作具体Nas服务的代码实现,如果想要了解或者贡献整个项目,请关注:Github python_nas项目
def open(self):
self.nfs = libnfs.NFS('nfs://{}'.format(self.mount_point))
log.info('nfs connect successfully!')
这里有个关键点就是分段读写文件,避免内存溢出。
def read(self):
log.info('nfs read start...')
a = self.nfs.open('/{}'.format(self.filename), mode='r')
with open(self.download_path, 'a') as f:
while True:
content = a.read(1024*1024)
if content == '':
break
f.write(content)
a.close()
log.info('nfs read end...')
def write(self, content):
log.info('nfs write start...')
a = self.nfs.open('/{}'.format(self.filename), mode='w+')
a.seek(self.file_size)
a.write(content)
a.close()
log.info('nfs write end...')
def delete(self):
log.info('nfs file delete start...')
self.nfs.unlink('/{}'.format(self.filename))
log.info('nfs file delete end...')
def open(self):
self.smb = SMBConnection(
self.username,
self.password,
self.my_name.encode('utf-8'),
self.remote_name.encode('utf-8'),
use_ntlm_v2=True
)
self.smb.connect(self.host, self.port)
log.info('cifs connect successfully!')
def read(self):
log.info('cifs read start...')
file_obj = open(self.download_path, 'wb')
self.smb.retrieveFile(
self.directory,
self.filename,
file_obj
)
file_obj.close()
log.info('cifs read end...')
def write(self):
log.info('cifs write start...')
file_obj = open(self.client_path, 'rb')
self.smb.storeFile(
self.directory,
self.filename,
file_obj
)
file_obj.close()
log.info('cifs write end...')
def delete(self):
log.info('cifs delete start...')
self.smb.deleteFiles('path3', self.filename)
log.info('cifs delete end...')
def close(self):
self.smb.close()
def open(self):
self.ftp = FTP()
self.ftp.connect(
host=self.host.encode('utf-8'),
port=self.port.encode('utf-8')
)
self.ftp.login(self.username, self.password)
log.info('ftp connect successfully!')
def read(self):
log.info('ftp read start...')
buff_size = 1024
fp = open(self.download_path, "wb")
self.ftp.retrbinary(
"RETR {}".format(self.filename),
fp.write,
buff_size
)
fp.close()
log.info('ftp read end...')
def write(self):
log.info('ftp write start...')
buff_size = 1024
fp = open(self.client_path, "rb")
self.ftp.storbinary(
"STOR {}".format(self.filename),
fp,
buff_size
)
fp.close()
log.info('ftp write end...')
def delete(self):
log.info('ftp delete start...')
self.ftp.delete(self.filename)
log.info('ftp delete end...')
def close(self):
self.ftp.quit(self.filename)
还有一些其他的API接口就不一一赘述了,具体实现细节大家可以查看github上面的项目代码,具体地址我会在文末贴出。整个项目的核心是通过celery实现任务的调度,还有全程通过python连接和操作nas服务,后续还会不断完善~~~