From 37dcec77bbf030084c1a6ac9b741c0e2e0b941cf Mon Sep 17 00:00:00 2001 From: anthony Date: Tue, 2 Aug 2011 17:31:36 -0700 Subject: [PATCH] Bug 10197: implement pool-wise VM sync, For XenServer, VM fullSync is pool-wise now, VM deltaSync is still per host Conflicts: server/src/com/cloud/vm/VirtualMachineManagerImpl.java --- .../computing/FakeComputingResource.java | 3 +- .../computing/LibvirtComputingResource.java | 5 +- .../agent/api/StartupRoutingCommand.java | 63 ++++++- .../kvm/resource/KvmDummyResourceBase.java | 3 +- .../xen/resource/CitrixResourceBase.java | 56 ++++-- .../cloud/vm/VirtualMachineManagerImpl.java | 174 +++++++++++++----- .../src/com/cloud/vm/dao/VMInstanceDao.java | 4 +- .../com/cloud/vm/dao/VMInstanceDaoImpl.java | 23 +++ .../HypervisorVersionChangedException.java | 33 ++++ 9 files changed, 290 insertions(+), 74 deletions(-) create mode 100755 utils/src/com/cloud/utils/exception/HypervisorVersionChangedException.java diff --git a/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java b/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java index 30fe5491c2b..e6a4ea4646a 100644 --- a/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java @@ -69,6 +69,7 @@ import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.StartupRoutingCommand.VmState; import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; @@ -127,7 +128,7 @@ public class FakeComputingResource extends ServerResourceBase implements ServerR @Override public StartupCommand[] initialize() { - Map changes = null; + Map changes = null; final List info = getHostInfo(); diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index 67ec09ac47b..b6438ec5815 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -2503,8 +2503,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } final List info = getHostInfo(); - - final StartupRoutingCommand cmd = new StartupRoutingCommand((Integer)info.get(0), (Long)info.get(1), (Long)info.get(2), (Long)info.get(4), (String)info.get(3), HypervisorType.KVM, RouterPrivateIpStrategy.HostLocal, changes); + + final StartupRoutingCommand cmd = new StartupRoutingCommand((Integer)info.get(0), (Long)info.get(1), (Long)info.get(2), (Long)info.get(4), (String)info.get(3), HypervisorType.KVM, RouterPrivateIpStrategy.HostLocal); + cmd.setStateChanges(changes); fillNetworkInformation(cmd); cmd.getHostDetails().putAll(getVersionStrings()); cmd.setPool(_pool); diff --git a/api/src/com/cloud/agent/api/StartupRoutingCommand.java b/api/src/com/cloud/agent/api/StartupRoutingCommand.java index 971247e156e..7785dc54252 100755 --- a/api/src/com/cloud/agent/api/StartupRoutingCommand.java +++ b/api/src/com/cloud/agent/api/StartupRoutingCommand.java @@ -26,11 +26,26 @@ import com.cloud.network.Networks.RouterPrivateIpStrategy; import com.cloud.vm.VirtualMachine.State; public class StartupRoutingCommand extends StartupCommand { + public class VmState { + State state; + String host; + public VmState(State state, String host) { + this.state = state; + this.host = host; + } + public State getState() { + return state; + } + public String getHost() { + return host; + } + } int cpus; long speed; long memory; long dom0MinMemory; - Map vms; + boolean poolSync; + Map vms; String caps; String pool; HypervisorType hypervisorType; @@ -50,20 +65,30 @@ public class StartupRoutingCommand extends StartupCommand { String caps, HypervisorType hypervisorType, RouterPrivateIpStrategy privIpStrategy, - Map vms) { + Map vms) { this(cpus, speed, memory, dom0MinMemory, caps, hypervisorType, vms); getHostDetails().put(RouterPrivateIpStrategy.class.getCanonicalName(), privIpStrategy.toString()); } + public StartupRoutingCommand(int cpus, + long speed, + long memory, + long dom0MinMemory, + String caps, + HypervisorType hypervisorType, + RouterPrivateIpStrategy privIpStrategy) { +this(cpus, speed, memory, dom0MinMemory, caps, hypervisorType, new HashMap(), new HashMap()); +getHostDetails().put(RouterPrivateIpStrategy.class.getCanonicalName(), privIpStrategy.toString()); +} + public StartupRoutingCommand(int cpus, long speed, long memory, long dom0MinMemory, final String caps, - final HypervisorType hypervisorType, - + final HypervisorType hypervisorType, final Map hostDetails, - Map vms) { + Map vms) { super(Host.Type.Routing); this.cpus = cpus; this.speed = speed; @@ -73,17 +98,27 @@ public class StartupRoutingCommand extends StartupCommand { this.hypervisorType = hypervisorType; this.hostDetails = hostDetails; this.caps = caps; + this.poolSync = false; } public StartupRoutingCommand(int cpus2, long speed2, long memory2, long dom0MinMemory2, String caps2, HypervisorType hypervisorType2, - Map vms2) { + Map vms2) { this(cpus2, speed2, memory2, dom0MinMemory2, caps2, hypervisorType2, new HashMap(), vms2); } - - public void setChanges(Map vms) { + + public void setChanges(Map vms) { this.vms = vms; } + + public void setStateChanges(Map vms) { + for( String vm_name : vms.keySet() ) { + if( this.vms == null ) { + this.vms = new HashMap(); + } + this.vms.put(vm_name, new VmState(vms.get(vm_name), null)); + } + } public int getCpus() { return cpus; @@ -105,7 +140,7 @@ public class StartupRoutingCommand extends StartupCommand { return dom0MinMemory; } - public Map getVmStates() { + public Map getVmStates() { return vms; } @@ -137,7 +172,15 @@ public class StartupRoutingCommand extends StartupCommand { this.pool = pool; } - public HypervisorType getHypervisorType() { + public boolean isPoolSync() { + return poolSync; + } + + public void setPoolSync(boolean poolSync) { + this.poolSync = poolSync; + } + + public HypervisorType getHypervisorType() { return hypervisorType; } diff --git a/core/src/com/cloud/hypervisor/kvm/resource/KvmDummyResourceBase.java b/core/src/com/cloud/hypervisor/kvm/resource/KvmDummyResourceBase.java index dc98fcfef2e..8b14991f465 100644 --- a/core/src/com/cloud/hypervisor/kvm/resource/KvmDummyResourceBase.java +++ b/core/src/com/cloud/hypervisor/kvm/resource/KvmDummyResourceBase.java @@ -28,6 +28,7 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.StartupRoutingCommand.VmState; import com.cloud.host.Host.Type; import com.cloud.hypervisor.Hypervisor; import com.cloud.resource.ServerResource; @@ -48,7 +49,7 @@ public class KvmDummyResourceBase extends ServerResourceBase implements ServerRe @Override public StartupCommand[] initialize() { - StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.KVM, new HashMap(), new HashMap()); + StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.KVM, new HashMap(), new HashMap()); cmd.setDataCenter(_zoneId); cmd.setPod(_podId); cmd.setCluster(_clusterId); diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index fd74450b7da..f0b19fba1b6 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -120,6 +120,7 @@ import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.StartupRoutingCommand.VmState; import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; @@ -2462,7 +2463,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException("Com'on no control domain? What the crap?!#@!##$@"); } - protected HashMap sync(Connection conn) { + protected HashMap deltaSync(Connection conn) { HashMap newStates; HashMap oldStates = null; @@ -2556,6 +2557,46 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return changes; } + + protected void fullSync(StartupRoutingCommand cmd, Connection conn) { + synchronized (_vms) { + _vms.clear(); + } + try { + final HashMap vmStates = new HashMap(); + Map vmRs = VM.getAllRecords(conn); + for (VM.Record record : vmRs.values()) { + if (record.isControlDomain || record.isASnapshot || record.isATemplate) { + continue; // Skip DOM0 + } + String vm_name = record.nameLabel; + VmPowerState ps = record.powerState; + final State state = convertToState(ps); + Host host = record.residentOn; + String host_uuid = null; + if( host != null ) { + host_uuid = host.getUuid(conn); + if( host_uuid.equals(_host.uuid)) { + synchronized (_vms) { + _vms.put(vm_name, state); + } + } + } + if (s_logger.isTraceEnabled()) { + s_logger.trace("VM " + vm_name + ": powerstate = " + ps + "; vm state=" + state.toString()); + } + VmState vm_state = cmd.new VmState(state, host_uuid); + vmStates.put(vm_name, vm_state); + } + cmd.setChanges(vmStates); + } catch (final Throwable e) { + String msg = "Unable to get vms through host " + _host.uuid + " due to to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } + } + + protected ReadyAnswer execute(ReadyCommand cmd) { Connection conn = getConnection(); Long dcId = cmd.getDataCenterId(); @@ -3733,7 +3774,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return null; } } - HashMap newStates = sync(conn); + HashMap newStates = deltaSync(conn); if (newStates == null) { s_logger.warn("Unable to get current status from sync"); return null; @@ -3970,25 +4011,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.warn("Unable to get host information for " + _host.ip); return null; } - StartupRoutingCommand cmd = new StartupRoutingCommand(); fillHostInfo(conn, cmd); - Map changes = null; - synchronized (_vms) { - _vms.clear(); - changes = sync(conn); - } - + fullSync(cmd, conn); cmd.setHypervisorType(HypervisorType.XenServer); - cmd.setChanges(changes); cmd.setCluster(_cluster); + cmd.setPoolSync(true); StartupStorageCommand sscmd = initializeLocalSR(conn); if (sscmd != null) { return new StartupCommand[] { cmd, sscmd }; } - return new StartupCommand[] { cmd }; } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index d417f1fb85d..64f3f20ca0c 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -54,6 +54,7 @@ import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.StartupRoutingCommand.VmState; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.to.VirtualMachineTO; @@ -1436,7 +1437,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene } public Commands deltaSync(long hostId, Map newStates) { - Map states = convertToInfos(newStates); + Map states = convertDeltaToInfos(newStates); Commands commands = new Commands(OnError.Continue); for (Map.Entry entry : states.entrySet()) { @@ -1463,7 +1464,8 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene return commands; } - protected Map convertToInfos(final Map states) { + + protected Map convertDeltaToInfos(final Map states) { final HashMap map = new HashMap(); if (states == null) { @@ -1485,7 +1487,38 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene Long id = vmGuru.convertToId(name); if (id != null) { - map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null, entry.getValue())); + map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null,entry.getValue())); + break; + } + } + } + + return map; + } + + protected Map convertToInfos(final Map states) { + final HashMap map = new HashMap(); + + if (states == null) { + return map; + } + + Collection> vmGurus = _vmGurus.values(); + + for (Map.Entry entry : states.entrySet()) { + for (VirtualMachineGuru 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().getState(), entry.getValue().getHost() )); + break; + } + + Long id = vmGuru.convertToId(name); + if (id != null) { + map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null,entry.getValue().getState(), entry.getValue().getHost() )); break; } } @@ -1664,57 +1697,92 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene } } - public Commands fullSync(final long hostId, final Map newStates) { + public Commands fullSync(final long hostId, StartupRoutingCommand startup) { + Commands commands = new Commands(OnError.Continue); - final List vms = _vmDao.listByHostId(hostId); - s_logger.debug("Found " + vms.size() + " VMs for host " + hostId); - - Map infos = convertToInfos(newStates); - - for (VMInstanceVO vm : vms) { - AgentVmInfo info = infos.remove(vm.getId()); - - VMInstanceVO castedVm = null; - if (info == null) { - info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped); - castedVm = info.guru.findById(vm.getId()); - } else { - castedVm = info.vm; - } - - HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType()); - - Command command = compareState(hostId, castedVm, info, true, hvGuru.trackVmHostChange()); - if (command != null) { - commands.addCommand(command); - } - } - - for (final AgentVmInfo left : infos.values()) { - boolean found = false; - for (VirtualMachineGuru vmGuru : _vmGurus.values()) { - VMInstanceVO vm = vmGuru.findByName(left.name); - if (vm != null) { - found = true; - HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType()); - if(hvGuru.trackVmHostChange()) { - Command command = compareState(hostId, vm, left, true, true); - if (command != null) { - commands.addCommand(command); - } - } else { - s_logger.warn("Stopping a VM, VM " + left.name + " migrate from Host " + vm.getHostId() + " to Host " + hostId ); - commands.addCommand(cleanup(left.name)); + Map infos = convertToInfos(startup.getVmStates()); + if( startup.isPoolSync()) { + long hId = 0; + Host host = _hostDao.findById(hostId); + long clusterId= host.getClusterId(); + final List vms = _vmDao.listByClusterId(clusterId); + s_logger.debug("Found " + vms.size() + " VMs for cluster " + clusterId); + for (VMInstanceVO vm : vms) { + AgentVmInfo info = infos.remove(vm.getId()); + VMInstanceVO castedVm = null; + if (info == null) { + info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped); + hId = 0; + castedVm = info.guru.findById(vm.getId()); + } else { + castedVm = info.vm; + String host_guid = info.getHost(); + host = _hostDao.findByGuid(host_guid); + if ( host == null ) { + infos.put(vm.getId(), info); + continue; } - break; + hId = host.getId(); + } + HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType()); + + Command command = compareState(hId, castedVm, info, true, hvGuru.trackVmHostChange()); + if (command != null) { + commands.addCommand(command); } } - if ( ! found ) { + for (final AgentVmInfo left : infos.values()) { s_logger.warn("Stopping a VM that we have no record of: " + left.name); commands.addCommand(cleanup(left.name)); } + + } else { + final List vms = _vmDao.listByHostId(hostId); + s_logger.debug("Found " + vms.size() + " VMs for host " + hostId); + for (VMInstanceVO vm : vms) { + AgentVmInfo info = infos.remove(vm.getId()); + + VMInstanceVO castedVm = null; + if (info == null) { + info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped); + castedVm = info.guru.findById(vm.getId()); + } else { + castedVm = info.vm; + } + + HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType()); + + Command command = compareState(hostId, castedVm, info, true, hvGuru.trackVmHostChange()); + if (command != null) { + commands.addCommand(command); + } + } + + for (final AgentVmInfo left : infos.values()) { + boolean found = false; + for (VirtualMachineGuru vmGuru : _vmGurus.values()) { + VMInstanceVO vm = vmGuru.findByName(left.name); + if (vm != null) { + found = true; + HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType()); + if(hvGuru.trackVmHostChange()) { + Command command = compareState(hostId, vm, left, true, true); + if (command != null) { + commands.addCommand(command); + } + } else { + s_logger.warn("Stopping a VM, VM " + left.name + " migrate from Host " + vm.getHostId() + " to Host " + hostId ); + commands.addCommand(cleanup(left.name)); + } + break; + } + } + if ( ! found ) { + s_logger.warn("Stopping a VM that we have no record of: " + left.name); + commands.addCommand(cleanup(left.name)); + } + } } - return commands; } @@ -1794,7 +1862,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene StartupRoutingCommand startup = (StartupRoutingCommand) cmd; - Commands commands = fullSync(agentId, startup.getVmStates()); + Commands commands = fullSync(agentId, startup); if (commands.size() > 0) { s_logger.debug("Sending clean commands to the agent"); @@ -1857,15 +1925,25 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene protected class AgentVmInfo { public String name; public State state; + public String host; public VMInstanceVO vm; public VirtualMachineGuru guru; @SuppressWarnings("unchecked") - public AgentVmInfo(String name, VirtualMachineGuru guru, VMInstanceVO vm, State state) { + public AgentVmInfo(String name, VirtualMachineGuru guru, VMInstanceVO vm, State state, String host) { this.name = name; this.state = state; this.vm = vm; this.guru = (VirtualMachineGuru) guru; + this.host = host; + } + + public AgentVmInfo(String name, VirtualMachineGuru guru, VMInstanceVO vm, State state) { + this(name, guru, vm, state, null); + } + + public String getHost() { + return host; } } diff --git a/server/src/com/cloud/vm/dao/VMInstanceDao.java b/server/src/com/cloud/vm/dao/VMInstanceDao.java index 61c9be500ca..5c50d5692c0 100644 --- a/server/src/com/cloud/vm/dao/VMInstanceDao.java +++ b/server/src/com/cloud/vm/dao/VMInstanceDao.java @@ -79,5 +79,7 @@ public interface VMInstanceDao extends GenericDao, StateDao< List listByTypeAndState(State state, VirtualMachine.Type type); List listByAccountId(long accountId); - public Long countAllocatedVirtualRoutersForAccount(long accountId); + public Long countAllocatedVirtualRoutersForAccount(long accountId); + + List listByClusterId(long clusterId); } diff --git a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java index 9e841f887f9..d25a394feb7 100644 --- a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -26,11 +26,18 @@ import javax.ejb.Local; import org.apache.log4j.Logger; +import com.cloud.cluster.agentlb.HostTransferMapVO; +import com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDaoImpl; +import com.cloud.org.Managed; +import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.Attribute; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.JoinBuilder.JoinType; import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.UpdateBuilder; @@ -45,6 +52,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem public static final Logger s_logger = Logger.getLogger(VMInstanceDaoImpl.class); + protected final SearchBuilder VMClusterSearch; protected final SearchBuilder IdStatesSearch; protected final SearchBuilder AllFieldsSearch; protected final SearchBuilder ZoneTemplateNonExpungedSearch; @@ -60,11 +68,18 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem protected final Attribute _updateTimeAttr; + protected final HostDaoImpl _hostDao = ComponentLocator.inject(HostDaoImpl.class); protected VMInstanceDaoImpl() { IdStatesSearch = createSearchBuilder(); IdStatesSearch.and("id", IdStatesSearch.entity().getId(), Op.EQ); IdStatesSearch.and("states", IdStatesSearch.entity().getState(), Op.IN); IdStatesSearch.done(); + + VMClusterSearch = createSearchBuilder(); + SearchBuilder hostSearch = _hostDao.createSearchBuilder(); + VMClusterSearch.join("hostSearch", hostSearch, hostSearch.entity().getId(), VMClusterSearch.entity().getHostId(), JoinType.INNER); + hostSearch.and("clusterId", hostSearch.entity().getClusterId(), SearchCriteria.Op.EQ); + VMClusterSearch.done(); AllFieldsSearch = createSearchBuilder(); AllFieldsSearch.and("host", AllFieldsSearch.entity().getHostId(), Op.EQ); @@ -162,6 +177,14 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem return listBy(sc); } + + @Override + public List listByClusterId(long clusterId) { + SearchCriteria sc = VMClusterSearch.create(); + sc.setJoinParameters("hostSearch", "clusterId", clusterId); + + return listBy(sc); + } @Override public List listByZoneIdAndType(long zoneId, VirtualMachine.Type type) { diff --git a/utils/src/com/cloud/utils/exception/HypervisorVersionChangedException.java b/utils/src/com/cloud/utils/exception/HypervisorVersionChangedException.java new file mode 100755 index 00000000000..bfd3f57fe39 --- /dev/null +++ b/utils/src/com/cloud/utils/exception/HypervisorVersionChangedException.java @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.utils.exception; + +import com.cloud.utils.SerialVersionUID; + +public class HypervisorVersionChangedException extends RuntimeException { + + private static final long serialVersionUID = SerialVersionUID.CloudRuntimeException; + + public HypervisorVersionChangedException(String message) { + super(message); + } + + protected HypervisorVersionChangedException() { + super(); + } +}