VMware {code} Community
Chandrashekhar
Contributor
Contributor

"A specified parameter was not correct" error while executing queryPerfComposite()

Hi,

I am getting "A specified parameter was not correct" error while executing queryPerfComposite() method. I want to get performance counter information for host systems and virtual machines from vCenter server. I am following steps below :

1) Connect to vCenter server using VI SDK.

2) Get performance manager MOR for vCenter.

3) get MOR of all the hosts present in vCenter.

4) For each host MOR, execute "queryAvailablePerfMetric()" method.

5) Finally, after checking available perfMetrics, call queryPerfComposite().

At step 5, I am getting above error. Anyone has any clue for this?

Below is my code snippet :

final ArrayList<ManagedObjectReference> hostMORList = connection.getServiceUtil().getDecendentMoRefs(null, "HostSystem");

for (ManagedObjectReference hostMor : hostMORList) { final String machineName = (String) connection.getServiceUtil().getDynamicProperty(hostMor, "name");

System.out.println("DEBUG : Machine name : " + machineName);

final PerfCounterInfo[] counterInfo = (PerfCounterInfo])connection.getServiceUtil().getDynamicProperty(perfManager,"perfCounter");

Calendar metricEndTime = Calendar.getInstance();

Calendar metricStartTime = (Calendar) metricEndTime.clone();

metricStartTime.add(Calendar.HOUR, -1);

final PerfMetricId[] availCounterIds = servicePort.queryAvailablePerfMetric( perfManager,hostMor,metricStartTime,metricEndTime, this.interval);

final PerfCompositeMetric newValues = getCounterValues(hostMor,counterIds);

-


/

  • Searches performance counter information for specified entity. Entity can be host or virtual machine.

  • @param hostMor Managed object reference to host system

  • @param metricList Metric id's from which values to be retrieved

  • @return Performance counter values and information

  • @throws RemoteException throws remote exception

*/

private PerfCompositeMetric getCounterValues(final ManagedObjectReference hostMor,final PerfMetricId[] metricList) throws RemoteException {

final PerfQuerySpec qSpecs = new PerfQuerySpec();

qSpecs.setEntity(hostMor);

qSpecs.setMaxSample(new Integer(this.sampleCount));

qSpecs.setMetricId(metricList);

qSpecs.setIntervalId(new Integer(this.interval));

final PerfCompositeMetric compositeMetrics = servicePort.queryPerfComposite(perfManager, qSpecs);

return compositeMetrics;

}

-


and here is the stack trace after exception :

Exception in thread "main" AxisFault

faultCode: ServerFaultCode

faultSubcode:

faultString: A specified parameter was not correct.

metricId

faultActor:

faultNode:

faultDetail:

InvalidArgumentFault:<invalidProperty>metricId</invalidProperty>

A specified parameter was not correct.

metricId

-


Am I missing anything in this code?

My logic to get performance counters from hosts and VM's is as follows :

1) Log in to vCenter server.

2) get performance manager MOR of vCenter.

3) Check available performance counters for performance manager.

4) Get MOR to all the hosts present under vCenter server.

5) For each host MOR, execute queryAvailablePerfMetric() method.

6) Call queryPerfComposite for each host MOR so that it will give performance counter information for host and its all the virtual machines also.

Is my logic correct? Please let me know if i am missing anything...

Thanks in advance!!!!

Message was edited by: Chandrashekhar

Reply
0 Kudos
3 Replies
njain
Expert
Expert

Hi Chandrashekhar,

From the stack trace, it seems that the value for the "metricId" property is not set correctly when invoking queryPerfComposite method.

In the code snippet provided above, you get the available metric Ids by invoking queryAvailablePerfMetric method and get the values in "availCounterIds" variable. But when you call "getCounterValues" method, you are passing "counterIds" and not "availCounterIds". I think this is causing the metrics to be set as null in the PerfQuerySpec and "QueryPerfComposite" method requires metricId parameter to be set.

Can you check the values for metricId that you are setting in the PerfQuerySpec and validate if the values are being set correctly?

Chandrashekhar
Contributor
Contributor

Thanks a billion njain for your answer !! Smiley Happy

I looked at my code. You were asking about "counterIds" varialble. Actually, "availCounterIds" variable contains all the counter ID's available for vCenter. From those counter, I select some counters like cpu.usage.average, memory.used.average, etc. and store those ID's in "counterIds". I have one filterCounters() method which does this. So, after filtering out counters, I pass "counterIds" to QueryPerfComposite() method.

Meanwhile, I found out that, when I select particular counter, I create one object of type "PerfMetricId" to be used in QueryPerfComposite() method. Problem is, I want counter values for all the instance of device like if my server has 8 cores, I want cpu.usage.average for all the 8 cores. Thats why, I keep "instance" property of perfMetricId object as ""*. when I use "" *as instance, then only I get the "A specified parameter was not correct" error. If I set this instance to "", then my program works fine.

But if I make instance "" then, I cant get values for all the instances, and I want value for all the instances. I guess I have narrowed down cause of problem. How can I solve this problem now?

Here is a snippet of my filterCounters() method./**

Filters out unwanted counters from list.*

@param availableCounters Counters available for system*

@return Performance counter information in the form of perfmetricId*

*/

+private PerfMetricId[filterCounters(final PerfCounterInfo] availableCounters) {

*

  • // Get counter information for all available instances

*+{color:#0000ff} final ArrayList<PerfMetricId> filteredCounters = new ArrayList<PerfMetricId>();+*

for (final PerfCounterInfo counter : availableCounters) {

*+

  • final String counterName = counter.getNameInfo().getKey();*

+*

final String category = counter.getGroupInfo().getLabel();

final String rollupType = counter.getRollupType().getValue();

final int counterId = counter.getKey();

/ *

  • counterRequired() method just searches throught list of counters supplied by user and checks if current counter is needed or not.

  • If counter is needed, then returns null, false otherwise.

final boolean counterRequired = counterRequired(counterName,category,rollupType);

  • selectedCounters.put(counterId, counter);*

if (counterRequired) {+* *+

System.out.println("DEBUG : We need " + category + "." + counterName + "." + rollupType + " counter. ID : " + counter.getKey());+

PerfMetricId counterMetric = new PerfMetricId(null,null,counterId,""); // If I keep instance as "" error comes.

filteredCounters.add(counterMetric);

}

}

return filteredCounters.toArray(new PerfMetricId[0]);

}

Documentation of PerfMetricId suggests that, we should use "" to get values for all the instances. Here is the part of it 😘

  • An asterisk (*) to specify all instances of the metric for the specified counterId

  • Double-quotes ("") to specify aggregated statistics

Can you suggest something? I have re cheked my code and whenever I set instance to "*", then only I get error. How to get values for all the instances?

Reply
0 Kudos
sajuptpm
Contributor
Contributor

Reply
0 Kudos