分类 开发技术 下的文章

OpenStack(Mitaka)平台子网迁移过程笔记

由于公司搬家,由于服务器所在网段变化,原来搭建的OpenStack服务集群,需要进行迁移,找了很多资料没有相关的可借鉴经验,这里将自己的操作过程记录下来,以便查看
也希望对后来者能够有所帮助

本次迁移主要用于平行迁移整个OpenStack集群,确保原云主机在新的子网内可直接使用,避免重新搭建整个平台造成时间浪费

软件环境

操作系统:Ubuntu 14.04
OpenStack:Mitaka
云主机网络:provider网络,没有vlan

以下操作命令均在Ubuntu下可用,其他发行版请自行Google相关操作命令

主要目标

  1. 不需要重新搭建整个OpenStack平台
  2. 将集群从42网段迁移到129网段
  3. 原有数十台云主机,可在新网段下直接启动,除云主机绑定子网IP变化外,其他不变

执行思路

1. 搬迁服务器

服务器搬家公司体力活,不多说

2. 修改集群服务器IP到新网段,如42.10对应129.10

# 打开配置文件
sudo vim /etc/network/interface
# 修改address、gateway、dns-servers为新的网段129下的配置
# 重新启动网络环境(14.04之后不再支持service network restart重启网络)
sudo ifdown em1
sudo ifup em1

完成所有服务器的ip配置后,验证服务器之间网络是否互相已通

ping ***.***129.10

3. 更新服务器hostname映射

原先安装OpenStack时使用的是hostname访问相关服务,这里需要修改hostname到ip的映射关系

# 打开配置文件
sudo vim /etc/hosts
# 修改ip和hostname之间的映射
***.***.129.10 stack-control

4. 重新启动nova、neutron控制节点和所有服务

涉及到rabbitmq、nova-compute、nova-shcedule、neutron、nuetron-linuxbridge-agent等等
最简单也最暴力的方式:重启服务器
有闲心的就一个个重启也行

sudo service nova-api restart
sudo service nova-scheduler restart
# 等等

5. 登陆horizon,验证OpenStack平台是否已正常工作(注意,此时还不能启动云主机)

由于云主机IP还没有重新绑定,这里登陆后只做验证,不要启动云主机
vms.png

确认所有的主机均处于激活状态,以确保OpenStack的control和compute节点已互相发现

6. 新建基于129网段的新的provider子网

由于原先的42网段IP已经绑定到了云主机,无法直接删除,需要将云主机重新绑定到129网段IP后再删除
这里先新建新的129网段配置,用于后面云主机绑定
subnet.png

7. 修改云主机port配置,以绑定到129子网IP,以替换原先的42子网IP

将原云主机的42网段IP绑定到129网段的对应IP

# 初始化管理员连接参数。我这里用自己保存的shell配置脚本,方便使用
. adminrc
# 查询出来所有的port配置
neutron port-list

例如:
port-list.png

其中id列在后面port-update需要使用,fixed_ips对应每一个port绑定的固定ip,我们实际需要修改的正是这里的fixed_ips

# 更新每个port的绑定ip
neutron port-update --fixed-ip subnet_id='新的129网段子网名称或ID',ip_address='129网段IP' 'port ID'

在horizon中可以查看到IP地址列已经更新为129网段
vm-status.png

8. 启动云主机,并验证IP地址是否获取正常,以及是否能够访问

例如:这里已显示成功获取129网段IP地址
vm-log.png

可以ping一下,确认129网段IP可以正常通讯

9. 删除原42网段子网配置

42网段的子网以没有意义,可以直接删除

通过上述方式操作后,目前OpenStack集群工作正常,没有发现其他问题
如果有更好的方法,欢迎大家沟通学习

顺便吐槽一下,OpenStack的官方文档在有些场景下还是不够全面,除了这里的migration没有文档,还有升级mitaka到新发布的newton都也不知道怎么操作,唉!还是自己再摸索摸索吧

Android 4.1.2完整源代码打包

下了好久,这里打包出来,供有同样需要的朋友使用

注:这里的压缩包不含git版本库,直接使用repo下载下来的代码加到一起有17G,7z压缩后也有13G,因为没有和AOSP同步代码的需要,本人也只是为了阅读代码,所以就不提供了。有需要的朋友,还是使用repo直接从官方同步代码吧

另:包里的代码没有尝试编译过,本子不给力,就不奢求了。因为是直接从用git下载下来的库里提出来的(除了删除repo下来的文件夹中的.repo目录之外,其他没动),考虑到git本身有传输校验机制,所以代码的完整性还是能够保证的^_^

国内连AOSP总是会传输中断,写了个shell脚本,这里也一并贴出来,或许有用

# !/bin/sh
while [ 0 -eq 0 ];
do
    ./repo sync
    if [ $? -ne 0 ]; then
        echo "./repo sync failed, sleep 2m and try again"
        sleep 2m
    else
        break
    fi
done

下面是共享连接:
http://pan.baidu.com/share/link?shareid=210480&uk=1476703362

汇编中调用RegCreateKeyExW等函数返回998错误码的问题解决

  最近在集中测试install.stub的汇编优化版,测试到这里出现了莫名其妙的问题,同样的C代码调用RegCreateKeyExW没有问题,但是在MASM中调用就会返回998错误

  后来在这里找到了答案http://technet.microsoft.com/en-us/library/ms724844%28v=VS.85%29.aspx

  原来RegCreateKeyExW传入的字符串需要对齐到字,即简单来说就是Unicode字符串的首地址要能够被2整除,可惜MSDN文档中没有这一提醒。。。

修正方法:

1、MASM中的静态字符串没有对齐到字,所以需要手动操作,最好把WSTR集中放到一起,因为WSTR本身是字对齐的,如果调试中发现上述的错误在前面通过补0进行对齐即可

2、也可以将字符串拷贝到栈上,因为栈上分配的空间是对齐到双字的,所以不存在对齐到字的问题

从Windows(x86)到Linux(x64)的代码移植总结

由于最新的引擎要支持x64 Linux,算是实战了一把代码移植技术,这里就将移植相关的技术做一总结,和各位沟通交流,也方便作为手册随时查阅

这里总结的是从win32到 x64 Linux的移植,其中涉及到32到64移植和windows到Linux的移植过程,这里先说明一下。

首先就Windows和Linux之间的差异列举如下,开发环境基于VC 2005(Windows 7)和GCC(x64 Linux)

1、基本类型间差异

  有做过windows 32位到windows64位移植的朋友应该清楚,VC 64对VC 32的兼容性很高,除了指针的长度从32位提高到了64位,其他基本类型没有任何差别,这样使得windows中的32到64移植基本没有什么工作量,只要代码中没有指针到其他类型的强制转换,基本上代码拉过来直接编译一下就能用了。这里的32到64的变化有一个名词就叫LLP64(long long and pointer 64)。这样的话VC 64中要使用64 bit的整形,就需要使用long long类型。

  在GCC 64中,采用的则是另外一种模型,即LP64,其中基本类型long从32位变换为64位。在LP64模型中,牺牲掉了兼容性,这样导致代码中凡是涉及long的地方都要谨慎对待,尤其在编写32位代码过程中将long认为和int等同,则更有可能存在潜在问题。

  除此之外,wchar_t的长度也是不一样的,VC下是2字节,GCC下则是4字节。

2、数据对齐问题

  由于在x86架构下,32位和64位数据对齐可以说不是什么问题,只是VC和GCC之间使用的关键字不同,使用方法也不太一样,所以有必要简单提一下。

3、字节序问题

  由于这次是在x86和x86_64之间进行移植,都是little endian的,所以字节序问题不存在,如果有朋友需要将代码移植到其他平台,比如PowerPC,Sparc等,则需要重点关注了。

4、字符串编码问题

  针对char和wchar_t,就有窄字符编码和宽字符编码的问题。Windows中窄字符就是MBCS编码,即多字节编码,如中文windows就是GBK(这一系列GB2312,GBK,GB18030等),MBCS编码兼容ASCII码。宽字符编码就是windows宣传的Unicode编码,采用UTF16编码。而linux中的主流操作系统窄字符编码即UTF8(可配,系统默认一般为UTF8),而宽字符编码为UTF32。

5、OS相关API不一致问题

  Windows是非类Unix系的操作系统,不包含POSIX接口,只有自己的Windows API。包括多线程API,线程同步API,文件操作API,Socket API,管道API等等,不管是函数名和参数都是有很大差异的。

  有一点有必要独立拎出来提一下,那就是Windows的Crital secion是递归锁,而linux下默认则不是。

6、编译环境的不一致

  Windows下的编译环境,即这里的VC,她是一个集成开发环境,包含强大而智能的编译环境,开发者需要做的就是点一下Build命令即可,编译依赖等问题根本不是问题。

  而linux下则更多需要开发者动手自己操作,这也是linux常归于高手的一个原因,因为她不喜欢懒人。

  了解了这些差异,基本上能够预见移植过程中的常见问题,这也是知己知彼的道理,针对这些差异都有对应的一些解决方案,或者说是屏蔽方案,总的一个思想就是,通过封装统一平台差异,无法统一的就采用条件编译,针对不同平台编写功能表征一致的代码。

  一切以统一为先,毕竟跨平台开发最好的就是一份代码处处编译,这样才能减少多平台维护的成本,尽管这样会影响性能,但是对比来看性能的些许损失还是值得的。

好了,这里说说针对不同差异的一些解决办法

1、基本类型差异

针对类型差异,需要通过统一类型来进行屏蔽,简单来说就是通过typedef或者#define对不同平台间的类型进行统一抽象,相同类型统一为相同位长。

例如:
typedef sp_byte_t unsigned char
typedef sp_int8_t sp_byte_t
typedef sp_int16_t short
typedef sp_int32_t int
等等

这样可以程度避免由于基本类型位长不同而导致的一些列问题。对于平台相关的基本类型,比如long,尽量不用,这也是多一事不如少一事的道理,如果确实需要进行大数运算而涉及到64位整型,那么需要注意基本类型间转换而导致的溢出或者数据丢失,而且如果要使用类printf的函数,输出的指示符也要注意。

如果涉及到32位进程和64位进程间的通信,也要注意平台间类型的使用,否则由于位长的不一致,而导致数据错乱,比如size_t的使用,等等

这里顺带着把对其问题说说

在VC中使用#pragma pack可以指定结构体的对齐方式

例如:

#pragma pack(1)
struct s {
    char t1;
    char t2;
    int t3;
}
#pragma pack()

而在GCC中则需要使用attribute属性设置

例如:

struct s {
    char t1;
    char t2;
    int t3;
} __attribute__((packed))

2、字符串编码问题

这里说说我采用的一种策略。即linux模拟windows的字符串编码模式

这样就涉及分别统一窄字符和宽字符编码

需要注意如下几个问题:

① 确保源代码文件能够正常解析

由于vc中的默认源代码编码为GBK,使用GCC编译时,需要指定源代码编码名称,否则以GCC默认的UTF8解码会出现乱码或者报错,通过参数-finput-charset=GBK设置即可

② 确保编译后可执行文件中字符串编码正确

上面的参数只是告诉GCC如何正常解析源代码文件,当完成编译后,生成可执行文件时,GCC保存到可执行文件中的字符串编码默认是UTF8,所以这里也要修改为GBK,通过参数-fexec-charset=GBK

③ 确保运行时宽窄字符能够正常转换

这涉及到locale,因为C运行库中的mbstowcs和wcstombs是locale相关的,linux下默认的是UTF8,所以这里也要设置,否则运行时会出现转码错误。

可以在程序开始时设置环境变量LC_ALL=zh_CN.GBK即可

或者在运行中调用setlocale

④ 上面提到wchart_t在两系统的长度是不一样的

在windows中采用UTF16编码,在Linux中采用UTF32编码。一般没有什么问题,但是如果windows程序需要和linux程序进行交互的话,可能需要注意UTF32和UTF16之间的编码转换。

或者涉及到Java封装,比如我这次移植的内核,需要对C接口进行Java封装,涉及到wchar_t到Java的UTF16编码字符串(Java中采用unsigned short表示)转换,就需要注意着一点

通过上面的一系列配置,linux中的仿windows编码环境也就弄好了,这样能够减少windows代码移植的工作量。

当然还有其他的方式,比如环境无关的统一字符串编码等等,就留给今后探索吧

3、OS相关API不一致问题

这类问题是硬伤,需要一些的底层库进行跨平台封装,以统一特性。

可以自行开发,也可以使用开源库

这里推荐一些开源的库,用起来确实不错

① Boost.Thread

这是Boost封装的多线程库,包括一些有用的同步对象,目前已经作为标准放入了C++ 11中。

② Boost.filesystem

这是Boost提供的文件系统操作库,包括常见的删除文件/夹,复制文件/夹,创建文件夹等操作,只是该库采用异常处理处理错误信息,所以需要注意try catch

③ Boost.Asio

这是Boost提供的异步网络底层库,效率不错

④ ACE

重量级的网络库,封装了常见的网络通信相关的设计模式,如果需要开发大型的网络通信平台,可以考虑使用该库。

4、编译环境不一致问题

有了VC的出现,编译问题变得很简单,因为微软做了大量的底层工作,所以门槛很低,所以Windows下的编译问题可以忽略不计。

可是到了Linux下,编译环境的使用是需要用户了解相关的脚边知识的,所以无形中加大了Linux下大规模软件的构建门槛。

因为在Linux下需要做的更多,所以这里先说说Linux下编译环境相关的一些知识。

① make & makefile

这是基本的编译工具,很多高级的构建工具多基于此。

Make其实是基于依赖的强大构建系统,主要包括三要素:依赖,目标,策略

目标即想要生成的对象。

依赖即生成该对象所需要的其他模块。

策略即如何生成该对象的方法。

Make的使用说简单也简单,说复杂也复杂,这里难以展开,有兴趣的朋友可以搜索相关技术文章。

② CMake

这里就不提及automake & autoconf了,没用过也不太喜欢用。

CMake可以认为是automake的替代品,她通过内建的脚本语言描述构建策略,简化了对对底层命令的直接操作,而且抽象了构建模式,比如,要构建一个可执行程序,需要告诉她的只有编译该可执行文件所需要的源代码文件,她会帮你完成源代码分析,并构造出依赖树,最后调用适当的编译器完成构建。

同时,CMake还具有很高的自定义能力,强大的构建模式完全不影响你按需修改自己的构建策略。

最后还有一点,那就是CMake是跨平台的,不同平台使用同一CMake脚本,针对不同平台她会调用相关的编译器,当然如果你有多个编译器,也是可以自由指定的。

CMake是KDE的基础构建工具,不熟悉CMake,我想KDE应该了解吧^_^。

③ SCons

SCons是用python编写又一跨平台构建工具,她完全替换了make系统,而且构建脚本语言就是python语言,所以用起来确实很不错,这里也顺便推荐一下。考虑到SCons是基于python的脚本语言构建的,所以针对大型系统的构建效率如何就不太确定了,所以使用前最好先评估一下系统规模。

(转)linux 头文件、库文件查找顺序

include的header文件,连结数据库,系统定义,总共有下列来源指定gcc去那找。

当初在编译时指定的(在~gcc/gcc/collect2.c:locatelib()

写在specs内的

后来用-D -I -L指定的

gcc环境变量设定(编译的时候)

ld.so的环境变量(这是run time的时候)

一、头文件

gcc 在编译时如何去寻找所需要的头文件 :

※所以header file的搜寻会从-I开始

※然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH

※再找内定目录

/usr/include

/usr/local/include

/usr/lib/gcc-lib/i386-linux/2.95.2/include

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g -3

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include

库文件但是如果装gcc的时候,是有给定的prefix的话,那么就是

/usr/include

prefix/include

prefix/xxx-xxx-xxx-gnulibc/include

prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include

二、库文件

cos()等函式库的选项要多加 -lm

编译的时候:

※gcc会去找-L

※再找gcc的环境变量LIBRARY_PATH

※再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

三、运行时动态库的搜索路径

1、在配置文件/etc/ld.so.conf中指定动态库搜索路径

2、通过环境变量LD_LIBRARY_PATH指定动态库搜索路径(当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔)

3、在编译目标代码时指定该程序的动态库搜索路径(还可以在编译目标代码时指定程序的动态库搜索路径。

这是通过gcc 的参数"-Wl,-rpath,"指定(如例3所示)。当指定多个动态库搜索路径时,路径之间用冒号":"分隔)

4、默认的动态库搜索路径/lib

5、默认的动态库搜索路径/usr/lib

可以通过执行可执行文件pos得到的结果不同获知其搜索到了哪个动态库,从而获得第1个动态库搜索顺序,然后删除该动态库,

再执行程序pos,获得第2个动态库搜索路径,再删除第2个被搜索到的动态库,

如此往复,将可得到Linux搜索动态库的先后顺序。

程序pos执行的输出结果和搜索到的动态库的对应关系如表1所示

程序pos输出结果 使用的动态库 对应的动态库搜索路径指定方式

./ ./libpos.so 编译目标代码时指定的动态库搜索路径

/root/test/env/lib /root/test/env/lib/libpos.so 环境变量LD_LIBRARY_PATH指定的动态库搜索路径

/root/test/conf/lib /root/test/conf/lib/libpos.so 配置文件/etc/ld.so.conf中指定的动态库搜索路径

/lib /lib/libpos.so 默认的动态库搜索路径/lib

/usr/lib /usr/lib/libpos.so 默认的动态库搜索路径/usr/lib

综合以上结果可知,动态库的搜索路径搜索的先后顺序是:

  1. 编译目标代码时指定的动态库搜索路径;
  2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
  3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径;
  4. 默认的动态库搜索路径/lib;
  5. 默认的动态库搜索路径/usr/lib。