Skip to content

Commit 2be9d96

Browse files
committed
changes for download extension
Signed-off-by: Abhishek Kumar <[email protected]>
1 parent 2c70e03 commit 2be9d96

File tree

18 files changed

+714
-21
lines changed

18 files changed

+714
-21
lines changed

api/src/main/java/com/cloud/event/EventTypes.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,7 @@ public class EventTypes {
845845
public static final String EVENT_EXTENSION_UPDATE = "EXTENSION.UPDATE";
846846
public static final String EVENT_EXTENSION_DELETE = "EXTENSION.DELETE";
847847
public static final String EVENT_EXTENSION_SYNC = "EXTENSION.SYNC";
848+
public static final String EVENT_EXTENSION_DOWNLOAD = "EXTENSION.DOWNLOAD";
848849
public static final String EVENT_EXTENSION_RESOURCE_REGISTER = "EXTENSION.RESOURCE.REGISTER";
849850
public static final String EVENT_EXTENSION_RESOURCE_UNREGISTER = "EXTENSION.RESOURCE.UNREGISTER";
850851
public static final String EVENT_EXTENSION_CUSTOM_ACTION_ADD = "EXTENSION.CUSTOM.ACTION.ADD";

api/src/main/java/org/apache/cloudstack/api/response/ExtractResponse.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,20 @@
1818

1919
import java.util.Date;
2020

21-
import com.google.gson.annotations.SerializedName;
22-
2321
import org.apache.cloudstack.api.ApiConstants;
2422
import org.apache.cloudstack.api.BaseResponse;
2523

2624
import com.cloud.serializer.Param;
25+
import com.google.gson.annotations.SerializedName;
2726

2827
public class ExtractResponse extends BaseResponse {
2928
@SerializedName(ApiConstants.ID)
3029
@Param(description = "the id of extracted object")
31-
private String id;
30+
protected String id;
3231

3332
@SerializedName(ApiConstants.NAME)
3433
@Param(description = "the name of the extracted object")
35-
private String name;
34+
protected String name;
3635

3736
@SerializedName("extractId")
3837
@Param(description = "the upload id of extracted object")
@@ -80,7 +79,7 @@ public class ExtractResponse extends BaseResponse {
8079

8180
@SerializedName(ApiConstants.URL)
8281
@Param(description = "if mode = upload then url of the uploaded entity. if mode = download the url from which the entity can be downloaded")
83-
private String url;
82+
protected String url;
8483

8584
public ExtractResponse() {
8685
}

client/src/main/java/org/apache/cloudstack/ServerDaemon.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,14 @@ protected void initShareConfigFromProperties() {
147147
setShareCacheCtl(ServerPropertiesUtil.getShareCacheControl());
148148
setShareDirList(ServerPropertiesUtil.getShareDirAllowed());
149149
setShareSecret(ServerPropertiesUtil.getShareSecret());
150+
151+
logger.info(String.format("/%s static context enabled=%s, baseDir=%s, dirList=%s, cacheCtl=%s, secret=%s",
152+
ServerPropertiesUtil.SHARE_DIR,
153+
shareEnabled,
154+
shareBaseDir,
155+
shareDirList,
156+
shareCacheCtl,
157+
(StringUtils.isNotBlank(shareSecret) ? "configured" : "not configured")));
150158
}
151159

152160
@Override

client/src/main/java/org/apache/cloudstack/ShareSignedUrlFilter.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,9 @@
3232

3333
import org.apache.cloudstack.utils.security.HMACSignUtil;
3434
import org.apache.commons.codec.DecoderException;
35-
import org.apache.commons.lang3.StringUtils;
3635

3736
/**
38-
* Optional HMAC token check: /share/...?...&exp=1699999999&sig=BASE64URL(HMACSHA256(path|exp))
37+
* HMAC token check: /share/...?...&exp=1699999999&sig=BASE64URL(HMACSHA256(path|exp))
3938
*/
4039
public class ShareSignedUrlFilter implements Filter {
4140
private final String secret;

client/src/test/java/org/apache/cloudstack/ShareSignedUrlFilterTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@
3131
import org.apache.cloudstack.utils.security.HMACSignUtil;
3232
import org.junit.Test;
3333

34+
/**
35+
* Unit tests for {@link ShareSignedUrlFilter}.
36+
*
37+
* Tests cover:
38+
* - invalid or missing `exp` parameter
39+
* - expired tokens outside the allowed time delta
40+
* - valid signatures when `exp` is within the allowed delta
41+
*/
3442
public class ShareSignedUrlFilterTest {
3543

3644
@Test
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
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.api;
19+
20+
import javax.inject.Inject;
21+
22+
import org.apache.cloudstack.acl.RoleType;
23+
import org.apache.cloudstack.api.APICommand;
24+
import org.apache.cloudstack.api.ApiCommandResourceType;
25+
import org.apache.cloudstack.api.ApiConstants;
26+
import org.apache.cloudstack.api.ApiErrorCode;
27+
import org.apache.cloudstack.api.BaseAsyncCmd;
28+
import org.apache.cloudstack.api.Parameter;
29+
import org.apache.cloudstack.api.ServerApiException;
30+
import org.apache.cloudstack.api.response.ExtensionResponse;
31+
import org.apache.cloudstack.api.response.ManagementServerResponse;
32+
import org.apache.cloudstack.api.response.SuccessResponse;
33+
import org.apache.cloudstack.extension.Extension;
34+
import org.apache.cloudstack.framework.extensions.api.response.DownloadExtensionResponse;
35+
import org.apache.cloudstack.framework.extensions.manager.ExtensionsManager;
36+
37+
import com.cloud.event.EventTypes;
38+
import com.cloud.exception.ConcurrentOperationException;
39+
import com.cloud.user.Account;
40+
41+
@APICommand(name = "downloadExtension",
42+
description = "To download the extension files as an archive",
43+
responseObject = SuccessResponse.class,
44+
responseHasSensitiveInfo = false,
45+
entityType = {Extension.class},
46+
authorized = {RoleType.Admin},
47+
since = "4.23.0")
48+
public class DownloadExtensionCmd extends BaseAsyncCmd {
49+
50+
@Inject
51+
ExtensionsManager extensionsManager;
52+
53+
/////////////////////////////////////////////////////
54+
//////////////// API parameters /////////////////////
55+
/////////////////////////////////////////////////////
56+
57+
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, required = true,
58+
entityType = ExtensionResponse.class, description = "ID of the extension")
59+
private Long id;
60+
61+
@Parameter(name = ApiConstants.MANAGEMENT_SERVER_ID, type = CommandType.UUID,
62+
entityType = ManagementServerResponse.class,
63+
description = "ID of the management server from which files are to be downloaded")
64+
private Long managementServerId;
65+
66+
/////////////////////////////////////////////////////
67+
/////////////////// Accessors ///////////////////////
68+
/////////////////////////////////////////////////////
69+
70+
public Long getId() {
71+
return id;
72+
}
73+
74+
public Long getManagementServerId() {
75+
return managementServerId;
76+
}
77+
78+
/////////////////////////////////////////////////////
79+
/////////////// API Implementation///////////////////
80+
/////////////////////////////////////////////////////
81+
82+
@Override
83+
public void execute() throws ServerApiException, ConcurrentOperationException {
84+
DownloadExtensionResponse response = extensionsManager.downloadExtension(this);
85+
if (response != null) {
86+
setResponseObject(response);
87+
} else {
88+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to download extension");
89+
}
90+
}
91+
92+
@Override
93+
public long getEntityOwnerId() {
94+
return Account.ACCOUNT_ID_SYSTEM;
95+
}
96+
97+
@Override
98+
public ApiCommandResourceType getApiResourceType() {
99+
return ApiCommandResourceType.Extension;
100+
}
101+
102+
@Override
103+
public Long getApiResourceId() {
104+
return getId();
105+
}
106+
107+
@Override
108+
public String getEventType() {
109+
return EventTypes.EVENT_EXTENSION_DOWNLOAD;
110+
}
111+
112+
@Override
113+
public String getEventDescription() {
114+
return "Download extension: " + getId();
115+
}
116+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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.api.response;
19+
20+
import org.apache.cloudstack.api.ApiConstants;
21+
import org.apache.cloudstack.api.response.ExtractResponse;
22+
23+
import com.cloud.serializer.Param;
24+
import com.google.gson.annotations.SerializedName;
25+
26+
public class DownloadExtensionResponse extends ExtractResponse {
27+
28+
@SerializedName(ApiConstants.MANAGEMENT_SERVER_ID)
29+
@Param(description = "the management server ID of the host")
30+
private String managementServerId;
31+
32+
@SerializedName(ApiConstants.MANAGEMENT_SERVER_NAME)
33+
@Param(description = "the management server name of the host")
34+
private String managementServerName;
35+
36+
public String getManagementServerId() {
37+
return managementServerId;
38+
}
39+
40+
public void setManagementServerId(String managementServerId) {
41+
this.managementServerId = managementServerId;
42+
}
43+
44+
public String getManagementServerName() {
45+
return managementServerName;
46+
}
47+
48+
public void setManagementServerName(String managementServerName) {
49+
this.managementServerName = managementServerName;
50+
}
51+
}
Lines changed: 27 additions & 0 deletions
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 DownloadExtensionFilesCommand extends ExtensionServerActionBaseCommand {
23+
24+
public DownloadExtensionFilesCommand(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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.apache.cloudstack.framework.extensions.api.CreateExtensionCmd;
3636
import org.apache.cloudstack.framework.extensions.api.DeleteCustomActionCmd;
3737
import org.apache.cloudstack.framework.extensions.api.DeleteExtensionCmd;
38+
import org.apache.cloudstack.framework.extensions.api.DownloadExtensionCmd;
3839
import org.apache.cloudstack.framework.extensions.api.ListCustomActionCmd;
3940
import org.apache.cloudstack.framework.extensions.api.ListExtensionsCmd;
4041
import org.apache.cloudstack.framework.extensions.api.RegisterExtensionCmd;
@@ -43,6 +44,7 @@
4344
import org.apache.cloudstack.framework.extensions.api.UnregisterExtensionCmd;
4445
import org.apache.cloudstack.framework.extensions.api.UpdateCustomActionCmd;
4546
import org.apache.cloudstack.framework.extensions.api.UpdateExtensionCmd;
47+
import org.apache.cloudstack.framework.extensions.api.response.DownloadExtensionResponse;
4648
import org.apache.cloudstack.framework.extensions.command.ExtensionServerActionBaseCommand;
4749

4850
import com.cloud.agent.api.Answer;
@@ -100,4 +102,6 @@ Pair<Boolean, ExtensionResourceMap> extensionResourceMapDetailsNeedUpdate(final
100102
Answer getInstanceConsole(VirtualMachine vm, Host host);
101103

102104
boolean syncExtension(SyncExtensionCmd cmd);
105+
106+
DownloadExtensionResponse downloadExtension(DownloadExtensionCmd cmd);
103107
}

0 commit comments

Comments
 (0)