您的位置:首页 > 运维架构 > 网站架构

OpenStack_Swift源码分析——Ring代码的组织架构

2014-05-14 10:24 567 查看

1、从部署文件看Ring

OpenStaci_Swfit源码分析-单机部署swift中详细介绍了swift 部署以及API的基本使用,其中在remakerings中介绍了设备的添加以及Ring文件的创建,首先看其具体的部署

#!/bin/bash
cd /etc/swift
rm -f *.builder *.ring.gz backups/*.builder backups/*.ring.gz
swift-ring-builder object.builder create 18 3 1
swift-ring-builder object.builder add z1-127.0.0.1:6010/sdb1 100     #z1 表示 zone1 127.0.0.1:6010 为设备ip地址和端口号,sdb1为设备的存储空间,100代表权重 这些都会调用swift-master/bin/swift-ring-builder 中的main方#法然后再代用swift-master/swift/cli/ringbuilder下的具体方法。ring代码分析将在下一篇博客中具体介绍
swift-ring-builder object.builder add z2-127.0.0.1:6020/sdb2 100
swift-ring-builder object.builder add z3-127.0.0.1:6030/sdb3 100
swift-ring-builder object.builder add z4-127.0.0.1:6040/sdb4 100
swift-ring-builder object.builder rebalance
swift-ring-builder container.builder create 18 3 1
swift-ring-builder container.builder add z1-127.0.0.1:6011/sdb1 100
swift-ring-builder container.builder add z2-127.0.0.1:6021/sdb2 100
swift-ring-builder container.builder add z3-127.0.0.1:6031/sdb3 100
swift-ring-builder container.builder add z4-127.0.0.1:6041/sdb4 100
swift-ring-builder container.builder rebalance
swift-ring-builder account.builder create 18 3 1
swift-ring-builder account.builder add z1-127.0.0.1:6012/sdb1 100
swift-ring-builder account.builder add z2-127.0.0.1:6022/sdb2 100
swift-ring-builder account.builder add z3-127.0.0.1:6032/sdb3 100
swift-ring-builder account.builder add z4-127.0.0.1:6042/sdb4 100
swift-ring-builder account.builder rebalance
上面脚本文件执行后会创建object、container、account三个Ring,在这里我只分析Object Ring的创建,其他两个类似。首先看如何创建Ring文件:

swift-ring-builder object.builder create 18 3 1
如上脚本片段在执行是首先会,执行/usr/local/bin中的swift-ring-builder这条命令,用vi打开后其里面内容为:

#!/usr/bin/python
# EASY-INSTALL-DEV-SCRIPT: 'swift==1.13.1.rc1.38.g856c155','swift-ring-builder'
__requires__ = 'swift==1.13.1.rc1.38.g856c155'
from pkg_resources import require; require('swift==1.13.1.rc1.38.g856c155')
del require
__file__ = '/root/swift/bin/swift-ring-builder'
execfile(__file__)
从其实现代码可以清楚的看出__file__所映射的具体执行代码,也就是swift源代码bin文件夹下的swift-ring-builder,打开此文件看看其具体的实现

import sys

from swift.cli.ringbuilder import main

if __name__ == "__main__":
sys.exit(main())


从执行main对应的是从swift.cli.ringbuilder中的main函数,找到个文件,打开看看其具体的代码实现:

def main(arguments=None):
print Commands.__doc__
exit(0)
global argv, backup_dir, builder, builder_file, ring_file
if arguments:
argv = arguments
else:
argv = sys_argv

if len(argv) < 2:
print "swift-ring-builder %(MAJOR_VERSION)s.%(MINOR_VERSION)s\n" % \
globals()
print Commands.default.__doc__.strip()
print
cmds = [c for c, f in Commands.__dict__.iteritems()
if f.__doc__ and c[0] != '_' and c != 'default']
cmds.sort()
for cmd in cmds:
print Commands.__dict__[cmd].__doc__.strip()
print
print parse_search_value.__doc__.strip()
print
for line in wrap(' '.join(cmds), 79, initial_indent='Quick list: ',
subsequent_indent='            '):
print line
print('Exit codes: 0 = operation successful\n'
'            1 = operation completed with warnings\n'
'            2 = error')
exit(EXIT_SUCCESS)
#根据输入会得到 .ring.gz 和.builder 文件
builder_file, ring_file = parse_builder_ring_filename_args(argv)
#对于 swift-ring-builder account.builder 打印 信息
#print argv
#['/usr/local/bin/swift-ring-builder', 'account.ring.gz']
if exists(builder_file):
#如果存在 builder_file 则加载
builder = RingBuilder.load(builder_file)
#如果 arg<3 或者 argv[2] 不是create 或者 write_builder中的任意一个 则出错
elif len(argv) < 3 or argv[2] not in('create', 'write_builder'):
print 'Ring Builder file does not exist: %s' % argv[1]
exit(EXIT_ERROR)

backup_dir = pathjoin(dirname(argv[1]), 'backups')
try:
mkdir(backup_dir)
except OSError as err:
if err.errno != EEXIST:
raise

if len(argv) == 2:
command = "default"
else:
command = argv[2]
if argv[0].endswith('-safe'):
try:
#why lock?
with lock_parent_directory(abspath(argv[1]), 15):
#执行命令 如 argv[2]=create 则会 Commands.create()
Commands.__dict__.get(command, Commands.unknown.im_func)()

except exceptions.LockTimeout:
print "Ring/builder dir currently locked."
exit(2)
else:
Commands.__dict__.get(command, Commands.unknown.im_func)()

if __name__ == '__main__':
main()
首先会从

swift-ring-builder object.builder create 18 3 1

截取参数,根据第二个参数argv[1],得到要创建的ring为object ring,并创建object.builder 和object.ring.gz两个文件,这两文件主要作用就是存入ring的相关信息。

截取第三个参数argv[2]

if len(argv) == 2:
command = "default"
else:
command = argv[2]
然后是得到command =create 后,

if argv[0].endswith('-safe'):
try:
#why lock?
with lock_parent_directory(abspath(argv[1]), 15):
#执行命令 如 argv[2]=create 则会 Commands.create()
Commands.__dict__.get(command, Commands.unknown.im_func)()

except exceptions.LockTimeout:
print "Ring/builder dir currently locked."
exit(2)
else:
Commands.__dict__.get(command, Commands.unknown.im_func)()
这段代码就是调用Commands类的具体方法了,我们现在得到的是create,故其会调用Commands类的create方法,同理对于如下脚本片段,从argv[1]中得到要对object ring进行操作,因为执行create后已经创建了object.builder 和object.ring.gz文件,现在只需把他们反序列化回来既可。

swift-ring-builder object.builder add z1-127.0.0.1:6010/sdb1 100
swift-ring-builder object.builder add z2-127.0.0.1:6020/sdb2 100
swift-ring-builder object.builder add z3-127.0.0.1:6030/sdb3 100
swift-ring-builder object.builder add z4-127.0.0.1:6040/sdb4 100
上面四条命令时为ring添加4个设备,如

z1-127.0.0.1:6010/sdb1 100

z1代表zone1 127.0.0.1代表设备ip地址,6010代表设备绑定的ip号,sdb1代表设备的将数据存储的位置,100为权重。

在添加了设备后需要对Ring进行重新平衡,语句

swift-ring-builder object.builder rebalance
调用Commands 类中的reblance方法,重新平衡Ring。

2、Ring实现代码的组织架构

第一节介绍了从部署文件中看Ring的创建,这一节将介绍Ring的实现中代码的调用关系:



图1 Ring中类主要调用关系

上图简单的画出了各个类之间的简单调用关系,Command类主要是出来运行脚本的,并通过运行脚本出来具体的方法,RingBuilder方法主要是用来出来具体的方法,其save方法是将设备的一些信息以及创建环所需要的其他信息存入*.builder文件中,RingData类中更多save方法会将replica2part2dev(备份到分区到设备映射)以及设备的基本属性和part_shift(右移位数)存入文件。Ring类中的_reload()方法对RingData进行反序列化,同时get_part(),get_part_nodes(),get_more_nodes(),提供了对外访问这些信息的接口。在下面几篇博客中我将对这些调用关系以及具体代码实现做详细介绍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐