Skip to content

Commit f9bba6e

Browse files
committed
New feature: Reconcile commands (CopyCommand, MigrateCommand, MigrateVolumeCommand)
1 parent 1c1dad9 commit f9bba6e

File tree

72 files changed

+3654
-94
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+3654
-94
lines changed

agent/src/main/java/com/cloud/agent/Agent.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,9 @@ protected void processRequest(final Request request, final Link link) {
797797
}
798798
commandsInProgress.incrementAndGet();
799799
try {
800+
if (cmd.isReconcile()) {
801+
cmd.setRequestSequence(request.getSequence());
802+
}
800803
answer = serverResource.executeRequest(cmd);
801804
} finally {
802805
commandsInProgress.decrementAndGet();
@@ -1003,9 +1006,13 @@ public void processResponse(final Response response, final Link link) {
10031006
for (final IAgentControlListener listener : controlListeners) {
10041007
listener.processControlResponse(response, (AgentControlAnswer)answer);
10051008
}
1006-
} else if (answer instanceof PingAnswer && (((PingAnswer) answer).isSendStartup()) && reconnectAllowed) {
1007-
logger.info("Management server requested startup command to reinitialize the agent");
1008-
sendStartup(link);
1009+
} else if (answer instanceof PingAnswer) {
1010+
if (((PingAnswer) answer).isSendStartup() && reconnectAllowed) {
1011+
logger.info("Management server requested startup command to reinitialize the agent");
1012+
sendStartup(link);
1013+
} else {
1014+
serverResource.processPingAnswer((PingAnswer) answer);
1015+
}
10091016
} else {
10101017
updateLastPingResponseTime();
10111018
}
@@ -1073,6 +1080,9 @@ public void processOtherTask(final Task task) {
10731080
Answer answer = null;
10741081
commandsInProgress.incrementAndGet();
10751082
try {
1083+
if (command.isReconcile()) {
1084+
command.setRequestSequence(req.getSequence());
1085+
}
10761086
answer = serverResource.executeRequest(command);
10771087
} finally {
10781088
commandsInProgress.decrementAndGet();

api/src/main/java/com/cloud/agent/api/Command.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,31 @@ public static enum OnError {
3535
Continue, Stop
3636
}
3737

38+
public enum State {
39+
CREATED, // Command is created by management server
40+
STARTED, // Command is started by agent
41+
PROCESSING, // Processing by agent
42+
PROCESSING_IN_BACKEND, // Processing in backend by agent
43+
COMPLETED, // Operation succeeds by agent or management server
44+
FAILED, // Operation fails by agent
45+
RECONCILE_RETRY, // Ready for retry of reconciliation
46+
RECONCILING, // Being reconciled by management server
47+
RECONCILED, // Reconciled by management server
48+
RECONCILE_SKIPPED, // Skip the reconciliation as the resource state is inconsistent with the command
49+
RECONCILE_FAILED, // Fail to reconcile by management server
50+
TIMED_OUT, // Timed out on management server or agent
51+
INTERRUPTED, // Interrupted by management server or agent (for example agent is restarted),
52+
DANGLED_IN_BACKEND // Backend process which cannot be processed normally (for example agent is restarted)
53+
}
54+
3855
public static final String HYPERVISOR_TYPE = "hypervisorType";
3956

4057
// allow command to carry over hypervisor or other environment related context info
4158
@LogLevel(Log4jLevel.Trace)
4259
protected Map<String, String> contextMap = new HashMap<String, String>();
4360
private int wait; //in second
4461
private boolean bypassHostMaintenance = false;
62+
private transient long requestSequence = 0L;
4563

4664
protected Command() {
4765
this.wait = 0;
@@ -82,6 +100,10 @@ public String getContextParam(String name) {
82100
return contextMap.get(name);
83101
}
84102

103+
public Map<String, String> getContextMap() {
104+
return contextMap;
105+
}
106+
85107
public boolean allowCaching() {
86108
return true;
87109
}
@@ -94,6 +116,18 @@ public void setBypassHostMaintenance(boolean bypassHostMaintenance) {
94116
this.bypassHostMaintenance = bypassHostMaintenance;
95117
}
96118

119+
public boolean isReconcile() {
120+
return false;
121+
}
122+
123+
public long getRequestSequence() {
124+
return requestSequence;
125+
}
126+
127+
public void setRequestSequence(long requestSequence) {
128+
this.requestSequence = requestSequence;
129+
}
130+
97131
@Override
98132
public boolean equals(Object o) {
99133
if (this == o) return true;

api/src/main/java/com/cloud/agent/api/to/DiskTO.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public class DiskTO {
4646
private Long diskSeq;
4747
private String path;
4848
private Volume.Type type;
49-
private Map<String, String> _details;
49+
private Map<String, String> details;
5050

5151
public DiskTO() {
5252

@@ -92,10 +92,10 @@ public void setType(Volume.Type type) {
9292
}
9393

9494
public void setDetails(Map<String, String> details) {
95-
_details = details;
95+
this.details = details;
9696
}
9797

9898
public Map<String, String> getDetails() {
99-
return _details;
99+
return details;
100100
}
101101
}

api/src/main/java/com/cloud/agent/api/to/NetworkTO.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class NetworkTO {
3636
protected TrafficType type;
3737
protected URI broadcastUri;
3838
protected URI isolationUri;
39-
protected boolean isSecurityGroupEnabled;
39+
protected boolean securityGroupEnabled;
4040
protected String name;
4141
protected String ip6address;
4242
protected String ip6gateway;
@@ -112,7 +112,7 @@ public String getName() {
112112
}
113113

114114
public void setSecurityGroupEnabled(boolean enabled) {
115-
this.isSecurityGroupEnabled = enabled;
115+
this.securityGroupEnabled = enabled;
116116
}
117117

118118
/**
@@ -221,7 +221,7 @@ public void setIsolationuri(URI isolationUri) {
221221
}
222222

223223
public boolean isSecurityGroupEnabled() {
224-
return this.isSecurityGroupEnabled;
224+
return this.securityGroupEnabled;
225225
}
226226

227227
public void setIp6Dns1(String ip6Dns1) {

api/src/main/java/com/cloud/agent/api/to/NicTO.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ public void setUuid(String uuid) {
8686
this.nicUuid = uuid;
8787
}
8888

89+
public String getNicUuid() {
90+
return nicUuid;
91+
}
92+
93+
public void setNicUuid(String nicUuid) {
94+
this.nicUuid = nicUuid;
95+
}
96+
8997
@Override
9098
public String toString() {
9199
return new StringBuilder("[Nic:").append(type).append("-").append(ip).append("-").append(broadcastUri).append("]").toString();

api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public class VirtualMachineTO {
6161
@LogLevel(LogLevel.Log4jLevel.Off)
6262
String vncPassword;
6363
String vncAddr;
64-
Map<String, String> params;
64+
Map<String, String> details;
6565
String uuid;
6666
String bootType;
6767
String bootMode;
@@ -191,7 +191,11 @@ public Integer getMaxSpeed() {
191191
return maxSpeed;
192192
}
193193

194-
public boolean getLimitCpuUse() {
194+
public boolean isEnableHA() {
195+
return enableHA;
196+
}
197+
198+
public boolean isLimitCpuUse() {
195199
return limitCpuUse;
196200
}
197201

@@ -289,11 +293,11 @@ public void setVncAddr(String vncAddr) {
289293
}
290294

291295
public Map<String, String> getDetails() {
292-
return params;
296+
return details;
293297
}
294298

295299
public void setDetails(Map<String, String> params) {
296-
this.params = params;
300+
this.details = params;
297301
}
298302

299303
public String getUuid() {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.command;
18+
19+
20+
import com.cloud.agent.api.Answer;
21+
import com.cloud.agent.api.Command;
22+
import com.cloud.hypervisor.Hypervisor;
23+
import org.apache.cloudstack.framework.config.ConfigKey;
24+
25+
import java.util.Arrays;
26+
import java.util.List;
27+
28+
public interface ReconcileCommandService {
29+
30+
ConfigKey<Boolean> ReconcileCommandsEnabled = new ConfigKey<>("Advanced", Boolean.class,
31+
"reconcile.commands.enabled", "true",
32+
"Indicates whether the background task to reconcile the commands is enabled or not",
33+
false);
34+
35+
ConfigKey<Integer> ReconcileCommandsInterval = new ConfigKey<>("Advanced", Integer.class,
36+
"reconcile.commands.interval", "60",
37+
"Interval (in seconds) for the background task to reconcile the commands",
38+
false);
39+
ConfigKey<Integer> ReconcileCommandsMaxAttempts = new ConfigKey<>("Advanced", Integer.class,
40+
"reconcile.commands.max.attempts", "30",
41+
"The maximum number of attempts to reconcile the commands",
42+
true);
43+
44+
ConfigKey<Integer> ReconcileCommandsWorkers = new ConfigKey<>("Advanced", Integer.class,
45+
"reconcile.commands.workers", "100",
46+
"The Number of worker threads to reconcile the commands",
47+
false);
48+
49+
List<Hypervisor.HypervisorType> SupportedHypervisorTypes = Arrays.asList(Hypervisor.HypervisorType.KVM);
50+
51+
void persistReconcileCommands(Long hostId, Long requestSequence, Command[] cmd);
52+
53+
boolean updateReconcileCommand(long requestSeq, Command command, Answer answer, Command.State newStateByManagement, Command.State newStateByAgent);
54+
55+
void processCommand(Command pingCommand, Answer pingAnswer);
56+
57+
void processAnswers(long requestSeq, Command[] commands, Answer[] answers);
58+
59+
void updateReconcileCommandToInterruptedByManagementServerId(long managementServerId);
60+
61+
void updateReconcileCommandToInterruptedByHostId(long hostId);
62+
}

core/src/main/java/com/cloud/agent/api/MigrateCommand.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@
2929

3030
public class MigrateCommand extends Command {
3131
private String vmName;
32-
private String destIp;
32+
private String destinationIp;
3333
private Map<String, MigrateDiskInfo> migrateStorage;
3434
private boolean migrateStorageManaged;
3535
private boolean migrateNonSharedInc;
3636
private boolean autoConvergence;
3737
private String hostGuid;
38-
private boolean isWindows;
39-
private VirtualMachineTO vmTO;
38+
private boolean windows;
39+
private VirtualMachineTO virtualMachine;
4040
private boolean executeInSequence = false;
4141
private List<MigrateDiskInfo> migrateDiskInfoList = new ArrayList<>();
4242
private Map<String, DpdkTO> dpdkInterfaceMapping = new HashMap<>();
@@ -64,11 +64,11 @@ public void setVlanToPersistenceMap(Map<String, Boolean> vlanToPersistenceMap) {
6464
protected MigrateCommand() {
6565
}
6666

67-
public MigrateCommand(String vmName, String destIp, boolean isWindows, VirtualMachineTO vmTO, boolean executeInSequence) {
67+
public MigrateCommand(String vmName, String destinationIp, boolean windows, VirtualMachineTO virtualMachine, boolean executeInSequence) {
6868
this.vmName = vmName;
69-
this.destIp = destIp;
70-
this.isWindows = isWindows;
71-
this.vmTO = vmTO;
69+
this.destinationIp = destinationIp;
70+
this.windows = windows;
71+
this.virtualMachine = virtualMachine;
7272
this.executeInSequence = executeInSequence;
7373
}
7474

@@ -105,15 +105,15 @@ public boolean isAutoConvergence() {
105105
}
106106

107107
public boolean isWindows() {
108-
return isWindows;
108+
return windows;
109109
}
110110

111111
public VirtualMachineTO getVirtualMachine() {
112-
return vmTO;
112+
return virtualMachine;
113113
}
114114

115115
public String getDestinationIp() {
116-
return destIp;
116+
return destinationIp;
117117
}
118118

119119
public String getVmName() {
@@ -233,4 +233,9 @@ public void setSourceDiskOnStorageFileSystem(boolean isDiskOnFileSystemStorage)
233233
this.isSourceDiskOnStorageFileSystem = isDiskOnFileSystemStorage;
234234
}
235235
}
236+
237+
@Override
238+
public boolean isReconcile() {
239+
return true;
240+
}
236241
}

core/src/main/java/com/cloud/agent/api/PingAnswer.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,16 @@
1919

2020
package com.cloud.agent.api;
2121

22+
import java.util.ArrayList;
23+
import java.util.List;
24+
2225
public class PingAnswer extends Answer {
2326
private PingCommand _command = null;
2427

2528
private boolean sendStartup = false;
2629

30+
private List<String> reconcileCommands = new ArrayList<>();
31+
2732
protected PingAnswer() {
2833
}
2934

@@ -44,4 +49,16 @@ public boolean isSendStartup() {
4449
public void setSendStartup(boolean sendStartup) {
4550
this.sendStartup = sendStartup;
4651
}
52+
53+
public List<String> getReconcileCommands() {
54+
return reconcileCommands;
55+
}
56+
57+
public void setReconcileCommands(List<String> reconcileCommands) {
58+
this.reconcileCommands = reconcileCommands;
59+
}
60+
61+
public void addReconcileCommand(String reconcileCommand) {
62+
this.reconcileCommands.add(reconcileCommand);
63+
}
4764
}

core/src/main/java/com/cloud/agent/api/PingCommand.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@
2020
package com.cloud.agent.api;
2121

2222
import com.cloud.host.Host;
23+
import org.apache.cloudstack.command.CommandInfo;
2324

2425
public class PingCommand extends Command {
2526
Host.Type hostType;
2627
long hostId;
2728
boolean outOfBand;
29+
@LogLevel(LogLevel.Log4jLevel.Trace)
30+
private CommandInfo[] commandInfos = new CommandInfo[] {};
2831

2932
protected PingCommand() {
3033
}
@@ -78,4 +81,12 @@ public int hashCode() {
7881
result = 31 * result + (int) (hostId ^ (hostId >>> 32));
7982
return result;
8083
}
84+
85+
public CommandInfo[] getCommandInfos() {
86+
return commandInfos;
87+
}
88+
89+
public void setCommandInfos(CommandInfo[] commandInfos) {
90+
this.commandInfos = commandInfos;
91+
}
8192
}

0 commit comments

Comments
 (0)