VMware {code} Community
HilaCA
Contributor
Contributor

Deploy OVF C#

I'm trying to deploy OVF by using C#, When I'm deploying the OVF with my tool I'm getting and "Operating system not found" error. however when I'm deploying the same OVF manually  the machine is up and running perfectly. I'm not sure what I'm doing wrong.

        public VsphereResponse CreateOvf(string datacenterName, string path, string teamFolder, WindowsIdentity userIdentity, string rpName, string teamName, string envName, string machName, string ovfFile)
        {
            VsphereResponse response = new VsphereResponse();

            ManagedObjectReference dataStoreWithMostFreeSpace = GetDataStoreWithMostFreeSpace(datacenterName, userIdentity);
            ManagedObjectReference datacenterRef = vsHandler.Connection.Service.FindByInventoryPath(vsHandler.Connection.ServiceContent.searchIndex, datacenterName);
            ManagedObjectReference moRpRef = vsHandler.GetDecendentMoRef(datacenterRef, NodeTypeEnum.ResourcePool.ToString(), rpName);
            ManagedObjectReference temp = vsHandler.GetDecendentMoRef(datacenterRef, NodeTypeEnum.Folder.ToString(), teamName);
            ManagedObjectReference vmFolder = vsHandler.GetDecendentMoRef(temp, NodeTypeEnum.Folder.ToString(), envName);
            ManagedObjectReference hostmor = vsHandler.GetFirstDecendentMoRef(null, NodeTypeEnum.HostSystem.ToString());

            OvfCreateImportSpecParams importSpecParams = CreateImportSpecParams(machName, hostmor);
            string ovfDescriptor = getOvfDescriptorFromLocal(ovfFile);
            
            OvfCreateImportSpecResult ovfImportResult = vsHandler.Connection.Service.CreateImportSpec(vsHandler.Connection.ServiceContent.ovfManager, ovfDescriptor, moRpRef, dataStoreWithMostFreeSpace, importSpecParams);
            OvfFileItem[] fileItemAttr = ovfImportResult.fileItem;
            if (fileItemAttr != null)
            {
                ManagedObjectReference httpNfcLease = vsHandler.Connection.Service.ImportVApp(moRpRef, ovfImportResult.importSpec, vmFolder, hostmor);
                HttpNfcLeaseInfo httpNfcLeaseInfo = vsHandler.GetDynamicProperty(httpNfcLease, "info") as HttpNfcLeaseInfo;
                while (httpNfcLeaseInfo == null)
                {
                    httpNfcLeaseInfo = vsHandler.GetDynamicProperty(httpNfcLease, "info") as HttpNfcLeaseInfo;
                }
        
                HttpNfcLeaseDeviceUrl[] deviceUrlArr = httpNfcLeaseInfo.deviceUrl;
                if (deviceUrlArr != null)
                {
                    int step = 100/fileItemAttr.Length;
                    int progress = 0;
                    foreach (HttpNfcLeaseDeviceUrl deviceUrl in deviceUrlArr)
                    {
                        string deviceKey = deviceUrl.importKey;
                        foreach (OvfFileItem ovfFileItem in fileItemAttr)
                        {
                            if (deviceKey.Equals(ovfFileItem.deviceId))
                            {
                                SendVMDKFile(ovfFileItem.create, ovfFile, deviceUrl.url, ovfFileItem.size);

                                progress += step;
                                vsHandler.Connection.Service.HttpNfcLeaseProgress(httpNfcLease, progress);
                                break;
                            }
                        }
                    }
                    vsHandler.Connection.Service.HttpNfcLeaseProgress(httpNfcLease, 100);
                    vsHandler.Connection.Service.HttpNfcLeaseComplete(httpNfcLease);
                }

            }

            return response;
        }

    private void SendVMDKFile(Boolean put, string fileName, string url, long diskCapacity)
        {
            Console.WriteLine("Destination host URL: " + url);
            Uri uri = new Uri(url);
            WebRequest request = HttpWebRequest.Create(uri);
            if (put)
            {
                request.Method = "PUT";
            }
            else
            {
                request.Method = "POST";
            }
            request.ContentLength = diskCapacity;
            request.ContentType = "application/x-vnd.vmware-streamVmdk";

            using (FileStream fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                //// Read the source file into a byte array.
                Stream dataStream = request.GetRequestStream();

                // Write the byte array to the other FileStream.
                int len = 0;
                byte[] buffer = new byte[1024 * 1024];

                while ((len = fileStream.Read(buffer, 0, buffer.Length-len)) > 0)
                {
                    dataStream.Write(buffer, 0, len);
                }
                dataStream.Flush();
                dataStream.Close();
            }
        }

    private string getOvfDescriptorFromLocal(string ovfDescriptorUrl)
        {
            string strContent = "";
            StreamReader sr = new System.IO.StreamReader(ovfDescriptorUrl);
            strContent = sr.ReadToEnd();
            return strContent;
        }

    private OvfCreateImportSpecParams CreateImportSpecParams(string newVmName, ManagedObjectReference hostmor)
        {
            OvfCreateImportSpecParams importSpecParams = new OvfCreateImportSpecParams();
            importSpecParams.hostSystem = hostmor;
            importSpecParams.locale = "";
            importSpecParams.entityName = newVmName;
            importSpecParams.deploymentOption = "";
            return importSpecParams;
        }

public VsphereResponse CreateOvf(string datacenterName, string path, string teamFolder, WindowsIdentity userIdentity, string rpName, string teamName, string envName, string machName, string ovfFile)
        {
            VsphereResponse response = new VsphereResponse();
 
            ManagedObjectReference dataStoreWithMostFreeSpace = GetDataStoreWithMostFreeSpace(datacenterName, userIdentity);
            ManagedObjectReference datacenterRef = vsHandler.Connection.Service.FindByInventoryPath(vsHandler.Connection.ServiceContent.searchIndex, datacenterName);
            ManagedObjectReference moRpRef = vsHandler.GetDecendentMoRef(datacenterRef, NodeTypeEnum.ResourcePool.ToString(), rpName);
            ManagedObjectReference temp = vsHandler.GetDecendentMoRef(datacenterRef, NodeTypeEnum.Folder.ToString(), teamName);
            ManagedObjectReference vmFolder = vsHandler.GetDecendentMoRef(temp, NodeTypeEnum.Folder.ToString(), envName);
            ManagedObjectReference hostmor = vsHandler.GetFirstDecendentMoRef(null, NodeTypeEnum.HostSystem.ToString());
Reply
0 Kudos
1 Reply
AndyBWL
Contributor
Contributor

First off apologies: this post is >1yr old and responding to old posts is a bit off form.....but I have just spent 3 days fighting with the same problem so thought it worthwhile posting what I had to do.

I am using the latest managment SDK for 6.5.0 targetting .NET runtime 4.5.0.

I started with the sample code as given in the OVFManagerImportLocalVApp and found that it did upload the VMDK but that on inspection it contained no partitions &c.

So the things I had to change were:

  • I explicitly set the Expect100Continue as "true" in the underlying service of the request. Not sure that this is anbsolutely required but the Java examples explicitly set it so I followed.
  • I set the Content-Length header value with the size of the VMDK I was uploading.
  • I had to set AllowWriteStreamBuffering to "false" as per https://support.microsoft.com/en-gb/help/908573/a-post-or-put-request-may-fail-when-you-use-the-http...
  • I only upload a 64K buffer at any given time.
  • I renew the lease (porbably over often) in the upload loop

The final VMDK upload function that appears to work is:

void SendVMDKFile(Boolean put, string fileName, string url, long diskCapacity, ManagedObjectReference httpNfcLease)

{

byte[] buffer = new byte[(64*1024)+1];

Trace.TraceInformation("Destination host URL: " + url);

Uri uri = new Uri(url);

HttpWebRequest request = HttpWebRequest.CreateHttp(uri);

NetworkCredential nwCred = new NetworkCredential();

long szVMDK = diskCapacity;

if (0 == szVMDK)

{

     System.IO.FileInfo fi = new System.IO.FileInfo(fileName);

     szVMDK = fi.Length;

}

request.ContentType = "application/x-vnd.vmware-streamVmdk";

request.ServicePoint.Expect100Continue = true;

request.KeepAlive = true;

request.Timeout = WebClientTimeout;

request.AllowWriteStreamBuffering = false;

request.ContentLength = szVMDK;

if (put)

{

     request.Method = "PUT";

}

else

{

     request.Method = "POST";

}

System.IO.FileStream fileStream = new FileStream(fileName, FileMode.Open);

Stream dataStream = request.GetRequestStream();

int len = 0;

long totalWritten = 0;

long threshold = 0;

if (0 != szVMDK)

{

     threshold = szVMDK / 20;

}

while ((len = fileStream.Read(buffer, 0, (64*1024))) > 0)

{

     dataStream.Write(buffer, 0, len);

     dataStream.Flush();

     totalWritten += len;

     if (0 != szVMDK)

     {

         _server.getConnection().Service.HttpNfcLeaseProgress(httpNfcLease, (int)(((double)(totalWritten / threshold)) * 5));

     }

     Trace.TraceInformation("SendVMDKFile: Written {0} of {1} ({2:G}). Status {3}", totalWritten, szVMDK, ((double)(totalWritten / threshold)),fileStream.Position);

}

dataStream.Flush();

dataStream.Close();

fileStream.Close();

}

As mentioned, it hits the HttpNcfLeasedProgress a *lot* most of the other samples fire this off to a separate thread and update it significantly fewer times. But I have left it "as is".

So hopefully this is useful to someone else

Reply
0 Kudos