VMware {code} Community
OwainNorth
Contributor
Contributor

Refresh vApp list?

Hi there

I'm writing a wrapper API around the VCD API, and so far have (eventually, obvious documentation rant etc) figured out how to get the basic listings of Organizations, vApps, VMs and such. I'm now working on instantiating a vApp from a template. This is working, using this code:

InstantiateVAppTemplateParamsType T = new InstantiateVAppTemplateParamsType();

T.AllEULAsAccepted = true;
T.AllEULAsAcceptedSpecified = true;
T.Description = "Auto-created vApp FTW";
T.name = "NEW-SERVER-1";
T.deploy = true;
T.deploySpecified = true;
T.IsSourceDelete = false;
T.IsSourceDeleteSpecified = true;
T.powerOn = true;
T.powerOnSpecified = true;
ReferenceType RT = new ReferenceType();
RT.href = VAppTemplates[0].VCDTemplate.href;
RT.name = VAppTemplates[0].VCDTemplate.name;
RT.type = VAppTemplates[0].VCDTemplate.type;
RT.VCloudExtension = VAppTemplates[0].VCDTemplate.VCloudExtension;
T.Source = RT;
Vapp NewVApp = this.VCDVdc.InstantiateVappTemplate(T);
And this works, the new vApp is rolled out. However I then want to change the name of the VM within the new vApp. I tried doing this:
NewVApp.GetChildrenVms()[0].Resource.name = "NEW-SERVER-1"; // the vApp only has one child VM
NewVApp.UpdateVapp(NewVApp.Resource);
However I get an ArgumentOutOfRangeException, as the vApp returned apparently has no child VMs.
Am I doing something stupid? Do I somehow need to force a refresh of these cached catalogs, as within the .NET SDK classes it does seem as if it does the web calls in the constructor, gets the data then stores it locally within data dictionaries. Is there any way of refreshing these? Or am I going about it completely wrong?
Many thanks for any suggestions.
O.
0 Kudos
6 Replies
rkamal
VMware Employee
VMware Employee

Hi,

Your Vapp might not have been completely created.

Try waiting until the Vapp gets created completely. Then fetch the Vapp again using the getVappByReference/Id methods and do the update.

Regards,

Rajesh Kamal.

Vapp NewVApp = this.VCDVdc.InstantiateVappTemplate(T);

// waiting for the vapp task to complete.

List<Task> tasks = NewVApp.Tasks[0].WaitForTask(0);
// try fetching the vapp again and then do  the update.
OwainNorth
Contributor
Contributor

Hi Rajesh

Thanks for getting back to me, I've been playing with this all morning but still to no avail. I've tried re-fetching the vApp as follows:

InstantiateVAppTemplateParamsType T = new InstantiateVAppTemplateParamsType();

T.AllEULAsAccepted = true;

T.AllEULAsAcceptedSpecified = true;

T.Description = "Auto-created vApp FTW";

T.name = Name;

T.deploy = true;

T.deploySpecified = true;

T.IsSourceDelete = false;

T.IsSourceDeleteSpecified = true;

T.powerOn = false;

T.powerOnSpecified = true;


ReferenceType RT = new ReferenceType();

RT.href = VAppTemplates[0].VCDTemplate.href;

RT.name = VAppTemplates[0].VCDTemplate.name;

RT.type = VAppTemplates[0].VCDTemplate.type;

//RT.VCloudExtension = VAppTemplates[0].VCDTemplate.VCloudExtension;

T.Source = RT;


// Instantiate template

Vapp NewVApp = this.VCDVdc.InstantiateVappTemplate(T);


// Wait for completion, don't really know what I'm doing here so bodge stuff until it works

TaskType TT = NewVApp.Resource.Tasks.Task[0];

ReferenceType R = new ReferenceType() { href = TT.href, name = String.Empty, type = TT.type };

Task Tsk;

do { Tsk = Task.GetTaskByReference(_VCDClient, R); }

while (Tsk.Resource.status == TaskStatusType.running);


// Get the vApp

Vapp V = Vapp.GetVappByReference(_VCDClient, _VCDVdc.GetVappRefByName(Name));

Console.WriteLine("Name: " + V.Resource.name);

But still get the exception that implies I need to reload some dictionary somehow:

System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.

   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at com.vmware.vcloud.sdk.Vdc.GetVappRefByName(String name)
I'll carry on fighting my way through, but if you can see anything I'm obviously doing wrong (which I do not doubt) I'd be most appreciative.
O.
0 Kudos
OwainNorth
Contributor
Contributor

Ah, getting somewhere. If I go all the way back to the Organization level and re-run the getter methods, I find the vApp, but going directly back to the getVAppByReference() method of the Vdc does not seem to re-cache but instead load from dictionary. This now works:

InstantiateVAppTemplateParamsType T = new InstantiateVAppTemplateParamsType();

T.AllEULAsAccepted = true;
T.AllEULAsAcceptedSpecified = true;
T.Description = "Auto-created vApp FTW";
T.name = Name;
T.deploy = true;
T.deploySpecified = true;
T.IsSourceDelete = false;
T.IsSourceDeleteSpecified = true;
T.powerOn = false;
T.powerOnSpecified = true;
ReferenceType RT = new ReferenceType();
RT.href = VAppTemplates[0].VCDTemplate.href;
RT.name = VAppTemplates[0].VCDTemplate.name;
RT.type = VAppTemplates[0].VCDTemplate.type;
T.Source = RT;
// Instantiate template
Vapp NewVApp = this.VCDVdc.InstantiateVappTemplate(T);
foreach (Task ThisT in NewVApp.Tasks)
{
    Console.WriteLine("Waiting on {0}", ThisT.Resource.type);
    _VCloudManager.WaitForTaskCompletion(ThisT);
}
// Get the vApp
Vapp NewerVApp = Vapp.GetVappByReference(_VCDClient, Vdc.GetVdcByReference(_VCDClient,      Organization.GetOrganizationByReference(_VCDClient,      _VCDVdc.GetOrgReference()).GetVdcRefByName(_VCDVdc.Resource.name)).GetVappRefByName(Name));
Console.WriteLine("Updating...");
NewerVApp.GetChildrenVms()[0].Resource.name = Name;
Task UpdateTsk = NewerVApp.UpdateVapp(NewerVApp.Resource);
_VCloudManager.WaitForTaskCompletion(UpdateTsk);

The rename reckons it works, but it actually doesn't. I suspect this is a different issue though, so I'll start looking at that now.

Thanks for your help.

O.

0 Kudos
johanneshiemer
Enthusiast
Enthusiast

Hi,

I faced the same issue today (Java SDK). And in my opinion it is definitely a bug. There should be an option to refresh the vDC after creation of a Vapp.

Any chance to get an update?

0 Kudos
rkamal
VMware Employee
VMware Employee

Hi,

You can refresh your vdc object by just making a Vdc.getVdcByReference() or Vdc.getVdcById() methods.

Ex:

     // Create the vapp.

     Vapp vapp = vdcObj.InstantiateVappTemplate();

     // Refreshing the vdc

     vdcObj = Vdc.getVdcByReference(client, vdcObj.getReference()) or Vdc.getVdcById(client, vdcObj.getResource().getId());

Regards,

Rajesh Kamal

johanneshiemer
Enthusiast
Enthusiast

Hi Rajesh,

thanks a lot, works. Would be nice, to have a vhc.Refresh(); in future.

0 Kudos