深入理解ceph-disk prepare 源码逻辑
文章目录
- CEPH-DISK代码逻辑
- DEF MAIN:
- DEF PARSE_ARGS:
- DEF Prepare.set_subparser(subparsers)
- def _prepare(self):PrepareBluestore的_prepare函数
- def prepare(self, *to_prepare_list):PrepareData类中的prepare函数
- def prepare_device(self, *to_prepare_list): #prepare_device
- def prepare(self):prepare_device的prepare函数,执行基本分区的prepare工作`db,wal`
- def populate_data_path_device(self, *to_prepare_list):创建临时文件系统,写入Ceph_fsid以及fsid,磁盘属性等信息
CEPH-DISK代码逻辑
ceph
L版本12.2.1
本文以最新的BLUESTORE
为例进行逻辑梳理
主要分为:prepare
和activate
,本文主要从源码描述prepare的工作过程
ceph-disk -v prepare /dev/sdb
ceph-disk -v activate /dev/sdb1
DEF MAIN:
ceph-disk的main函数入口
def main(argv):#python强大的命令行解析模块,将输入命令解析为具体的对应项,并调用对应的函数做处理,如prepare,activateargs = parse_args(argv)#启动部署的日志级别,分为DEBUG,STDOUT,BASICsetup_logging(args.verbose, args.log_stdout)#设置python的全局变量,创建对应的文件,包括prepare锁文件,activate锁文件,suppress_prefix抑制标记setup_statedir(dir)#同步配置文件的目录为/etc/cephsetup_sysconfdir(args.sysconfdir) #设置ceph的全局用户组和用户权限global CEPH_PREF_USERCEPH_PREF_USER = args.setuserglobal CEPH_PREF_GROUPCEPH_PREF_GROUP = args.setgroup#启动执行args传入的函数if args.verbose:args.func(args)else:main_catch(args.func, args)
DEF PARSE_ARGS:
通过强大的parser命令行解析器模块对输入的参数进行解析
def parse_args(argv):#构建一个ArgrmentParser对象parser = argparse.ArgumentParser('ceph-disk',)#add_arguemnt添加命令行参数,`-`和`--`开头的参数表示可选参数,其他的表示必须输入的参数parser.add_argument('-v', '--verbose',action='store_true', default=None,help='be more verbose',)#python强大的命令行解析模块,添加一个子命令解析器subparsers = parser.add_subparsers(title='subcommands',description='valid subcommands',help='sub-command help',)#对prepare 子命令进行解析,并设置参数的函数属性为Prepare.mainPrepare.set_subparser(subparsers)#对activate子命令进行解析,并设置参数的函数属性为main_activatemake_activate_parser(subparsers)#对activate-lockbox子命令进行解析,并设置参数的函数属性为main_activate_lockboxmake_activate_lockbox_parser(subparsers)#对激活数据(data)子命令进行解析,设置参数的函数属性main_activate_space(name, args)make_activate_block_parser(subparsers)#对激活日志(jounal)子命令进行解析,设置参数属性为main_activate_space(name, args)make_activate_journal_parser(subparsers)#对激活所有的osd分区,激活所有的/dev/disk/by-parttypeuuid中找到的分区,使用main_activate_all函数make_activate_all_parser(subparsers)#对显示系统上所有的分区以及与ceph有关联的分区信息,list命令进行解析,main_listmake_list_parser(subparsers)#对supress-activate函数进行解析,使得磁盘不会被激活,使用main_suppress make_suppress_parser(subparsers)#对deactivate子命令进行解析,停止osd服务并将osd标记为out,删除/var/lib/ceph/osd/ceph-id目录make_deactivate_parser(subparsers)#破坏osd,破坏的前提是该osd进程必须是down状态。如果完成破坏,那么一个新的osd就可以在当前位置进程创建,并且可以使用相同的osd_idmake_destroy_parser(subparsers)#对格式化命令进行解析,主要功能是使用sgdisk删除一个设备的分区表和目录,主要参数是‘--zap-all’可以破坏gpt和MBR数据结构,以便磁盘可以为下次分区做准备make_zap_parser(subparsers)#对触发命令进行解析,激活给定的osd分区,主要是在系统重启时拉起一些系统进程或者systemd服务,通过异步执行该命令可以缩短udev动作的执行时间make_trigger_parser(subparsers)#解析修复命令,主要用来修复selinux,ceph相关标签、系统文件权限、修复ceph数据的可访问资源(selinux)make_fix_parser(subparsers)
DEF Prepare.set_subparser(subparsers)
解析prepare命令,并获取prepare
时的执行函数Prepare.main
,prepare时的步骤如下
判定部署参数中是否有对osd目录加密
--dmcrypt
,该参数用于ceph的ansible
自动化工具- 有加密,核对当前设备是否在正在使用中,如果正在使用中则返回错误。(由于我们有共享盘技术,所以部分磁盘会在prepare之前被占用,我们会注释掉这部分代码)
- 主要通过检测设备是否被挂载
- 检测是否有分区且分区被挂载
- 设备未被使用,则创建一个10M的五分区用来做加密的盒子
lockbox
- 格式化分区为ext4文件系统并挂载到目录
/var/lib/ceph/osd-lockbox
目录下
- 有加密,核对当前设备是否在正在使用中,如果正在使用中则返回错误。(由于我们有共享盘技术,所以部分磁盘会在prepare之前被占用,我们会注释掉这部分代码)
部署参数中没有对osd目录加密,则开始增加prepare list内容
- 先在磁盘设备上做出数据分区1,默认是100MB
- 根据设定的参数,如
ceph-disk -v prepare /deb/sdb --block.db /dev/sdb --block.wal /dev/sdb
指定了拥有db/wal分区的设备,会先做出第一分区data,其次第三分区db,第四分区wal - 创建uuid类型设备链接到分区,因为udev无法可靠地注意到对现有分区的GUID的更改
- 使用partprobe更新分区表
- mkfs使用默认设定的文件系统格式化第一分区,并创建临时文件夹挂载到第一分区将ceph_fsid,fsid,设备属性等信息写入文件系统
到目前为止所有分区就都prepare成功了,下一步就是activate
源码如下:def set_subparser(subparsers):#设置几个主要的参数解析器用来添加基础prepare命令集选项parents = [Prepare.parser(),PrepareData.parser(),Lockbox.parser(),]#添加prepare的子命令解析器subparsers.add_parser('prepare',parents=parents,...)#如果命令为prepare,最终主函数会执行如下prepare的主函数def main(args):Prepare.factory(args).prepare()#使用prepare类的工厂函数来执行#这里我们默认选择L版本之后bluestore的prepare函数def factory(args):if args.bluestore:return PrepareBluestore(args)else:return PrepareFilestore(args)
def _prepare(self):PrepareBluestore的_prepare函数
def _prepare(self)#对部署参数中是否有osd目录的加密进行判断,有的话则需要prepare单独的lockbox分区if self.data.args.dmcrypt:self.lockbox.prepare()to_prepare_list = []if getattr(self.data.args, 'block.db'):to_prepare_list.append(self.blockdb)if getattr(self.data.args, 'block.wal'):to_prepare_list.append(self.blockwal)to_prepare_list.append(self.block)#如果没有则增加完prepare_list中的内容之后开始进行osd主要分区的准备工作#当前prepare中的函数prepare_device()被PrepareBluestoreData继承self.data.prepare(*to_prepare_list)
def prepare(self, *to_prepare_list):PrepareData类中的prepare函数
def prepare(self, *to_prepare_list)if self.type == self.DEVICE:#当前使用的prepare_device函数为PrepareBluestoreData类中的函数self.prepare_device(*to_prepare_list)elif self.type == self.FILE:self.prepare_file(*to_prepare_list)else:raise Error('unexpected type ', self.type)
def prepare_device(self, *to_prepare_list): #prepare_device
def prepare_device(self, *to_prepare_list): super(PrepareBluestoreData, self).prepare_device(*to_prepare_list)#先做出第一分区,默认100MBself.set_data_partition()for to_prepare in to_prepare_list:#当前prepare根据PrepareBluestore的_prepare函数def _prepare(self):中的prepare_list中的对象prepare对应的分区,此时先prepare db分区,其次wal分区to_prepare.prepare()#使用默认文件系统格式化第一分区并创建临时文件self.populate_data_path_device(*to_prepare_list)
def prepare(self):prepare_device的prepare函数,执行基本分区的prepare工作db,wal
def prepare(self)if self.type == self.DEVICE:#如果是Device,一般是bluestore,否则为filestore#根据传入的设备类型进行prepare_device,先是db高速设备,其次是wal超高速设备self.prepare_device()elif self.type == self.FILE:self.prepare_file()elif self.type == self.NONE:passelse:raise Error('unexpected type ', self.type)#上一个函数的prepare_device,在该函数过程中会根据设备类型创建uuid链接到分区,并使用partprobe更新分区表def prepare_device(self):reusing_partition = False#判定当前设备是否有分区if is_partition(getattr(self.args, self.name)):LOG.debug('%s %s is a partition',self.name.capitalize(), getattr(self.args, self.name))partition = DevicePartition.factory(path=None, dev=getattr(self.args, self.name), args=self.args)if isinstance(partition, DevicePartitionCrypt):raise Error(getattr(self.args, self.name) +' partition already exists'' and --dmcrypt specified')LOG.warning('OSD will not be hot-swappable' +' if ' + self.name + ' is not' +' the same device as the osd data')if partition.get_ptype() == partition.ptype_for_name(self.name):LOG.debug('%s %s was previously prepared with ''ceph-disk. Reusing it.',self.name.capitalize(),getattr(self.args, self.name))reusing_partition = True# Read and reuse the partition uuid from this journal's# previous life. We reuse the uuid instead of changing it# because udev does not reliably notice changes to an# existing partition's GUID. See# http://tracker.ceph.com/issues/10146setattr(self.args, self.name + '_uuid', partition.get_uuid())LOG.debug('Reusing %s with uuid %s',self.name,getattr(self.args, self.name + '_uuid'))else:LOG.warning('%s %s was not prepared with ''ceph-disk. Symlinking directly.',self.name.capitalize(),getattr(self.args, self.name))self.space_symlink = getattr(self.args, self.name)returnself.space_symlink = '/dev/disk/by-partuuid/{uuid}'.format(uuid=getattr(self.args, self.name + '_uuid'))#如果有对设备映射表的加密标记,则对加密分区创建链接if self.args.dmcrypt:self.space_dmcrypt = self.space_symlinkself.space_symlink = '/dev/mapper/{uuid}'.format(uuid=getattr(self.args, self.name + '_uuid'))if reusing_partition:# confirm that the space_symlink exists. It should since# this was an active space# in the past. Continuing otherwise would be futile.assert os.path.exists(self.space_symlink)returnnum = self.desired_partition_number()if num == 0:LOG.warning('OSD will not be hot-swappable if %s ''is not the same device as the osd data',self.name)device = Device.factory(getattr(self.args, self.name), self.args)#创建对应分区num = device.create_partition(uuid=getattr(self.args, self.name + '_uuid'),name=self.name,size=self.space_size,num=num)partition = device.get_partition(num)LOG.debug('%s is GPT partition %s',self.name.capitalize(),self.space_symlink)if isinstance(partition, DevicePartitionCrypt):partition.format()partition.map()command_check_call(['sgdisk','--typecode={num}:{uuid}'.format(num=num,uuid=partition.ptype_for_name(self.name),),'--',getattr(self.args, self.name),],)#partprobe更新分区表update_partition(getattr(self.args, self.name), 'prepared')LOG.debug('%s is GPT partition %s',self.name.capitalize(),self.space_symlink)
def populate_data_path_device(self, *to_prepare_list):创建临时文件系统,写入Ceph_fsid以及fsid,磁盘属性等信息
prepare_device的最后一步是创建临时文件系统,写入Ceph_fsid以及fsid,磁盘属性等信息到该文件系统
def populate_data_path_device(self, *to_prepare_list):partition = self.partitionif isinstance(partition, DevicePartitionCrypt):partition.map()try:args = ['mkfs','-t',self.args.fs_type,]if self.mkfs_args is not None:args.extend(self.mkfs_args.split())#如果默认文件系统为xfs,则使用mkfs -t xfs -f强制执行,否则不需要-f参数if self.args.fs_type == 'xfs':args.extend(['-f']) # always forceelse:args.extend(MKFS_ARGS.get(self.args.fs_type, []))args.extend(['--',partition.get_dev(),])LOG.debug('Creating %s fs on %s',self.args.fs_type, partition.get_dev())command_check_call(args, exit=True)#执行挂载path = mount(dev=partition.get_dev(),fstype=self.args.fs_type,options=self.mount_options)try:self.populate_data_path(path, *to_prepare_list)finally:path_set_context(path)unmount(path)finally:if isinstance(partition, DevicePartitionCrypt):partition.unmap()if not is_partition(self.args.data):command_check_call(['sgdisk','--typecode=%d:%s' % (partition.get_partition_number(),partition.ptype_for_name('osd')),'--',self.args.data,],exit=True,)#parprobe更新分区表,且在此过程中会执行两次udevadm settle --timeout=600,第一次是为了解决正在等待进行的udev事件完成,以防其中有事件依赖于设备上的现有分区;第二次执行是为了向调用者保证已经处理了与分区表变化相关的所有udev事件(95-ceph-osd.rules动作和模式改变,组改变等)已完成。update_partition(self.args.data, 'prepared')command_check_call(['udevadm', 'trigger','--action=add','--sysname-match',os.path.basename(partition.rawdev)])
相关文章:

Deep Learning 学习随记(三)续 Softmax regression练习
上一篇讲的Softmax regression,当时时间不够,没把练习做完。这几天学车有点累,又特别想动动手自己写写matlab代码 所以等到了现在,这篇文章就当做上一篇的续吧。 回顾: 上一篇最后给出了softmax regression的代价函数和…

html画三个重叠的矩形,html5 实现两个矩形的叠加
Canvas Primer - Example: Drawing shadowswindow.addEventListener(load, function () {//得到canvas,并检测是否支持canvasvar elem document.getElementById(myCanvas);if (!elem || !elem.getContext) {return;}// 得到可以画图的上下文contextvar context el…

sqlplusw下登录sys账户
今天使用sqlplusw时,发现每次使用sys用户登录时总是报错,提示要以sysdba或者sysoper的身份登录,错误提示如下图所示:可是界面上没地方可以输入角色的地方呀,后经尝试发现,在口令输入框里首先输入密码&#…

mybatis =或这个=提示错误Tag name expecte问题解决
解决方案: 1、将<号或者>号进行转义 DATE_SUB(CURDATE(), INTERVAL 31 DAY) < DATE(created) 2、使用<![CDATA[ ]]>符号进行说明 <![CDATA[DATE_SUB(CURDATE(), INTERVAL 31 DAY) < DATE(created)]]> 附: 附录:常见…

s-sgdisk源码分析 “--set-alignment=value分区对齐参数”
文章目录边界对齐子命令使用源码分析sgdisk.cc main函数入口gptcl.cc DoOptions解析并执行具体命令函数gpt.cc CreatePartition创建分区函数,设置起始扇区对齐gpt.cc Align分区对齐函数,设置起始扇区对齐sgdisk命令是由 gdisk-0.8.6-4.el7.x86_64程序包安…

NuGet学习笔记(3) 搭建属于自己的NuGet服务器
文章导读 创建NuGetServer Web站点 发布站点到IIS 添加本地站点到包包数据源 在上一篇NuGet学习笔记(2) 使用图形化界面打包自己的类库 中讲解了如何打包自己的类库,接下来进行最重要的一步,从零开始搭建属于自己的NuGet服务器,诚然园子里及其…

计算机网络共享打不开,网络和共享中心打不开,共享无法访问没有权限
在Win7系统下如果别的计算机设置了共享,那么在本机设置网络发现后就可以打开网络搜索到共享计算机和共享文件了,不过一些朋友反馈win7系统网络发现无法启用的问题,下面小编整理了解决方法,大家可以参考一下哦。解决方法如下&#…
千万不要把 bool 当成函数参数
我们有很多 Coding Style 或 代码规范。 但这一条可能会经常被我们所遗忘,就是我们 经常会在函数的参数里使用bool参数,这会大大地降低代码的可读性。 不信?我们先来看看下面的代码。 当你读到下面的代码,你会觉得这个代码是什么意…

修改ceph-disk源码,增加指定ceph.conf部署osd的功能
文章目录 ceph环境源码修改 主文件:`ceph-disk/main.py`main函数入口parse_args(argv)增加子命令解析get_conf函数使`conf`生效修改所有调用get_conf函数的上级函数参数配置由于最近工作中需要优化osd部署流程,单节点并发加盘过程需要指定特定conf文件,来完成单盘db,wal分区…

相关计算机专业的英语文献,英文文献及翻译计算机专业.doc
英文文献及翻译计算机专业外文资料翻译—英文原文NET-BASED TASK MANAGEMENT SYSTEMHector Garcia-Molina, Jeffrey D. Ullman, Jennifer WisdomABSTRACTIn net-based collaborative design environment, design resources become more and more varied and complex. Besides c…

作业 3 应用分支与循环结构解决问题 统计字符个数
/*统计字符,包括空格或回车,数字字符和其他字符*/#include<stdio.h> int main(void) {int digit,space,letter,other; /*定义4个变量分别存放统计结果*/ char ch;int i;digitspaceletterother0; /*置…

php后期静态绑定
从php5.3开始,php增加了一个叫后期绑定的功能,用于在继承范围内引用静态调用的类 该功能从语言内部角度考虑北命名为“后期静态绑定”;“后期绑定”意思说:static::不再被解析为定义当前方法所在的类&#…

pytest 9 pytest-datadir读取文件信息
安装:pip install pytest-datadir 介绍:用于操作测试数据目录和文件的插件。pytest-datadir他会寻找包含测试模块名字的文件夹或者全局的一个文件夹名字为data下的数据。比如以下的一个结构: firstdemo.py可以从test_firstdemo文件夹下的文件…

深入理解ceph-disk activate 源码逻辑
文章目录CEPH-DISK代码逻辑Activate osd的主要逻辑如下DEF main_activate激活osd的入口函数DEF mount_activate挂载临时目录,分配osd id并初始化osdDEF activate 分配osd_id以及初始化osdCEPH-DISK代码逻辑 本文在上文 :深入理解ceph-disk prepare 源码逻辑基础上描…

simple_html_dom meta,HTML DOM Meta content 属性
HTML DOM Meta content 属性Meta 对象定义和用法content 属性可设置或者返回 meta 元素 content 属性值。content 属性指定了 meta 信息的内容。注意: 这个属性可用的值依赖于name 和httpEquiv 属性的值。语法设置 content 属性:linkObject.content"…

struts2登录后返回登录前的页面
在Action中添加 String getUrl() { return ServletActionContext.getRequest().getHeader("referer"); } 然后配置struts的这个Action的result为:<result type"redirect">${url}</resu…

Exchange 2010 恢复误删除的邮箱账户及其邮箱
在误删除邮箱后,AD中相应的账号也会随之删除,此时该如何恢复? 先来模拟邮箱被误删除,在EMC控制台中删除别名为jqq的邮箱 打开ADUC,发现相应的jqq账号也被删除了: 1.恢复AD账号 下载运行ADRecycle Bin,点击【…

Python 函数初识 (1)
一、今日主要内容 认识函数 函数:对功能或者动作的封装(定义) 语法: def 函数名字(形参) 函数体 函数的调用格式:函数名(实参) 函数的返回值 关键字:return 终止函数的运行 1、函数内部不写return,默认函数末尾返回…

python的popen函数
最近了解了一下python的popen函数的使用,主要是用来执行linux命令 函数使用 使用之前需要导入import os模块 使用方式: os.popen(cmd)返回值: 返回一个文件句柄 import os cmd"/sbin/partx /dev/sdb" result_listos.popen(cmd) print result_list执行…

计算机竞赛CCC可以直接学吗,CCC 计算机竞赛到底有多牛!
加拿大计算机竞赛是什么?难度情况?加拿大计算机竞赛是由加拿大滑铁卢大学主办的,每年举办一次,是一场面向中学生的计算机程序设计比赛,CCC竞赛的一个目的是为广大中学生朋友们提供一个机会来测试自己分析、设计以及编程…

PHP basename() 函数
定义和用法 basename() 函数返回路径中的文件名部分。 语法 basename(path,suffix) 参数描述path必需。规定要检查的路径。suffix可选。规定文件扩展名。如果文件有 suffix,则不会输出这个扩展名。转载于:https://www.cnblogs.com/wuyou/p/3387079.html

真实工作经验总结——案例解析企业选型操作步骤
这是一个融合了本人以前工作经验的案例,包含有多个企业的选型需求。选型的过程也参考了本人以前所经历的部分事实。展现的目的在于让PUBer看到一个相对真实的选型。企业介绍这是一家中型的电脑和周边设备生产企业,即一个典型的电子企业。企业有内贸和外贸…

Oracle Goldengate Windows平台Oracle-Oracle单向复制
实验目的 Goldengate最基本的从源端一对一的单向复制,注意其中Goldengate版本取决于Oracle的版本。单向复制一般适用于保持目标数据库的实时更新,且目标数据库用来检索,如报表或者分析使用。 Source DB 操作系统:Windows 10 64 Or…

C语言解析命令行函数:getopt系列
头文件:/usr/include/getopt.h 函数传入较长参数 函数getopt_long_only和getopt_long两者用法差不多,都可以用来解析命令行选项 函数出处 #include <getopt.h> //getopt_long()头文件位置 int getopt_long (int ___argc, char *const *___ar…

宁波大学计算机专业复试,2016年宁波大学信息科学与工程学院计算机专业考研复试题库. (1)...
2016年宁波大学信息科学与工程学院计算机专业考研复试题库(二)——————————————————————————————————————————一、选择题1.下列有关浮点数加减运算的叒述中,正确的是()。对阶操作丌会引起阶码上溢戒下溢右规和尾…

RedHat、CentOS设置静态IP、主机名、关闭防火墙(虚拟机VMware客户机)
设置静态IP、主机名 1. /etc/sysconfig/network [roothadoop ~]# vi /etc/sysconfig/network NETWORKINGyes HOSTNAMEhadoop #主机名 GATEWAY192.168.80.1 #网关 2. /etc/sysconfig/network-scripts/ifcfg-eth0 [roothadoop ~]# vi /etc/sysconfig/network-scripts/ifc…

关于box2d相关学习教程记录一下
Box2D 2.0.1版本 认识Box2D世界掉落的苹果——b2Body刚体创建圆形刚体创建静止不动的刚体在运行时创建刚体刚体的上衣——b2BodyDef.userDataBox2D能再简单点吗——LDEasyBox2D让刚体听我的——ApplyForce、ApplyImpulse、SetLinearVelocity创建多边形刚体创建圆角刚体给圆角刚…

韦东山网课https://edu.csdn.net/course/play/207/1117
接口讲解https://edu.csdn.net/course/play/207/1117转载于:https://www.cnblogs.com/chulin/p/9878555.html

使用dd查看磁盘前4个扇区的内容
想要获取磁盘前四个扇区的内容可以先将扇区内容从磁盘dd出来,使用如下命令 dd if/dev/sdb ofmbr.txt bs1 count2048 改命令将sdb磁盘的前2048个字节内容即4个扇区内容备份到文件mbr.txt里面。 其中bs为块大小1即为1个字节,count表示块个数,即…

在SharePoint 2010使用OWA查看自己邮箱的内容
在SharePoint 2010使用OWA 背景: 利用 Outlook Web Access Web 部件,可以在 SharePoint 网站中显示从 Microsoft Exchange Server 2003 至 2007 电子邮件帐户中的文件夹中选择的内容. 这些 Web 部件连接到您的组织的 Office Outlook Web Access 服务器,而…