mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	CLOUDSTACK-1158: Wrap qemu-img into it's own util
Signed-off-by: Edison Su <sudison@gmail.com>
This commit is contained in:
		
							parent
							
								
									aa79ccf985
								
							
						
					
					
						commit
						ea0daeaee3
					
				| @ -67,6 +67,16 @@ | |||||||
|             </execution> |             </execution> | ||||||
|           </executions> |           </executions> | ||||||
|         </plugin> |         </plugin> | ||||||
|  |         <plugin> | ||||||
|  |         <groupId>org.apache.maven.plugins</groupId> | ||||||
|  |         <artifactId>maven-surefire-plugin</artifactId> | ||||||
|  |         <version>2.14</version> | ||||||
|  |         <configuration> | ||||||
|  |           <excludes> | ||||||
|  |             <exclude>**/Qemu*.java</exclude> | ||||||
|  |           </excludes> | ||||||
|  |         </configuration> | ||||||
|  |       </plugin> | ||||||
|     </plugins> |     </plugins> | ||||||
|   </build> |   </build> | ||||||
| </project> | </project> | ||||||
|  | |||||||
| @ -57,6 +57,10 @@ import javax.ejb.Local; | |||||||
| import javax.naming.ConfigurationException; | import javax.naming.ConfigurationException; | ||||||
| 
 | 
 | ||||||
| import org.apache.log4j.Logger; | import org.apache.log4j.Logger; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImgFile; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImgException; | ||||||
| import org.libvirt.Connect; | import org.libvirt.Connect; | ||||||
| import org.libvirt.Domain; | import org.libvirt.Domain; | ||||||
| import org.libvirt.DomainInfo; | import org.libvirt.DomainInfo; | ||||||
| @ -193,7 +197,6 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef; | |||||||
| import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef; | import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef; | ||||||
| import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy; | import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy; | ||||||
| import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk; | import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk; | ||||||
| import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk.PhysicalDiskFormat; |  | ||||||
| import com.cloud.hypervisor.kvm.storage.KVMStoragePool; | import com.cloud.hypervisor.kvm.storage.KVMStoragePool; | ||||||
| import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager; | import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager; | ||||||
| import com.cloud.network.Networks.BroadcastDomainType; | import com.cloud.network.Networks.BroadcastDomainType; | ||||||
| @ -1418,12 +1421,12 @@ ServerResource { | |||||||
|         StoragePoolType poolType = pool.getType(); |         StoragePoolType poolType = pool.getType(); | ||||||
|         PhysicalDiskFormat volFormat = vol.getFormat(); |         PhysicalDiskFormat volFormat = vol.getFormat(); | ||||||
|           |           | ||||||
|         if(pool.getType() == StoragePoolType.CLVM && volFormat == KVMPhysicalDisk.PhysicalDiskFormat.RAW) { |         if(pool.getType() == StoragePoolType.CLVM && volFormat == PhysicalDiskFormat.RAW) { | ||||||
|             return "CLVM"; |             return "CLVM"; | ||||||
|         } else if ((poolType == StoragePoolType.NetworkFilesystem |         } else if ((poolType == StoragePoolType.NetworkFilesystem | ||||||
|                   || poolType == StoragePoolType.SharedMountPoint |                   || poolType == StoragePoolType.SharedMountPoint | ||||||
|                   || poolType == StoragePoolType.Filesystem) |                   || poolType == StoragePoolType.Filesystem) | ||||||
|                   && volFormat == KVMPhysicalDisk.PhysicalDiskFormat.QCOW2 ) { |                   && volFormat == PhysicalDiskFormat.QCOW2 ) { | ||||||
|             return "QCOW2"; |             return "QCOW2"; | ||||||
|         } |         } | ||||||
|         return null; |         return null; | ||||||
| @ -2230,14 +2233,25 @@ ServerResource { | |||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + cmd.getUniqueName()); |                 s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + cmd.getUniqueName()); | ||||||
|                 Script.runSimpleBashScript("qemu-img convert" | 
 | ||||||
|                         + " -f raw -O qcow2 " |                 QemuImgFile srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(), | ||||||
|                         + KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(), |  | ||||||
|                                 primary.getSourcePort(), |                                 primary.getSourcePort(), | ||||||
|                                 primary.getAuthUserName(), |                                 primary.getAuthUserName(), | ||||||
|                                 primary.getAuthSecret(), |                                 primary.getAuthSecret(), | ||||||
|                                 disk.getPath()) |                                 disk.getPath())); | ||||||
|                                 + " " + tmpltPath + "/" + cmd.getUniqueName() + ".qcow2"); |                 srcFile.setFormat(PhysicalDiskFormat.RAW); | ||||||
|  | 
 | ||||||
|  |                 QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + cmd.getUniqueName() + ".qcow2"); | ||||||
|  |                 destFile.setFormat(PhysicalDiskFormat.QCOW2); | ||||||
|  | 
 | ||||||
|  |                 QemuImg q = new QemuImg(); | ||||||
|  |                 try { | ||||||
|  |                     q.convert(srcFile, destFile); | ||||||
|  |                 } catch (QemuImgException e) { | ||||||
|  |                     s_logger.error("Failed to create new template while converting " | ||||||
|  |                                     + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage()); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 File templateProp = new File(tmpltPath + "/template.properties"); |                 File templateProp = new File(tmpltPath + "/template.properties"); | ||||||
|                 if (!templateProp.exists()) { |                 if (!templateProp.exists()) { | ||||||
|                     templateProp.createNewFile(); |                     templateProp.createNewFile(); | ||||||
|  | |||||||
| @ -25,6 +25,7 @@ import javax.xml.parsers.DocumentBuilder; | |||||||
| import javax.xml.parsers.DocumentBuilderFactory; | import javax.xml.parsers.DocumentBuilderFactory; | ||||||
| import javax.xml.parsers.ParserConfigurationException; | import javax.xml.parsers.ParserConfigurationException; | ||||||
| 
 | 
 | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
| import org.apache.log4j.Logger; | import org.apache.log4j.Logger; | ||||||
| import org.w3c.dom.Document; | import org.w3c.dom.Document; | ||||||
| import org.w3c.dom.Element; | import org.w3c.dom.Element; | ||||||
|  | |||||||
| @ -15,25 +15,13 @@ | |||||||
| // specific language governing permissions and limitations | // specific language governing permissions and limitations | ||||||
| // under the License. | // under the License. | ||||||
| package com.cloud.hypervisor.kvm.storage; | package com.cloud.hypervisor.kvm.storage; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
| 
 | 
 | ||||||
| public class KVMPhysicalDisk { | public class KVMPhysicalDisk { | ||||||
|     private String path; |     private String path; | ||||||
|     private String name; |     private String name; | ||||||
|     private KVMStoragePool pool; |     private KVMStoragePool pool; | ||||||
| 
 | 
 | ||||||
|     public static enum PhysicalDiskFormat { |  | ||||||
|         RAW("raw"), QCOW2("qcow2"), TAR("tar"), DIR("dir"); |  | ||||||
|         String format; |  | ||||||
| 
 |  | ||||||
|         private PhysicalDiskFormat(String format) { |  | ||||||
|             this.format = format; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public String toString() { |  | ||||||
|             return this.format; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public static String RBDStringBuilder(String monHost, int monPort, |     public static String RBDStringBuilder(String monHost, int monPort, | ||||||
|                             String authUserName, String authSecret, String image) { |                             String authUserName, String authSecret, String image) { | ||||||
|         String rbdOpts; |         String rbdOpts; | ||||||
|  | |||||||
| @ -18,7 +18,7 @@ package com.cloud.hypervisor.kvm.storage; | |||||||
| 
 | 
 | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk.PhysicalDiskFormat; | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
| import com.cloud.storage.Storage.StoragePoolType; | import com.cloud.storage.Storage.StoragePoolType; | ||||||
| 
 | 
 | ||||||
| public interface KVMStoragePool { | public interface KVMStoragePool { | ||||||
|  | |||||||
| @ -23,10 +23,11 @@ import java.util.concurrent.ConcurrentHashMap; | |||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
| 
 | 
 | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
|  | 
 | ||||||
| import com.cloud.hypervisor.kvm.resource.KVMHABase; | import com.cloud.hypervisor.kvm.resource.KVMHABase; | ||||||
| import com.cloud.hypervisor.kvm.resource.KVMHABase.PoolType; | import com.cloud.hypervisor.kvm.resource.KVMHABase.PoolType; | ||||||
| import com.cloud.hypervisor.kvm.resource.KVMHAMonitor; | import com.cloud.hypervisor.kvm.resource.KVMHAMonitor; | ||||||
| import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk.PhysicalDiskFormat; |  | ||||||
| import com.cloud.storage.Storage.StoragePoolType; | import com.cloud.storage.Storage.StoragePoolType; | ||||||
| import com.cloud.storage.StorageLayer; | import com.cloud.storage.StorageLayer; | ||||||
| import com.cloud.utils.exception.CloudRuntimeException; | import com.cloud.utils.exception.CloudRuntimeException; | ||||||
| @ -134,18 +135,18 @@ public class KVMStoragePoolManager { | |||||||
|         // LibvirtStorageAdaptor-specific statement |         // LibvirtStorageAdaptor-specific statement | ||||||
|         if (destPool.getType() == StoragePoolType.RBD) { |         if (destPool.getType() == StoragePoolType.RBD) { | ||||||
|             return adaptor.createDiskFromTemplate(template, name, |             return adaptor.createDiskFromTemplate(template, name, | ||||||
|                     KVMPhysicalDisk.PhysicalDiskFormat.RAW, template.getSize(), destPool); |                     PhysicalDiskFormat.RAW, template.getSize(), destPool); | ||||||
|         } else if (destPool.getType() == StoragePoolType.CLVM) { |         } else if (destPool.getType() == StoragePoolType.CLVM) { | ||||||
|             return adaptor.createDiskFromTemplate(template, name, |             return adaptor.createDiskFromTemplate(template, name, | ||||||
|                                        KVMPhysicalDisk.PhysicalDiskFormat.RAW, template.getSize(), |                                        PhysicalDiskFormat.RAW, template.getSize(), | ||||||
|                                        destPool); |                                        destPool); | ||||||
|         } else if (template.getFormat() == KVMPhysicalDisk.PhysicalDiskFormat.DIR) { |         } else if (template.getFormat() == PhysicalDiskFormat.DIR) { | ||||||
|             return adaptor.createDiskFromTemplate(template, name, |             return adaptor.createDiskFromTemplate(template, name, | ||||||
|                     KVMPhysicalDisk.PhysicalDiskFormat.DIR, |                     PhysicalDiskFormat.DIR, | ||||||
|                     template.getSize(), destPool); |                     template.getSize(), destPool); | ||||||
|         } else { |         } else { | ||||||
|             return adaptor.createDiskFromTemplate(template, name, |             return adaptor.createDiskFromTemplate(template, name, | ||||||
|                     KVMPhysicalDisk.PhysicalDiskFormat.QCOW2, |                     PhysicalDiskFormat.QCOW2, | ||||||
|             template.getSize(), destPool); |             template.getSize(), destPool); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -22,8 +22,14 @@ import java.net.URISyntaxException; | |||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.HashMap; | ||||||
| import org.apache.log4j.Logger; | import org.apache.log4j.Logger; | ||||||
| import org.apache.commons.codec.binary.Base64; | import org.apache.commons.codec.binary.Base64; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImgFile; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImgException; | ||||||
| import org.libvirt.Connect; | import org.libvirt.Connect; | ||||||
| import org.libvirt.LibvirtException; | import org.libvirt.LibvirtException; | ||||||
| import org.libvirt.Secret; | import org.libvirt.Secret; | ||||||
| @ -43,7 +49,6 @@ import com.cloud.hypervisor.kvm.resource.LibvirtStoragePoolDef.poolType; | |||||||
| import com.cloud.hypervisor.kvm.resource.LibvirtStoragePoolDef.authType; | import com.cloud.hypervisor.kvm.resource.LibvirtStoragePoolDef.authType; | ||||||
| import com.cloud.hypervisor.kvm.resource.LibvirtStorageVolumeDef.volFormat; | import com.cloud.hypervisor.kvm.resource.LibvirtStorageVolumeDef.volFormat; | ||||||
| import com.cloud.hypervisor.kvm.resource.LibvirtStorageVolumeXMLParser; | import com.cloud.hypervisor.kvm.resource.LibvirtStorageVolumeXMLParser; | ||||||
| import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk.PhysicalDiskFormat; |  | ||||||
| import com.cloud.exception.InternalErrorException; | import com.cloud.exception.InternalErrorException; | ||||||
| import com.cloud.storage.Storage.StoragePoolType; | import com.cloud.storage.Storage.StoragePoolType; | ||||||
| import com.cloud.storage.StorageLayer; | import com.cloud.storage.StorageLayer; | ||||||
| @ -399,11 +404,11 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { | |||||||
|                     disk.setFormat(pool.getDefaultFormat()); |                     disk.setFormat(pool.getDefaultFormat()); | ||||||
|                 } |                 } | ||||||
|             } else if (pool.getType() == StoragePoolType.RBD) { |             } else if (pool.getType() == StoragePoolType.RBD) { | ||||||
|                 disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.RAW); |                 disk.setFormat(PhysicalDiskFormat.RAW); | ||||||
|             } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.QCOW2) { |             } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.QCOW2) { | ||||||
|                 disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.QCOW2); |                 disk.setFormat(PhysicalDiskFormat.QCOW2); | ||||||
|             } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.RAW) { |             } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.RAW) { | ||||||
|                 disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.RAW); |                 disk.setFormat(PhysicalDiskFormat.RAW); | ||||||
|             } |             } | ||||||
|             return disk; |             return disk; | ||||||
|         } catch (LibvirtException e) { |         } catch (LibvirtException e) { | ||||||
| @ -647,57 +652,57 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { | |||||||
| 
 | 
 | ||||||
|             We then create a KVMPhysicalDisk object that we can return |             We then create a KVMPhysicalDisk object that we can return | ||||||
|         */ |         */ | ||||||
| 
 |         try { | ||||||
|         if (destPool.getType() != StoragePoolType.RBD) { |             if (destPool.getType() != StoragePoolType.RBD) { | ||||||
|             disk = destPool.createPhysicalDisk(newUuid, format, template.getVirtualSize()); |                 disk = destPool.createPhysicalDisk(newUuid, format, template.getVirtualSize()); | ||||||
| 
 |                 if (template.getFormat() == PhysicalDiskFormat.TAR) { | ||||||
|             if (template.getFormat() == PhysicalDiskFormat.TAR) { |                     Script.runSimpleBashScript("tar -x -f " + template.getPath() + " -C " + disk.getPath()); | ||||||
|                 Script.runSimpleBashScript("tar -x -f " + template.getPath() + " -C " + disk.getPath()); |                 } else if (template.getFormat() == PhysicalDiskFormat.DIR) { | ||||||
|             } else if (template.getFormat() == PhysicalDiskFormat.DIR) { |                     Script.runSimpleBashScript("mkdir -p " + disk.getPath()); | ||||||
|                 Script.runSimpleBashScript("mkdir -p " + disk.getPath()); |                     Script.runSimpleBashScript("chmod 755 " + disk.getPath()); | ||||||
|                 Script.runSimpleBashScript("chmod 755 " + disk.getPath()); |                     Script.runSimpleBashScript("cp -p -r " + template.getPath() + "/* " + disk.getPath()); | ||||||
|                 Script.runSimpleBashScript("cp -p -r " + template.getPath() + "/* " + disk.getPath()); |                 } else if (format == PhysicalDiskFormat.QCOW2) { | ||||||
|             } else if (format == PhysicalDiskFormat.QCOW2) { |                     QemuImgFile backingFile = new QemuImgFile(template.getPath(), template.getFormat()); | ||||||
|                 Script.runSimpleBashScript("qemu-img create -f " |                     QemuImgFile destFile = new QemuImgFile(disk.getPath()); | ||||||
|                         + template.getFormat() + " -b  " + template.getPath() + " " |                     QemuImg qemu = new QemuImg(); | ||||||
|                         + disk.getPath()); |                     qemu.create(destFile, backingFile); | ||||||
|             } else if (format == PhysicalDiskFormat.RAW) { |                 } else if (format == PhysicalDiskFormat.RAW) { | ||||||
|                 Script.runSimpleBashScript("qemu-img convert -f " |                     QemuImgFile sourceFile = new QemuImgFile(template.getPath(), template.getFormat()); | ||||||
|                                         + template.getFormat() + " -O raw " + template.getPath() |                     QemuImgFile destFile = new QemuImgFile(disk.getPath(), PhysicalDiskFormat.RAW); | ||||||
|                                         + " " + disk.getPath()); |                     QemuImg qemu = new QemuImg(); | ||||||
|             } |                     qemu.convert(sourceFile, destFile); | ||||||
|         } else { |                 } | ||||||
|             disk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + newUuid, newUuid, destPool); |  | ||||||
|             disk.setFormat(format); |  | ||||||
|             disk.setSize(template.getVirtualSize()); |  | ||||||
|             disk.setVirtualSize(disk.getSize()); |  | ||||||
| 
 |  | ||||||
|             if (srcPool.getType() != StoragePoolType.RBD) { |  | ||||||
|                 Script.runSimpleBashScript("qemu-img convert" |  | ||||||
|                         + " -f " + template.getFormat() |  | ||||||
|                         + " -O " + format |  | ||||||
|                         + " " + template.getPath() |  | ||||||
|                         + " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(), |  | ||||||
|                                                 destPool.getSourcePort(), |  | ||||||
|                                                 destPool.getAuthUserName(), |  | ||||||
|                                                 destPool.getAuthSecret(), |  | ||||||
|                                                 disk.getPath())); |  | ||||||
|             } else { |             } else { | ||||||
|                 template.setFormat(PhysicalDiskFormat.RAW); |                 disk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + newUuid, newUuid, destPool); | ||||||
|                 Script.runSimpleBashScript("qemu-img convert" |                 disk.setFormat(format); | ||||||
|                         + " -f " + template.getFormat() |                 disk.setSize(template.getVirtualSize()); | ||||||
|                         + " -O " + format |                 disk.setVirtualSize(disk.getSize()); | ||||||
|                         + " " + KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(), | 
 | ||||||
|                                                 srcPool.getSourcePort(), |                 QemuImg qemu = new QemuImg(); | ||||||
|                                                 srcPool.getAuthUserName(), |                 QemuImgFile srcFile; | ||||||
|                                                 srcPool.getAuthSecret(), |                 QemuImgFile destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(), | ||||||
|                                                 template.getPath()) |                         destPool.getSourcePort(), | ||||||
|                         + " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(), |                         destPool.getAuthUserName(), | ||||||
|                                                 destPool.getSourcePort(), |                         destPool.getAuthSecret(), | ||||||
|                                                 destPool.getAuthUserName(), |                         disk.getPath())); | ||||||
|                                                 destPool.getAuthSecret(), |                 destFile.setFormat(format); | ||||||
|                                                 disk.getPath())); | 
 | ||||||
|  |                 if (srcPool.getType() != StoragePoolType.RBD) { | ||||||
|  |                     srcFile = new QemuImgFile(template.getPath(), template.getFormat()); | ||||||
|  |                 } else { | ||||||
|  |                     template.setFormat(PhysicalDiskFormat.RAW); | ||||||
|  |                     srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(), | ||||||
|  |                             srcPool.getSourcePort(), | ||||||
|  |                             srcPool.getAuthUserName(), | ||||||
|  |                             srcPool.getAuthSecret(), | ||||||
|  |                             template.getPath())); | ||||||
|  |                     srcFile.setFormat(template.getFormat()); | ||||||
|  |                 } | ||||||
|  |                 qemu.convert(srcFile, destFile); | ||||||
|             } |             } | ||||||
|  |         } catch (QemuImgException e) { | ||||||
|  |             s_logger.error("Failed to create " + disk.getPath() + | ||||||
|  |                     " due to a failed executing of qemu-img: " + e.getMessage()); | ||||||
|         } |         } | ||||||
|         return disk; |         return disk; | ||||||
|     } |     } | ||||||
| @ -759,49 +764,65 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { | |||||||
|         PhysicalDiskFormat sourceFormat = disk.getFormat(); |         PhysicalDiskFormat sourceFormat = disk.getFormat(); | ||||||
|         PhysicalDiskFormat destFormat = newDisk.getFormat(); |         PhysicalDiskFormat destFormat = newDisk.getFormat(); | ||||||
| 
 | 
 | ||||||
|  |         QemuImg qemu = new QemuImg(); | ||||||
|  |         QemuImgFile srcFile = null; | ||||||
|  |         QemuImgFile destFile = null; | ||||||
|  | 
 | ||||||
|         if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() != StoragePoolType.RBD)) { |         if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() != StoragePoolType.RBD)) { | ||||||
|             if (sourceFormat == PhysicalDiskFormat.TAR) { |             if (sourceFormat == PhysicalDiskFormat.TAR) { | ||||||
|                 Script.runSimpleBashScript("tar -x -f " + sourcePath + " -C " + destPath); |                 Script.runSimpleBashScript("tar -x -f " + sourcePath + " -C " + destPath); | ||||||
| 
 |  | ||||||
|             } else if (sourceFormat == PhysicalDiskFormat.DIR) { |             } else if (sourceFormat == PhysicalDiskFormat.DIR) { | ||||||
|                 Script.runSimpleBashScript("mkdir -p " + destPath); |                 Script.runSimpleBashScript("mkdir -p " + destPath); | ||||||
|                 Script.runSimpleBashScript("chmod 755 " + destPath); |                 Script.runSimpleBashScript("chmod 755 " + destPath); | ||||||
|                 Script.runSimpleBashScript("cp -p -r " + sourcePath + "/* " + destPath); |                 Script.runSimpleBashScript("cp -p -r " + sourcePath + "/* " + destPath); | ||||||
| 
 |  | ||||||
|             } else if (sourceFormat.equals(destFormat) && |  | ||||||
|                 Script.runSimpleBashScript("qemu-img info " + sourcePath + "|grep backing") == null) { |  | ||||||
|                 Script.runSimpleBashScript("cp -f " + sourcePath + " " + destPath); |  | ||||||
| 
 |  | ||||||
|             } else { |             } else { | ||||||
|                 Script.runSimpleBashScript("qemu-img convert -f " + sourceFormat |                 srcFile = new QemuImgFile(sourcePath, sourceFormat); | ||||||
|                     + " -O " + destFormat |                 try { | ||||||
|                     + " " + sourcePath |                     Map<String, String> info = qemu.info(srcFile); | ||||||
|                     + " " + destPath); |                     String backingFile = info.get(new String("backing_file")); | ||||||
|  |                     if (sourceFormat.equals(destFormat) && backingFile == null) { | ||||||
|  |                         Script.runSimpleBashScript("cp -f " + sourcePath + " " + destPath); | ||||||
|  |                     } else { | ||||||
|  |                         destFile = new QemuImgFile(destPath, destFormat); | ||||||
|  |                     } | ||||||
|  |                 } catch (QemuImgException e) { | ||||||
|  |                     s_logger.error("Failed to fetch the information of file " | ||||||
|  |                             + srcFile.getFileName() + " the error was: " + e.getMessage()); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } else if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() == StoragePoolType.RBD))  { |         } else if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() == StoragePoolType.RBD))  { | ||||||
|             Script.runSimpleBashScript("qemu-img convert -f " + sourceFormat |             srcFile = new QemuImgFile(sourcePath, sourceFormat); | ||||||
|                     + " -O " + destFormat |             destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(), | ||||||
|                     + " " + sourcePath |                     destPool.getSourcePort(), | ||||||
|                     + " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(), |                     destPool.getAuthUserName(), | ||||||
|                                                 destPool.getSourcePort(), |                     destPool.getAuthSecret(), | ||||||
|                                                 destPool.getAuthUserName(), |                     destPath)); | ||||||
|                                                 destPool.getAuthSecret(), |             destFile.setFormat(destFormat); | ||||||
|                                                 destPath)); |  | ||||||
|         } else { |         } else { | ||||||
|             Script.runSimpleBashScript("qemu-img convert -f " + sourceFormat |             srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(), | ||||||
|                     + " -O " + destFormat |                     srcPool.getSourcePort(), | ||||||
|                     + " " + KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(), |                     srcPool.getAuthUserName(), | ||||||
|                                                 srcPool.getSourcePort(), |                     srcPool.getAuthSecret(), | ||||||
|                                                 srcPool.getAuthUserName(), |                     sourcePath)); | ||||||
|                                                 srcPool.getAuthSecret(), |             srcFile.setFormat(sourceFormat); | ||||||
|                                                 sourcePath) |             destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(), | ||||||
|                     + " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(), |                     destPool.getSourcePort(), | ||||||
|                                                 destPool.getSourcePort(), |                     destPool.getAuthUserName(), | ||||||
|                                                 destPool.getAuthUserName(), |                     destPool.getAuthSecret(), | ||||||
|                                                 destPool.getAuthSecret(), |                     destPath)); | ||||||
|                                                 destPath)); |             destFile.setFormat(destFormat); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if (srcFile != null && destFile != null) { | ||||||
|  |             try { | ||||||
|  |                 qemu.convert(srcFile, destFile); | ||||||
|  |             } catch (QemuImgException e) { | ||||||
|  |                 s_logger.error("Failed to convert " + srcFile.getFileName() + " to " | ||||||
|  |                         + destFile.getFileName() + " the error was: " + e.getMessage()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|         return newDisk; |         return newDisk; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -18,9 +18,9 @@ package com.cloud.hypervisor.kvm.storage; | |||||||
| 
 | 
 | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
| import org.libvirt.StoragePool; | import org.libvirt.StoragePool; | ||||||
| 
 | 
 | ||||||
| import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk.PhysicalDiskFormat; |  | ||||||
| import com.cloud.storage.Storage.StoragePoolType; | import com.cloud.storage.Storage.StoragePoolType; | ||||||
| 
 | 
 | ||||||
| public class LibvirtStoragePool implements KVMStoragePool { | public class LibvirtStoragePool implements KVMStoragePool { | ||||||
|  | |||||||
| @ -18,7 +18,7 @@ package com.cloud.hypervisor.kvm.storage; | |||||||
| 
 | 
 | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk.PhysicalDiskFormat; | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
| import com.cloud.storage.Storage.StoragePoolType; | import com.cloud.storage.Storage.StoragePoolType; | ||||||
| 
 | 
 | ||||||
| public interface StorageAdaptor { | public interface StorageAdaptor { | ||||||
|  | |||||||
| @ -0,0 +1,352 @@ | |||||||
|  | // 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 | ||||||
|  | // 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 org.apache.cloudstack.utils.qemu; | ||||||
|  | 
 | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImgFile; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImgException; | ||||||
|  | 
 | ||||||
|  | import com.cloud.utils.script.Script; | ||||||
|  | import com.cloud.utils.script.OutputInterpreter; | ||||||
|  | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.HashMap; | ||||||
|  | 
 | ||||||
|  | public class QemuImg { | ||||||
|  | 
 | ||||||
|  |     /* The qemu-img binary. We expect this to be in $PATH */ | ||||||
|  |     public String _qemuImgPath = "qemu-img"; | ||||||
|  | 
 | ||||||
|  |     /* Shouldn't we have KVMPhysicalDisk and LibvirtVMDef read this? */ | ||||||
|  |     public static enum PhysicalDiskFormat { | ||||||
|  |         RAW("raw"), QCOW2("qcow2"), VMDK("vmdk"), FILE("file"), RBD("rbd"), SHEEPDOG("sheepdog"), HTTP("http"), HTTPS("https"), TAR("tar"), DIR("dir"); | ||||||
|  |         String format; | ||||||
|  | 
 | ||||||
|  |         private PhysicalDiskFormat(String format) { | ||||||
|  |             this.format = format; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public String toString() { | ||||||
|  |             return this.format; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public QemuImg() { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Create a QemuImg object | ||||||
|  |      * | ||||||
|  |      * | ||||||
|  |      * @param qemuImgPath | ||||||
|  |      *            A alternative path to the qemu-img binary | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public QemuImg(String qemuImgPath) { | ||||||
|  |         this._qemuImgPath = qemuImgPath; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* These are all methods supported by the qemu-img tool */ | ||||||
|  | 
 | ||||||
|  |     /* Perform a consistency check on the disk image */ | ||||||
|  |     public void check(QemuImgFile file) { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Create a new image | ||||||
|  |      * | ||||||
|  |      * This method calls 'qemu-img create' | ||||||
|  |      *  | ||||||
|  |      * @param file | ||||||
|  |      *            The file to create | ||||||
|  |      * @param backingFile | ||||||
|  |      *            A backing file if used (for example with qcow2) | ||||||
|  |      * @param options | ||||||
|  |      *            Options for the create. Takes a Map<String, String> with key value | ||||||
|  |      *            pairs which are passed on to qemu-img without validation. | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public void create(QemuImgFile file, QemuImgFile backingFile, Map<String, String> options) throws QemuImgException { | ||||||
|  |         Script s = new Script(_qemuImgPath); | ||||||
|  |         s.add("create"); | ||||||
|  | 
 | ||||||
|  |         if (options != null && !options.isEmpty()) { | ||||||
|  |             s.add("-o"); | ||||||
|  |             String optionsStr = ""; | ||||||
|  |             for (Map.Entry<String, String> option : options.entrySet()) { | ||||||
|  |                 optionsStr += option.getKey() + "=" + option.getValue() + ","; | ||||||
|  |             } | ||||||
|  |             s.add(optionsStr); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /* | ||||||
|  |             -b for a backing file does not show up in the docs, but it works. | ||||||
|  |             Shouldn't this be -o backing_file=filename instead? | ||||||
|  |         */ | ||||||
|  |         s.add("-f"); | ||||||
|  |         if (backingFile != null) { | ||||||
|  |             s.add(backingFile.getFormat().toString()); | ||||||
|  |             s.add("-b"); | ||||||
|  |             s.add(backingFile.getFileName()); | ||||||
|  |         } else { | ||||||
|  |             s.add(file.getFormat().toString()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         s.add(file.getFileName()); | ||||||
|  | 
 | ||||||
|  |         if (backingFile == null) { | ||||||
|  |             s.add(Long.toString(file.getSize())); | ||||||
|  |         } | ||||||
|  |         String result = s.execute(); | ||||||
|  |         if (result != null) { | ||||||
|  |             throw new QemuImgException(result); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Create a new image | ||||||
|  |      * | ||||||
|  |      * This method calls 'qemu-img create' | ||||||
|  |      * | ||||||
|  |      * @param file | ||||||
|  |      *            The file to create | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public void create(QemuImgFile file) throws QemuImgException { | ||||||
|  |         this.create(file, null, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Create a new image | ||||||
|  |      * | ||||||
|  |      * This method calls 'qemu-img create' | ||||||
|  |      * | ||||||
|  |      * @param file | ||||||
|  |      *            The file to create | ||||||
|  |      * @param backingFile | ||||||
|  |      *            A backing file if used (for example with qcow2) | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public void create(QemuImgFile file, QemuImgFile backingFile) throws QemuImgException { | ||||||
|  |         this.create(file, backingFile, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Create a new image | ||||||
|  |      * | ||||||
|  |      * This method calls 'qemu-img create' | ||||||
|  |      * | ||||||
|  |      * @param file | ||||||
|  |      *            The file to create | ||||||
|  |      * @param options | ||||||
|  |      *            Options for the create. Takes a Map<String, String> with key value | ||||||
|  |      *            pairs which are passed on to qemu-img without validation. | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public void create(QemuImgFile file, Map<String, String> options) throws QemuImgException { | ||||||
|  |         this.create(file, null, options); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Convert a image from source to destination | ||||||
|  |      * | ||||||
|  |      * This method calls 'qemu-img convert' and takes two objects | ||||||
|  |      * as an argument. | ||||||
|  |      *  | ||||||
|  |      * | ||||||
|  |      * @param srcFile | ||||||
|  |      *            The source file | ||||||
|  |      * @param destFile | ||||||
|  |      *            The destination file | ||||||
|  |      * @param options | ||||||
|  |      *            Options for the convert. Takes a Map<String, String> with key value | ||||||
|  |      *            pairs which are passed on to qemu-img without validation. | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public void convert(QemuImgFile srcFile, QemuImgFile destFile, Map<String, String> options) throws QemuImgException { | ||||||
|  |         Script s = new Script(_qemuImgPath); | ||||||
|  |         s.add("convert"); | ||||||
|  |         s.add("-f"); | ||||||
|  |         s.add(srcFile.getFormat().toString()); | ||||||
|  |         s.add("-O"); | ||||||
|  |         s.add(destFile.getFormat().toString()); | ||||||
|  | 
 | ||||||
|  |         if (options != null && !options.isEmpty()) { | ||||||
|  |             s.add("-o"); | ||||||
|  |             String optionsStr = ""; | ||||||
|  |             for (Map.Entry<String, String> option : options.entrySet()) { | ||||||
|  |                 optionsStr += option.getKey() + "=" + option.getValue() + ","; | ||||||
|  |             } | ||||||
|  |             s.add(optionsStr); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         s.add(srcFile.getFileName()); | ||||||
|  |         s.add(destFile.getFileName()); | ||||||
|  | 
 | ||||||
|  |         String result = s.execute(); | ||||||
|  |         if (result != null) { | ||||||
|  |             throw new QemuImgException(result); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Convert a image from source to destination | ||||||
|  |      * | ||||||
|  |      * This method calls 'qemu-img convert' and takes two objects | ||||||
|  |      * as an argument. | ||||||
|  |      * | ||||||
|  |      * | ||||||
|  |      * @param srcFile | ||||||
|  |      *            The source file | ||||||
|  |      * @param destFile | ||||||
|  |      *            The destination file | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public void convert(QemuImgFile srcFile, QemuImgFile destFile) throws QemuImgException { | ||||||
|  |         this.convert(srcFile, destFile, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Commit the changes recorded in the file in its base image. | ||||||
|  |      * | ||||||
|  |      * This method calls 'qemu-img commit' and takes one object as | ||||||
|  |      * an argument | ||||||
|  |      * | ||||||
|  |      * @param file | ||||||
|  |      *            The file of which changes have to be committed | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public void commit(QemuImgFile file) throws QemuImgException { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Execute qemu-img info for the given file | ||||||
|  |      * | ||||||
|  |      * Qemu-img returns human readable output, but this method does it's best | ||||||
|  |      * to turn that into machine readeable data. | ||||||
|  |      * | ||||||
|  |      * Spaces in keys are replaced by underscores (_). | ||||||
|  |      * Sizes (virtual_size and disk_size) are returned in bytes | ||||||
|  |      * Paths (image and backing_file) are the absolute path to the file | ||||||
|  |      * | ||||||
|  |      * @param file | ||||||
|  |      *            A QemuImgFile object containing the file to get the information from | ||||||
|  |      * @return A HashMap with String key-value information as returned by 'qemu-img info' | ||||||
|  |      */ | ||||||
|  |     public Map<String, String> info(QemuImgFile file) throws QemuImgException { | ||||||
|  |         Script s = new Script(_qemuImgPath); | ||||||
|  |         s.add("info"); | ||||||
|  |         s.add(file.getFileName()); | ||||||
|  |         OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser(); | ||||||
|  |         String result = s.execute(parser); | ||||||
|  |         if (result != null) { | ||||||
|  |             throw new QemuImgException(result); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         HashMap<String,String> info = new HashMap<String,String>(); | ||||||
|  |         String[] outputBuffer = parser.getLines().trim().split("\n"); | ||||||
|  |         for (int i = 0; i < outputBuffer.length; i++) { | ||||||
|  |             String[] lineBuffer = outputBuffer[i].split(":", 2); | ||||||
|  |             if (lineBuffer.length == 2) { | ||||||
|  |                 String key = lineBuffer[0].trim().replace(" ", "_"); | ||||||
|  |                 String value = null; | ||||||
|  | 
 | ||||||
|  |                 if (key.equals("virtual_size")) { | ||||||
|  |                     value = lineBuffer[1].trim().replaceAll("^.*\\(([0-9]+).*$", "$1"); | ||||||
|  |                 } else { | ||||||
|  |                     value = lineBuffer[1].trim(); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 info.put(key, value); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return info; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* List, apply, create or delete snapshots in image */ | ||||||
|  |     public void snapshot() throws QemuImgException { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Changes the backing file of an image */ | ||||||
|  |     public void rebase() throws QemuImgException { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Resize an image | ||||||
|  |      * | ||||||
|  |      * This method simple calls 'qemu-img resize'. | ||||||
|  |      * A negative size value will get prefixed with - and a positive with + | ||||||
|  |      * | ||||||
|  |      * Sizes are in bytes and will be passed on that way | ||||||
|  |      * | ||||||
|  |      * @param file | ||||||
|  |      *            The file to resize | ||||||
|  |      * @param size | ||||||
|  |      *            The new size | ||||||
|  |      * @param delta | ||||||
|  |      *            Flag if the new size is a delta | ||||||
|  |      */ | ||||||
|  |     public void resize(QemuImgFile file, long size, boolean delta) throws QemuImgException { | ||||||
|  |         String newSize = null; | ||||||
|  | 
 | ||||||
|  |         if (size == 0) { | ||||||
|  |             throw new QemuImgException("size should never be exactly zero"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (delta) { | ||||||
|  |             if (size > 0) { | ||||||
|  |                 newSize = "+" + Long.toString(size); | ||||||
|  |             } else { | ||||||
|  |                 newSize = Long.toString(size); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             if (size <= 0) { | ||||||
|  |                 throw new QemuImgException("size should not be negative if 'delta' is false!"); | ||||||
|  |             } | ||||||
|  |             newSize = Long.toString(size); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Script s = new Script(_qemuImgPath); | ||||||
|  |         s.add("resize"); | ||||||
|  |         s.add(file.getFileName()); | ||||||
|  |         s.add(newSize); | ||||||
|  |         s.execute(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Resize an image | ||||||
|  |      * | ||||||
|  |      * This method simple calls 'qemu-img resize'. | ||||||
|  |      * A negative size value will get prefixed with - and a positive with + | ||||||
|  |      * | ||||||
|  |      * Sizes are in bytes and will be passed on that way | ||||||
|  |      * | ||||||
|  |      * @param file | ||||||
|  |      *            The file to resize | ||||||
|  |      * @param size | ||||||
|  |      *            The new size | ||||||
|  |      */ | ||||||
|  |     public void resize(QemuImgFile file, long size) throws QemuImgException { | ||||||
|  |         this.resize(file, size, false); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,25 @@ | |||||||
|  | // 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 | ||||||
|  | // 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 org.apache.cloudstack.utils.qemu; | ||||||
|  | 
 | ||||||
|  | public class QemuImgException extends Exception { | ||||||
|  | 
 | ||||||
|  |     public QemuImgException(String message) { | ||||||
|  |         super(message); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,72 @@ | |||||||
|  | // 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 | ||||||
|  | // 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 org.apache.cloudstack.utils.qemu; | ||||||
|  | 
 | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
|  | 
 | ||||||
|  | public class QemuImgFile { | ||||||
|  | 
 | ||||||
|  |     private long size = 0; | ||||||
|  |     private String fileName; | ||||||
|  |     private PhysicalDiskFormat format = PhysicalDiskFormat.RAW; | ||||||
|  | 
 | ||||||
|  |     public QemuImgFile(String fileName) { | ||||||
|  |         this.fileName = fileName; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public QemuImgFile(String fileName, long size) { | ||||||
|  |         this.fileName = fileName; | ||||||
|  |         this.size = size; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public QemuImgFile(String fileName, long size, PhysicalDiskFormat format) { | ||||||
|  |         this.fileName = fileName; | ||||||
|  |         this.size = size; | ||||||
|  |         this.format = format; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public QemuImgFile(String fileName, PhysicalDiskFormat format) { | ||||||
|  |         this.fileName = fileName; | ||||||
|  |         this.size = size; | ||||||
|  |         this.format = format; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setFileName(String fileName) { | ||||||
|  |         this.fileName = fileName; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setSize(long size) { | ||||||
|  |         this.size = size; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setFormat(PhysicalDiskFormat format) { | ||||||
|  |         this.format = format; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getFileName() { | ||||||
|  |         return this.fileName; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public long getSize() { | ||||||
|  |         return this.size; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public PhysicalDiskFormat getFormat() { | ||||||
|  |         return this.format; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,62 @@ | |||||||
|  | // 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 | ||||||
|  | // 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 org.apache.cloudstack.utils.qemu; | ||||||
|  | 
 | ||||||
|  | import org.junit.Ignore; | ||||||
|  | import org.junit.Test; | ||||||
|  | import static org.junit.Assert.assertEquals; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImgFile; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
|  | 
 | ||||||
|  | @Ignore | ||||||
|  | public class QemuImgFileTest { | ||||||
|  |     @Test | ||||||
|  |     public void testFileNameAtContructor() { | ||||||
|  |         String filename = "/tmp/test-image.qcow2"; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename); | ||||||
|  |         assertEquals(file.getFileName(), filename); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testFileNameAndSizeAtContructor() { | ||||||
|  |         long size = 1024; | ||||||
|  |         String filename = "/tmp/test-image.qcow2"; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename, size); | ||||||
|  |         assertEquals(file.getFileName(), filename); | ||||||
|  |         assertEquals(file.getSize(), size); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testFileNameAndSizeAndFormatAtContructor() { | ||||||
|  |         PhysicalDiskFormat format = PhysicalDiskFormat.RAW; | ||||||
|  |         long size = 1024; | ||||||
|  |         String filename = "/tmp/test-image.qcow2"; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename, size, format); | ||||||
|  |         assertEquals(file.getFileName(), filename); | ||||||
|  |         assertEquals(file.getSize(), size); | ||||||
|  |         assertEquals(file.getFormat(), format); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testFileNameAndFormatAtContructor() { | ||||||
|  |         PhysicalDiskFormat format = PhysicalDiskFormat.RAW; | ||||||
|  |         String filename = "/tmp/test-image.qcow2"; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename, format); | ||||||
|  |         assertEquals(file.getFileName(), filename); | ||||||
|  |         assertEquals(file.getFormat(), format); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,289 @@ | |||||||
|  | // 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 | ||||||
|  | // 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 org.apache.cloudstack.utils.qemu; | ||||||
|  | 
 | ||||||
|  | import org.junit.Ignore; | ||||||
|  | import org.junit.Test; | ||||||
|  | import static org.junit.Assert.assertEquals; | ||||||
|  | import static org.junit.Assert.fail; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImgFile; | ||||||
|  | import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.UUID; | ||||||
|  | import java.io.File; | ||||||
|  | 
 | ||||||
|  | @Ignore | ||||||
|  | public class QemuImgTest { | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testCreateAndInfo() throws QemuImgException { | ||||||
|  |         String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  | 
 | ||||||
|  |         /* 10TB virtual_size */ | ||||||
|  |         long size = 10995116277760l; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename, size, PhysicalDiskFormat.QCOW2); | ||||||
|  | 
 | ||||||
|  |         QemuImg qemu = new QemuImg(); | ||||||
|  |         qemu.create(file); | ||||||
|  |         Map<String, String> info = qemu.info(file); | ||||||
|  | 
 | ||||||
|  |         if (info == null) { | ||||||
|  |             fail("We didn't get any information back from qemu-img"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Long infoSize = Long.parseLong(info.get(new String("virtual_size"))); | ||||||
|  |         assertEquals(Long.valueOf(size), Long.valueOf(infoSize)); | ||||||
|  | 
 | ||||||
|  |         String infoPath = info.get(new String("image")); | ||||||
|  |         assertEquals(filename, infoPath); | ||||||
|  | 
 | ||||||
|  |         File f = new File(filename); | ||||||
|  |         f.delete(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testCreateAndInfoWithOptions() throws QemuImgException { | ||||||
|  |         String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  | 
 | ||||||
|  |         /* 10TB virtual_size */ | ||||||
|  |         long size = 10995116277760l; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename, size, PhysicalDiskFormat.QCOW2); | ||||||
|  |         String clusterSize = "131072"; | ||||||
|  |         Map<String, String> options = new HashMap<String, String>(); | ||||||
|  | 
 | ||||||
|  |         options.put("cluster_size", clusterSize); | ||||||
|  | 
 | ||||||
|  |         QemuImg qemu = new QemuImg(); | ||||||
|  |         qemu.create(file, options); | ||||||
|  |         Map<String, String> info = qemu.info(file); | ||||||
|  | 
 | ||||||
|  |         Long infoSize = Long.parseLong(info.get(new String("virtual_size"))); | ||||||
|  |         assertEquals(Long.valueOf(size), Long.valueOf(infoSize)); | ||||||
|  | 
 | ||||||
|  |         String infoPath = info.get(new String("image")); | ||||||
|  |         assertEquals(filename, infoPath); | ||||||
|  | 
 | ||||||
|  |         String infoClusterSize = info.get(new String("cluster_size")); | ||||||
|  |         assertEquals(clusterSize, infoClusterSize); | ||||||
|  | 
 | ||||||
|  |         File f = new File(filename); | ||||||
|  |         f.delete(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testCreateAndResize() throws QemuImgException { | ||||||
|  |         String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  | 
 | ||||||
|  |         long startSize = 20480; | ||||||
|  |         long endSize = 40960; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.QCOW2); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             QemuImg qemu = new QemuImg(); | ||||||
|  |             qemu.create(file); | ||||||
|  |             qemu.resize(file, endSize); | ||||||
|  |             Map<String, String> info = qemu.info(file); | ||||||
|  | 
 | ||||||
|  |             if (info == null) { | ||||||
|  |                 fail("We didn't get any information back from qemu-img"); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             Long infoSize = Long.parseLong(info.get(new String("virtual_size"))); | ||||||
|  |             assertEquals(Long.valueOf(endSize), Long.valueOf(infoSize)); | ||||||
|  |         } catch (QemuImgException e) { | ||||||
|  |             fail(e.getMessage()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         File f = new File(filename); | ||||||
|  |         f.delete(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testCreateAndResizeDeltaPositive() throws QemuImgException { | ||||||
|  |         String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  | 
 | ||||||
|  |         long startSize = 20480; | ||||||
|  |         long increment = 20480; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.RAW); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             QemuImg qemu = new QemuImg(); | ||||||
|  |             qemu.create(file); | ||||||
|  |             qemu.resize(file, increment, true); | ||||||
|  |             Map<String, String> info = qemu.info(file); | ||||||
|  | 
 | ||||||
|  |             if (info == null) { | ||||||
|  |                 fail("We didn't get any information back from qemu-img"); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             Long infoSize = Long.parseLong(info.get(new String("virtual_size"))); | ||||||
|  |             assertEquals(Long.valueOf(startSize + increment), Long.valueOf(infoSize)); | ||||||
|  |         } catch (QemuImgException e) { | ||||||
|  |             fail(e.getMessage()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         File f = new File(filename); | ||||||
|  |         f.delete(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testCreateAndResizeDeltaNegative() throws QemuImgException { | ||||||
|  |         String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  | 
 | ||||||
|  |         long startSize = 81920; | ||||||
|  |         long increment = -40960; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.RAW); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             QemuImg qemu = new QemuImg(); | ||||||
|  |             qemu.create(file); | ||||||
|  |             qemu.resize(file, increment, true); | ||||||
|  |             Map<String, String> info = qemu.info(file); | ||||||
|  | 
 | ||||||
|  |             if (info == null) { | ||||||
|  |                 fail("We didn't get any information back from qemu-img"); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             Long infoSize = Long.parseLong(info.get(new String("virtual_size"))); | ||||||
|  |             assertEquals(Long.valueOf(startSize + increment), Long.valueOf(infoSize)); | ||||||
|  |         } catch (QemuImgException e) { | ||||||
|  |             fail(e.getMessage()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         File f = new File(filename); | ||||||
|  |         f.delete(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test(expected = QemuImgException.class) | ||||||
|  |     public void testCreateAndResizeFail() throws QemuImgException  { | ||||||
|  |         String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  | 
 | ||||||
|  |         long startSize = 20480; | ||||||
|  | 
 | ||||||
|  |         /* Negative new size, expect failure */ | ||||||
|  |         long endSize = -1; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.QCOW2); | ||||||
|  | 
 | ||||||
|  |         QemuImg qemu = new QemuImg(); | ||||||
|  |         try { | ||||||
|  |             qemu.create(file); | ||||||
|  |             qemu.resize(file, endSize); | ||||||
|  |         } finally { | ||||||
|  |             File f = new File(filename); | ||||||
|  |             f.delete(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test(expected = QemuImgException.class) | ||||||
|  |     public void testCreateAndResizeZero() throws QemuImgException { | ||||||
|  |         String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  | 
 | ||||||
|  |         long startSize = 20480; | ||||||
|  |         QemuImgFile file = new QemuImgFile(filename, 20480, PhysicalDiskFormat.QCOW2); | ||||||
|  | 
 | ||||||
|  |         QemuImg qemu = new QemuImg(); | ||||||
|  |         qemu.create(file); | ||||||
|  |         qemu.resize(file, 0); | ||||||
|  | 
 | ||||||
|  |         File f = new File(filename); | ||||||
|  |         f.delete(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testCreateWithBackingFile() throws QemuImgException { | ||||||
|  |         String firstFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  |         String secondFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  | 
 | ||||||
|  |         QemuImgFile firstFile = new QemuImgFile(firstFileName, 20480, PhysicalDiskFormat.QCOW2); | ||||||
|  |         QemuImgFile secondFile = new QemuImgFile(secondFileName, PhysicalDiskFormat.QCOW2); | ||||||
|  | 
 | ||||||
|  |         QemuImg qemu = new QemuImg(); | ||||||
|  |         qemu.create(firstFile); | ||||||
|  |         qemu.create(secondFile, firstFile); | ||||||
|  | 
 | ||||||
|  |         Map<String, String> info = qemu.info(secondFile); | ||||||
|  |         if (info == null) { | ||||||
|  |             fail("We didn't get any information back from qemu-img"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         String backingFile = info.get(new String("backing_file")); | ||||||
|  |         if (backingFile == null) { | ||||||
|  |             fail("The second file does not have a property backing_file! Create failed?"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testConvertBasic() throws QemuImgException { | ||||||
|  |         long srcSize = 20480; | ||||||
|  |         String srcFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  |         String destFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  | 
 | ||||||
|  |         QemuImgFile srcFile = new QemuImgFile(srcFileName, srcSize); | ||||||
|  |         QemuImgFile destFile = new QemuImgFile(destFileName); | ||||||
|  | 
 | ||||||
|  |         QemuImg qemu = new QemuImg(); | ||||||
|  |         qemu.create(srcFile); | ||||||
|  |         qemu.convert(srcFile, destFile); | ||||||
|  |         Map<String, String> info = qemu.info(destFile); | ||||||
|  |         if (info == null) { | ||||||
|  |             fail("We didn't get any information back from qemu-img"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         File sf = new File(srcFileName); | ||||||
|  |         sf.delete(); | ||||||
|  | 
 | ||||||
|  |         File df = new File(destFileName); | ||||||
|  |         df.delete(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testConvertAdvanced() throws QemuImgException { | ||||||
|  |         long srcSize = 4019200; | ||||||
|  |         String srcFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  |         String destFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; | ||||||
|  |         PhysicalDiskFormat srcFormat = PhysicalDiskFormat.RAW; | ||||||
|  |         PhysicalDiskFormat destFormat = PhysicalDiskFormat.QCOW2; | ||||||
|  | 
 | ||||||
|  |         QemuImgFile srcFile = new QemuImgFile(srcFileName, srcSize, srcFormat); | ||||||
|  |         QemuImgFile destFile = new QemuImgFile(destFileName, destFormat); | ||||||
|  | 
 | ||||||
|  |         QemuImg qemu = new QemuImg(); | ||||||
|  |         qemu.create(srcFile); | ||||||
|  |         qemu.convert(srcFile, destFile); | ||||||
|  | 
 | ||||||
|  |         Map<String, String> info = qemu.info(destFile); | ||||||
|  | 
 | ||||||
|  |         PhysicalDiskFormat infoFormat = PhysicalDiskFormat.valueOf(info.get(new String("file_format")).toUpperCase()); | ||||||
|  |         assertEquals(destFormat, infoFormat); | ||||||
|  | 
 | ||||||
|  |         Long infoSize = Long.parseLong(info.get(new String("virtual_size"))); | ||||||
|  |         assertEquals(Long.valueOf(srcSize), Long.valueOf(infoSize)); | ||||||
|  | 
 | ||||||
|  |         File sf = new File(srcFileName); | ||||||
|  |         sf.delete(); | ||||||
|  | 
 | ||||||
|  |         File df = new File(destFileName); | ||||||
|  |         df.delete(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -460,20 +460,7 @@ public class Script implements Callable<String> { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static String runSimpleBashScript(String command) { |     public static String runSimpleBashScript(String command) { | ||||||
| 
 |         return Script.runSimpleBashScript(command, 0); | ||||||
|         Script s = new Script("/bin/bash"); |  | ||||||
|         s.add("-c"); |  | ||||||
|         s.add(command); |  | ||||||
| 
 |  | ||||||
|         OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser(); |  | ||||||
|         if (s.execute(parser) != null) |  | ||||||
|             return null; |  | ||||||
| 
 |  | ||||||
|         String result = parser.getLine(); |  | ||||||
|         if (result == null || result.trim().isEmpty()) |  | ||||||
|             return null; |  | ||||||
|         else |  | ||||||
|             return result.trim(); |  | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     public static String runSimpleBashScript(String command, int timeout) { |     public static String runSimpleBashScript(String command, int timeout) { | ||||||
| @ -493,10 +480,4 @@ public class Script implements Callable<String> { | |||||||
|             return result.trim(); |             return result.trim(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static void main(String[] args) { |  | ||||||
|         String path = findScript(".", "try.sh"); |  | ||||||
|         Script script = new Script(path, 5000, s_logger); |  | ||||||
|         script.execute(); |  | ||||||
|         System.exit(1); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user