@tony-yin
2018-04-25T10:18:04.000000Z
字数 3894
阅读 6591
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
服务,后续还会不断完善~~~