CloudStack在文档中指明需要加入一台干净的Xenserver作为hyperviser。

但是实际使用中,总会存在不同的需求,很多场景是试用CloudStack接管当前已有的hyperviser而非完整重新部署,那么之前在hyperviser中启动的vm,则会被判断为非CloudStack管理而被关闭或删除,如此则会产生对现有环境的不良影响。现实部署环境中,总有些情况,是要求保留现有环境中已有的vm。
以Xenserver为例,非CS管理的vm,会被关闭,CS对于xenserver中vm生命周期的管理比较特殊,在关闭vm之后,还会删除vm实例,只保留磁盘文件,即vdi,这样的结果,对于原有vm设置并不熟悉的管理员来说,相当于噩梦一般的存在了。
那么我们从代码中来看一下为什么虚拟机会被删除。以CS 4.0.2为例:
在XenCenter中新建一台vm,等待一段时间就会发现,该vm关机并且消失了。
此时查看log,会发现如下信息:
2013-08-05 20:19:47,038 WARN [cloud.vm.VirtualMachineManagerImpl](DirectAgent-84:null) Found an alien VM Windows 7 (32-bit) (1)

2013-08-05 20:19:47,038 DEBUG[cloud.vm.VirtualMachineManagerImp
l] (DirectAgent-84:null) Cleaningup a VM that is no longer found : Windows 7 (32-bit) (1)
2013-08-05 20:19:47,045 DEBUG [agent.transport.Request](DirectAgent-84:null) Seq 1-229638607: Sending  
{Cmd , MgmtId: 345049672023, via: 1, Ver: v1, Flags: 100111,[{"StopCommand":{"isProxy":false,"vmName":"Windows 7 (32-bit)(1)","wait":0}}] }
2013-08-05 20:19:47,045 DEBUG [agent.transport.Request](DirectAgent-84:null) Seq 1-229638607: Executing: 
{ Cmd , MgmtId: 345049672023, via: 1, Ver: v1,Flags: 100111, [{"StopCommand":{"isProxy":false,"vmName":"Windows 7(32-bit) (1)","wait":0}}] }
“Windows 7 (32-bit) (1)” 是我所建vm的名字。


第一行log出现在VirtualMachineManagerImp
l.java中的convertToInfos(Map>)方法中,
    protected Map<Long, AgentVmInfo> convertToInfos(final Map<String, Pair<String, State>> newStates) {
final HashMap<Long, AgentVmInfo> map = new HashMap<Long, AgentVmInfo>();
if (newStates == null) {
return map;
}
Collection<VirtualMachineGuru<? extends VMInstanceVO>> vmGurus = _vmGurus.values();
boolean is_alien_vm = true;
long alien_vm_count = -1;
for (Map.Entry<String, Pair<String, State>> entry : newStates.entrySet()) {
is_alien_vm = true;
for (VirtualMachineGuru<? extends VMInstanceVO> vmGuru : vmGurus) {
String name = entry.getKey();
VMInstanceVO vm = vmGuru.findByName(name);
if (vm != null) {
map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().second(), entry.getValue().first()));
is_alien_vm = false;
break;
}
Long id = vmGuru.convertToId(name);
if (id != null) {
map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null, entry.getValue().second(), entry.getValue().first()));
is_alien_vm = false;
break;
}
}
// alien VMs
if (is_alien_vm){
map.put(alien_vm_count--, new AgentVmInfo(entry.getKey(), null, null, entry.getValue().second(), entry.getValue().first()));
s_logger.warn("Found an alien VM " + entry.getKey());
}
}
return map;
}

该方法会在开始定义一个map作为返回值,之后遍历db中所有的vm(vmGurus)并与newStates比较,判断为alien的vm会赋一个负数值,并放入map中返回给上一级方法,其中map的value是newAgentVmInfo(),传入参数中guru和vm为null。上一级方法调用者为:deltaSync和fullSync。

在deltaSync会遍历返回的map,对于vm为null的项,则判定为非CS管理的alien vm,之后进入cleanup发送StopCommand,此时则会看到之前的第二行log。
    public void deltaSync(Map<String, Pair<String, State>> newStates) {
Map<Long, AgentVmInfo> states = convertToInfos(newStates); for (Map.Entry<Long, AgentVmInfo> entry : states.entrySet()) {
AgentVmInfo info = entry.getValue();
VMInstanceVO vm = info.vm;
Command command = null;
if (vm != null) {
Host host = _resourceMgr.findHostByGuid(info.getHostUuid());
long hId = host.getId(); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
command = compareState(hId, vm, info, false, hvGuru.trackVmHostChange());
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Cleaning up a VM that is no longer found <deltaSync>: " + info.name);
}
command = cleanup(info.name);
}
if (command != null){
try {
Host host = _resourceMgr.findHostByGuid(info.getHostUuid());
if (host != null){
Answer answer = _agentMgr.send(host.getId(), cleanup(info.name));
if (!answer.getResult()) {
s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
}
}
} catch (Exception e) {
s_logger.warn("Unable to stop a VM due to " + e.getMessage());
}
}
}
}

fullSync中有类似逻辑,会在host刚刚加入CS或者重启CSmanagement-server的时候调用到,代码见fullSync最后一段逻辑:

        for (final AgentVmInfo left : infos.values()) {
if (!VirtualMachineName.isValidVmName(left.name)) continue; // if the vm doesn't follow CS naming ignore it for stopping
try {
Host host = _hostDao.findByGuid(left.getHostUuid());
if (host != null){
s_logger.warn("Stopping a VM which we do not have any record of " + left.name);
Answer answer = _agentMgr.send(host.getId(), cleanup(left.name));
if (!answer.getResult()) {
s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
}
}
} catch (Exception e) {
s_logger.warn("Unable to stop a VM due to " + e.getMessage());
}
}

第一行中的if语句给出了一个合理的设计,如果命名不符合CS命名规则,则不对该VM做任何处理,如果命名规则符合CS的命名规则,则会进入cleanup流程,这样既不会删除原有vm,同时又保证了CS的管理的虚拟机有唯一的命名。

但是fullSync只在host和CS连接的时候运行一次,其他时候都是由deltaSync对vm状态进行处理,所以,alienvm仍然会被删除。
这应该是4.0.2在尝试兼容额外虚拟机的时候,所遗留的bug。
可以参考fullSync的逻辑,将上面deltaSync稍作修改,对 command =cleanup(info.name);进行判断,修改为:
 
if (VirtualMachineName.isValidVmName(info.name)){
command =cleanup(info.name);
}
 
如此则可避免CS对非CS管理的vm做额外处理,从而删除掉我们并不想删除的vm。
后果:cloudstack的capacity是根据db来计算的,如此修改则可能对capacity造成影响,使统计值与真实值出现偏差。此方法仅可用于特殊需求环境,或者暂时无法移除额外虚拟机的情况。

禁止CloudStack删除Xenserver原有虚拟机的更多相关文章

  1. kali开启禁止或删除ssh 开机启动

    开启禁止或删除ssh 开机启动 # update-rc.d ssh enable #//开机启动 # update-rc.d ssh disable #//禁止开机启动 # update-rc.d - ...

  2. XenServer中虚拟机和快照导出与导入

    我们在工作中经常会遇到,把Xenserver中的虚拟机或者快照导出,然后导入到另一台Xenserver,或者导出来备份下来,以防虚拟机出现故障. 下面介绍一下用xe命令如何导出/导入虚拟机或快照,当然 ...

  3. MAC卸载/删除 Parallels Desktop虚拟机的方法

    一些MAC用户在自己的电脑上安装了虚拟机之后,想要将它卸载,但是不知道该怎么做.今天小编就为大家带来了这个问题的解决方法. 解决方案(删除/卸载虚拟机 (VM): 1.启动Parallels Desk ...

  4. XenServer安装虚拟机---先扩容存放ISO镜像文件

    我们都知道xenserver安装后,不管你的盘有多大,只有4G的空间. 故操作是:新建LV卷,可自定义大小 1.vgdisplay #先查看剩余空间 [root@XenServer /]# vgdis ...

  5. 搭建自己的XenServer+CloudStack云平台,提供IaaS服务(一)环境搭建

    目标 搭建一个完整的基于XenServer和CloudStack的虚拟化平台,提供IaaS服务. 搭建三台安装了XenServer的服务器 搭建一台安装了CloudStack的服务器用以管理云平台 搭 ...

  6. XenServer 5.5 断电重启虚拟机磁盘丢失的修复

    1.现象 公司云平台使用的是XenServer 5.5,版本比较老了.最近几天因为机房改造,导致云环境断电,重启之后发现有2台机器无法ping到,所以再次重启,登录修复网卡,最后发现无法用XenCen ...

  7. 【虚拟机】WIN8.1系统虚拟机完全彻底删除

    一.首先删除注册表 用管理员身份打开CMD,输入F:\>VMware-workstation-full-12.5.5-5234757.exe/clean,根据自己的虚拟机安装文件的路径进行改变( ...

  8. CloudStack系统虚拟机启动但不在Host表中

    有网友问到这个问题,CloudStack中,系统虚拟机正常启动,Running状态. 可是在host表中没有对应项,上传下载模板等功能也不正常. 原因:系统虚拟机启动之后,会通过管理网段主动连接man ...

  9. CloudStack云基础架构的一些概念

    1. Zones(区域) 一个区域在CloudStack配置中是最大的组织单元.一个区域通常代表一个单独的数据中心,虽然在一个数据中心也允许有多个区域.将基础架构设施加入到区域中的好处是提供物理隔离和 ...

随机推荐

  1. 5、Redis中对Set类型的操作命令

    写在前面的话:读书破万卷,编码如有神 -------------------------------------------------------------------- ------------ ...

  2. Codeforces Round #356 (Div. 2) E. Bear and Square Grid 滑块

    E. Bear and Square Grid 题目连接: http://www.codeforces.com/contest/680/problem/E Description You have a ...

  3. BZOJ 2330 SCOI2011糖果 差分约束

    2330: [SCOI2011]糖果 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2819  Solved: 820 题目连接 http://www ...

  4. CF 277.5 C.Given Length and Sum of Digits.. 构造

    #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #incl ...

  5. 可变参数模拟printf()函数实现一个my_print()函数以及调用可变参数需注意的陷阱

    入栈规则 可变参数函数的实现与函数调用的栈帧结构是密切相关的.所以在我们实现可变参数之前,先得搞清楚 栈是怎样传参的. 正常情况下,C的函数参数入栈遵照__stdcall规则, 它是从右到左的,即函数 ...

  6. 通过yum来安装vsftpd

    Linux系统:centos6.6.  安装步骤  1.通过yum来安装vsftpd [root@localhost ~]# yum -y install vsftpd 2.设置为开机启动 [root ...

  7. X-010 FriendlyARM tiny4412 uboot移植之移植网卡驱动TFTP用起来

    <<<<<<<<<<<<<<<<<<<<<<<<< ...

  8. 使用Django来处理对于静态文件的请求

    引言 本方法适用于linux+python2.7+django1.2,使用django自带的web服务. 同样也适用于sina app engine. 1.准备工作 准备css文件,准备js文件,准备 ...

  9. datagrid在MVC中的运用04-同时添加搜索和操作区域

    本文介绍在datagrid上同时添加搜索和操作区域. 仅仅是增加操作区域 □ 方法1 $('#dg').datagrid({ toolbar: '#tb' }); <div id="t ...

  10. springmvc最简单的搭建,初学者必看

    web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=" ...