Package com.cloud.storage.template

Source Code of com.cloud.storage.template.UploadManagerImpl$UploadJob

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.storage.template;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.naming.ConfigurationException;

import org.apache.log4j.Logger;

import com.cloud.agent.api.storage.CreateEntityDownloadURLAnswer;
import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand;
import com.cloud.agent.api.storage.DeleteEntityDownloadURLAnswer;
import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand;
import com.cloud.agent.api.storage.UploadAnswer;
import com.cloud.agent.api.storage.UploadCommand;
import com.cloud.agent.api.storage.UploadProgressCommand;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.Upload;
import com.cloud.storage.UploadVO;
import com.cloud.storage.resource.SecondaryStorageResource;
import com.cloud.storage.template.TemplateUploader.Status;
import com.cloud.storage.template.TemplateUploader.UploadCompleteCallback;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;

public class UploadManagerImpl implements UploadManager {


   public class Completion implements UploadCompleteCallback {
        private final String jobId;

        public Completion(String jobId) {
            this.jobId = jobId;
        }

        @Override
        public void uploadComplete(Status status) {
            setUploadStatus(jobId, status);
        }
    }
  
   private static class UploadJob {
       private final TemplateUploader tu;
       private final String jobId;
       private final String name;
       private final ImageFormat format;
       private String tmpltPath;
       private String description;
       private String checksum;
       private Long accountId;
       private String installPathPrefix;
       private long templatesize;
       private long id;

       public UploadJob(TemplateUploader tu, String jobId, long id, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix) {
           super();
           this.tu = tu;
           this.jobId = jobId;
           this.name = name;
           this.format = format;
           this.accountId = accountId;
           this.description = descr;
           this.checksum = cksum;
           this.installPathPrefix = installPathPrefix;
           this.templatesize = 0;
           this.id = id;
       }

       public TemplateUploader getTd() {
           return tu;
       }

       public String getDescription() {
           return description;
       }

       public String getChecksum() {
           return checksum;
       }

       public UploadJob(TemplateUploader td, String jobId, UploadCommand cmd) {
           this.tu = td;
           this.jobId = jobId;
           this.name = cmd.getName();
           this.format = cmd.getFormat();          
       }

       public TemplateUploader getTemplateUploader() {
           return tu;
       }

       public String getJobId() {
           return jobId;
       }

       public String getTmpltName() {
           return name;
       }

       public ImageFormat getFormat() {
           return format;
       }

       public Long getAccountId() {
           return accountId;
       }

       public long getId() {
           return id;
       }

       public void setTmpltPath(String tmpltPath) {
           this.tmpltPath = tmpltPath;
       }

       public String getTmpltPath() {
           return tmpltPath;
       }

       public String getInstallPathPrefix() {
           return installPathPrefix;
       }

       public void cleanup() {
           if (tu != null) {
               String upldPath = tu.getUploadLocalPath();
               if (upldPath != null) {
                   File f = new File(upldPath);
                   f.delete();
               }
           }
       }

       public void setTemplatesize(long templatesize) {
           this.templatesize = templatesize;
       }

       public long getTemplatesize() {
           return templatesize;
       }
   }
       public static final Logger s_logger = Logger.getLogger(UploadManagerImpl.class);
       private ExecutorService threadPool;
       private final Map<String, UploadJob> jobs = new ConcurrentHashMap<String, UploadJob>();
       private String parentDir;
       private Adapters<Processor> _processors;
       private String publicTemplateRepo;
       private String extractMountPoint = "/mnt/SecStorage/extractmnt";
       private StorageLayer _storage;
       private int installTimeoutPerGig;
       private boolean _sslCopy;
       private String _name;
       private boolean hvm;
         
 
  @Override
  public String uploadPublicTemplate(long id, String url, String name,
      ImageFormat format, Long accountId, String descr,
      String cksum, String installPathPrefix, String userName,
      String passwd, long templateSizeInBytes) {   
   
        UUID uuid = UUID.randomUUID();
        String jobId = uuid.toString();

        String completePath = parentDir + File.separator + installPathPrefix;
        s_logger.debug("Starting upload from " + completePath);
       
        URI uri;
    try {
        uri = new URI(url);
    } catch (URISyntaxException e) {
        s_logger.error("URI is incorrect: " + url);
        throw new CloudRuntimeException("URI is incorrect: " + url);
    }
    TemplateUploader tu;
    if ((uri != null) && (uri.getScheme() != null)) {
        if (uri.getScheme().equalsIgnoreCase("ftp")) {
            tu = new FtpTemplateUploader(completePath, url, new Completion(jobId), templateSizeInBytes);                               
        } else {
          s_logger.error("Scheme is not supported " + url);
            throw new CloudRuntimeException("Scheme is not supported " + url);
        }
    } else {
        s_logger.error("Unable to download from URL: " + url);
        throw new CloudRuntimeException("Unable to download from URL: " + url);
    }
    UploadJob uj = new UploadJob(tu, jobId, id, name, format, hvm, accountId, descr, cksum, installPathPrefix);
    jobs.put(jobId, uj);
    threadPool.execute(tu);

    return jobId;
       
  }

  @Override
  public String getUploadError(String jobId) {
        UploadJob uj = jobs.get(jobId);
        if (uj != null) {
            return uj.getTemplateUploader().getUploadError();
        }
        return null;
  }

  @Override
  public int getUploadPct(String jobId) {
    UploadJob uj = jobs.get(jobId);
        if (uj != null) {
            return uj.getTemplateUploader().getUploadPercent();
        }
        return 0;
  }

  @Override
  public Status getUploadStatus(String jobId) {
        UploadJob job = jobs.get(jobId);
        if (job != null) {
            TemplateUploader tu = job.getTemplateUploader();
            if (tu != null) {
                return tu.getStatus();
            }
        }
        return Status.UNKNOWN;
  }
 
    public static UploadVO.Status convertStatus(Status tds) {
        switch (tds) {
        case ABORTED:
            return UploadVO.Status.NOT_UPLOADED;
        case UPLOAD_FINISHED:
            return UploadVO.Status.UPLOAD_IN_PROGRESS;
        case IN_PROGRESS:
            return UploadVO.Status.UPLOAD_IN_PROGRESS;
        case NOT_STARTED:
            return UploadVO.Status.NOT_UPLOADED;
        case RECOVERABLE_ERROR:
            return UploadVO.Status.NOT_UPLOADED;
        case UNKNOWN:
            return UploadVO.Status.UNKNOWN;
        case UNRECOVERABLE_ERROR:
            return UploadVO.Status.UPLOAD_ERROR;
        case POST_UPLOAD_FINISHED:
            return UploadVO.Status.UPLOADED;
        default:
            return UploadVO.Status.UNKNOWN;
        }
    }

    @Override
    public com.cloud.storage.UploadVO.Status getUploadStatus2(String jobId) {
        return convertStatus(getUploadStatus(jobId));
    }
  @Override
  public String getPublicTemplateRepo() {
    // TODO Auto-generated method stub
    return null;
  }

    private UploadAnswer handleUploadProgressCmd(UploadProgressCommand cmd) {
        String jobId = cmd.getJobId();
        UploadAnswer answer;
        UploadJob uj = null;
        if (jobId != null)
            uj = jobs.get(jobId);
        if (uj == null) {          
           return new UploadAnswer(null, 0, "Cannot find job", com.cloud.storage.UploadVO.Status.UNKNOWN, "", "", 0);           
        }
        TemplateUploader td = uj.getTemplateUploader();
        switch (cmd.getRequest()) {
        case GET_STATUS:
            break;
        case ABORT:
            td.stopUpload();
            sleep();
            break;
        /*case RESTART:
            td.stopUpload();
            sleep();
            threadPool.execute(td);
            break;*/
        case PURGE:
            td.stopUpload();
            answer = new UploadAnswer(jobId, getUploadPct(jobId), getUploadError(jobId), getUploadStatus2(jobId), getUploadLocalPath(jobId), getInstallPath(jobId), getUploadTemplateSize(jobId));
            jobs.remove(jobId);
            return answer;
        default:
            break; // TODO
        }
        return new UploadAnswer(jobId, getUploadPct(jobId), getUploadError(jobId), getUploadStatus2(jobId), getUploadLocalPath(jobId), getInstallPath(jobId),
                getUploadTemplateSize(jobId));
   
 
    @Override
    public UploadAnswer handleUploadCommand(SecondaryStorageResource resource, UploadCommand cmd) {
      s_logger.warn("Handling the upload " +cmd.getInstallPath() + " " + cmd.getId());
        if (cmd instanceof UploadProgressCommand) {
            return handleUploadProgressCmd((UploadProgressCommand) cmd);
        }

        String user = null;
        String password = null;
        String jobId = uploadPublicTemplate(cmd.getId(), cmd.getUrl(), cmd.getName(),
                          cmd.getFormat(), cmd.getAccountId(), cmd.getDescription(),
                          cmd.getChecksum(), cmd.getInstallPath(), user, password,
                          cmd.getTemplateSizeInBytes());
        sleep();
        if (jobId == null) {
            return new UploadAnswer(null, 0, "Internal Error", com.cloud.storage.UploadVO.Status.UPLOAD_ERROR, "", "", 0);
        }
        return new UploadAnswer(jobId, getUploadPct(jobId), getUploadError(jobId), getUploadStatus2(jobId), getUploadLocalPath(jobId), getInstallPath(jobId),
                getUploadTemplateSize(jobId));
    }
   
    @Override
    public CreateEntityDownloadURLAnswer handleCreateEntityURLCommand(CreateEntityDownloadURLCommand cmd){      
     
      boolean isApacheUp = checkAndStartApache();
      if (!isApacheUp){
        String errorString = "Error in starting Apache server ";
            s_logger.error(errorString);
            return new CreateEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE);
      }
        // Create the directory structure so that its visible under apache server root
      String extractDir = "/var/www/html/userdata/";
        Script command = new Script("mkdir", s_logger);
        command.add("-p");
        command.add(extractDir);
        String result = command.execute();
        if (result != null) {
            String errorString = "Error in creating directory =" + result;
            s_logger.error(errorString);
            return new CreateEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE);
        }
       
        // Create a random file under the directory for security reasons.
        String uuid = cmd.getExtractLinkUUID();
    command = new Script("touch", s_logger);
      command.add(extractDir + uuid);
      result = command.execute();
      if (result != null) {
        String errorString = "Error in creating file " +uuid+ " ,error: " + result;
        s_logger.warn(errorString);
        return new CreateEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE);
      }

       
        // Create a symbolic link from the actual directory to the template location. The entity would be directly visible under /var/www/html/userdata/cmd.getInstallPath();
        command = new Script("/bin/bash", s_logger);
        command.add("-c");
        command.add("ln -sf /mnt/SecStorage/" + cmd.getParent() + File.separator + cmd.getInstallPath() + " " + extractDir + uuid);
        result = command.execute();
        if (result != null) {
            String errorString = "Error in linking  err=" + result;
            s_logger.error(errorString);
            return new CreateEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE);
        }
       
        return new CreateEntityDownloadURLAnswer("", CreateEntityDownloadURLAnswer.RESULT_SUCCESS);
       
    }
   
    @Override
    public DeleteEntityDownloadURLAnswer handleDeleteEntityDownloadURLCommand(DeleteEntityDownloadURLCommand cmd){

        //Delete the soft link. Example path = volumes/8/74eeb2c6-8ab1-4357-841f-2e9d06d1f360.vhd
        s_logger.warn("handleDeleteEntityDownloadURLCommand Path:"+cmd.getPath() + " Type:" +cmd.getType().toString());
        String path = cmd.getPath();
        Script command = new Script("/bin/bash", s_logger);
        command.add("-c");
       
    //We just need to remove the UUID.vhd
        String extractUrl = cmd.getExtractUrl();
        command.add("unlink /var/www/html/userdata/" +extractUrl.substring(extractUrl.lastIndexOf(File.separator) + 1));
        String result = command.execute();
        if (result != null) {
            String errorString = "Error in deleting =" + result;
            s_logger.warn(errorString);
            return new DeleteEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE);
        }
       
        // If its a volume also delete the Hard link since it was created only for the purpose of download.
        if(cmd.getType() == Upload.Type.VOLUME){
            command = new Script("/bin/bash", s_logger);
            command.add("-c");
            command.add("rm -f /mnt/SecStorage/" + cmd.getParentPath() +File.separator+ path);
            s_logger.warn(" " +parentDir +File.separator+ path);
            result = command.execute();
            if (result != null) {
                String errorString = "Error in linking  err=" + result;
                s_logger.warn(errorString);
                return new DeleteEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE);
            }
        }
       
        return new DeleteEntityDownloadURLAnswer("", CreateEntityDownloadURLAnswer.RESULT_SUCCESS);
    }

  private String getInstallPath(String jobId) {
    // TODO Auto-generated method stub
    return null;
  }

  private String getUploadLocalPath(String jobId) {
    // TODO Auto-generated method stub
    return null;
  }

  private long getUploadTemplateSize(String jobId){
    UploadJob uj = jobs.get(jobId);
        if (uj != null) {
            return uj.getTemplatesize();
        }
        return 0;
  }

  @Override
  public boolean configure(String name, Map<String, Object> params)
      throws ConfigurationException {
        _name = name;

        String value = null;

        _storage = (StorageLayer) params.get(StorageLayer.InstanceConfigKey);
        if (_storage == null) {
            value = (String) params.get(StorageLayer.ClassConfigKey);
            if (value == null) {
                throw new ConfigurationException("Unable to find the storage layer");
            }

            Class<StorageLayer> clazz;
            try {
                clazz = (Class<StorageLayer>) Class.forName(value);
            } catch (ClassNotFoundException e) {
                throw new ConfigurationException("Unable to instantiate " + value);
            }
            _storage = ComponentLocator.inject(clazz);
        }
        String useSsl = (String)params.get("sslcopy");
        if (useSsl != null) {
          _sslCopy = Boolean.parseBoolean(useSsl);
         
        }
        String inSystemVM = (String)params.get("secondary.storage.vm");
        if (inSystemVM != null && "true".equalsIgnoreCase(inSystemVM)) {
          s_logger.info("UploadManager: starting additional services since we are inside system vm");
          startAdditionalServices();
          //blockOutgoingOnPrivate();
        }

        value = (String) params.get("install.timeout.pergig");
        this.installTimeoutPerGig = NumbersUtil.parseInt(value, 15 * 60) * 1000;

        value = (String) params.get("install.numthreads");
        final int numInstallThreads = NumbersUtil.parseInt(value, 10);       

        String scriptsDir = (String) params.get("template.scripts.dir");
        if (scriptsDir == null) {
            scriptsDir = "scripts/storage/secondary";
        }

        // Add more processors here.
        threadPool = Executors.newFixedThreadPool(numInstallThreads);

        return true;
  }
 
  private void startAdditionalServices() {
     
   
    Script command = new Script("rm", s_logger);
    command.add("-rf");
      command.add(extractMountPoint);
      String result = command.execute();
      if (result != null) {
        s_logger.warn("Error in creating file " +extractMountPoint+ " ,error: " + result );
        return;
      }
     
    command = new Script("touch", s_logger);
      command.add(extractMountPoint);
      result = command.execute();
      if (result != null) {
        s_logger.warn("Error in creating file " +extractMountPoint+ " ,error: " + result );
        return;
      }
     
      command = new Script("/bin/bash", s_logger);
    command.add("-c");
      command.add("ln -sf " + parentDir + " " +extractMountPoint);
      result = command.execute();
      if (result != null) {
        s_logger.warn("Error in linking  err=" + result );
        return;
      }
   
  }

  @Override
  public String getName() {
    return _name;
  }

  @Override
  public boolean start() {
    return true;
  }

  @Override
  public boolean stop() {
    return true;
  }

    /**
     * Get notified of change of job status. Executed in context of uploader thread
     *
     * @param jobId
     *            the id of the job
     * @param status
     *            the status of the job
     */
    public void setUploadStatus(String jobId, Status status) {
        UploadJob uj = jobs.get(jobId);
        if (uj == null) {
            s_logger.warn("setUploadStatus for jobId: " + jobId + ", status=" + status + " no job found");
            return;
        }
        TemplateUploader tu = uj.getTemplateUploader();
        s_logger.warn("Upload Completion for jobId: " + jobId + ", status=" + status);
        s_logger.warn("UploadedBytes=" + tu.getUploadedBytes() + ", error=" + tu.getUploadError() + ", pct=" + tu.getUploadPercent());

        switch (status) {
        case ABORTED:
        case NOT_STARTED:
        case UNRECOVERABLE_ERROR:
            // Delete the entity only if its a volume. TO DO - find a better way of finding it a volume.
            if(uj.getTemplateUploader().getUploadLocalPath().indexOf("volume") > -1){
                uj.cleanup();
            }
            break;
        case UNKNOWN:
            return;
        case IN_PROGRESS:
            s_logger.info("Resuming jobId: " + jobId + ", status=" + status);
            tu.setResume(true);
            threadPool.execute(tu);
            break;
        case RECOVERABLE_ERROR:
            threadPool.execute(tu);
            break;
        case UPLOAD_FINISHED:
            tu.setUploadError("Upload success, starting install ");
            String result = postUpload(jobId);
            if (result != null) {
                s_logger.error("Failed post upload script: " + result);
                tu.setStatus(Status.UNRECOVERABLE_ERROR);
                tu.setUploadError("Failed post upload script: " + result);
            } else {
              s_logger.warn("Upload completed successfully at " + new SimpleDateFormat().format(new Date()));
                tu.setStatus(Status.POST_UPLOAD_FINISHED);
                tu.setUploadError("Upload completed successfully at " + new SimpleDateFormat().format(new Date()));
            }
            // Delete the entity only if its a volume. TO DO - find a better way of finding it a volume.
            if(uj.getTemplateUploader().getUploadLocalPath().indexOf("volume") > -1){
                uj.cleanup();
            }
            break;
        default:
            break;
        }
    }

  private String postUpload(String jobId) {
    return null;
  }

    private void sleep() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // ignore
        }
    }

  private boolean checkAndStartApache() {
           
      //Check whether the Apache server is running
      Script command = new Script("/bin/bash", s_logger);
      command.add("-c");
      command.add("if [ -d /etc/apache2 ] ; then service apache2 status | grep pid; else service httpd status | grep pid; fi ");
      String result = command.execute();
     
      //Apache Server is not running. Try to start it.
      if (result != null) {            
       
        /*s_logger.warn("Apache server not running, trying to start it");
      String port = Integer.toString(TemplateConstants.DEFAULT_TMPLT_COPY_PORT);
      String intf = TemplateConstants.DEFAULT_TMPLT_COPY_INTF;
     
      command = new Script("/bin/bash", s_logger);
      command.add("-c");
      command.add("iptables -D INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j DROP;" +
                "iptables -D INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j HTTP;" +
                "iptables -D INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j DROP;" +
                "iptables -D INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j HTTP;" +
                "iptables -F HTTP;" +
                "iptables -X HTTP;" +
                "iptables -N HTTP;" +
              "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j DROP;" +
              "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j DROP;" +
              "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j HTTP;" +
                  "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j HTTP;");
   
      result = command.execute();
      if (result != null) {
        s_logger.warn("Error in opening up httpd port err=" + result );
        return false;
      }*/     
     
      command = new Script("/bin/bash", s_logger);
      command.add("-c");
      command.add("if [ -d /etc/apache2 ] ; then service apache2 start; else service httpd start; fi ");
      result = command.execute();
      if (result != null) {
        s_logger.warn("Error in starting httpd service err=" + result );
        return false;
      }
      }
     
    return true;
  }
}    
TOP

Related Classes of com.cloud.storage.template.UploadManagerImpl$UploadJob

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.