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

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(),提供了对外访问这些信息的接口。在下面几篇博客中我将对这些调用关系以及具体代码实现做详细介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值