/** * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. * * This software is licensed under the GNU General Public License v3 or later. * * It is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package com.cloud.storage.template; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import org.apache.log4j.Logger; import com.cloud.storage.StorageLayer; import com.cloud.utils.exception.CloudRuntimeException; import com.trilead.ssh2.SCPClient; public class ScpTemplateDownloader extends TemplateDownloaderBase implements TemplateDownloader { private static final Logger s_logger = Logger.getLogger(ScpTemplateDownloader.class); public ScpTemplateDownloader(StorageLayer storageLayer, String downloadUrl, String toDir, long maxTemplateSizeInBytes, DownloadCompleteCallback callback) { super(storageLayer, downloadUrl, toDir, maxTemplateSizeInBytes, callback); URI uri; try { uri = new URI(_downloadUrl); } catch (URISyntaxException e) { s_logger.warn("URI syntax error: " + _downloadUrl); _status = Status.UNRECOVERABLE_ERROR; return; } String path = uri.getPath(); String filename = path.substring(path.lastIndexOf("/") + 1); _toFile = toDir + File.separator + filename; } @Override public long download(boolean resume, DownloadCompleteCallback callback) { if (_status == Status.ABORTED || _status == Status.UNRECOVERABLE_ERROR || _status == Status.DOWNLOAD_FINISHED) { return 0; } _resume = resume; _start = System.currentTimeMillis(); URI uri; try { uri = new URI(_downloadUrl); } catch (URISyntaxException e1) { _status = Status.UNRECOVERABLE_ERROR; return 0; } String username = uri.getUserInfo(); String queries = uri.getQuery(); String password = null; if (queries != null) { String[] qs = queries.split("&"); for (String q : qs) { String[] tokens = q.split("="); if (tokens[0].equalsIgnoreCase("password")) { password = tokens[1]; break; } } } int port = uri.getPort(); if (port == -1) { port = 22; } long length = 0; File file = new File(_toFile); com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(uri.getHost(), port); try { if (_storage != null) { file.createNewFile(); _storage.setWorldReadableAndWriteable(file); } sshConnection.connect(null, 60000, 60000); if (!sshConnection.authenticateWithPassword(username, password)) { throw new CloudRuntimeException("Unable to authenticate"); } SCPClient scp = new SCPClient(sshConnection); String src = uri.getPath(); _status = Status.IN_PROGRESS; scp.get(src, _toDir); if (!file.exists()) { _status = Status.UNRECOVERABLE_ERROR; s_logger.debug("unable to scp the file " + _downloadUrl); return 0; } _status = Status.DOWNLOAD_FINISHED; _totalBytes = file.length(); String downloaded = "(download complete)"; _errorString = "Downloaded " + _remoteSize + " bytes " + downloaded; _downloadTime += System.currentTimeMillis() - _start; return _totalBytes; } catch (Exception e) { s_logger.warn("Unable to download " + _downloadUrl, e); _status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; _errorString = e.getMessage(); return 0; } finally { sshConnection.close(); if (_status == Status.UNRECOVERABLE_ERROR && file.exists()) { file.delete(); } if (callback != null) { callback.downloadComplete(_status); } } } @Override public int getDownloadPercent() { if (_status == Status.DOWNLOAD_FINISHED) { return 100; } else if (_status == Status.IN_PROGRESS) { return 50; } else { return 0; } } public static void main(String[] args) { String url ="scp://root@sol10-2/root/alex/agent.zip?password=password"; TemplateDownloader td = new ScpTemplateDownloader(null, url,"/tmp/mysql", TemplateDownloader.DEFAULT_MAX_TEMPLATE_SIZE_IN_BYTES, null); long bytes = td.download(true, null); if (bytes > 0) { System.out.println("Downloaded (" + bytes + " bytes)" + " in " + td.getDownloadTime()/1000 + " secs"); } else { System.out.println("Failed download"); } } }