Skip to content

Commit f0c5ecf

Browse files
committed
prepare entry-point on all MS
Signed-off-by: Abhishek Kumar <[email protected]>
1 parent 22fec2a commit f0c5ecf

File tree

7 files changed

+182
-46
lines changed

7 files changed

+182
-46
lines changed

engine/orchestration/src/main/java/com/cloud/agent/manager/ClusteredAgentManagerImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.apache.cloudstack.framework.config.ConfigKey;
4848
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
4949
import org.apache.cloudstack.framework.extensions.command.GetExtensionEntryPointChecksumCommand;
50+
import org.apache.cloudstack.framework.extensions.command.PrepareExtensionEntryPointCommand;
5051
import org.apache.cloudstack.framework.extensions.manager.ExtensionsManager;
5152
import org.apache.cloudstack.ha.dao.HAConfigDao;
5253
import org.apache.cloudstack.maintenance.ManagementServerMaintenanceManager;
@@ -98,6 +99,7 @@
9899
import com.cloud.resource.ServerResource;
99100
import com.cloud.serializer.GsonHelper;
100101
import com.cloud.utils.DateUtil;
102+
import com.cloud.utils.Pair;
101103
import com.cloud.utils.concurrency.NamedThreadFactory;
102104
import com.cloud.utils.db.QueryBuilder;
103105
import com.cloud.utils.db.SearchCriteria.Op;
@@ -1327,6 +1329,13 @@ public String dispatch(final ClusterServicePdu pdu) {
13271329
} else if (cmds.length == 1 && cmds[0] instanceof GetExtensionEntryPointChecksumCommand) {
13281330
final GetExtensionEntryPointChecksumCommand cmd = (GetExtensionEntryPointChecksumCommand) cmds[0];
13291331
return extensionsManager.handleGetExtensionEntryPointChecksumCommand(cmd);
1332+
} else if (cmds.length == 1 && cmds[0] instanceof PrepareExtensionEntryPointCommand) {
1333+
final PrepareExtensionEntryPointCommand cmd = (PrepareExtensionEntryPointCommand) cmds[0];
1334+
Pair<Boolean, String> result = extensionsManager.prepareExtensionEntryPointOnCurrentServer(
1335+
cmd.getExtensionName(), cmd.isExtensionUserDefined(), cmd.getExtensionRelativeEntryPointPath());
1336+
final Answer[] answers = new Answer[1];
1337+
answers[0] = new Answer(cmd, result.first(), result.second());
1338+
return _gson.toJson(answers);
13301339
}
13311340

13321341
try {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
18+
package org.apache.cloudstack.framework.extensions.command;
19+
20+
import org.apache.cloudstack.extension.Extension;
21+
22+
import com.cloud.agent.api.Command;
23+
24+
public class ExtensionServerActionBaseCommand extends Command {
25+
long msId;
26+
long extensionId;
27+
String extensionName;
28+
boolean extensionUserDefined;
29+
String extensionRelativeEntryPointPath;
30+
31+
protected ExtensionServerActionBaseCommand(long msId, Extension extension) {
32+
this.msId = msId;
33+
this.extensionId = extension.getId();
34+
this.extensionName = extension.getName();
35+
this.extensionUserDefined = extension.isUserDefined();
36+
this.extensionRelativeEntryPointPath = extension.getRelativeEntryPoint();
37+
}
38+
39+
public long getMsId() {
40+
return msId;
41+
}
42+
43+
public long getExtensionId() {
44+
return extensionId;
45+
}
46+
47+
public String getExtensionName() {
48+
return extensionName;
49+
}
50+
51+
public boolean isExtensionUserDefined() {
52+
return extensionUserDefined;
53+
}
54+
55+
public String getExtensionRelativeEntryPointPath() {
56+
return extensionRelativeEntryPointPath;
57+
}
58+
59+
@Override
60+
public boolean executeInSequence() {
61+
return false;
62+
}
63+
}

framework/extensions/src/main/java/org/apache/cloudstack/framework/extensions/command/GetExtensionEntryPointChecksumCommand.java

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,40 +17,11 @@
1717

1818
package org.apache.cloudstack.framework.extensions.command;
1919

20-
import com.cloud.agent.api.Command;
20+
import org.apache.cloudstack.extension.Extension;
2121

22-
public class GetExtensionEntryPointChecksumCommand extends Command {
23-
long msId;
24-
long extensionId;
25-
String extensionName;
26-
String extensionRelativeEntryPointPath;
22+
public class GetExtensionEntryPointChecksumCommand extends ExtensionServerActionBaseCommand {
2723

28-
public GetExtensionEntryPointChecksumCommand(long msId, long extensionId, String extensionName,
29-
String extensionRelativeEntryPointPath) {
30-
this.msId = msId;
31-
this.extensionId = extensionId;
32-
this.extensionName = extensionName;
33-
this.extensionRelativeEntryPointPath = extensionRelativeEntryPointPath;
34-
}
35-
36-
public long getMsId() {
37-
return msId;
38-
}
39-
40-
public long getExtensionId() {
41-
return extensionId;
42-
}
43-
44-
public String getExtensionName() {
45-
return extensionName;
46-
}
47-
48-
public String getExtensionRelativeEntryPointPath() {
49-
return extensionRelativeEntryPointPath;
50-
}
51-
52-
@Override
53-
public boolean executeInSequence() {
54-
return false;
24+
public GetExtensionEntryPointChecksumCommand(long msId, Extension extension) {
25+
super(msId, extension);
5526
}
5627
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
18+
package org.apache.cloudstack.framework.extensions.command;
19+
20+
import org.apache.cloudstack.extension.Extension;
21+
22+
public class PrepareExtensionEntryPointCommand extends ExtensionServerActionBaseCommand {
23+
24+
public PrepareExtensionEntryPointCommand(long msId, Extension extension) {
25+
super(msId, extension);
26+
}
27+
}

framework/extensions/src/main/java/org/apache/cloudstack/framework/extensions/manager/ExtensionsManager.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,18 @@
4646

4747
import com.cloud.host.Host;
4848
import com.cloud.org.Cluster;
49+
import com.cloud.utils.Pair;
4950
import com.cloud.utils.component.Manager;
5051

5152
public interface ExtensionsManager extends Manager {
5253

5354
Extension createExtension(CreateExtensionCmd cmd);
5455

56+
Pair<Boolean, String> prepareExtensionEntryPointOnCurrentServer(String name, boolean userDefined,
57+
String relativeEntryPoint);
58+
59+
void prepareExtensionEntryPointAcrossServers(Extension extension);
60+
5561
List<ExtensionResponse> listExtensions(ListExtensionsCmd cmd);
5662

5763
boolean deleteExtension(DeleteExtensionCmd cmd);

framework/extensions/src/main/java/org/apache/cloudstack/framework/extensions/manager/ExtensionsManagerImpl.java

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import org.apache.cloudstack.framework.extensions.api.UpdateCustomActionCmd;
6666
import org.apache.cloudstack.framework.extensions.api.UpdateExtensionCmd;
6767
import org.apache.cloudstack.framework.extensions.command.GetExtensionEntryPointChecksumCommand;
68+
import org.apache.cloudstack.framework.extensions.command.PrepareExtensionEntryPointCommand;
6869
import org.apache.cloudstack.framework.extensions.dao.ExtensionCustomActionDao;
6970
import org.apache.cloudstack.framework.extensions.dao.ExtensionCustomActionDetailsDao;
7071
import org.apache.cloudstack.framework.extensions.dao.ExtensionDao;
@@ -230,9 +231,10 @@ public Extension createExtension(CreateExtensionCmd cmd) {
230231
entryPoint = getValidatedExtensionRelativeEntryPoint(name, entryPoint);
231232
}
232233
final String entryPointFinal = entryPoint;
233-
return Transaction.execute((TransactionCallbackWithException<Extension, CloudRuntimeException>) status -> {
234+
ExtensionVO extensionVO = Transaction.execute((TransactionCallbackWithException<ExtensionVO, CloudRuntimeException>) status -> {
234235
ExtensionVO extension = new ExtensionVO(name, description, EnumUtils.getEnum(Extension.Type.class, typeStr),
235236
entryPointFinal);
237+
extension.setEntryPointSync(true);
236238
extension = extensionDao.persist(extension);
237239

238240
Map<String, String> details = cmd.getDetails();
@@ -243,10 +245,68 @@ public Extension createExtension(CreateExtensionCmd cmd) {
243245
}
244246
extensionDetailsDao.saveDetails(detailsVOList);
245247
}
246-
externalProvisioner.prepareExtensionEntryPoint(extension.getName(), extension.isUserDefined(), extension.getRelativeEntryPoint());
247248
CallContext.current().setEventResourceId(extension.getId());
248249
return extension;
249250
});
251+
prepareExtensionEntryPointAcrossServers(extensionVO);
252+
return extensionVO;
253+
}
254+
255+
protected boolean prepareExtensionEntryPointOnMSPeer(Extension extension, ManagementServerHostVO msHost) {
256+
final String msPeer = Long.toString(msHost.getMsid());
257+
logger.debug("Sending prepare extension entry-point for {} command to MS: {}", extension, msPeer);
258+
final Command[] commands = new Command[1];
259+
commands[0] = new PrepareExtensionEntryPointCommand(ManagementServerNode.getManagementServerId(), extension);
260+
String answersStr = clusterManager.execute(msPeer, 0L, GsonHelper.getGson().toJson(commands), true);
261+
Answer[] answers = null;
262+
try {
263+
answers = GsonHelper.getGson().fromJson(answersStr, Answer[].class);
264+
} catch (Exception e) {
265+
logger.error("Failed to parse answer JSON from {} on {}: {}", extension, msHost, e.getMessage(), e);
266+
}
267+
Answer answer = answers != null && answers.length > 0 ? answers[0] : null;
268+
boolean result = false;
269+
String error = "Unknown error";
270+
if (answer != null) {
271+
result = answer.getResult();
272+
error = answer.getDetails();
273+
}
274+
if (!result) {
275+
logger.error("Failed to prepare entry-point for {} on {} due to {}", extension, msHost, error);
276+
return false;
277+
}
278+
return true;
279+
}
280+
281+
public Pair<Boolean, String> prepareExtensionEntryPointOnCurrentServer(String name, boolean userDefined,
282+
String relativeEntryPoint) {
283+
try {
284+
externalProvisioner.prepareExtensionEntryPoint(name, userDefined, relativeEntryPoint);
285+
} catch (CloudRuntimeException e) {
286+
logger.error("Failed to prepare entry-point for Extension [name: {}, userDefined: {}, relativeEntryPoint: {}] on this server",
287+
name, userDefined, relativeEntryPoint, e);
288+
return new Pair<>(false, e.getMessage());
289+
}
290+
return new Pair<>(true, null);
291+
}
292+
293+
@Override
294+
public void prepareExtensionEntryPointAcrossServers(Extension extension) {
295+
boolean sync = true;
296+
List<ManagementServerHostVO> msHosts = managementServerHostDao.listBy(ManagementServerHost.State.Up);
297+
for (ManagementServerHostVO msHost : msHosts) {
298+
if (msHost.getMsid() == ManagementServerNode.getManagementServerId()) {
299+
sync = sync && prepareExtensionEntryPointOnCurrentServer(extension.getName(), extension.isUserDefined(),
300+
extension.getRelativeEntryPoint()).first();
301+
continue;
302+
}
303+
sync = sync && prepareExtensionEntryPointOnMSPeer(extension, msHost);
304+
}
305+
if (extension.isEntryPointSync() != sync) {
306+
ExtensionVO updateExtension = extensionDao.createForUpdate(extension.getId());
307+
updateExtension.setEntryPointSync(sync);
308+
extensionDao.update(extension.getId(), updateExtension);
309+
}
250310
}
251311

252312
@Override
@@ -1071,7 +1131,7 @@ protected String getChecksumFromMSPeer(Extension extension, ManagementServerHost
10711131
logger.debug("Retrieving checksum for {} from MS: {}", extension, msPeer);
10721132
final Command[] cmds = new Command[1];
10731133
cmds[0] = new GetExtensionEntryPointChecksumCommand(ManagementServerNode.getManagementServerId(),
1074-
extension.getId(), extension.getName(), extension.getRelativeEntryPoint());
1134+
extension);
10751135
return clusterManager.execute(msPeer, 0L, GsonHelper.getGson().toJson(cmds), true);
10761136
}
10771137

plugins/hypervisors/external/src/main/java/org/apache/cloudstack/hypervisor/external/discoverer/ExternalServerDiscoverer.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
import javax.naming.ConfigurationException;
2727

2828
import org.apache.cloudstack.agent.manager.ExternalAgentManager;
29+
import org.apache.cloudstack.extension.ExtensionResourceMap;
2930
import org.apache.cloudstack.framework.extensions.dao.ExtensionDao;
3031
import org.apache.cloudstack.framework.extensions.dao.ExtensionResourceMapDao;
32+
import org.apache.cloudstack.framework.extensions.manager.ExtensionsManager;
3133
import org.apache.cloudstack.framework.extensions.vo.ExtensionResourceMapVO;
3234
import org.apache.cloudstack.framework.extensions.vo.ExtensionVO;
3335
import org.apache.cloudstack.hypervisor.external.resource.ExternalResourceBase;
@@ -43,11 +45,9 @@
4345
import com.cloud.dc.ClusterVO;
4446
import com.cloud.exception.ConnectionException;
4547
import com.cloud.exception.DiscoveryException;
46-
import org.apache.cloudstack.extension.ExtensionResourceMap;
4748
import com.cloud.host.Host;
4849
import com.cloud.host.HostVO;
4950
import com.cloud.host.Status;
50-
import com.cloud.hypervisor.ExternalProvisioner;
5151
import com.cloud.hypervisor.Hypervisor;
5252
import com.cloud.resource.Discoverer;
5353
import com.cloud.resource.DiscovererBase;
@@ -58,19 +58,19 @@
5858
public class ExternalServerDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter {
5959

6060
@Inject
61-
private AgentManager agentManager;
61+
AgentManager agentManager;
6262

6363
@Inject
64-
private ExtensionDao externalOrchestratorDao;
64+
ExtensionDao extensionDao;
6565

6666
@Inject
6767
ExtensionResourceMapDao extensionResourceMapDao;
6868

6969
@Inject
70-
ExternalAgentManager externalAgentManager = null;
70+
ExternalAgentManager externalAgentManager;
7171

7272
@Inject
73-
ExternalProvisioner externalProvisioner;
73+
ExtensionsManager extensionsManager;
7474

7575
@Override
7676
public boolean processAnswers(long agentId, long seq, Answer[] answers) {
@@ -177,7 +177,7 @@ public Map<? extends ServerResource, Map<String, String>> find(long dcId, Long p
177177

178178
ExtensionResourceMapVO extensionResourceMapVO = extensionResourceMapDao.findByResourceIdAndType(clusterId,
179179
ExtensionResourceMap.ResourceType.Cluster);
180-
ExtensionVO extensionVO = externalOrchestratorDao.findById(extensionResourceMapVO.getExtensionId());
180+
ExtensionVO extensionVO = extensionDao.findById(extensionResourceMapVO.getExtensionId());
181181
params.put("extensionName", extensionVO.getName());
182182
params.put("extensionRelativeEntryPoint", extensionVO.getRelativeEntryPoint());
183183

@@ -200,7 +200,7 @@ protected HashMap<String, Object> buildConfigParams(HostVO host) {
200200
logger.debug("Cluster ID: {} not registered with any extension", clusterId);
201201
return params;
202202
}
203-
ExtensionVO extensionVO = externalOrchestratorDao.findById(extensionResourceMapVO.getExtensionId());
203+
ExtensionVO extensionVO = extensionDao.findById(extensionResourceMapVO.getExtensionId());
204204
if (extensionVO == null) {
205205
logger.error("Extension with ID: {} not found", extensionResourceMapVO.getExtensionId());
206206
return params;
@@ -256,9 +256,9 @@ public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] st
256256
final ClusterVO cluster = _clusterDao.findById(host.getClusterId());
257257
ExtensionResourceMapVO extensionResourceMapVO = extensionResourceMapDao.findByResourceIdAndType(cluster.getId(),
258258
ExtensionResourceMap.ResourceType.Cluster);
259-
ExtensionVO extension = externalOrchestratorDao.findById(extensionResourceMapVO.getExtensionId());
259+
ExtensionVO extension = extensionDao.findById(extensionResourceMapVO.getExtensionId());
260260
logger.debug("Creating host for {}", extension);
261-
externalProvisioner.prepareExtensionEntryPoint(extension.getName(), extension.isUserDefined(), extension.getRelativeEntryPoint());
261+
extensionsManager.prepareExtensionEntryPointAcrossServers(extension);
262262
return _resourceMgr.fillRoutingHostVO(host, ssCmd, Hypervisor.HypervisorType.External, details, hostTags);
263263
}
264264

0 commit comments

Comments
 (0)