Example #1
0
        internal List<XenRef<VDI>> ImportFile(Session xenSession, string vmname, string pathToOvf, string filename, string compression, string version, string passcode, string sruuid, string description, string vdiuuid)
        {
            List<XenRef<VDI>> vdiRef = new List<XenRef<VDI>>();

            // Get the disk transport method from the configuration in XenOvfTransport.Properties.Settings.TransferType.
            TransferType useTransport = (TransferType)Enum.Parse(typeof(TransferType), Properties.Settings.Default.TransferType, true);
            TransferMethod useTransferMethod = TransferMethod.Image;
            string sourcefile = filename;
            string encryptfilename = null;
            string uncompressedfilename = null;
            string destinationPath = Properties.Settings.Default.xenISOMount;
            string StartPath = Directory.GetCurrentDirectory();
            Directory.SetCurrentDirectory(pathToOvf);
            Stream dataStream = null;
            long dataCapacity = 0;

            #region SET UP TRANSPORT
            if (filename != null)
            {
                if (IsKnownURIType(filename))
                {
                    Uri fileUri = new Uri(filename);
                    filename = DownloadFileAsync(fileUri, 0);
                    sourcefile = filename;
                }

                if (File.Exists(filename))
                {
                    string ext = Path.GetExtension(filename);

                    try
                    {
                        encryptfilename = "enc_" + filename;
                        uncompressedfilename = "unc_" + filename;
                        // OK.. lets see is the file encrypted?
                        #region ENCRYPTION
                        if (passcode != null)
                        {
                            var statusMessage = string.Format(Messages.START_FILE_DECRYPTION, filename);
                            OnUpdate(new XenOvfTranportEventArgs(XenOvfTranportEventType.MarqueeOn, "Security", statusMessage));
                            log.Debug(statusMessage);
                            OVF.DecryptToTempFile(EncryptionClass, filename, version, passcode, encryptfilename);
                            sourcefile = encryptfilename;
                            statusMessage += Messages.COMPLETE;
                            OnUpdate(new XenOvfTranportEventArgs(XenOvfTranportEventType.MarqueeOff, "Security", statusMessage));
                        }
                        #endregion

                        #region COMPRESSION
                        // Identity == no compression, it is meant when a URL is used to identify the compression during transport.
                        if (compression != null &&
                            !compression.ToLower().Equals("none") &&
                            !compression.ToLower().Equals("identity"))
                        {
                            // gz is the only understood 'compressed' format, strip it..
                            // the OVF is marked with "compressed=gzip" therefor it will get decompress
                            // correctly and use with its disk extension (vmdk/vhd/vdi)...
                            if (ext.ToLower().EndsWith(".gz"))
                            {
                                string newfilename = Path.GetFileNameWithoutExtension(uncompressedfilename);
                                uncompressedfilename = newfilename;
                                ext = Path.GetExtension(uncompressedfilename);
                            }
                            var statusMessage = string.Format(Messages.START_FILE_EXPANSION, filename);
                            OnUpdate(new XenOvfTranportEventArgs(XenOvfTranportEventType.MarqueeOn, "Compression", statusMessage));
                            var ovfCompressor = new OvfCompressor();
                            ovfCompressor.UncompressFile(sourcefile, uncompressedfilename, compression);
                            if (File.Exists(encryptfilename)) { File.Delete(encryptfilename); }
                            sourcefile = uncompressedfilename;
                            statusMessage += Messages.COMPLETE;
                            OnUpdate(new XenOvfTranportEventArgs(XenOvfTranportEventType.MarqueeOff, "Compression", statusMessage));
                        }
                        #endregion

                        #region DISK SELECTION
                        bool knownDisk = false;
                        foreach (string diskext in VirtualDisk.SupportedDiskFormats)
                        {
                            if (ext.ToLower().Contains(diskext.ToLower()))
                            {
                                knownDisk = true;
                                break;
                            }
                        }
                        if (knownDisk)
                        {
                            log.DebugFormat("Found file {0} using {1} Stream", filename, ext);
                            vhdDisk = VirtualDisk.OpenDisk(sourcefile, FileAccess.Read);
                            dataStream = vhdDisk.Content;
                            dataCapacity = vhdDisk.Capacity;
                        }
                        else if (ext.ToLower().Contains("wim"))
                        {
                            log.WarnFormat("EXPERIMENTAL CODE: Found file {0} using WIM file structure", filename);
                            wimDisk = new DiscUtils.Wim.WimFile(new FileStream(sourcefile, FileMode.Open, FileAccess.Read));
                            //wimFS = wimDisk.GetImage(wimDisk.BootImage);

                            dataStream = null;

                            string manifest = wimDisk.Manifest;
                            Wim_Manifest wimManifest = (Wim_Manifest)Tools.Deserialize(manifest, typeof(Wim_Manifest));
                            ulong imagesize = wimManifest.Image[wimDisk.BootImage].TotalBytes; // <----<<< Image data size
                            wimFileCount = wimManifest.Image[wimDisk.BootImage].FileCount;
                            dataCapacity = (long)(imagesize + AdditionalSpace);
                            useTransferMethod = TransferMethod.Files;
                        }
                        else if (ext.ToLower().Contains("xva"))
                        {
                            log.WarnFormat("EXPERIMENTAL CODE: Found file {0} using XVA Stream (DISK {1} is being imported).", filename, xvadisk);
                            DiscUtils.Xva.VirtualMachine vm = new DiscUtils.Xva.VirtualMachine(new FileStream(sourcefile, FileMode.Open, FileAccess.Read));
                            int i = 0;
                            foreach (DiscUtils.Xva.Disk d in vm.Disks)
                            {
                                if (i == xvadisk)
                                {
                                    vhdDisk = d;
                                    break;
                                }
                            }
                            dataStream = vhdDisk.Content;
                            dataCapacity = vhdDisk.Capacity;
                        }
                        else if (ext.ToLower().EndsWith("iso"))
                        {
                            if (string.IsNullOrEmpty(sruuid))
                            {
                                useTransport = TransferType.Skip;
                            }
                            else
                            {
                                //DiscUtils.Iso9660.CDReader cdr = new DiscUtils.Iso9660.CDReader(File.OpenRead(filename), true);
                                dataStream = File.OpenRead(filename);
                                dataCapacity = dataStream.Length + (512 * KB);  // Xen does 512KB rounding this is to ensure it doesn't round down below size.
                            }
                        }
                        #endregion
                    }
                    catch (Exception ex)
                    {
                        log.Error(Messages.ISCSI_ERROR_CANNOT_OPEN_DISK);
                        throw new Exception(Messages.ISCSI_ERROR_CANNOT_OPEN_DISK, ex);
                    }
                }
                else
                {
                    throw new FileNotFoundException(string.Format(Messages.FILE_MISSING, filename));
                }
            }
            else
            {
                log.Error(Messages.ERROR_FILE_NAME_NULL);
                throw new InvalidDataException(Messages.ERROR_FILE_NAME_NULL);
            }
            #endregion

            try
            {
                #region SEE IF TARGET SR HAS ENOUGH SPACE
                if (useTransport == TransferType.UploadRawVDI ||
                    useTransport == TransferType.iSCSI)
                {
                    long freespace;
                    string contenttype = string.Empty;
                    if(vdiuuid != null)
                    {
                        XenRef<VDI> vdiLookup = VDI.get_by_uuid(xenSession, vdiuuid);
                        freespace = VDI.get_virtual_size(xenSession, vdiLookup);
                    }
                    else
                    {
                        XenRef<SR> srRef = SR.get_by_uuid(xenSession, sruuid);
                        long size = SR.get_physical_size(xenSession, srRef);
                        long usage = SR.get_physical_utilisation(xenSession, srRef);
                        contenttype = SR.get_content_type(xenSession, srRef);
                        freespace = size - usage;
                    }

                    if (freespace <= dataCapacity)
                    {
                        string message = string.Format(Messages.NOT_ENOUGH_SPACE_IN_SR, sruuid, Convert.ToString(vhdDisk.Capacity), filename);
                        log.Error(message);
                        throw new IOException(message);
                    }
                }
                #endregion

                #region UPLOAD FILE
                switch (useTransport)
                {
                    case TransferType.UploadRawVDI:
                        {
                            vdiRef.Add(UploadRawVDI(xenSession, sruuid, vmname, dataStream, dataCapacity, description));
                            break;
                        }
                    case TransferType.iSCSI:
                        {
                            if (useTransferMethod == TransferMethod.Image)
                            {
                                vdiRef.Add(UploadiSCSI(xenSession, sruuid, vmname, dataStream, dataCapacity, description, vdiuuid));
                            }
                            else
                            {
                                for (int i = 0; i < wimDisk.ImageCount; i++)
                                {
                                    Wim_Manifest wimManifest = (Wim_Manifest)Tools.Deserialize(wimDisk.Manifest, typeof(Wim_Manifest));
                                    wimFileCount = wimManifest.Image[i].FileCount;
                                    int wimArch = wimManifest.Image[i].Windows.Architecture;
                                    vdiRef.Add(UploadiSCSIbyWimFile(xenSession, sruuid, vmname, wimDisk, i, dataCapacity, wimFileCount, wimArch, ""));
                                }
                            }
                            break;
                        }
                    case TransferType.Skip:
                        {
                            log.Info("ImportFile: Upload Skipped");
                            break;
                        }
                    default:
                        {
                            log.Error(Messages.UNSUPPORTED_TRANSPORT);
                            throw new InvalidDataException(Messages.UNSUPPORTED_TRANSPORT);
                        }
                }
                #endregion
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException)
                    throw;
                throw new Exception(Messages.FILE_TRANSPORT_FAILED, ex);
            }
            finally
            {
                if (vhdDisk != null)
                {
                    vhdDisk.Dispose();
                    vhdDisk = null;
                }
                if (wimDisk != null)
                {
                    wimDisk = null;
                }
                if (File.Exists(encryptfilename)) { File.Delete(encryptfilename); }
                if (File.Exists(uncompressedfilename)) { File.Delete(uncompressedfilename); }
            }

            Directory.SetCurrentDirectory(StartPath);
            log.DebugFormat("OVF.Import.ImportFile leave: created {0} VDIs", vdiRef.Count);
            return vdiRef;
        }
        protected override void Run()
        {
            base.Run();

            var session = Connection.Session;

            var url = session.Url;
            Uri uri = new Uri(url);

            var appFolder = Path.Combine(m_applianceDirectory, m_applianceFileName);
            var appFile = string.Format("{0}.ovf", m_applianceFileName);

            if (!Directory.Exists(appFolder))
                Directory.CreateDirectory(appFolder);
            PercentComplete = 5;

            Description = Messages.EXPORTING_VMS;
            EnvelopeType env;
            try
            {
                m_transportAction = new XenOvfTransport.Export(uri, session)
                                        {
                                            UpdateHandler = UpdateHandler,
                                            ShouldVerifyDisks = m_shouldVerify,
                                            Cancel = Cancelling //in case the Cancel button has already been pressed
                                        };
                m_transportAction.SetTvmNetwork(m_networkUuid, m_isTvmIpStatic, m_tvmIpAddress, m_tvmSubnetMask, m_tvmGateway);
                env = (m_transportAction as XenOvfTransport.Export).Process(appFolder, m_applianceFileName, (from VM vm in m_vmsToExport select vm.uuid).ToArray());
                PercentComplete = 60;
            }
            catch (OperationCanceledException)
            {
                throw new CancelledException();
            }

            foreach (var eula in m_eulas)
            {
                if (Cancelling)
                    throw new CancelledException();
                Description = Messages.ADDING_EULAS;
                OVF.AddEula(env, eula);
            }

            if (Cancelling)
                throw new CancelledException();

            var ovfPath = Path.Combine(appFolder, appFile);
            Description = String.Format(Messages.CREATING_FILE, appFile);
            OVF.SaveAs(env, ovfPath);
            PercentComplete = 70;

            if (Cancelling)
                    throw new CancelledException();

            if (m_signAppliance)
            {
                Description = Messages.SIGNING_APPLIANCE;
                OVF.Sign(m_certificate, appFolder, appFile);
            }
            else if (m_createManifest)
            {
                Description = Messages.CREATING_MANIFEST;
                OVF.Manifest(appFolder, appFile);
            }

            PercentComplete = 90;

            if (Cancelling)
                    throw new CancelledException();

            if (m_createOVA)
            {
                Description = String.Format(Messages.CREATING_FILE, String.Format("{0}.ova", m_applianceFileName));
                OVF.ConvertOVFtoOVA(appFolder, appFile, m_compressOVFfiles);
            }
            else if (m_compressOVFfiles)
            {
                Description = Messages.COMPRESSING_FILES;
                m_compressor = new OvfCompressor { CancelCompression = Cancelling }; //in case the Cancel button has already been pressed}

                try
                {
                    m_compressor.CompressOvfFiles(ovfPath, "GZip");
                }
                catch (OperationCanceledException)
                {
                    throw new CancelledException();
                }
            }

            PercentComplete = 100;
            Description = Messages.COMPLETED;
        }