Skip to content

Commit e24876c

Browse files
committed
Reconcile: add columns for resource id and type
- add column resource_id and resource_type - set resource_id and resource_type based on the srcData - skip Migrating VMs with reconcile commands - clean up volumes attached to Migrating vms without reconcile commands - skip Migrating volumes with reconcile commands - skip Migrating volumes attached to vms with reconcile commands - cleanup volumes in Migrating/Creating with last_id - add vmName to ReconcileMigrateAnswer
1 parent 307e4fb commit e24876c

File tree

11 files changed

+118
-25
lines changed

11 files changed

+118
-25
lines changed

api/src/main/java/org/apache/cloudstack/command/ReconcileCommandService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.cloud.agent.api.Answer;
2121
import com.cloud.agent.api.Command;
2222
import com.cloud.hypervisor.Hypervisor;
23+
import org.apache.cloudstack.api.ApiCommandResourceType;
2324
import org.apache.cloudstack.framework.config.ConfigKey;
2425

2526
import java.util.Arrays;
@@ -59,4 +60,6 @@ public interface ReconcileCommandService {
5960
void updateReconcileCommandToInterruptedByManagementServerId(long managementServerId);
6061

6162
void updateReconcileCommandToInterruptedByHostId(long hostId);
63+
64+
boolean isReconcileResourceNeeded(long resourceId, ApiCommandResourceType resourceType);
6265
}

core/src/main/java/org/apache/cloudstack/command/ReconcileMigrateAnswer.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
public class ReconcileMigrateAnswer extends ReconcileAnswer {
2727

2828
Long hostId;
29+
String vmName;
2930
VirtualMachine.State vmState;
3031
List<String> vmDisks;
3132

3233
public ReconcileMigrateAnswer() {
3334
}
3435

35-
public ReconcileMigrateAnswer(VirtualMachine.State vmState) {
36+
public ReconcileMigrateAnswer(String vmName, VirtualMachine.State vmState) {
37+
this.vmName = vmName;
3638
this.vmState = vmState;
3739
}
3840

@@ -44,6 +46,10 @@ public void setHostId(Long hostId) {
4446
this.hostId = hostId;
4547
}
4648

49+
public String getVmName() {
50+
return vmName;
51+
}
52+
4753
public VirtualMachine.State getVmState() {
4854
return vmState;
4955
}

engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,5 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long>, StateDao<Volume.S
163163

164164
VolumeVO findOneByIScsiName(String iScsiName);
165165

166-
VolumeVO findByInstanceIdAndPath(Long instanceId, String path);
167-
168-
VolumeVO findByLastIdAndState(long lastVolumeId, Volume.State state);
166+
VolumeVO findByLastIdAndState(long lastVolumeId, Volume.State...states);
169167
}

engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import com.cloud.utils.db.Filter;
5050
import com.cloud.utils.db.GenericDaoBase;
5151
import com.cloud.utils.db.GenericSearchBuilder;
52+
import com.cloud.utils.db.QueryBuilder;
5253
import com.cloud.utils.db.SearchBuilder;
5354
import com.cloud.utils.db.SearchCriteria;
5455
import com.cloud.utils.db.SearchCriteria.Func;
@@ -398,7 +399,6 @@ public VolumeDaoImpl() {
398399
AllFieldsSearch.and("passphraseId", AllFieldsSearch.entity().getPassphraseId(), Op.EQ);
399400
AllFieldsSearch.and("iScsiName", AllFieldsSearch.entity().get_iScsiName(), Op.EQ);
400401
AllFieldsSearch.and("path", AllFieldsSearch.entity().getPath(), Op.EQ);
401-
AllFieldsSearch.and("lastId", AllFieldsSearch.entity().getLastId(), Op.EQ);
402402
AllFieldsSearch.done();
403403

404404
RootDiskStateSearch = createSearchBuilder();
@@ -914,18 +914,10 @@ public VolumeVO findOneByIScsiName(String iScsiName) {
914914
}
915915

916916
@Override
917-
public VolumeVO findByInstanceIdAndPath(Long instanceId, String path) {
918-
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
919-
sc.setParameters("instanceId", instanceId);
920-
sc.setParameters("path", path);
921-
return findOneBy(sc);
922-
}
923-
924-
@Override
925-
public VolumeVO findByLastIdAndState(long lastVolumeId, State state) {
926-
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
927-
sc.setParameters("lastId", lastVolumeId);
928-
sc.setParameters("state", state);
929-
return findOneBy(sc);
917+
public VolumeVO findByLastIdAndState(long lastVolumeId, State ...states) {
918+
QueryBuilder<VolumeVO> sc = QueryBuilder.create(VolumeVO.class);
919+
sc.and(sc.entity().getLastId(), SearchCriteria.Op.EQ, lastVolumeId);
920+
sc.and(sc.entity().getState(), SearchCriteria.Op.IN, (Object[]) states);
921+
return sc.find();
930922
}
931923
}

engine/schema/src/main/java/org/apache/cloudstack/command/ReconcileCommandVO.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.cloud.utils.db.GenericDao;
3333

3434
import org.apache.cloudstack.acl.InfrastructureEntity;
35+
import org.apache.cloudstack.api.ApiCommandResourceType;
3536
import org.apache.cloudstack.api.InternalIdentity;
3637

3738
@Entity
@@ -51,6 +52,12 @@ public class ReconcileCommandVO implements InfrastructureEntity, InternalIdentit
5152
@Column(name = "request_sequence")
5253
private long requestSequence;
5354

55+
@Column(name = "resource_id")
56+
private long resourceId;
57+
58+
@Column(name = "resource_type")
59+
private ApiCommandResourceType resourceType;
60+
5461
@Column(name = "state_by_management")
5562
private Command.State stateByManagement;
5663

@@ -111,6 +118,22 @@ public void setRequestSequence(long requestSequence) {
111118
this.requestSequence = requestSequence;
112119
}
113120

121+
public long getResourceId() {
122+
return resourceId;
123+
}
124+
125+
public void setResourceId(long resourceId) {
126+
this.resourceId = resourceId;
127+
}
128+
129+
public ApiCommandResourceType getResourceType() {
130+
return resourceType;
131+
}
132+
133+
public void setResourceType(ApiCommandResourceType resourceType) {
134+
this.resourceType = resourceType;
135+
}
136+
114137
public Command.State getStateByManagement() {
115138
return stateByManagement;
116139
}

engine/schema/src/main/java/org/apache/cloudstack/command/dao/ReconcileCommandDao.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.cloud.agent.api.Command;
2121
import com.cloud.utils.db.GenericDao;
2222

23+
import org.apache.cloudstack.api.ApiCommandResourceType;
2324
import org.apache.cloudstack.command.ReconcileCommandVO;
2425

2526
import java.util.List;
@@ -39,4 +40,6 @@ public interface ReconcileCommandDao extends GenericDao<ReconcileCommandVO, Long
3940
void updateCommandsToInterruptedByManagementServerId(long managementServerId);
4041

4142
void updateCommandsToInterruptedByHostId(long hostId);
43+
44+
List<ReconcileCommandVO> listByResourceIdAndTypeAndStates(long resourceId, ApiCommandResourceType resourceType, Command.State... states);
4245
}

engine/schema/src/main/java/org/apache/cloudstack/command/dao/ReconcileCommandDaoImpl.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Date;
2121
import java.util.List;
2222

23+
import org.apache.cloudstack.api.ApiCommandResourceType;
2324
import org.apache.cloudstack.command.ReconcileCommandVO;
2425
import org.springframework.stereotype.Component;
2526

@@ -35,6 +36,7 @@
3536
public class ReconcileCommandDaoImpl extends GenericDaoBase<ReconcileCommandVO, Long> implements ReconcileCommandDao {
3637

3738
final SearchBuilder<ReconcileCommandVO> updateCommandSearch;
39+
final SearchBuilder<ReconcileCommandVO> resourceSearch;
3840

3941
public ReconcileCommandDaoImpl() {
4042

@@ -46,6 +48,12 @@ public ReconcileCommandDaoImpl() {
4648
updateCommandSearch.and("reqSequence", updateCommandSearch.entity().getRequestSequence(), SearchCriteria.Op.EQ);
4749
updateCommandSearch.and("commandName", updateCommandSearch.entity().getCommandName(), SearchCriteria.Op.EQ);
4850
updateCommandSearch.done();
51+
52+
resourceSearch = createSearchBuilder();
53+
resourceSearch.and("resourceId", resourceSearch.entity().getResourceId(), SearchCriteria.Op.EQ);
54+
resourceSearch.and("resourceType", resourceSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
55+
resourceSearch.and("stateByManagement", resourceSearch.entity().getStateByManagement(), SearchCriteria.Op.IN);
56+
resourceSearch.done();
4957
}
5058

5159
@Override
@@ -114,4 +122,13 @@ public void updateCommandsToInterruptedByHostId(long hostId) {
114122

115123
update(vo, sc);
116124
}
125+
126+
@Override
127+
public List<ReconcileCommandVO> listByResourceIdAndTypeAndStates(long resourceId, ApiCommandResourceType resourceType, Command.State... states) {
128+
QueryBuilder<ReconcileCommandVO> sc = QueryBuilder.create(ReconcileCommandVO.class);
129+
sc.and(sc.entity().getResourceId(), SearchCriteria.Op.EQ, resourceId);
130+
sc.and(sc.entity().getResourceType(), SearchCriteria.Op.EQ, resourceType);
131+
sc.and(sc.entity().getStateByManagement(), SearchCriteria.Op.IN, (Object[]) states);
132+
return sc.list();
133+
}
117134
}

engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ CREATE TABLE IF NOT EXISTS `cloud`.`reconcile_commands` (
4444
`management_server_id` bigint unsigned NOT NULL COMMENT 'node id of the management server',
4545
`host_id` bigint unsigned NOT NULL COMMENT 'id of the host',
4646
`request_sequence` bigint unsigned NOT NULL COMMENT 'sequence of the request',
47+
`resource_id` bigint unsigned DEFAULT NULL COMMENT 'id of the resource',
48+
`resource_type` varchar(255) NOT NULL COMMENT 'type if the resource',
4749
`state_by_management` varchar(255) COMMENT 'state of the command updated by management server',
4850
`state_by_agent` varchar(255) COMMENT 'state of the command updated by cloudstack agent',
4951
`command_name` varchar(255) COMMENT 'name of the command',

framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@
7171
import com.cloud.network.dao.NetworkDao;
7272
import com.cloud.network.dao.NetworkVO;
7373
import com.cloud.storage.Snapshot;
74-
import com.cloud.storage.Storage.ImageFormat;
7574
import com.cloud.storage.Volume;
75+
import com.cloud.storage.VolumeVO;
7676
import com.cloud.storage.VolumeDetailVO;
7777
import com.cloud.storage.dao.SnapshotDao;
7878
import com.cloud.storage.dao.SnapshotDetailsDao;
@@ -169,6 +169,8 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager,
169169
private NetworkDao networkDao;
170170
@Inject
171171
private NetworkOrchestrationService networkOrchestrationService;
172+
@Inject
173+
private ReconcileCommandService reconcileCommandService;
172174

173175
private volatile long _executionRunNumber = 1;
174176

@@ -1199,10 +1201,22 @@ private boolean cleanupVolume(final long volumeId) {
11991201
return true;
12001202
}
12011203
if (vol.getState().isTransitional()) {
1202-
if (Volume.State.Migrating.equals(vol.getState()) && Arrays.asList(ImageFormat.RAW, ImageFormat.QCOW2).contains(vol.getFormat())
1203-
&& ReconcileCommandService.ReconcileCommandsEnabled.value()) {
1204-
logger.debug("Skipping cleaning up Migrating volume: " + vol);
1205-
return true;
1204+
if (Volume.State.Migrating.equals(vol.getState())) {
1205+
if (ReconcileCommandService.ReconcileCommandsEnabled.value()) {
1206+
if (reconcileCommandService.isReconcileResourceNeeded(volumeId, ApiCommandResourceType.Volume)) {
1207+
logger.debug(String.format("Skipping cleaning up Migrating volume: %s, it will be reconciled", vol));
1208+
return true;
1209+
}
1210+
if (vol.getInstanceId() != null && reconcileCommandService.isReconcileResourceNeeded(vol.getInstanceId(), ApiCommandResourceType.VirtualMachine)) {
1211+
logger.debug(String.format("Skipping cleaning up Migrating volume: %s, the vm %s will be reconciled", vol, _vmInstanceDao.findById(vol.getInstanceId())));
1212+
return true;
1213+
}
1214+
}
1215+
VolumeVO destVolume = _volsDao.findByLastIdAndState(vol.getId(), Volume.State.Migrating, Volume.State.Creating);
1216+
if (destVolume != null) {
1217+
logger.debug(String.format("Found destination volume of Migrating volume %s: %s", vol, destVolume));
1218+
cleanupVolume(destVolume.getId());
1219+
}
12061220
}
12071221
logger.debug("Cleaning up volume with Id: " + volumeId);
12081222
boolean status = vol.stateTransit(Volume.Event.OperationFailed);
@@ -1220,6 +1234,18 @@ private boolean cleanupVirtualMachine(final long vmId) throws Exception {
12201234
return true;
12211235
}
12221236
if (vmInstanceVO.getState().isTransitional()) {
1237+
if (VirtualMachine.State.Migrating.equals(vmInstanceVO.getState())) {
1238+
if (ReconcileCommandService.ReconcileCommandsEnabled.value()
1239+
&& reconcileCommandService.isReconcileResourceNeeded(vmId, ApiCommandResourceType.VirtualMachine)) {
1240+
logger.debug(String.format("Skipping cleaning up Instance %s, it will be reconciled", vmInstanceVO));
1241+
return true;
1242+
}
1243+
logger.debug("Cleaning up volumes with instance Id: " + vmId);
1244+
List<VolumeVO> volumes = _volsDao.findByInstance(vmInstanceVO.getId());
1245+
for (VolumeVO volume : volumes) {
1246+
cleanupVolume(volume.getId());
1247+
}
1248+
}
12231249
logger.debug("Cleaning up Instance with Id: " + vmId);
12241250
return virtualMachineManager.stateTransitTo(vmInstanceVO, VirtualMachine.Event.OperationFailed, vmInstanceVO.getHostId());
12251251
}

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtReconcileCommandWrapper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@ private ReconcileAnswer handle(final ReconcileMigrateCommand reconcileCommand, f
8484
if (VirtualMachine.State.Running.equals(state)) {
8585
disks = getVmDiskPaths(libvirtComputingResource.getDisks(conn, vmName));
8686
}
87-
answer = new ReconcileMigrateAnswer(state);
87+
answer = new ReconcileMigrateAnswer(vmName, state);
8888
answer.setVmDisks(disks);
8989
} catch (LibvirtException e) {
9090
logger.debug(String.format("Failed to get state of VM %s, assume it is Stopped", vmName));
9191
VirtualMachine.State state = VirtualMachine.State.Stopped;
92-
answer = new ReconcileMigrateAnswer(state);
92+
answer = new ReconcileMigrateAnswer(vmName, state);
9393
}
9494
return answer;
9595
}

0 commit comments

Comments
 (0)