Skip to content

Commit 02305fb

Browse files
committed
Merge remote-tracking branch 'apache/4.19'
2 parents ed7389c + f2da882 commit 02305fb

73 files changed

Lines changed: 987 additions & 179 deletions

File tree

Some content is hidden

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

api/src/main/java/org/apache/cloudstack/api/command/user/volume/CheckAndRepairVolumeCmd.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.cloudstack.api.ServerApiException;
3030
import org.apache.cloudstack.api.response.VolumeResponse;
3131
import org.apache.cloudstack.context.CallContext;
32+
import org.apache.commons.lang3.EnumUtils;
3233

3334
import com.cloud.event.EventTypes;
3435
import com.cloud.exception.InvalidParameterValueException;
@@ -69,9 +70,9 @@ public Long getId() {
6970

7071
public String getRepair() {
7172
if (org.apache.commons.lang3.StringUtils.isNotEmpty(repair)) {
72-
RepairValues repairType = Enum.valueOf(RepairValues.class, repair.toUpperCase());
73+
RepairValues repairType = EnumUtils.getEnumIgnoreCase(RepairValues.class, repair);
7374
if (repairType == null) {
74-
throw new InvalidParameterValueException(String.format("Repair parameter can only take the following values: %s" + Arrays.toString(RepairValues.values())));
75+
throw new InvalidParameterValueException(String.format("Repair parameter can only take the following values: %s", Arrays.toString(RepairValues.values())));
7576
}
7677
return repair.toLowerCase();
7778
}

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import org.apache.cloudstack.api.EntityReference;
2525

2626
@EntityReference(value = UserData.class)
27-
public class UserDataResponse extends BaseResponseWithAnnotations {
27+
public class UserDataResponse extends BaseResponseWithAnnotations implements ControlledEntityResponse {
2828

2929
@SerializedName(ApiConstants.ID)
3030
@Param(description = "ID of the ssh keypair")
@@ -40,6 +40,14 @@ public class UserDataResponse extends BaseResponseWithAnnotations {
4040
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the owner of the userdata")
4141
private String accountName;
4242

43+
@SerializedName(ApiConstants.PROJECT_ID)
44+
@Param(description = "the project id of the userdata", since = "4.19.1")
45+
private String projectId;
46+
47+
@SerializedName(ApiConstants.PROJECT)
48+
@Param(description = "the project name of the userdata", since = "4.19.1")
49+
private String projectName;
50+
4351
@SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain id of the userdata owner")
4452
private String domainId;
4553

@@ -118,6 +126,16 @@ public void setAccountName(String accountName) {
118126
this.accountName = accountName;
119127
}
120128

129+
@Override
130+
public void setProjectId(String projectId) {
131+
this.projectId = projectId;
132+
}
133+
134+
@Override
135+
public void setProjectName(String projectName) {
136+
this.projectName = projectName;
137+
}
138+
121139
public String getDomainName() {
122140
return domain;
123141
}
Lines changed: 63 additions & 0 deletions
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.api.command.user.volume;
19+
20+
import com.cloud.exception.InvalidParameterValueException;
21+
import junit.framework.TestCase;
22+
import org.junit.After;
23+
import org.junit.Before;
24+
import org.junit.Test;
25+
import org.junit.runner.RunWith;
26+
import org.mockito.MockitoAnnotations;
27+
import org.mockito.junit.MockitoJUnitRunner;
28+
import org.springframework.test.util.ReflectionTestUtils;
29+
30+
@RunWith(MockitoJUnitRunner.class)
31+
public class CheckAndRepairVolumeCmdTest extends TestCase {
32+
private CheckAndRepairVolumeCmd checkAndRepairVolumeCmd;
33+
private AutoCloseable closeable;
34+
35+
@Before
36+
public void setup() {
37+
closeable = MockitoAnnotations.openMocks(this);
38+
checkAndRepairVolumeCmd = new CheckAndRepairVolumeCmd();
39+
}
40+
41+
@After
42+
public void tearDown() throws Exception {
43+
closeable.close();
44+
}
45+
46+
@Test
47+
public void testGetRepair() {
48+
ReflectionTestUtils.setField(checkAndRepairVolumeCmd, "repair", "all");
49+
assertEquals("all", checkAndRepairVolumeCmd.getRepair());
50+
51+
ReflectionTestUtils.setField(checkAndRepairVolumeCmd, "repair", "LEAKS");
52+
assertEquals("leaks", checkAndRepairVolumeCmd.getRepair());
53+
54+
ReflectionTestUtils.setField(checkAndRepairVolumeCmd, "repair", null);
55+
assertNull(checkAndRepairVolumeCmd.getRepair());
56+
}
57+
58+
@Test(expected = InvalidParameterValueException.class)
59+
public void testGetRepairInvalid() {
60+
ReflectionTestUtils.setField(checkAndRepairVolumeCmd, "repair", "RANDOM STRING");
61+
checkAndRepairVolumeCmd.getRepair();
62+
}
63+
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import org.apache.commons.daemon.DaemonContext;
3131
import org.apache.commons.lang3.StringUtils;
3232
import org.eclipse.jetty.jmx.MBeanContainer;
33-
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
3433
import org.eclipse.jetty.server.HttpConfiguration;
3534
import org.eclipse.jetty.server.HttpConnectionFactory;
3635
import org.eclipse.jetty.server.NCSARequestLog;
@@ -174,7 +173,7 @@ public void start() throws Exception {
174173

175174
// HTTP config
176175
final HttpConfiguration httpConfig = new HttpConfiguration();
177-
httpConfig.addCustomizer( new ForwardedRequestCustomizer() );
176+
// it would be nice to make this dynamic but we take care of this ourselves for now: httpConfig.addCustomizer( new ForwardedRequestCustomizer() );
178177
httpConfig.setSecureScheme("https");
179178
httpConfig.setSecurePort(httpsPort);
180179
httpConfig.setOutputBufferSize(32768);

core/src/main/java/com/cloud/storage/template/HttpTemplateDownloader.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.net.URI;
2929
import java.net.URISyntaxException;
3030
import java.util.Date;
31+
import java.util.List;
3132

3233
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
3334
import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType;
@@ -78,6 +79,7 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te
7879
private long maxTemplateSizeInBytes;
7980
private ResourceType resourceType = ResourceType.TEMPLATE;
8081
private final HttpMethodRetryHandler myretryhandler;
82+
private boolean followRedirects = false;
8183

8284
public HttpTemplateDownloader(StorageLayer storageLayer, String downloadUrl, String toDir, DownloadCompleteCallback callback, long maxTemplateSizeInBytes,
8385
String user, String password, Proxy proxy, ResourceType resourceType) {
@@ -109,7 +111,7 @@ public HttpTemplateDownloader(StorageLayer storageLayer, String downloadUrl, Str
109111
private GetMethod createRequest(String downloadUrl) {
110112
GetMethod request = new GetMethod(downloadUrl);
111113
request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler);
112-
request.setFollowRedirects(true);
114+
request.setFollowRedirects(followRedirects);
113115
return request;
114116
}
115117

@@ -335,6 +337,12 @@ private boolean checkServerResponse(long localFileSize) throws IOException {
335337
} else if ((responseCode = client.executeMethod(request)) != HttpStatus.SC_OK) {
336338
status = Status.UNRECOVERABLE_ERROR;
337339
errorString = " HTTP Server returned " + responseCode + " (expected 200 OK) ";
340+
if (List.of(HttpStatus.SC_MOVED_PERMANENTLY, HttpStatus.SC_MOVED_TEMPORARILY).contains(responseCode)
341+
&& !followRedirects) {
342+
errorString = String.format("Failed to download %s due to redirection, response code: %d",
343+
downloadUrl, responseCode);
344+
logger.error(errorString);
345+
}
338346
return true; //FIXME: retry?
339347
}
340348
return false;
@@ -536,4 +544,12 @@ public VerifyFormat invoke() {
536544
return this;
537545
}
538546
}
547+
548+
@Override
549+
public void setFollowRedirects(boolean followRedirects) {
550+
this.followRedirects = followRedirects;
551+
if (this.request != null) {
552+
this.request.setFollowRedirects(followRedirects);
553+
}
554+
}
539555
}

core/src/main/java/com/cloud/storage/template/MetalinkTemplateDownloader.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public MetalinkTemplateDownloader(StorageLayer storageLayer, String downloadUrl,
5858
protected GetMethod createRequest(String downloadUrl) {
5959
GetMethod request = new GetMethod(downloadUrl);
6060
request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler);
61-
request.setFollowRedirects(true);
61+
request.setFollowRedirects(followRedirects);
6262
if (!toFileSet) {
6363
String[] parts = downloadUrl.split("/");
6464
String filename = parts[parts.length - 1];
@@ -171,4 +171,12 @@ public Status getStatus() {
171171
public void setStatus(Status status) {
172172
this.status = status;
173173
}
174+
175+
@Override
176+
public void setFollowRedirects(boolean followRedirects) {
177+
super.setFollowRedirects(followRedirects);
178+
if (this.request != null) {
179+
this.request.setFollowRedirects(followRedirects);
180+
}
181+
}
174182
}

core/src/main/java/com/cloud/storage/template/S3TemplateDownloader.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType;
3535
import org.apache.commons.httpclient.Header;
3636
import org.apache.commons.httpclient.HttpClient;
37+
import org.apache.commons.httpclient.HttpStatus;
3738
import org.apache.commons.httpclient.URIException;
3839
import org.apache.commons.httpclient.methods.GetMethod;
3940
import org.apache.commons.httpclient.params.HttpMethodParams;
@@ -43,6 +44,7 @@
4344
import java.io.IOException;
4445
import java.io.InputStream;
4546
import java.util.Date;
47+
import java.util.List;
4648

4749
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
4850
import static java.util.Arrays.asList;
@@ -70,8 +72,8 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp
7072
private long downloadTime;
7173
private long totalBytes;
7274
private long maxTemplateSizeInByte;
73-
7475
private boolean resume = false;
76+
private boolean followRedirects = false;
7577

7678
public S3TemplateDownloader(S3TO s3TO, String downloadUrl, String installPath, DownloadCompleteCallback downloadCompleteCallback,
7779
long maxTemplateSizeInBytes, String username, String password, Proxy proxy, ResourceType resourceType) {
@@ -89,7 +91,7 @@ public S3TemplateDownloader(S3TO s3TO, String downloadUrl, String installPath, D
8991
this.getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, HTTPUtils.getHttpMethodRetryHandler(5));
9092

9193
// Follow redirects
92-
this.getMethod.setFollowRedirects(true);
94+
this.getMethod.setFollowRedirects(followRedirects);
9395

9496
// Set file extension.
9597
this.fileExtension = StringUtils.substringAfterLast(StringUtils.substringAfterLast(downloadUrl, "/"), ".");
@@ -122,10 +124,11 @@ public long download(boolean resume, DownloadCompleteCallback callback) {
122124
return 0;
123125
}
124126

125-
if (!HTTPUtils.verifyResponseCode(responseCode)) {
127+
boolean failedDueToRedirection = List.of(HttpStatus.SC_MOVED_PERMANENTLY,
128+
HttpStatus.SC_MOVED_TEMPORARILY).contains(responseCode) && !followRedirects;
129+
if (!HTTPUtils.verifyResponseCode(responseCode) || failedDueToRedirection) {
126130
errorString = "Response code for GetMethod of " + downloadUrl + " is incorrect, responseCode: " + responseCode;
127131
logger.warn(errorString);
128-
129132
status = Status.UNRECOVERABLE_ERROR;
130133
return 0;
131134
}
@@ -371,4 +374,12 @@ public long getTotalBytes() {
371374
public String getFileExtension() {
372375
return fileExtension;
373376
}
377+
378+
@Override
379+
public void setFollowRedirects(boolean followRedirects) {
380+
this.followRedirects = followRedirects;
381+
if (this.getMethod != null) {
382+
this.getMethod.setFollowRedirects(followRedirects);
383+
}
384+
}
374385
}

core/src/main/java/com/cloud/storage/template/SimpleHttpMultiFileDownloader.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.io.RandomAccessFile;
2626
import java.util.Date;
2727
import java.util.HashMap;
28+
import java.util.List;
2829
import java.util.Map;
2930

3031
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
@@ -71,6 +72,7 @@ public class SimpleHttpMultiFileDownloader extends ManagedContextRunnable implem
7172
private final HttpMethodRetryHandler retryHandler;
7273

7374
private HashMap<String, String> urlFileMap;
75+
private boolean followRedirects = false;
7476

7577
public SimpleHttpMultiFileDownloader(StorageLayer storageLayer, String[] downloadUrls, String toDir,
7678
DownloadCompleteCallback callback, long maxTemplateSizeInBytes,
@@ -92,7 +94,7 @@ public SimpleHttpMultiFileDownloader(StorageLayer storageLayer, String[] downloa
9294
private GetMethod createRequest(String downloadUrl) {
9395
GetMethod request = new GetMethod(downloadUrl);
9496
request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryHandler);
95-
request.setFollowRedirects(true);
97+
request.setFollowRedirects(followRedirects);
9698
return request;
9799
}
98100

@@ -168,7 +170,7 @@ private long downloadFile(String downloadUrl) {
168170
urlFileMap.put(downloadUrl, currentToFile);
169171
file = new File(currentToFile);
170172
long localFileSize = checkLocalFileSizeForResume(resume, file);
171-
if (checkServerResponse(localFileSize)) return 0;
173+
if (checkServerResponse(localFileSize, downloadUrl)) return 0;
172174
if (!tryAndGetRemoteSize()) return 0;
173175
if (!canHandleDownloadSize()) return 0;
174176
checkAndSetDownloadSize();
@@ -315,7 +317,7 @@ private boolean tryAndGetRemoteSize() {
315317
return true;
316318
}
317319

318-
private boolean checkServerResponse(long localFileSize) throws IOException {
320+
private boolean checkServerResponse(long localFileSize, String downloadUrl) throws IOException {
319321
int responseCode = 0;
320322

321323
if (localFileSize > 0) {
@@ -329,6 +331,12 @@ private boolean checkServerResponse(long localFileSize) throws IOException {
329331
} else if ((responseCode = client.executeMethod(request)) != HttpStatus.SC_OK) {
330332
currentStatus = Status.UNRECOVERABLE_ERROR;
331333
errorString = " HTTP Server returned " + responseCode + " (expected 200 OK) ";
334+
if (List.of(HttpStatus.SC_MOVED_PERMANENTLY, HttpStatus.SC_MOVED_TEMPORARILY).contains(responseCode)
335+
&& !followRedirects) {
336+
errorString = String.format("Failed to download %s due to redirection, response code: %d",
337+
downloadUrl, responseCode);
338+
logger.error(errorString);
339+
}
332340
return true; //FIXME: retry?
333341
}
334342
return false;
@@ -476,4 +484,12 @@ public DownloadCommand.ResourceType getResourceType() {
476484
public Map<String, String> getDownloadedFilesMap() {
477485
return urlFileMap;
478486
}
487+
488+
@Override
489+
public void setFollowRedirects(boolean followRedirects) {
490+
this.followRedirects = followRedirects;
491+
if (this.request != null) {
492+
this.request.setFollowRedirects(followRedirects);
493+
}
494+
}
479495
}

core/src/main/java/com/cloud/storage/template/TemplateDownloader.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,6 @@ enum Status {
9292
boolean isInited();
9393

9494
long getMaxTemplateSizeInBytes();
95+
96+
void setFollowRedirects(boolean followRedirects);
9597
}

core/src/main/java/com/cloud/storage/template/TemplateDownloaderBase.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public abstract class TemplateDownloaderBase extends ManagedContextRunnable impl
4141
protected long _start;
4242
protected StorageLayer _storage;
4343
protected boolean _inited = false;
44+
protected boolean followRedirects = false;
4445
private long maxTemplateSizeInBytes;
4546

4647
public TemplateDownloaderBase(StorageLayer storage, String downloadUrl, String toDir, long maxTemplateSizeInBytes, DownloadCompleteCallback callback) {
@@ -147,4 +148,9 @@ public void setResume(boolean resume) {
147148
public boolean isInited() {
148149
return _inited;
149150
}
151+
152+
@Override
153+
public void setFollowRedirects(boolean followRedirects) {
154+
this.followRedirects = followRedirects;
155+
}
150156
}

0 commit comments

Comments
 (0)