bug 9397 : CreateTemplate - generate MD5 checksum of the template. The code will calculate the checksum after the template has been created in the secondary storage. This code would be executed by ssvm. This would be agnostic of the way the template was created (not hypervisor specific).

This commit is contained in:
nit 2011-05-10 12:24:18 +05:30
parent 029a9e6a8a
commit d91999533b
5 changed files with 131 additions and 2 deletions

View File

@ -0,0 +1,42 @@
/**
* 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.agent.api;
public class ComputeChecksumCommand extends Command {
public ComputeChecksumCommand() {
super();
}
private String templatePath;
public ComputeChecksumCommand(String templatePath) {
super();
this.templatePath = templatePath;
}
public String getTemplatePath() {
return templatePath;
}
@Override
public boolean executeInSequence() {
return true;
}
}

View File

@ -297,6 +297,10 @@ public class VMTemplateVO implements VirtualMachineTemplate {
return checksum;
}
public void setChecksum(String checksum) {
this.checksum = checksum;
}
@Override
public String getDisplayText() {
return displayText;

View File

@ -18,8 +18,14 @@
package com.cloud.storage.resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -34,6 +40,7 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckHealthAnswer;
import com.cloud.agent.api.CheckHealthCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.ComputeChecksumCommand;
import com.cloud.agent.api.GetStorageStatsAnswer;
import com.cloud.agent.api.GetStorageStatsCommand;
import com.cloud.agent.api.PingCommand;
@ -138,11 +145,71 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return execute((SecStorageFirewallCfgCommand)cmd);
} else if (cmd instanceof SecStorageSetupCommand){
return execute((SecStorageSetupCommand)cmd);
} else if (cmd instanceof ComputeChecksumCommand){
return execute((ComputeChecksumCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
private Answer execute(ComputeChecksumCommand cmd) {
String relativeTemplatePath = cmd.getTemplatePath();
String parent = _parent;
if (relativeTemplatePath.startsWith(File.separator)) {
relativeTemplatePath = relativeTemplatePath.substring(1);
}
if (!parent.endsWith(File.separator)) {
parent += File.separator;
}
String absoluteTemplatePath = parent + relativeTemplatePath;
MessageDigest digest;
String checksum = null;
File f = new File(absoluteTemplatePath);
InputStream is = null;
byte[] buffer = new byte[8192];
int read = 0;
if(s_logger.isDebugEnabled()){
s_logger.debug("parent path " +parent+ " relative template path " +relativeTemplatePath );
}
try {
digest = MessageDigest.getInstance("MD5");
is = new FileInputStream(f);
while( (read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
byte[] md5sum = digest.digest();
BigInteger bigInt = new BigInteger(1, md5sum);
checksum = bigInt.toString(16);
if(s_logger.isDebugEnabled()){
s_logger.debug("Successfully calculated checksum for file " +absoluteTemplatePath+ " - " +checksum );
}
}catch(IOException e) {
String logMsg = "Unable to process file for MD5 - " + absoluteTemplatePath;
s_logger.error(logMsg);
return new Answer(cmd, false, checksum);
}catch (NoSuchAlgorithmException e) {
return new Answer(cmd, false, checksum);
}
finally {
try {
is.close();
} catch (IOException e) {
if(s_logger.isDebugEnabled()){
s_logger.debug("Could not close the file " +absoluteTemplatePath);
}
return new Answer(cmd, false, checksum);
}
}
return new Answer(cmd, true, checksum);
}
private Answer execute(SecStorageSetupCommand cmd) {
if (!_inSystemVM){
return new Answer(cmd, true, null);

View File

@ -1735,6 +1735,7 @@ public class ApiResponseHelper implements ResponseGenerator {
templateResponse.setZoneId(destZoneId);
templateResponse.setZoneName(ApiDBUtils.findZoneById(destZoneId).getName());
templateResponse.setSourceTemplateId(template.getSourceTemplateId());
templateResponse.setChecksum(template.getChecksum());
GuestOS os = ApiDBUtils.findGuestOSById(template.getGuestOSId());
if (os != null) {
@ -1901,6 +1902,7 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setPublic(template.isPublicTemplate());
response.setPasswordEnabled(template.getEnablePassword());
response.setCrossZones(template.isCrossZones());
response.setChecksum(template.getChecksum());
VolumeVO volume = null;
if (snapshotId != null) {

View File

@ -37,6 +37,7 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.AttachIsoCommand;
import com.cloud.agent.api.AttachVolumeAnswer;
import com.cloud.agent.api.AttachVolumeCommand;
import com.cloud.agent.api.ComputeChecksumCommand;
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
import com.cloud.agent.api.GetVmStatsAnswer;
@ -94,6 +95,7 @@ import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
@ -1547,7 +1549,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
// Specify RAW format makes it unusable for snapshots.
privateTemplate.setFormat(ImageFormat.RAW);
}
String checkSum = getChecksum(secondaryStorageHost.getId(), answer.getPath());
privateTemplate.setChecksum(checkSum);
_templateDao.update(templateId, privateTemplate);
// add template zone ref for this template
@ -1581,7 +1584,18 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
return privateTemplate;
}
private String getChecksum(Long hostId, String templatePath){
Answer answer;
try {
answer = _agentMgr.send(hostId, new ComputeChecksumCommand(templatePath));
return answer.getDetails();
} catch (AgentUnavailableException e) {
s_logger.error("Unable to send ComputeChecksumCommand to " + hostId, e);
} catch (OperationTimedoutException e) {
s_logger.error("Unable to send ComputeChecksumCommand to " + hostId, e);
}
return null;
}
// used for vm transitioning to error state
private void updateVmStateForFailedVmCreation(Long vmId) {
UserVmVO vm = _vmDao.findById(vmId);