VMware {code} Community
DroppedAtBirth
Contributor
Contributor

Get list of DataCenter/DataStore

Trying to get a list of DataCenters/Datastores using the ws sdk, using Vim25Api dll in vb.net. Get error "Not initialized: vmodl.ManagedObject obj" on the last line, not sure what I am doing wrong or missing, am new to WS SDK. Any help would be greatly appricated.

Dim dc As ManagedObjectReference = VCConnection.FindByInventoryPath(_sic.searchIndex, dcname)

Dim dc2ds As TraversalSpec = New TraversalSpec()

dc2ds.type = "Datacenter"

dc2ds.name = "dc2ds"

dc2ds.path = "datastore"

dc2ds.selectSet = New SelectionSpec() {New SelectionSpec()}

dc2ds.selectSet(0).name = dc2ds.name

Dim pspecDS As PropertySpec = New PropertySpec()

pspecDS.type = "Datastore"

pspecDS.pathSet = New String() {"host", "summary.name", "summary.capacity", "summary.freeSpace", "summary.type", "summary.url"}

pspecDS.all = True

Dim ospec As ObjectSpec = New ObjectSpec()

ospec.obj = dc

ospec.skip = False

ospec.selectSet = New SelectionSpec()

Dim pfspec As PropertyFilterSpec = New PropertyFilterSpec()

pfspec.propSet = New PropertySpec()

pfspec.objectSet = New ObjectSpec()

Dim pfSpecList As PropertyFilterSpec() = New PropertyFilterSpec()

Dim oCont As ObjectContent() = VCConnection.RetrieveProperties(PROP_COLLECTOR, pfSpecList)

0 Kudos
19 Replies
jrackliffe
Hot Shot
Hot Shot

So you don't show the code you use for initializing your PROP_COLLECTOR const. I assume it is refering back to your _sic.propertyCollector instance, but can you confirm? Because you are getting an uninit MOR I am guessing that is the source.

Your traversalspec looks solid when starting from a dc. I don't think you need your selectSpec logic as it is almost recursive as the Datacenter to Datastore should be a single hop.

And just because this has bitten me and others in C# and I don't know if VB.NET has this issue... make sure you set your "specified" = true properties (e.g. objspec.skipSpecified) or .NET's proxy won't send the data in the request.

So I think if you replace PROP_COLLECTOR w _sic.propertyCollector you might be in action.

J

0 Kudos
DroppedAtBirth
Contributor
Contributor

You are correct, PROP_COLLECTOR is just a refers to sic.propertyCollector. It is actually not needed so I removed PROPCOLLECTOR and replace with sic.propertyCollector. Before the Code above I have a Function VCLogin that setups the connection, MOR's, ServiceContent, and then connects. Have other functions working but most only run simple findobjects and getObjectProperty calls.

After changing the prop_collector and adding ospec.skipSpecified = True, i am still getting the same error message.

Still working on my understanding of TraversalSpec and other SDK objects. Maybe I am missing something in my Login Function.

_VCConnectionDetails.port = "443"

'Put URL Together

VCConnection.Url = "https://" + connection.server + ":" + connection.port + "/sdk/vimService"

'Setup Cookies

VCConnection.CookieContainer = New System.Net.CookieContainer

'Set Timeout

VCConnection.Timeout = 5000

Dim MO As New Vim25Api.ManagedObjectReference

Dim RootFolder As New Vim25Api.ManagedObjectReference

_sic = VCConnection.RetrieveServiceContent(MO)

'Set Folders

connection.RootFolder = _sic.rootFolder

connection.CustomFieldManager = _sic.customFieldsManager

'Session Manager

Dim session As New Vim25Api.UserSession

MO.Value = "SessionManager"

MO.type = "SessionManager"

'Login

session = VCConnection.Login(MO, connection.username, connection.password, "en")

0 Kudos
jrackliffe
Hot Shot
Hot Shot

How about this... lets make sure you are actually authenticated correctly. I also don't see all your ServiceInstance code in there. I see what I think is the SI instance (MO?), but you don't set the type. I think I translated to yourvar names right, but might need some tweaks and this is for Vim20 so the stuff in your VCConnection class may be a bit off, but it should be close.Real idea is to call CurrentTime which requires a valid ServiceInstance MOR, a proper VimService instance.

VCConnection = new VimService();

VCConnection.Url = "https://server.com/sdk";

VCConnection.CookieContainer = new System.Net.CookieContainer();

ManagedObjectReference MO = new ManagedObjectReference();

MO.type = "ServiceInstance";

MO.Value = "ServiceInstance";

_sic = service.RetrieveServiceContent(serviceRef);

VCConnection.Login(_sic.sessionManager, "user", "pwd", null);

//Simplest way to test if you are authorized... call CurrentTime.

Console.WriteLine(VCConnection.CurrentTime(MO).ToString());

0 Kudos
DroppedAtBirth
Contributor
Contributor

Adding the currenttime call causes an error when it runs, just returns a soap error. Which only confuses me more... I have working code that is using my VCLogic function... The code below works...

VCConnectionDetails = VCLogin(VCConnectionDetails)

Dim OC() As Vim25Api.ObjectContent

OC = find_objects(VCConnection, _VCConnectionDetails.RootFolder, "Datacenter", New String() {"name"}) '{"name", "capability"})

VCLogout(_VCConnectionDetails)

So why does my other function not think its connected? Sorry for all the questions, again still new to the WS SDK, have been using the CLI powershell for the past year but its much easier to figure out.

Have attached a copy of the code I am working with, should have done that to begin with.

0 Kudos
jrackliffe
Hot Shot
Hot Shot

Heh well that is why VMware does the Powershell and Perl toolkits as it masks the pain behind interacting w VI via SOAP.

Well I would need to see the find_objects function before I could figure out why one works and not the other. Also, what was the Soap exception you generated?

Either way... the first thing I recommend people do to get used to VI is to pull time, because it requires at minimum View while things like RootFolder are available for Anonymous.

If you can pull time you are connected to VI and authenticated so you should be doing well.

J

0 Kudos
DroppedAtBirth
Contributor
Contributor

The Soap error doesn't appear to contain much info.

at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)

at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)

at Vim25Api.VimService.CurrentTime(ManagedObjectReference _this)

0 Kudos
jrackliffe
Hot Shot
Hot Shot

There wasn't any Message in there? That would be very odd as there usually is some sort of inner exception in the response?

If you can't even get the time than trying to debug the rest will be nearly impossible.

0 Kudos
DroppedAtBirth
Contributor
Contributor

correct the message in the exception was blank, the stacktrace is what I posted. Inside the details I find "Element, Name="MethodNotFoundFault"" and outerxml says <detail><MethodNotFoundFault xmlns="urn:vim25" xsi:type="MethodNotFound" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><receiver type="SessionManager">SessionManager</receiver><method>CurrentTime</method></MethodNotFoundFault></detail>

0 Kudos
jrackliffe
Hot Shot
Hot Shot

Hmm.... MethodNotFound means that you have not even connected to vim because the SOAP proxy isn't linking up.

I have noticed that you append vimService to your Url. Can you just make it https://server.com/sdk and retry?

0 Kudos
DroppedAtBirth
Contributor
Contributor

Well, I am now connected, Current Time returns. Cleaned up the Login Function.:| But, still getting "Not initialized: vmodl.ManagedObject obj"

Private Function VCLogin(ByVal connection As VCConnectionDetails) As VCConnectionDetails

'SSL Validation

ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf GSI.ERP.CommonLibrary.ValidateCertificate)

_svcRef = New ManagedObjectReference

_svcRef.type = "ServiceInstance"

_svcRef.Value = "ServiceInstance"

_service = New Vim25Api.VimService

_service.Url = "https://" + connection.server + "/sdk"

_service.CookieContainer = New System.Net.CookieContainer

'Set Timeout

_service.Timeout = 5000

'Check Service

Try

_sic = service.RetrieveServiceContent(svcRef)

Catch ex As Exception

'todo: error, can't find service

Console.WriteLine("Error connecting, wrong IP?")

End Try

Try

'Login

service.Login(sic.sessionManager, connection.username, connection.password, "en")

Catch ex As Exception

'todo: exception : Error with loggin in. Wrong username or password

End Try

Return connection

End Function

0 Kudos
jrackliffe
Hot Shot
Hot Shot

Assuming because you didn't come back with a Eureka I am guessing you are still stuck?

So when you do a line by line debug are you sure that your objects are all not null?

thinking things like for FindByInvPath etc. Because you are using VB.NET you could be missing a Dim somewhere, but I am not 100%.

Nothing jumps out to me on any of your specs. Good news that you are pulling CurrentTime as at least you know some aspects of the API are functioning.

Have you tried any of the other ToolKits against that Host/VC? Thinking specifically of the Powershell toolkit to eliminate some config problem on your VC/Host.

J

0 Kudos
DroppedAtBirth
Contributor
Contributor

No, no breakthroughs.

In debug the line that errors appears to have all valid objects, but I must be missing something. Maybe I am missing something or calling FindByInventoryPath wrong, haven't used it before.

Just because the code is in VB.net and not C# doesn't mean I don't know how to program. option explicit is on, option strict is on, option infer is on. Meaning all variables and objects must be declared.

We currently have all our management code thru the powershell API, including cloning VM's, managing datastores, host, vm's, etc... But we have had many issues with powershell not being consistent, trying to run powershell thru .net works but running command line commands thru .net is not the most reliable way for programming, error trapping and exception handling become issues. I have moved about 1/3 of our code to the Web Service SDK and off of powershell but have many things I can't seem to figure out how to get working in the WS SDK.

0 Kudos
jrackliffe
Hot Shot
Hot Shot

Heh, sorry if it came across as questioning your aptitude. Pulling at straws a bit since we only have snippets of code. the VMODL is the basically the API saying something went wonky since that is the internal namespace so trying to figure out is it an input or output problem.

Can you tell me what the value property is of the DC? Also, I have never found the FindBy methods all that great, even though I don't use the index I have found just usingthe RetrieveProperties with an all-inclusive PFS works.

Also, this is sort of undocumented, but I am trying to convince Carter and Pablo to give it more light. The Powershell work is backed by a client side DLL that implements the SOAP interfaces in a pretty lean manner. Just add a ref to Vmware.Vim.dll and it should handle the proxy work for you. It also expose most if not all of the MOs and DOs in VI. Not sure if it will solve your problem, but like the Perl toolkit it does help you with a couple things.Youdon't need to do Powershell via .NET as you can just use that DLL for your proxy.

Also, did you try to run some of the sample applications against this instance? Especuially ones like SimpleClient are pretty good at stepping you through using the SOAP API.

J

0 Kudos
DroppedAtBirth
Contributor
Contributor

Have the Vmware.Vim.dll referenced, have tried using it before, unfortunately I don't find alot of documentation as to the dll's direct usage. But the vim25api, which is very close to the VMWare.vim.dll in structure, has alot of samples and appears to acutally have usage support.

Have not tried running any of the samples directly but have used them for examples to work off of.

0 Kudos
jrackliffe
Hot Shot
Hot Shot

Yeah you won't find a whole lot of doco on it because they don't advertise. Thats why I am advocating that the underlying DLL be promoted to a full "toolkit" and Powershell just be an implementer. Probably would make some folks lives easier. the Vim PS proxy is pretty much the same as using the SOAP proxy. Same examples.. same patterns.

Were you able to get the value (basically the mob id) of that Datacenter? Just trying to confirm that the FindBy is not blowing you up.

J

0 Kudos
DroppedAtBirth
Contributor
Contributor

I think the powershell API is a little more dumbed down than a simple proxy. Getting a list of datastores per datacenter is a simple powershell script, "Get-Datastore -Datacenter ( Get-DataCenter -name $name )", I don't see anything even near that simple in the dlls, but maybe I am missing something.

dc is indeed nothing, the line that is throwing the error doesn't have dc in it so I was not looking at it. Not sure why the findby is not working, i am using other findby's like findbydnsname and ip just fine in other calls. Am I missing something special with FindByInventoryPath ??

0 Kudos
jrackliffe
Hot Shot
Hot Shot

Yes, just like the Perl toolkit it has a number of "helpers" that are coded to simplify accessing VI. The Powershell What I was comparing was the Proxies generated by the standard SDK dist.

Following the example in the "Programming w .NET Assemblies" of the PS ".NET Developers Guide" guide I cooked this up in a few. First time I actually went for non-managedEntities so took an extra min or so. What I was referring to was the Find and Get functions in VimClient that could make your life easier. This is C#, but moving to VB.NET is trivial.



VimClient vc = new VimClient();
vc.ServiceUrl = "https://server/sdk";
vc.Login(user, pwd);

NameValueCollection filter = new NameValueCollection();
filter.Add("name", dcname);

Datacenter dc = (Datacenter)vc.FindEntityView(typeof(Datacenter), null, filter, null);
foreach (ManagedObjectReference ds in dc.Datastore)
{
Datastore dse = (Datastore)vc.GetView(ds, null);
Console.WriteLine(dse.Summary.Name);
Console.WriteLine(dse.Summary.Capacity.ToString());
Console.WriteLine(dse.Summary.FreeSpace.ToString());
Console.WriteLine(dse.Summary.Url);
}

vc.Disconnect(); 



I wasn't sure what you meant by "host", because a Datastore can be attached to multiple ESX Host.

This type of simplification though is what I see as the benefit of advocating .NET developers using the Vim.dll and not accessing SOAP directly for general automation implementations.

J

0 Kudos
DroppedAtBirth
Contributor
Contributor

Yes, easy enough to convert to vb.net.

Dim vc As VMware.Vim.VimClient = New VMware.Vim.VimClient()

vc.ServiceUrl = "https://" + server + "/sdk"

vc.Login(username, password)

Dim filter As NameValueCollection = New NameValueCollection()

filter.Add("name", dcname)

Dim dc As VMware.Vim.Datacenter = DirectCast(vc.FindEntityView(GetType(VMware.Vim.Datacenter), Nothing, filter, Nothing), VMware.Vim.Datacenter)

Dim ds As New VMware.Vim.ManagedObjectReference

For Each ds In dc.Datastore

Dim dse As VMware.Vim.Datastore = DirectCast(vc.GetView(ds, Nothing), VMware.Vim.Datastore)

Console.WriteLine(dse.Summary.Name)

Console.WriteLine(dse.Summary.Capacity.ToString())

Console.WriteLine(dse.Summary.FreeSpace.ToString())

Console.WriteLine(dse.Summary.Url)

Next

vc.Disconnect()

I am aware the multiple host attach to muliple datastores, I need to know the linkage because this is data we use in our environment.

Will take a look at the perl toolkit, haven't done perl in many years but it may have something useful.

0 Kudos
jrackliffe
Hot Shot
Hot Shot

The Perl Toolkit has a great community behind it. Basically because its the one with the most history and the unix-like underpinnings of ESX you have more folks with familiarity.

It has a number of the same "helper" symantics you see in Vim and PS to help make especially searching VI seamless.

Ohh... and should you go w Vim and want to add in the Hosts you can just add the following loop. I just wasn't sure if you meant the ESX Host, NFS, iSCSI target or something else.



foreach (DatastoreHostMount dhm in dse.Host)
{
HostSystem h = (HostSystem)vc.GetView(dhm.Key, null);
Console.WriteLine(h.Name);
} 


Good luck with your efforts. Still wish I could pinpoint the SOAP breakdown for you, but it seems like I am missing some bit of info.

J

0 Kudos