Skip to content

Commit ace87c5

Browse files
Script Fixes
1 parent b016642 commit ace87c5

File tree

14 files changed

+260
-45
lines changed

14 files changed

+260
-45
lines changed

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ public class ApiConstants {
212212
public static final String EXTENSION = "extension";
213213
public static final String EXTENSIONS = "extensions";
214214
public static final String EXTENSION_ID = "extensionid";
215+
public static final String EXTENSION_RESOURCE_ID = "extensionresourceid";
216+
public static final String EXTENSION_RESOURCE_MAP = "extensionresourcemap";
215217
public static final String SCRIPT = "script";
216218
public static final String FENCE = "fence";
217219
public static final String FETCH_LATEST = "fetchlatest";

api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddHostCmd.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public class AddHostCmd extends BaseCmd {
8585
protected Map externalDetails;
8686

8787
private Long extensionId;
88+
private Long extensionResourceId;
8889

8990
/////////////////////////////////////////////////////
9091
/////////////////// Accessors ///////////////////////
@@ -94,7 +95,7 @@ public AddHostCmd() {
9495

9596
}
9697

97-
public AddHostCmd(Long zoneId, Long podId, Long clusterId, String hypervisor, String username, String password, String url, Map externalDetails, Long extensionid) {
98+
public AddHostCmd(Long zoneId, Long podId, Long clusterId, String hypervisor, String username, String password, String url, Map externalDetails, Long extensionid, Long extensionResourceId) {
9899
this.zoneId = zoneId;
99100
this.podId = podId;
100101
this.clusterId = clusterId;
@@ -104,6 +105,7 @@ public AddHostCmd(Long zoneId, Long podId, Long clusterId, String hypervisor, St
104105
this.url = url;
105106
this.externalDetails = externalDetails;
106107
this.extensionId = extensionid;
108+
this.extensionResourceId = extensionResourceId;
107109
}
108110

109111
public Long getClusterId() {
@@ -154,6 +156,10 @@ public Long getExtensionId() {
154156
return extensionId;
155157
}
156158

159+
public Long getExtensionResourceId() {
160+
return extensionResourceId;
161+
}
162+
157163
public Map<String, String> getExternalDetails() {
158164
boolean isStringMap = true;
159165
if (externalDetails instanceof Map<?, ?>) {

engine/components-api/src/main/java/com/cloud/hypervisor/ExternalProvisioner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,5 @@ public interface ExternalProvisioner extends Adapter {
6262

6363
RunCustomActionAnswer runCustomAction(RunCustomActionCommand cmd);
6464

65-
void prepareScripts(Long extensionId);
65+
void prepareScripts(Long extensionId, Long extensionResourceId);
6666
}

plugins/hypervisors/external/src/main/java/com/cloud/agent/manager/ExternalAgentManagerImpl.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.cloud.hypervisor.ExternalProvisioner;
3636
import com.cloud.hypervisor.Hypervisor;
3737
import com.cloud.hypervisor.HypervisorGuruManagerImpl;
38+
import com.cloud.hypervisor.external.provisioner.api.ExtensionResourceMapResponse;
3839
import com.cloud.hypervisor.external.provisioner.api.ExtensionResponse;
3940
import com.cloud.hypervisor.external.provisioner.api.ListExtensionsCmd;
4041
import com.cloud.hypervisor.external.provisioner.api.CreateExtensionCmd;
@@ -184,8 +185,19 @@ public List<ExternalProvisioner> listExternalProvisioners() {
184185
public RunCustomActionAnswer runCustomAction(RunCustomActionCmd cmd) {
185186
String action = cmd.getActionName();
186187
Long extensionId = cmd.getExtensionId();
188+
String resourceId = cmd.getResourceId();
189+
String resourceType = cmd.getResourceType();
187190
Map<String, String> externalDetails = cmd.getExternalDetails();
188191

192+
HostPodVO pod = podDao.findByUuid(resourceId);
193+
if (pod == null) {
194+
throw new CloudRuntimeException("No Pod found with the provided UUID" + resourceId);
195+
}
196+
ExtensionResourceMapVO existing = extensionResourceMapDao.findByResourceIdAndType(pod.getId(), resourceType);
197+
if (existing == null) {
198+
throw new CloudRuntimeException("Extension is not registered with this resource");
199+
}
200+
189201
List<DetailVO> hostDetailsByExtension = hostDetailsDao.findByNameAndValue(ApiConstants.EXTENSION_ID, String.valueOf(extensionId));
190202
DetailVO hostDetail = hostDetailsByExtension.get(0);
191203

@@ -251,8 +263,23 @@ public List<ExtensionResponse> listExtensions(ListExtensionsCmd cmd) {
251263
for (ExtensionVO extension : result.first()) {
252264
Map<String, String> details = externalOrchestratorDetailDao.listDetailsKeyPairs(extension.getId());
253265
ExtensionResponse response = new ExtensionResponse(extension.getName(), extension.getType(), extension.getUuid(), details);
254-
String destinationPath = String.format(SimpleExternalProvisioner.EXTENSION_SCRIPT_PATH, extension.getId());
255-
response.setScriptPath(destinationPath);
266+
267+
List<ExtensionResourceMapVO> extensionResourceMapVOS = extensionResourceMapDao.listByExtensionId(extension.getId());
268+
List<ExtensionResourceMapResponse> resourceMapResponses = new ArrayList<>();
269+
270+
for (ExtensionResourceMapVO resourceMap : extensionResourceMapVOS) {
271+
HostPodVO pod = podDao.findById(resourceMap.getResourceId());
272+
ExtensionResourceMapResponse resourceResponse = new ExtensionResourceMapResponse(extension.getUuid(), pod.getUuid(), resourceMap.getResourceType());
273+
String scriptPath = String.format(SimpleExternalProvisioner.EXTENSION_SCRIPT_PATH, extension.getId(), resourceMap.getResourceId());
274+
resourceResponse.setScriptPath(scriptPath);
275+
276+
Map<String, String> resourceMapDetails = extensionResourceMapDetailsDao.listDetailsKeyPairs(resourceMap.getId());
277+
resourceResponse.setDetails(resourceMapDetails);
278+
279+
resourceMapResponses.add(resourceResponse);
280+
}
281+
282+
response.setResources(resourceMapResponses);
256283
response.setObjectName(ApiConstants.EXTENSIONS);
257284
responses.add(response);
258285
}
@@ -267,6 +294,11 @@ public boolean registerExtensionWithResource(RegisterExtensionCmd cmd) {
267294
String resourceType = cmd.getResourceType();
268295
if ("POD".equalsIgnoreCase(resourceType)) {
269296
HostPodVO pod = podDao.findByUuid(resourceId);
297+
ExtensionResourceMapVO existing = extensionResourceMapDao.findByResourceIdAndType(pod.getId(), resourceType);
298+
if (existing != null) {
299+
throw new CloudRuntimeException("Extension already registered with this resource");
300+
}
301+
270302
ExtensionResourceMapVO extensionMap = new ExtensionResourceMapVO();
271303
extensionMap.setExtensionId(extensionId);
272304
extensionMap.setResourceId(pod.getId());
@@ -315,7 +347,7 @@ private void createRequiredResourcesForExtensionInPod(RegisterExtensionCmd cmd,
315347

316348
String hosturl = "http://" + extension.getName() + "-" + extension.getId() + "-" + extensionResourceMap.getId() + "-host";
317349
AddHostCmd addHostCmd = new AddHostCmd(pod.getDataCenterId(), pod.getId(), cluster.getId(), Hypervisor.HypervisorType.External.toString(),
318-
"External", "External", hosturl, details, extension.getId());
350+
"External", "External", hosturl, details, extension.getId(), extensionResourceMap.getResourceId());
319351

320352
List<? extends Host> hosts;
321353
try {

plugins/hypervisors/external/src/main/java/com/cloud/hypervisor/external/discoverer/ExternalServerDiscoverer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] st
234234
}
235235

236236
ExternalProvisioner externalProvisioner = _externalAgentMgr.getExternalProvisioner(SimpleExternalProvisioner.class.getSimpleName());
237-
if (details.get(ApiConstants.EXTENSION_ID) != null){
238-
externalProvisioner.prepareScripts(Long.valueOf(details.get(ApiConstants.EXTENSION_ID)));
237+
if (details.get(ApiConstants.EXTENSION_ID) != null && details.get(ApiConstants.EXTENSION_RESOURCE_ID) != null) {
238+
externalProvisioner.prepareScripts(Long.valueOf(details.get(ApiConstants.EXTENSION_ID)), Long.valueOf(details.get(ApiConstants.EXTENSION_RESOURCE_ID)));
239239
}
240240

241241
return _resourceMgr.fillRoutingHostVO(host, ssCmd, Hypervisor.HypervisorType.External, details, hostTags);

plugins/hypervisors/external/src/main/java/com/cloud/hypervisor/external/provisioner/api/CreateExtensionCmd.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.cloud.exception.NetworkRuleConflictException;
2424
import com.cloud.exception.ResourceAllocationException;
2525
import com.cloud.exception.ResourceUnavailableException;
26-
import com.cloud.hypervisor.external.provisioner.simpleprovisioner.SimpleExternalProvisioner;
2726
import com.cloud.hypervisor.external.provisioner.vo.Extension;
2827
import com.cloud.user.Account;
2928
import com.cloud.vm.VmDetailConstants;
@@ -97,8 +96,6 @@ public Map getDetails() {
9796
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
9897
Extension extension = _externalMgr.createExtension(this);
9998
ExtensionResponse response = new ExtensionResponse(name, type, extension.getUuid(), getExternalDetails());
100-
String destinationPath = String.format(SimpleExternalProvisioner.EXTENSION_SCRIPT_PATH, extension.getId());
101-
response.setScriptPath(destinationPath);
10299
response.setResponseName(getCommandName());
103100
response.setObjectName(ApiConstants.EXTENSION);
104101
setResponseObject(response);
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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 com.cloud.hypervisor.external.provisioner.api;
19+
20+
import com.cloud.hypervisor.external.provisioner.vo.ExtensionResourceMapVO;
21+
import com.cloud.serializer.Param;
22+
import com.google.gson.annotations.SerializedName;
23+
import org.apache.cloudstack.api.ApiConstants;
24+
import org.apache.cloudstack.api.BaseResponse;
25+
import org.apache.cloudstack.api.EntityReference;
26+
27+
import java.util.Date;
28+
import java.util.Map;
29+
30+
@EntityReference(value = ExtensionResourceMapVO.class)
31+
public class ExtensionResourceMapResponse extends BaseResponse {
32+
@SerializedName(ApiConstants.EXTENSION_ID)
33+
@Param(description = "ID of the extension associated with this mapping")
34+
private String extensionId;
35+
36+
@SerializedName(ApiConstants.RESOURCE_ID)
37+
@Param(description = "ID of the resource associated with this mapping")
38+
private String resourceId;
39+
40+
@SerializedName(ApiConstants.RESOURCE_TYPE)
41+
@Param(description = "Type of the resource")
42+
private String resourceType;
43+
44+
@SerializedName(ApiConstants.SCRIPT)
45+
@Param(description = "the path of the script")
46+
private String script;
47+
48+
@SerializedName(ApiConstants.DETAILS)
49+
@Param(description = "the details of the resouce map")
50+
private Map<String, String> details;
51+
52+
@SerializedName(ApiConstants.CREATED)
53+
@Param(description = "Creation timestamp of the mapping")
54+
private Date created;
55+
56+
@SerializedName(ApiConstants.REMOVED)
57+
@Param(description = "Removal timestamp of the mapping, if applicable")
58+
private Date removed;
59+
60+
public ExtensionResourceMapResponse(String extensionId, String resourceId, String resourceType) {
61+
this.extensionId = extensionId;
62+
this.resourceId = resourceId;
63+
this.resourceType = resourceType;
64+
}
65+
66+
public String getExtensionId() {
67+
return extensionId;
68+
}
69+
70+
public void setExtensionId(String extensionId) {
71+
this.extensionId = extensionId;
72+
}
73+
74+
public String getResourceId() {
75+
return resourceId;
76+
}
77+
78+
public void setResourceId(String resourceId) {
79+
this.resourceId = resourceId;
80+
}
81+
82+
public String getResourceType() {
83+
return resourceType;
84+
}
85+
86+
public void setResourceType(String resourceType) {
87+
this.resourceType = resourceType;
88+
}
89+
90+
public String getScriptPath() {
91+
return script;
92+
}
93+
94+
public void setScriptPath(String script) {
95+
this.script = script;
96+
}
97+
98+
public Map<String, String> getDetails() {
99+
return details;
100+
}
101+
102+
public void setDetails(Map<String, String> details) {
103+
this.details = details;
104+
}
105+
106+
public Date getCreated() {
107+
return created;
108+
}
109+
110+
public void setCreated(Date created) {
111+
this.created = created;
112+
}
113+
114+
public Date getRemoved() {
115+
return removed;
116+
}
117+
118+
public void setRemoved(Date removed) {
119+
this.removed = removed;
120+
}
121+
}

plugins/hypervisors/external/src/main/java/com/cloud/hypervisor/external/provisioner/api/ExtensionResponse.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,12 @@
2525
import org.apache.cloudstack.api.EntityReference;
2626

2727
import java.util.Date;
28+
import java.util.List;
2829
import java.util.Map;
2930

3031
@EntityReference(value = Extension.class)
3132
public class ExtensionResponse extends BaseResponse {
3233

33-
@SerializedName(ApiConstants.ID)
34-
@Param(description = "ID of the extension")
35-
private String id;
36-
3734
@SerializedName(ApiConstants.UUID)
3835
@Param(description = "UUID of the extension")
3936
private String uuid;
@@ -47,12 +44,12 @@ public class ExtensionResponse extends BaseResponse {
4744
private String type;
4845

4946
@SerializedName(ApiConstants.DETAILS)
50-
@Param(description = "the details of the network")
47+
@Param(description = "the details of the extension")
5148
private Map<String, String> details;
5249

53-
@SerializedName(ApiConstants.SCRIPT)
54-
@Param(description = "the path of the script")
55-
private String script;
50+
@SerializedName(ApiConstants.EXTENSION_RESOURCE_ID)
51+
@Param(description = "List of resources to which extension is registered to", responseObject = ExtensionResourceMapResponse.class)
52+
private List<ExtensionResourceMapResponse> resources;
5653

5754
@SerializedName(ApiConstants.CREATED)
5855
@Param(description = "Creation timestamp of the extension")
@@ -97,12 +94,12 @@ public void setDetails(Map<String, String> details) {
9794
this.details = details;
9895
}
9996

100-
public String getScriptPath() {
101-
return script;
97+
public List<ExtensionResourceMapResponse> getResources() {
98+
return resources;
10299
}
103100

104-
public void setScriptPath(String script) {
105-
this.script = script;
101+
public void setResources(List<ExtensionResourceMapResponse> resources) {
102+
this.resources = resources;
106103
}
107104

108105
public Date getCreated() {

plugins/hypervisors/external/src/main/java/com/cloud/hypervisor/external/provisioner/api/RunCustomActionCmd.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ public class RunCustomActionCmd extends BaseAsyncCmd {
6060
entityType = ExtensionResponse.class, description = "the extension id used to call the custom action")
6161
private Long extensionId;
6262

63+
@Parameter(name = ApiConstants.RESOURCE_ID, type = CommandType.STRING, required = true,
64+
description = "UUID of the resource to register the extension with")
65+
private String resourceId;
66+
67+
@Parameter(name = ApiConstants.RESOURCE_TYPE, type = CommandType.STRING, required = true,
68+
description = "Type of the resource")
69+
private String resourceType;
70+
6371
@Parameter(name = ApiConstants.EXTERNAL_DETAILS, type = CommandType.MAP, description = "Details in key/value pairs using format externaldetails[i].keyname=keyvalue. Example: externaldetails[0].endpoint.url=urlvalue", since = "4.21.0")
6472
protected Map externalDetails;
6573

@@ -76,6 +84,14 @@ public Long getExtensionId() {
7684
return extensionId;
7785
}
7886

87+
public String getResourceId() {
88+
return resourceId;
89+
}
90+
91+
public String getResourceType() {
92+
return resourceType;
93+
}
94+
7995
public Map<String, String> getExternalDetails() {
8096
Map<String, String> customparameterMap = convertDetailsToMap(externalDetails);
8197
Map<String, String> details = new HashMap<>();

plugins/hypervisors/external/src/main/java/com/cloud/hypervisor/external/provisioner/dao/ExtensionResourceMapDao.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,10 @@
2020
import com.cloud.hypervisor.external.provisioner.vo.ExtensionResourceMapVO;
2121
import com.cloud.utils.db.GenericDao;
2222

23+
import java.util.List;
24+
2325
public interface ExtensionResourceMapDao extends GenericDao<ExtensionResourceMapVO, Long> {
26+
List<ExtensionResourceMapVO> listByExtensionId(long extensionId);
27+
28+
ExtensionResourceMapVO findByResourceIdAndType(long resourceId, String resourceType);
2429
}

0 commit comments

Comments
 (0)