Skip to content

Commit 5e2f02f

Browse files
Edison SuEdison Su
authored andcommitted
bug 13315: add httpproxy support in ssvm, only basic auth. User can add secstorage.proxy = http://username:password@hostname:port
status 13315: resolved fixed
1 parent 110f433 commit 5e2f02f

7 files changed

Lines changed: 129 additions & 8 deletions

File tree

api/src/com/cloud/agent/api/storage/DownloadCommand.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*/
1818
package com.cloud.agent.api.storage;
1919

20+
import java.net.URI;
21+
2022
import com.cloud.storage.Storage.ImageFormat;
2123
import com.cloud.template.VirtualMachineTemplate;
2224

@@ -43,10 +45,61 @@ public String getPassword() {
4345
return password;
4446
}
4547
}
48+
49+
public static class Proxy {
50+
private String _host;
51+
private int _port;
52+
private String _userName;
53+
private String _password;
54+
55+
public Proxy() {
56+
57+
}
58+
59+
public Proxy(String host, int port, String userName, String password) {
60+
this._host = host;
61+
this._port = port;
62+
this._userName = userName;
63+
this._password = password;
64+
}
65+
66+
public Proxy(URI uri) {
67+
this._host = uri.getHost();
68+
this._port = uri.getPort() == -1 ? 3128 : uri.getPort();
69+
String userInfo = uri.getUserInfo();
70+
if (userInfo != null) {
71+
String[] tokens = userInfo.split(":");
72+
if (tokens.length == 1) {
73+
this._userName = userInfo;
74+
this._password = "";
75+
} else if (tokens.length == 2) {
76+
this._userName = tokens[0];
77+
this._password = tokens[1];
78+
}
79+
}
80+
}
81+
82+
public String getHost() {
83+
return _host;
84+
}
85+
86+
public int getPort() {
87+
return _port;
88+
}
89+
90+
public String getUserName() {
91+
return _userName;
92+
}
93+
94+
public String getPassword() {
95+
return _password;
96+
}
97+
}
4698
private boolean hvm;
4799
private String description;
48100
private String checksum;
49101
private PasswordAuth auth;
102+
private Proxy _proxy;
50103
private Long maxDownloadSizeInBytes = null;
51104
private long id;
52105

@@ -128,6 +181,14 @@ public void setCreds(String userName, String passwd) {
128181
auth = new PasswordAuth(userName, passwd);
129182
}
130183

184+
public Proxy getProxy() {
185+
return _proxy;
186+
}
187+
188+
public void setProxy(Proxy proxy) {
189+
_proxy = proxy;
190+
}
191+
131192
public Long getMaxDownloadSizeInBytes() {
132193
return maxDownloadSizeInBytes;
133194
}

core/src/com/cloud/storage/template/DownloadManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import com.cloud.agent.api.storage.DownloadAnswer;
2424
import com.cloud.agent.api.storage.DownloadCommand;
25+
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
2526
import com.cloud.storage.VMTemplateHostVO;
2627
import com.cloud.storage.Storage.ImageFormat;
2728
import com.cloud.storage.resource.SecondaryStorageResource;
@@ -49,7 +50,7 @@ public interface DownloadManager extends Manager {
4950
* @param maxDownloadSizeInBytes (optional) max download size for the template, in bytes.
5051
* @return job-id that can be used to interrogate the status of the download.
5152
*/
52-
public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String userName, String passwd, long maxDownloadSizeInBytes);
53+
public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String userName, String passwd, long maxDownloadSizeInBytes, Proxy proxy);
5354

5455

5556
/**

core/src/com/cloud/storage/template/DownloadManagerImpl.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import com.cloud.agent.api.Answer;
4848
import com.cloud.agent.api.storage.DownloadAnswer;
4949
import com.cloud.agent.api.storage.DownloadCommand;
50+
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
5051
import com.cloud.agent.api.storage.DownloadProgressCommand;
5152
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
5253
import com.cloud.exception.InternalErrorException;
@@ -421,7 +422,7 @@ public Status getDownloadStatus(String jobId) {
421422
}
422423

423424
@Override
424-
public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String user, String password, long maxTemplateSizeInBytes) {
425+
public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String user, String password, long maxTemplateSizeInBytes, Proxy proxy) {
425426
UUID uuid = UUID.randomUUID();
426427
String jobId = uuid.toString();
427428
String tmpDir = installPathPrefix + File.separator + accountId + File.separator + id;
@@ -452,7 +453,7 @@ public String downloadPublicTemplate(long id, String url, String name, ImageForm
452453
TemplateDownloader td;
453454
if ((uri != null) && (uri.getScheme() != null)) {
454455
if (uri.getScheme().equalsIgnoreCase("http") || uri.getScheme().equalsIgnoreCase("https")) {
455-
td = new HttpTemplateDownloader(_storage, url, tmpDir, new Completion(jobId), maxTemplateSizeInBytes, user, password);
456+
td = new HttpTemplateDownloader(_storage, url, tmpDir, new Completion(jobId), maxTemplateSizeInBytes, user, password, proxy);
456457
} else if (uri.getScheme().equalsIgnoreCase("file")) {
457458
td = new LocalTemplateDownloader(_storage, url, tmpDir, maxTemplateSizeInBytes, new Completion(jobId));
458459
} else if (uri.getScheme().equalsIgnoreCase("scp")) {
@@ -582,7 +583,7 @@ public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, D
582583
}
583584

584585
long maxDownloadSizeInBytes = (cmd.getMaxDownloadSizeInBytes() == null) ? TemplateDownloader.DEFAULT_MAX_TEMPLATE_SIZE_IN_BYTES : (cmd.getMaxDownloadSizeInBytes());
585-
String jobId = downloadPublicTemplate(cmd.getId(), cmd.getUrl(), cmd.getName(), cmd.getFormat(), cmd.isHvm(), cmd.getAccountId(), cmd.getDescription(), cmd.getChecksum(), installPathPrefix, user, password, maxDownloadSizeInBytes);
586+
String jobId = downloadPublicTemplate(cmd.getId(), cmd.getUrl(), cmd.getName(), cmd.getFormat(), cmd.isHvm(), cmd.getAccountId(), cmd.getDescription(), cmd.getChecksum(), installPathPrefix, user, password, maxDownloadSizeInBytes, cmd.getProxy());
586587
sleep();
587588
if (jobId == null) {
588589
return new DownloadAnswer("Internal Error", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.apache.commons.httpclient.params.HttpMethodParams;
4646
import org.apache.log4j.Logger;
4747

48+
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
4849
import com.cloud.storage.StorageLayer;
4950
import com.cloud.utils.exception.CloudRuntimeException;
5051
import com.cloud.utils.Pair;
@@ -77,7 +78,7 @@ public class HttpTemplateDownloader implements TemplateDownloader {
7778

7879
private final HttpMethodRetryHandler myretryhandler;
7980

80-
public HttpTemplateDownloader (StorageLayer storageLayer, String downloadUrl, String toDir, DownloadCompleteCallback callback, long maxTemplateSizeInBytes, String user, String password) {
81+
public HttpTemplateDownloader (StorageLayer storageLayer, String downloadUrl, String toDir, DownloadCompleteCallback callback, long maxTemplateSizeInBytes, String user, String password, Proxy proxy) {
8182
this._storage = storageLayer;
8283
this.downloadUrl = downloadUrl;
8384
this.setToDir(toDir);
@@ -125,7 +126,14 @@ public boolean retryMethod(
125126

126127
toFile = f.getAbsolutePath();
127128
Pair<String, Integer> hostAndPort = validateUrl(downloadUrl);
128-
129+
130+
if (proxy != null) {
131+
client.getHostConfiguration().setProxy(proxy.getHost(), proxy.getPort());
132+
if (proxy.getUserName() != null) {
133+
Credentials proxyCreds = new UsernamePasswordCredentials(proxy.getUserName(), proxy.getPassword());
134+
client.getState().setProxyCredentials(AuthScope.ANY, proxyCreds);
135+
}
136+
}
129137
if ((user != null) && (password != null)) {
130138
client.getParams().setAuthenticationPreemptive(true);
131139
Credentials defaultcreds = new UsernamePasswordCredentials(user, password);
@@ -425,7 +433,7 @@ public static void main(String[] args) {
425433
// TODO Auto-generated catch block
426434
e.printStackTrace();
427435
}
428-
TemplateDownloader td = new HttpTemplateDownloader(null, url,"/tmp/mysql", null, TemplateDownloader.DEFAULT_MAX_TEMPLATE_SIZE_IN_BYTES, null, null);
436+
TemplateDownloader td = new HttpTemplateDownloader(null, url,"/tmp/mysql", null, TemplateDownloader.DEFAULT_MAX_TEMPLATE_SIZE_IN_BYTES, null, null, null);
429437
long bytes = td.download(true, null);
430438
if (bytes > 0) {
431439
System.out.println("Downloaded (" + bytes + " bytes)" + " in " + td.getDownloadTime()/1000 + " secs");

server/src/com/cloud/configuration/Config.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ public enum Config {
201201
SecStorageCapacityStandby("Advanced", AgentManager.class, Integer.class, "secstorage.capacity.standby", "10", "The minimal number of command execution sessions that system is able to serve immediately(standby capacity)", null),
202202
SecStorageSessionMax("Advanced", AgentManager.class, Integer.class, "secstorage.session.max", "50", "The max number of command execution sessions that a SSVM can handle", null),
203203
SecStorageCmdExecutionTimeMax("Advanced", AgentManager.class, Integer.class, "secstorage.cmd.execution.time.max", "30", "The max command execution time in minute", null),
204+
SecStorageProxy("Advanced", AgentManager.class, String.class, "secstorage.proxy", null, "http proxy used by ssvm, in http://username:password@proxyserver:port format", null),
205+
204206

205207
DirectAttachNetworkEnabled("Advanced", ManagementServer.class, Boolean.class, "direct.attach.network.externalIpAllocator.enabled", "false", "Direct-attach VMs using external DHCP server", "true,false"),
206208
DirectAttachNetworkExternalAPIURL("Advanced", ManagementServer.class, String.class, "direct.attach.network.externalIpAllocator.url", null, "Direct-attach VMs using external DHCP server (API url)", null),

server/src/com/cloud/storage/download/DownloadMonitorImpl.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*/
1818
package com.cloud.storage.download;
1919

20+
import java.net.URI;
21+
import java.net.URISyntaxException;
2022
import java.util.ArrayList;
2123
import java.util.Date;
2224
import java.util.HashSet;
@@ -36,12 +38,14 @@
3638
import com.cloud.agent.api.Command;
3739
import com.cloud.agent.api.storage.DeleteTemplateCommand;
3840
import com.cloud.agent.api.storage.DownloadCommand;
41+
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
3942
import com.cloud.agent.api.storage.DownloadProgressCommand;
4043
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
4144
import com.cloud.agent.api.storage.ListTemplateAnswer;
4245
import com.cloud.agent.api.storage.ListTemplateCommand;
4346
import com.cloud.agent.manager.Commands;
4447
import com.cloud.alert.AlertManager;
48+
import com.cloud.configuration.Config;
4549
import com.cloud.configuration.dao.ConfigurationDao;
4650
import com.cloud.dc.DataCenterVO;
4751
import com.cloud.dc.dao.ClusterDao;
@@ -146,6 +150,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
146150
private String _name;
147151
private Boolean _sslCopy = new Boolean(false);
148152
private String _copyAuthPasswd;
153+
private String _proxy = null;
149154
protected SearchBuilder<VMTemplateHostVO> ReadyTemplateStatesSearch;
150155

151156
Timer _timer;
@@ -162,6 +167,7 @@ public boolean configure(String name, Map<String, Object> params) {
162167
_name = name;
163168
final Map<String, String> configs = _configDao.getConfiguration("ManagementServer", params);
164169
_sslCopy = Boolean.parseBoolean(configs.get("secstorage.encrypt.copy"));
170+
_proxy = configs.get(Config.SecStorageProxy.key());
165171

166172
String cert = configs.get("secstorage.ssl.cert.domain");
167173
if (!"realhostip.com".equalsIgnoreCase(cert)) {
@@ -250,7 +256,7 @@ public boolean copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO d
250256
String sourceChecksum = _vmMgr.getChecksum(srcTmpltHost.getHostId(), srcTmpltHost.getInstallPath());
251257
DownloadCommand dcmd =
252258
new DownloadCommand(destServer.getStorageUrl(), url, template, TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd, maxTemplateSizeInBytes);
253-
259+
dcmd.setProxy(getHttpProxy());
254260
if (downloadJobExists) {
255261
dcmd = new DownloadProgressCommand(dcmd, destTmpltHost.getJobId(), RequestType.GET_OR_RESTART);
256262
}
@@ -335,6 +341,7 @@ private void downloadTemplateToStorage(VMTemplateVO template, HostVO sserver) {
335341
start();
336342
DownloadCommand dcmd =
337343
new DownloadCommand(secUrl, template, maxTemplateSizeInBytes);
344+
dcmd.setProxy(getHttpProxy());
338345
if (downloadJobExists) {
339346
dcmd = new DownloadProgressCommand(dcmd, vmTemplateHost.getJobId(), RequestType.GET_OR_RESTART);
340347
}
@@ -750,5 +757,18 @@ private Long getMaxTemplateSizeInBytes() {
750757
}
751758
}
752759

760+
private Proxy getHttpProxy() {
761+
if (_proxy == null) {
762+
return null;
763+
}
764+
try {
765+
URI uri = new URI(_proxy);
766+
Proxy prx = new Proxy(uri);
767+
return prx;
768+
} catch (URISyntaxException e) {
769+
return null;
770+
}
771+
}
772+
753773
}
754774

server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*/
1818
package com.cloud.storage.secondary;
1919

20+
import java.net.URI;
21+
import java.net.URISyntaxException;
2022
import java.util.ArrayList;
2123
import java.util.Collections;
2224
import java.util.Date;
@@ -225,6 +227,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
225227
private String _instance;
226228
private boolean _useLocalStorage;
227229
private boolean _useSSlCopy;
230+
private String _httpProxy;
228231
private String _allowedInternalSites;
229232
protected long _nodeId = ManagementServerNode.getManagementServerId();
230233

@@ -833,6 +836,31 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
833836
_loadScanner = new SystemVmLoadScanner<Long>(this);
834837
_loadScanner.initScan(STARTUP_DELAY, _capacityScanInterval);
835838
}
839+
840+
_httpProxy = configs.get(Config.SecStorageProxy.key());
841+
if (_httpProxy != null) {
842+
boolean valid = true;
843+
String errMsg = null;
844+
try {
845+
URI uri = new URI(_httpProxy);
846+
if (!"http".equalsIgnoreCase(uri.getScheme())) {
847+
errMsg = "Only support http proxy";
848+
valid = false;
849+
} else if (uri.getHost() == null) {
850+
errMsg = "host can not be null";
851+
valid = false;
852+
} else if (uri.getPort() == -1) {
853+
_httpProxy = _httpProxy + ":3128";
854+
}
855+
} catch (URISyntaxException e) {
856+
errMsg = e.toString();
857+
} finally {
858+
if (!valid) {
859+
s_logger.debug("ssvm http proxy " + _httpProxy + " is invalid: " + errMsg);
860+
throw new ConfigurationException("ssvm http proxy " + _httpProxy + "is invalid: " + errMsg);
861+
}
862+
}
863+
}
836864
if (s_logger.isInfoEnabled()) {
837865
s_logger.info("Secondary storage vm Manager is configured.");
838866
}

0 commit comments

Comments
 (0)