From 3881e13387535ff65f24915b62719ea25e15ea9d Mon Sep 17 00:00:00 2001 From: anthony Date: Tue, 19 Jul 2011 15:12:22 -0700 Subject: [PATCH] bug 10197: The step to upgrade xenserver, 1. put cluster in Unmanaged state through UI , then MS will not talk to hosts in the cluster 2. upgrade xenserver according to XenServer upgrade guide. 3. put cluster in Managed state through UI, then MS will reconnect hosts TODO, 1. UI 2. vm pool sync , leveraged from kelven's work --- api/src/com/cloud/api/ApiConstants.java | 1 + .../cloud/api/commands/ListClustersCmd.java | 14 +++ .../cloud/api/commands/UpdateClusterCmd.java | 23 ++--- .../cloud/api/response/ClusterResponse.java | 14 +++ api/src/com/cloud/host/Status.java | 4 +- api/src/com/cloud/org/Cluster.java | 2 + .../com/cloud/resource/ResourceService.java | 2 +- server/src/com/cloud/agent/AgentManager.java | 5 +- .../cloud/agent/manager/AgentManagerImpl.java | 10 ++- .../manager/ClusteredAgentManagerImpl.java | 14 +++ .../src/com/cloud/api/ApiResponseHelper.java | 1 + server/src/com/cloud/dc/ClusterVO.java | 14 +++ .../src/com/cloud/host/dao/HostDaoImpl.java | 12 ++- .../cloud/resource/ResourceManagerImpl.java | 87 ++++++++++++++++++- setup/db/create-schema.sql | 1 + 15 files changed, 186 insertions(+), 18 deletions(-) diff --git a/api/src/com/cloud/api/ApiConstants.java b/api/src/com/cloud/api/ApiConstants.java index 3a43d0a9afe..3f69a881dca 100755 --- a/api/src/com/cloud/api/ApiConstants.java +++ b/api/src/com/cloud/api/ApiConstants.java @@ -226,6 +226,7 @@ public class ApiConstants { public static final String PRIVATE_NETMASK = "privatenetmask"; public static final String PRIVATE_NETWORK_ID = "privatenetworkid"; public static final String ALLOCATION_STATE = "allocationstate"; + public static final String MANAGED_STATE = "managedstate"; public static final String STORAGE_ID="storageid"; public static final String PING_STORAGE_SERVER_IP = "pingstorageserverip"; public static final String PING_DIR = "pingdir"; diff --git a/api/src/com/cloud/api/commands/ListClustersCmd.java b/api/src/com/cloud/api/commands/ListClustersCmd.java index daee7e4cda6..d602f0a49b1 100644 --- a/api/src/com/cloud/api/commands/ListClustersCmd.java +++ b/api/src/com/cloud/api/commands/ListClustersCmd.java @@ -63,6 +63,9 @@ public class ListClustersCmd extends BaseListCmd { @Parameter(name=ApiConstants.ALLOCATION_STATE, type=CommandType.STRING, description="lists clusters by allocation state") private String allocationState; + @Parameter(name=ApiConstants.MANAGED_STATE, type=CommandType.STRING, description="whether this cluster is managed by cloudstack") + private String managedState; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -95,6 +98,17 @@ public class ListClustersCmd extends BaseListCmd { public String getAllocationState() { return allocationState; } + + + public String getManagedstate() { + return managedState; + } + + public void setManagedstate(String managedstate) { + this.managedState = managedstate; + } + + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/com/cloud/api/commands/UpdateClusterCmd.java b/api/src/com/cloud/api/commands/UpdateClusterCmd.java index 550d3ef2a97..d054e50e72d 100644 --- a/api/src/com/cloud/api/commands/UpdateClusterCmd.java +++ b/api/src/com/cloud/api/commands/UpdateClusterCmd.java @@ -18,9 +18,6 @@ package com.cloud.api.commands; -import java.util.ArrayList; -import java.util.List; - import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; @@ -28,15 +25,10 @@ import com.cloud.api.BaseCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; -import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.ClusterResponse; -import com.cloud.api.response.ListResponse; -import com.cloud.api.response.PodResponse; -import com.cloud.exception.DiscoveryException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.org.Cluster; import com.cloud.user.Account; -import com.cloud.uservm.UserVm; @Implementation(description="Updates an existing cluster", responseObject=ClusterResponse.class) public class UpdateClusterCmd extends BaseCmd { @@ -57,7 +49,10 @@ public class UpdateClusterCmd extends BaseCmd { private String clusterType; @Parameter(name=ApiConstants.ALLOCATION_STATE, type=CommandType.STRING, description="Allocation state of this cluster for allocation of new resources") - private String allocationState; + private String allocationState; + + @Parameter(name=ApiConstants.MANAGED_STATE, type=CommandType.STRING, description="whether this cluster is managed by cloudstack") + private String managedState; public String getClusterName() { return clusterName; @@ -97,6 +92,14 @@ public class UpdateClusterCmd extends BaseCmd { this.allocationState = allocationState; } + public String getManagedstate() { + return managedState; + } + + public void setManagedstate(String managedstate) { + this.managedState = managedstate; + } + @Override public void execute(){ Cluster cluster = _resourceService.getCluster(getId()); @@ -104,7 +107,7 @@ public class UpdateClusterCmd extends BaseCmd { throw new InvalidParameterValueException("Unable to find the cluster by id=" + getId()); } - Cluster result = _resourceService.updateCluster(cluster, getClusterType(), getHypervisor(), getAllocationState()); + Cluster result = _resourceService.updateCluster(cluster, getClusterType(), getHypervisor(), getAllocationState(), getManagedstate()); if (result != null) { ClusterResponse clusterResponse = _responseGenerator.createClusterResponse(cluster); clusterResponse.setResponseName(getCommandName()); diff --git a/api/src/com/cloud/api/response/ClusterResponse.java b/api/src/com/cloud/api/response/ClusterResponse.java index 0c2fcdfae54..2c49e5d646e 100644 --- a/api/src/com/cloud/api/response/ClusterResponse.java +++ b/api/src/com/cloud/api/response/ClusterResponse.java @@ -18,6 +18,8 @@ package com.cloud.api.response; import com.cloud.api.ApiConstants; +import com.cloud.api.Parameter; +import com.cloud.api.BaseCmd.CommandType; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; @@ -49,6 +51,10 @@ public class ClusterResponse extends BaseResponse { @SerializedName("allocationstate") @Param(description="the allocation state of the cluster") private String allocationState; + @SerializedName("managedstate") @Param(description="whether this cluster is managed by cloudstack") + private String managedState; + + public Long getId() { return id; } @@ -119,5 +125,13 @@ public class ClusterResponse extends BaseResponse { public void setAllocationState(String allocationState) { this.allocationState = allocationState; + } + + public String getManagedState() { + return managedState; + } + + public void setManagedState(String managedState) { + this.managedState = managedState; } } diff --git a/api/src/com/cloud/host/Status.java b/api/src/com/cloud/host/Status.java index 257505204cd..94f8bcb4bf8 100644 --- a/api/src/com/cloud/host/Status.java +++ b/api/src/com/cloud/host/Status.java @@ -77,7 +77,8 @@ public enum Status { RequestAgentRebalance(false, "Request rebalance for the certain host"), StartAgentRebalance(false, "Start rebalance for the certain host"), RebalanceCompleted(false, "Host is rebalanced successfully"), - RebalanceFailed(false, "Failed to rebalance the host"); + RebalanceFailed(false, "Failed to rebalance the host"), + PrepareUnmanaged(true, "prepare for cluster entering unmanaged status"); private final boolean isUserRequest; private final String comment; @@ -138,6 +139,7 @@ public enum Status { s_fsm.addTransition(Status.Up, Event.AgentConnected, Status.Connecting); s_fsm.addTransition(Status.Up, Event.ManagementServerDown, Status.Disconnected); s_fsm.addTransition(Status.Up, Event.StartAgentRebalance, Status.Rebalancing); + s_fsm.addTransition(Status.Up, Event.PrepareUnmanaged, Status.Disconnected); s_fsm.addTransition(Status.Updating, Event.PingTimeout, Status.Alert); s_fsm.addTransition(Status.Updating, Event.Ping, Status.Updating); s_fsm.addTransition(Status.Updating, Event.AgentConnected, Status.Connecting); diff --git a/api/src/com/cloud/org/Cluster.java b/api/src/com/cloud/org/Cluster.java index cc76133d620..697d6365ab9 100644 --- a/api/src/com/cloud/org/Cluster.java +++ b/api/src/com/cloud/org/Cluster.java @@ -22,6 +22,7 @@ package com.cloud.org; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.org.Managed.ManagedState; public interface Cluster extends Grouping { public static enum ClusterType { @@ -38,4 +39,5 @@ public interface Cluster extends Grouping { HypervisorType getHypervisorType(); ClusterType getClusterType(); AllocationState getAllocationState(); + ManagedState getManagedState(); } diff --git a/api/src/com/cloud/resource/ResourceService.java b/api/src/com/cloud/resource/ResourceService.java index 8775bc12961..d6e5ca9aa8e 100644 --- a/api/src/com/cloud/resource/ResourceService.java +++ b/api/src/com/cloud/resource/ResourceService.java @@ -61,7 +61,7 @@ public interface ResourceService { boolean deleteCluster(DeleteClusterCmd cmd); - Cluster updateCluster(Cluster cluster, String clusterType, String hypervisor, String allocationState); + Cluster updateCluster(Cluster cluster, String clusterType, String hypervisor, String allocationState, String managedstate); List discoverHosts(AddHostCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException; diff --git a/server/src/com/cloud/agent/AgentManager.java b/server/src/com/cloud/agent/AgentManager.java index 35b4562d07b..0851eb7d8fc 100755 --- a/server/src/com/cloud/agent/AgentManager.java +++ b/server/src/com/cloud/agent/AgentManager.java @@ -173,8 +173,11 @@ public interface AgentManager extends Manager { * Obtains statistics for a host; vCPU utilisation, memory utilisation, and network utilisation * * @param hostId - * @return HostStats + * @return HostStat */ + + boolean disconnect(long hostId); + HostStats getHostStatistics(long hostId); Long getGuestOSCategoryId(long hostId); diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index 42275cf17af..2bd0ed4c81a 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -965,6 +965,12 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { } } } + + @Override + public boolean disconnect(final long hostId) { + disconnect(hostId, Event.PrepareUnmanaged, false); + return true; + } @Override public void updateStatus(HostVO host, Status.Event event) { @@ -1077,7 +1083,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { _hostDao.disconnect(host, event, _nodeId); host = _hostDao.findById(host.getId()); - if (host.getStatus() == Status.Alert || host.getStatus() == Status.Down) { + if (event.equals(Event.PrepareUnmanaged) && (host.getStatus() == Status.Alert || host.getStatus() == Status.Down)) { _haMgr.scheduleRestartForVmsOnHost(host, investigate); } @@ -1544,6 +1550,8 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { return maintain(hostId); } else if (event == Event.ResetRequested) { return cancelMaintenance(hostId); + } else if (event == Event.PrepareUnmanaged) { + return disconnect(hostId); } else if (event == Event.Remove) { User caller = _accountMgr.getActiveUser(User.UID_SYSTEM); return deleteHost(hostId, false, false, caller); diff --git a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java index 7fd4dcec49a..c1f83ca9bfb 100644 --- a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java @@ -218,6 +218,20 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust return super.cancelMaintenance(hostId); } + @Override + public boolean disconnect(final long hostId) { + try { + Boolean result = _clusterMgr.propagateAgentEvent(hostId, Event.PrepareUnmanaged); + + if (result != null) { + return result; + } + } catch (AgentUnavailableException e) { + return false; + } + return super.disconnect(hostId); + } + protected AgentAttache createAttache(long id) { s_logger.debug("create forwarding ClusteredAgentAttache for " + id); final AgentAttache attache = new ClusteredAgentAttache(this, id); diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 838a16dd613..7166ac2bab4 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -967,6 +967,7 @@ public class ApiResponseHelper implements ResponseGenerator { clusterResponse.setHypervisorType(cluster.getHypervisorType().toString()); clusterResponse.setClusterType(cluster.getClusterType().toString()); clusterResponse.setAllocationState(cluster.getAllocationState().toString()); + clusterResponse.setManagedState(cluster.getManagedState().toString()); HostPodVO pod = ApiDBUtils.findPodById(cluster.getPodId()); if (pod != null) { clusterResponse.setPodName(pod.getName()); diff --git a/server/src/com/cloud/dc/ClusterVO.java b/server/src/com/cloud/dc/ClusterVO.java index 2d4312866f6..3bb649ae7e2 100644 --- a/server/src/com/cloud/dc/ClusterVO.java +++ b/server/src/com/cloud/dc/ClusterVO.java @@ -30,6 +30,7 @@ import javax.persistence.Table; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.org.Cluster; +import com.cloud.org.Managed.ManagedState; import com.cloud.org.Grouping; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.GenericDao; @@ -66,6 +67,10 @@ public class ClusterVO implements Cluster { @Enumerated(value=EnumType.STRING) AllocationState allocationState; + @Column(name="managed_state") + @Enumerated(value=EnumType.STRING) + ManagedState managedState; + @Column(name=GenericDao.REMOVED_COLUMN) private Date removed; @@ -80,6 +85,7 @@ public class ClusterVO implements Cluster { this.name = name; this.clusterType = Cluster.ClusterType.CloudManaged; this.allocationState = Grouping.AllocationState.Enabled; + this.managedState = ManagedState.Managed; } public long getId() { @@ -114,6 +120,14 @@ public class ClusterVO implements Cluster { this.allocationState = allocationState; } + public ManagedState getManagedState() { + return managedState; + } + + public void setManagedState(ManagedState managedState) { + this.managedState = managedState; + } + public ClusterVO(long clusterId) { this.id = clusterId; } diff --git a/server/src/com/cloud/host/dao/HostDaoImpl.java b/server/src/com/cloud/host/dao/HostDaoImpl.java index 6b8419bdf83..c02260d31a1 100644 --- a/server/src/com/cloud/host/dao/HostDaoImpl.java +++ b/server/src/com/cloud/host/dao/HostDaoImpl.java @@ -34,6 +34,8 @@ import org.apache.log4j.Logger; import com.cloud.cluster.agentlb.HostTransferMapVO; import com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.dao.ClusterDaoImpl; import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.host.HostTagVO; @@ -42,6 +44,7 @@ import com.cloud.host.Status; import com.cloud.host.Status.Event; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.info.RunningHostCountInfo; +import com.cloud.org.Managed; import com.cloud.utils.DateUtil; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.Attribute; @@ -100,6 +103,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao protected final GenericSearchBuilder HostsInStatusSearch; protected final GenericSearchBuilder CountRoutingByDc; protected final SearchBuilder HostTransferSearch; + protected final SearchBuilder ClusterManagedSearch; protected final Attribute _statusAttr; protected final Attribute _msIdAttr; @@ -108,6 +112,8 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao protected final HostDetailsDaoImpl _detailsDao = ComponentLocator.inject(HostDetailsDaoImpl.class); protected final HostTagsDaoImpl _hostTagsDao = ComponentLocator.inject(HostTagsDaoImpl.class); protected final HostTransferMapDaoImpl _hostTransferDao = ComponentLocator.inject(HostTransferMapDaoImpl.class); + protected final ClusterDaoImpl _clusterDao = ComponentLocator.inject(ClusterDaoImpl.class); + public HostDaoImpl() { @@ -234,6 +240,9 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao HostTransferSearch = _hostTransferDao.createSearchBuilder(); HostTransferSearch.and("id", HostTransferSearch.entity().getId(), SearchCriteria.Op.NULL); UnmanagedDirectConnectSearch.join("hostTransferSearch", HostTransferSearch, HostTransferSearch.entity().getId(), UnmanagedDirectConnectSearch.entity().getId(), JoinType.LEFTOUTER); + ClusterManagedSearch = _clusterDao.createSearchBuilder(); + ClusterManagedSearch.and("managed", ClusterManagedSearch.entity().getManagedState(), SearchCriteria.Op.EQ); + UnmanagedDirectConnectSearch.join("ClusterManagedSearch", ClusterManagedSearch, ClusterManagedSearch.entity().getId(), UnmanagedDirectConnectSearch.entity().getClusterId(), JoinType.INNER); UnmanagedDirectConnectSearch.done(); @@ -371,7 +380,8 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao SearchCriteria sc = UnmanagedDirectConnectSearch.create(); sc.setParameters("lastPinged", lastPingSecondsAfter); - sc.setParameters("statuses", Status.ErrorInMaintenance, Status.Maintenance, Status.PrepareForMaintenance); + sc.setParameters("statuses", Status.ErrorInMaintenance, Status.Maintenance, Status.PrepareForMaintenance); + sc.setJoinParameters("ClusterManagedSearch", "managed", Managed.ManagedState.Managed); List hosts = lockRows(sc, new Filter(HostVO.class, "clusterId", true, 0L, limit), true); for (HostVO host : hosts) { diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 0620341786b..f7cf0e5f807 100644 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -25,7 +25,6 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.ejb.Local; import javax.naming.ConfigurationException; @@ -59,6 +58,7 @@ import com.cloud.host.Host; import com.cloud.host.Host.HostAllocationState; import com.cloud.host.HostVO; import com.cloud.host.Status; +import com.cloud.host.Status.Event; import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDetailsDao; import com.cloud.hypervisor.Hypervisor; @@ -66,6 +66,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.kvm.resource.KvmDummyResourceBase; import com.cloud.org.Cluster; import com.cloud.org.Grouping; +import com.cloud.org.Managed; import com.cloud.storage.GuestOSCategoryVO; import com.cloud.storage.StorageManager; import com.cloud.storage.dao.GuestOSCategoryDao; @@ -582,7 +583,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma @Override @DB - public Cluster updateCluster(Cluster clusterToUpdate, String clusterType, String hypervisor, String allocationState) { + public Cluster updateCluster(Cluster clusterToUpdate, String clusterType, String hypervisor, String allocationState, String managedstate) { ClusterVO cluster = (ClusterVO) clusterToUpdate; // Verify cluster information and update the cluster if needed @@ -630,17 +631,97 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma doUpdate = true; } } + + Managed.ManagedState newManagedState = null; + Managed.ManagedState oldManagedState = cluster.getManagedState(); + if (managedstate != null && !managedstate.isEmpty()) { + try { + newManagedState = Managed.ManagedState.valueOf(managedstate); + } catch (IllegalArgumentException ex) { + throw new InvalidParameterValueException("Unable to resolve Managed State '" + managedstate + "' to a supported state"); + } + if (newManagedState == null) { + s_logger.error("Unable to resolve Managed State '" + managedstate + "' to a supported state"); + throw new InvalidParameterValueException("Unable to resolve Managed State '" + managedstate + "' to a supported state"); + } else { + doUpdate = true; + } + } + if (doUpdate) { Transaction txn = Transaction.currentTxn(); try { txn.start(); _clusterDao.update(cluster.getId(), cluster); - txn.commit(); + txn.commit(); } catch (Exception e) { s_logger.error("Unable to update cluster due to " + e.getMessage(), e); throw new CloudRuntimeException("Failed to update cluster. Please contact Cloud Support."); } } + + if( newManagedState != null && !newManagedState.equals(oldManagedState)) { + Transaction txn = Transaction.currentTxn(); + if( newManagedState.equals(Managed.ManagedState.Unmanaged) ) { + boolean success = true; + try { + txn.start(); + cluster.setManagedState(Managed.ManagedState.PrepareUnmanaged); + _clusterDao.update(cluster.getId(), cluster); + txn.commit(); + List hosts = _hostDao.listBy(cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); + for( HostVO host : hosts ) { + if( !host.getStatus().equals(Status.Down) && !host.getStatus().equals(Status.Disconnected) + && !host.getStatus().equals(Status.Up) && !host.getStatus().equals(Status.Alert) ) { + String msg = "host " + host.getPrivateIpAddress() + " should not be in " + host.getStatus().toString() + " status"; + throw new CloudRuntimeException("PrepareUnmanaged Failed due to " + msg); + } + } + + for( HostVO host : hosts ) { + if ( host.getStatus().equals(Status.Up )) { + _agentMgr.disconnect(host.getId()); + } + } + int retry = 10; + for ( int i = 0; i < retry; i++) { + success = true; + try { + Thread.sleep(20 * 1000); + } catch (Exception e) { + } + hosts = _hostDao.listBy(cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); + for( HostVO host : hosts ) { + if ( !host.getStatus().equals(Status.Down) && !host.getStatus().equals(Status.Disconnected) + && !host.getStatus().equals(Status.Alert)) { + success = false; + break; + } + } + if( success == true ) { + break; + } + } + if ( success == false ) { + throw new CloudRuntimeException("PrepareUnmanaged Failed due to some hosts are still in UP status after 5 Minutes, please try later "); + } + } finally { + if ( success == false ) { + txn.start(); + cluster.setManagedState(success? Managed.ManagedState.Unmanaged : Managed.ManagedState.PrepareUnmanagedError); + _clusterDao.update(cluster.getId(), cluster); + txn.commit(); + } + } + } else if( newManagedState.equals(Managed.ManagedState.Managed)) { + txn.start(); + cluster.setManagedState(Managed.ManagedState.Managed); + _clusterDao.update(cluster.getId(), cluster); + txn.commit(); + } + + } + return cluster; } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 0a93a8e19b2..c7e6ed17a15 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -280,6 +280,7 @@ CREATE TABLE `cloud`.`cluster` ( `hypervisor_type` varchar(32), `cluster_type` varchar(64) DEFAULT 'CloudManaged', `allocation_state` varchar(32) NOT NULL DEFAULT 'Enabled' COMMENT 'Is this cluster enabled for allocation for new resources', + `managed_state` varchar(32) NOT NULL DEFAULT 'Managed' COMMENT 'Is this cluster managed by cloudstack', `removed` datetime COMMENT 'date removed if not null', PRIMARY KEY (`id`), CONSTRAINT `fk_cluster__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `cloud`.`data_center`(`id`) ON DELETE CASCADE,