zoukankan      html  css  js  c++  java
  • eucalyptus volume 的一些创建流程以及理解

    目前eucalyptus中,数据的共享的逻辑卷采用aoe http://www.txrjy.com/baike/view.asp?ATA%20over%20Ethernet, http://support.coraid.com/support/linux/,
    和iscsi, http://baike.baidu.com/view/120148.htm.目前在我们的测试机中使用的是iscsi,进行逻辑卷的共享设置.
    在这些逻辑卷的实际测试使用中,在将卷绑定到虚拟机时,有时候会不够稳定,使卷无法绑定到虚拟机,或者是一个卷可以被多个虚拟机绑定,主要有以下三种情况:
    1、connect_iscsi_target failed
    这是由于iscsi的目标卷处于iactive状态,导致nc端在向目标卷发起连接登录的时候,无法连接,从而导致绑定失败.
    但是目前这种错误难以重现.推测是sc服务重启后,卷处于iactive状态,而没有对目标卷进行激活处理.
    具体查看目标机上的逻辑卷状态可以通过lvscan http://linux.die.net/man/8/lvscan进行查看,vgscan http://linux.die.net/man/8/vgscan查看逻辑卷组.
    clc端的错误日志: 下面日志表明.clc在attachvolume时,收到了结果为空的返回值.

    15:57:38 DEBUG [NioResponseHandler:cluster223-Worker-7] :1315900658432:NioResponseHandler:MSG_AWAIT_RESPONSE:MSG_POLL_INTERNAL:100:QueuedEventCallback.waitForResponse.354
    15:57:38 DEBUG [NioResponseHandler:cluster223-Worker-7] :1315900658536:NioResponseHandler:MSG_AWAIT_RESPONSE:MSG_POLL_INTERNAL:100:QueuedEventCallback.waitForResponse.354
    15:57:38 TRACE [QueuedEventCallback:New I/O client worker #2-12] <?xml version="1.0" encoding="UTF-8"?>
    <euca:AttachVolumeResponseType xmlns:euca="http://msgs.eucalyptus.com">
    <euca:BlockVolumeMessage>
    <euca:EucalyptusMessage>
    <euca:userId>admin</euca:userId>
    <euca:_return>false</euca:_return>
    <euca:statusMessage>ERROR</euca:statusMessage>
    </euca:EucalyptusMessage>
    </euca:BlockVolumeMessage>
    <euca:attachedVolume>
    <euca:attachTime>2011-09-13T07:57:38.565Z</euca:attachTime>
    </euca:attachedVolume>
    </euca:AttachVolumeResponseType>
    15:57:38 DEBUG [VolumeAttachCallback:New I/O client worker #2-12]
    <?xml version="1.0" encoding="UTF-8"?>
    <AttachVolume xmlns="http://eucalyptus.ucsb.edu/">
    <correlationId>cda55cc8-197d-4d3c-8382-24e7789930cb</correlationId>
    <userId>admin</userId>
    <return>true</return>
    <volumeId>vol-5DE1063D</volumeId>
    <instanceId>i-426E075E</instanceId>
    <remoteDev>//,192.168.5.223,iqn.2009-06.com.eucalyptus.cluster223:store3,KiErKVk7UC7vt6ZU12vd5ZUKgZJkZmG5cDZBVcbverPe2Tsp0DxAdWiWdhqhO6orpz36XWN1+/EvBoLzY+pQ0V19cWzBN17WLxOeoLv0zgq4p0hm22zdjJA/kWWD1ME2WnMDTAFe8dbFqyo8DrBO/ywFMBlxmZ7X/hzQb5YdHKAtTe0mOpxNqPgNg8rnrjI/MrQqA7xtUCybEcMlVFekLxwQpR5+UDlilZy2H4V1euzZtgAFkzzVIRsYJ+Hgg3H6f2DfCG+QbblAlLCPjdSi5+oozE/iDrNa+swwazKOXY7/jVCzK5KbM2vnRnuL7GgyHQBxr7KI27Lw/N/HAYLP9w==</remoteDev>
    <localDev>/dev/sdb</localDev>
    </AttachVolume>

    --------------------------------------------------------------------------------
    15:57:38 DEBUG [VolumeAttachCallback:New I/O client worker #2-12] com.eucalyptus.util.EucalyptusClusterException: [AttachVolumeResponseType attachedVolume=AttachedVolume null null null null null Tue Sep 13 15:57:38 CST 2011 correlationId=null userId=admin effectiveUserId=null _return=false statusMessage=ERROR]
    com.eucalyptus.util.EucalyptusClusterException: [AttachVolumeResponseType attachedVolume=AttachedVolume null null null null null Tue Sep 13 15:57:38 CST 2011 correlationId=null userId=admin effectiveUserId=null _return=false statusMessage=ERROR]

    cc端的错误日志: cc端在向nc端发送添加逻辑卷指令时,nc端反馈出了一个错误信息.

    [Tue Sep 13 15:59:55 2011][003491][EUCADEBUG ] AttachVolume(): params: userId=admin, volumeId=vol-5DE1063D, instanceId=i-426E075E, remoteDev=//,192.168.5.223,iqn.2009-06.com.eucalyptus.cluster223:store3,KiErKVk7UC7vt6ZU12vd5ZUKgZJkZmG5cDZBVcbverPe2Tsp0DxAdWiWdhqhO6orpz36XWN1+/EvBoLzY+pQ0V19cWzBN17WLxOeoLv0zgq4p0hm22zdjJA/kWWD1ME2WnMDTAFe8dbFqyo8DrBO/ywFMBlxmZ7X/hzQb5YdHKAtTe0mOpxNqPgNg8rnrjI/MrQqA7xtUCybEcMlVFekLxwQpR5+UDlilZy2H4V1euzZtgAFkzzVIRsYJ+Hgg3H6f2DfCG+QbblAlLCPjdSi5+oozE/iDrNa+swwazKOXY7/jVCzK5KbM2vnRnuL7GgyHQBxr7KI27Lw/N/HAYLP9w==, localDev=/dev/sdb
    [Tue Sep 13 15:59:55 2011][003491][EUCADEBUG ] find_instanceCache(): found instance in cache 'i-426E075E/192.168.5.245/192.168.138.67'
    [Tue Sep 13 15:59:55 2011][003491][EUCADEBUG ] ncClientCall(ncAttachVolume): called ncURL=http://192.168.5.45:8775/axis2/services/EucalyptusNC timeout=20
    [Tue Sep 13 15:59:55 2011][007546][EUCADEBUG ] DEBUG: requested URI http://192.168.5.45:8775/axis2/services/EucalyptusNC
    [Tue Sep 13 15:59:55 2011][007546][EUCADEBUG ] ncClientCall(ncAttachVolume): ppid=3491 client calling 'ncAttachVolume'
    [Tue Sep 13 15:59:56 2011][007546][EUCAERROR ] ERROR: AttachVolume returned an error
    nc端的错误日志: nc在向目标卷发起连接时,出现错误,连接失败从而在附加卷时出错.最终错误层层上达到clc端,造成在绑定卷时失败.
    [Tue Sep 13 16:06:03 2011][029948][EUCAINFO ] doAttachVolume() invoked (id=i-426E075E vol=vol-5DE1063D remote=//,192.168.5.223,iqn.2009-06.com.eucalyptus.cluster223:store3,KiErKVk7UC7vt6ZU12vd5ZUKgZJkZmG5cDZBVcbverPe2Tsp0DxAdWiWdhqhO6orpz36XWN1+/EvBoLzY+pQ0V19cWzBN17WLxOeoLv0zgq4p0hm22zdjJA/kWWD1ME2WnMDTAFe8dbFqyo8DrBO/ywFMBlxmZ7X/hzQb5YdHKAtTe0mOpxNqPgNg8rnrjI/MrQqA7xtUCybEcMlVFekLxwQpR5+UDlilZy2H4V1euzZtgAFkzzVIRsYJ+Hgg3H6f2DfCG+QbblAlLCPjdSi5+oozE/iDrNa+swwazKOXY7/jVCzK5KbM2vnRnuL7GgyHQBxr7KI27Lw/N/HAYLP9w== local=/dev/sdb)
    [Tue Sep 13 16:06:03 2011][029948][EUCAINFO ] connect_iscsi_target invoked (dev_string=//,192.168.5.223,iqn.2009-06.com.eucalyptus.cluster223:store3,KiErKVk7UC7vt6ZU12vd5ZUKgZJkZmG5cDZBVcbverPe2Tsp0DxAdWiWdhqhO6orpz36XWN1+/EvBoLzY+pQ0V19cWzBN17WLxOeoLv0zgq4p0hm22zdjJA/kWWD1ME2WnMDTAFe8dbFqyo8DrBO/ywFMBlxmZ7X/hzQb5YdHKAtTe0mOpxNqPgNg8rnrjI/MrQqA7xtUCybEcMlVFekLxwQpR5+UDlilZy2H4V1euzZtgAFkzzVIRsYJ+Hgg3H6f2DfCG+QbblAlLCPjdSi5+oozE/iDrNa+swwazKOXY7/jVCzK5KbM2vnRnuL7GgyHQBxr7KI27Lw/N/HAYLP9w==)
    [Tue Sep 13 16:06:03 2011][029948][EUCADEBUG ] system_output(): [//usr/lib/eucalyptus/euca_rootwrap //usr/share/eucalyptus/connect_iscsitarget.pl //,192.168.5.223,iqn.2009-06.com.eucalyptus.cluster223:store3,KiErKVk7UC7vt6ZU12vd5ZUKgZJkZmG5cDZBVcbverPe2Tsp0DxAdWiWdhqhO6orpz36XWN1+/EvBoLzY+pQ0V19cWzBN17WLxOeoLv0zgq4p0hm22zdjJA/kWWD1ME2WnMDTAFe8dbFqyo8DrBO/ywFMBlxmZ7X/hzQb5YdHKAtTe0mOpxNqPgNg8rnrjI/MrQqA7xtUCybEcMlVFekLxwQpR5+UDlilZy2H4V1euzZtgAFkzzVIRsYJ+Hgg3H6f2DfCG+QbblAlLCPjdSi5+oozE/iDrNa+swwazKOXY7/jVCzK5KbM2vnRnuL7GgyHQBxr7KI27Lw/N/HAYLP9w==]
    [Tue Sep 13 16:06:04 2011][029948][EUCAERROR ] ERROR: connect_iscsi_target failed
    [Tue Sep 13 16:06:04 2011][029948][EUCAERROR ] AttachVolume(): failed to connect to iscsi target
    [Tue Sep 13 16:06:04 2011][029948][EUCAERROR ] ERROR: doAttachVolume() failed error=1



    2、 Requested operation is not valid
    在nc的日志中有libvirt的错误信息:

    libvirt: Requested operation is not valid: Xm driver only supports modifying persistent config (code=55)
    AttachVolume() failed (err=-1) XML=<disk type='block'><driver name='phy'/><source dev='/dev/sde'/><target dev='sdq'/></disk>

    3、在sc端重启后,逻辑卷显示错误.

    在cloud重启后,无法显示卷绑定的实例,尽管这些卷正在被之用着。造成在clc端,卷可以被重复绑定。

    因而,针对上述的三个主要问题,讲解一下在解决问题过程中,对eucalyptus中,卷管理的一些理解.


    对eucalyptu中卷的管理分析,将从clc端开始,到nc端结束.
    卷管理的具体实现 ¶

    在clc端,处理volume请求在clc/modules/image-manager/src/main/java/com/eucalyptus/blockstorage/VolumeManager.java中,在这里可以处理volume请求的有:
    CreateVolume、DeleteVolume、DescribeVolumes、AttachVolume、detach。对此,将会着重从CreateVolume、DescribeVolumes和AttachVolume作分析,查找AttachVolume失败的原因.
    CreateVolume的大概流程:

    CreateVolume,接收CreateVolumeType --> 对创建请求作一些预处理和约束,创建卷时必须有快照或是卷大小的参数 --> 获取sc的配置信息,地址 --> 将要创建的卷的信息计入到后台数据库中
    --> 将创建卷的请求发送到sc端,
    CreateStorageVolumeType req = new CreateStorageVolumeType( newId, request.getSize( ), request.getSnapshotId( ) ); StorageUtil.send( sc.getName( ), req );
    --> clc的请求,由clc/modules/storage-controller/src/main/java/edu/ucsb/eucalyptus/cloud/ws/BlockStorage.java中的CreateStorageVolume接收处理,在其中作一些简单预处理,以及数据记录
    --> 将创建volume发送到VolumeCreator,进行异步创建 --> VolumeCreator中的run在进行一些基本条件的判断,最终交由LogicalStorageManager的OverlayManager解决卷的创建问题
    --> LogicalStorageManager是一个抽象类,在BlockStorageManagerFactory中将其实例化为
    clc/modules/storage-controller/src/main/java/com/eucalyptus/storage/OverlayManager.java的OverlayManager,
    最终在其中完成卷的创建工作,主要采用java调用一些系统命令完成,详细流程,可以参看具体的代码.

    DescribeVolumes的处理流程:

     VolumeManager中的DescribeVolumes接收到查看卷请求 -->从数据库中读取存储的volume卷信息 -->从运行的虚拟机实例列表中读取绑定的卷的信息
    -->clc/modules/core/src/main/java/com/eucalyptus/util/BlockStorageUtil.java中的BlockStorageUtil的getVolumeReply从sc中获取卷的信息,其中对数据库中存储的卷和虚拟机已经绑上的卷与
    sc上存在的卷进行映射处理 -->最终反馈给了界面显示
    从DescribeVolumes的简单流程中,可以看到在对volume的显示时与clc端数据库中存储的volume信息 虚拟机实例绑定的信息 以及具体sc上的卷的信息相关,这样的话,任何一个出问题,都有可能造成显示时的错误.

    AttachVolume的处理流程

    VolumeManager中的AttachVolume接收到绑定请求 --> 对绑定参数的合法性进行简单判断 --> 检查卷是否被重复绑定 --> 检查卷与实例是否在同一个cc上 -->从数据库中获取要绑定卷的地址信息
    --> 从sc中检查卷的的一些基本状况 -->将绑定请求发至cc端new VolumeAttachCallback( request ).dispatch( cluster ); --> cc将绑定请求发送到nc -->
    ./node/handlers_xen.c中的doAttachVolume对绑定请求进行处理 -->通过./node/handlers.c中的connect_iscsi_target进行与远程卷的连接,至此大概的处理流程也已经结束.
    上边的connect_iscsi_target是通过调用一个perl脚本处理的,脚本位置在tools/connect_iscsitarget.pl,安装后该文件在/usr/share/eucalyptus/connect_iscsitarget.pl中.
    connect_iscsi_target failed的错误,也正是由于该文件调用失败得来的.

    基于对volume卷管理的理解,现对于开头提到的三个bug进行更改:

    bug1 connect_iscsi_target failed

    从AttachVolume中可以看到,在绑定流程处理中,最终是通过nc的connect_iscsitarget.pl进行卷的绑定处理,从错误日志 也可以看出,要发起的目标地址是iqn.2009-06.com.eucalyptus.cluster223:store3
    但是nc在连接该地址时连接不上,连接不上原因有二:一是clc端的volume中的远端地址信息过于陈旧;二是sc端的卷的确无法登录.通过查看sc可以看到,在volume中,卷的空间还在,
    说明这些卷并未被删除,因此原因不在于clc,而是在于系统可能处于某个时段,sc的重启或是其他操作,使卷处于iactive状态.使的connect_iscsitarget.pl运行错误.
    对connect_iscsitarget.pl的简单分析,可以看到nc登录绑定原端的volume卷时,主要是通过一些iscsiadm基本命令.手工运行这些连接命令,也是无法登录,在sc上查看,卷处于iactive状态.
    由于该bug无法重现,因此预防措施是在sc重启时将目标卷重新进行激活,以尽量减少出错概率.
    com.eucalyptus.storage.OverlayManager.VolumeEntityWrapperManager.exportVolume(LVMVolumeInfo lvmVolumeInfo) throws EucalyptusCloudException中在lvm卷为ISCSIManager
    时,重新激活逻辑卷.exportVolume是sc在重新启动时调用的函数.Bootstrap.load -->BlockStorageBootstrapper.load -->BlockStorage?.ConvertVolumes? -->OverlayManager.checkPreconditions.

    bug2 Requested operation is not valid

    是传递的逻辑卷的参数不合法,在挂载设备时,设备名字/dev/sd[x][n],中x从a~p,n从0~15,否则就会出错,关于linux的scsi设备命名规范.
    可以参加 http://publib.boulder.ibm.com/infocenter/dsichelp/ds6000ic/index.jsp?topic=%2Fcom.ibm.storage.smric.help.doc%2Ff2c_linuxscsilimit_2hsag9.html

    bug3 在sc端重启后,逻辑卷显示错误

    在eucalyptus-cloud重启后,在describevolume时,volume的显示发生问题,无法显示被绑定到的虚拟机实例。从而造成逻辑卷还没有被绑定的假象,结果使已经被绑定的逻辑卷还可以被重复绑定,造成数据的错误。
    从DescribeVolumes的简单流程中,可以看到volume的显示与clc端的数据库信息volume、运行实例绑定的volume、和sc端存在的volume三者有关联。三者中的任何一个出错,都有可能造成volume的显示错误。
    因此,在DescribeVolumes中,分别将获取上述三者的信息计入日志文件中。比如:

    public DescribeVolumesResponseType DescribeVolumes( DescribeVolumesType request ) throws EucalyptusCloudException {
    DescribeVolumesResponseType reply = ( DescribeVolumesResponseType ) request.getReply( );
    EntityWrapper<Volume> db = getEntityWrapper( );
    try {
    String userName = request.isAdministrator( ) ? null : request.getUserId( );
    LOG.debug("start describe volume invoke =================");
    Map<String, AttachedVolume> attachedVolumes = new HashMap<String, AttachedVolume>( );
    for ( VmInstance vm : VmInstances.getInstance( ).listValues( ) ) {
    LOG.debug("==try get the instance volume ==hanxiangduo");
    LOG.debug( LogUtil.dumpObject(vm) );
    for ( AttachedVolume av : vm.getVolumes( ) ) {
    LOG.debug("=================attached volume");
    attachedVolumes.put( av.getVolumeId( ), av );
    LOG.debug( LogUtil.dumpObject(av) );
    }
    }

    List<Volume> volumes = db.query( Volume.ownedBy( userName ) );
    List<Volume> describeVolumes = Lists.newArrayList( );
    LOG.debug("== try get the volume from db== hanxiangduo");
    LOG.debug(LogUtil.dumpObject(volumes));
    for ( Volume v : volumes ) {
    LOG.debug("==============volume from db");
    if ( !State.ANNIHILATED.equals( v.getState( ) ) ) {
    LOG.debug("add the avilable volume in describevolume");
    LOG.debug( LogUtil.dumpObject(v) );
    describeVolumes.add( v );
    } else {
    db.delete( v );
    }
    }
    try {
    ArrayList<edu.ucsb.eucalyptus.msgs.Volume> volumeReplyList = StorageUtil.getVolumeReply( attachedVolumes, describeVolumes );
    reply.getVolumeSet( ).addAll( volumeReplyList );
    } catch ( Exception e ) {
    LOG.warn( "Error getting volume information from the Storage Controller: " + e );
    LOG.debug( e, e );
    }
    db.commit( );
    } catch ( Throwable t ) {
    db.commit( );
    }
    return reply;
    }

    上边分别记录了在eucalyptus-cloud重启后从数据库中读取到的volume和从运行实例中读取到的绑定卷的信息。分析日志发现在重启后运行实例的volume卷信息为空。
    但是,重启之后,从clc端的describeinstance日志中可以看到,其中是有实例volume卷的信息的,这说明是在从运行实例中获取绑定卷时出问题。cc端在向clc端返回的数据中,
    是有虚拟机实例的volume信息。因此,问题只能出在clc端在获取从cc端instance实例信息赋值记录的过程中。
    在clc端向cc请求运行的虚拟机实例信息,对clc端记录的虚拟机列表进行更新的过程大概是:
    VmStateHandler.upstreamMessage( ChannelHandlerContext? ctx, MessageEvent e )
    --> SystemState.handle( VmDescribeResponseType? request ) --> SystemState.updateVmInstance(final String originCluster, final VmInfo runVm)
    -->VmInstance.setVolumes(final List<AttachedVolume?> volList );最终在这里实现对clc的实例列表进行赋值。
    下面是原始的赋值代码:

     public void setVolumes( final List<AttachedVolume> newVolumes ) {
    for ( AttachedVolume vol : newVolumes ) {
    vol.setInstanceId( this.getInstanceId( ) );
    vol.setStatus( "attached" );
    }
    Set<AttachedVolume> oldVolumes = Sets.newHashSet( this.getVolumes( ) );
    this.volumes.retainAll( volumes );
    this.volumes.addAll( volumes );
    for ( AttachedVolume v : oldVolumes ) {
    if ( "attaching".equals( v.getStatus( ) ) && !this.volumes.contains( v ) ) {
    this.volumes.add( v );
    }
    }

    通过分析上述代码,可以发现,在第一次赋值时,从cc端传递过来的volume信息是根本不能够被设置成功的。因此修改此处的setvolume实现,通过attachvolume的简单流程,已经绑定的卷不可以再被绑定,最终该bug解决。 这个bug已经有人提出,解决方法https://bugs.launchpad.net/eucalyptus/+bug/822505


  • 相关阅读:
    矩阵运算(二维数组)
    AndroidManifest.xml
    单位和尺寸
    java Map集合类
    http相关
    文件管理与XMl、JSON解析
    Handler与多线程
    App内容分享
    Fragment以及懒加载
    广播接收器与短信
  • 原文地址:https://www.cnblogs.com/hanxiangduo/p/2322256.html
Copyright © 2011-2022 走看看