/**
* Abiquo community edition
* cloud management application for hybrid clouds
* Copyright (C) 2008-2010 - Abiquo Holdings S.L.
*
* This application is free software; you can redistribute it and/or
* modify it under the terms of the GNU LESSER GENERAL PUBLIC
* LICENSE as published by the Free Software Foundation under
* version 3 of the License
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* LESSER GENERAL PUBLIC LICENSE v.3 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package com.abiquo.nodecollector.domain.collectors.hyperv;
import static org.jinterop.dcom.impls.JIObjectFactory.narrowObject;
import java.util.ArrayList;
import java.util.List;
import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.core.IJIComObject;
import org.jinterop.dcom.core.JIArray;
import org.jinterop.dcom.core.JIString;
import org.jinterop.dcom.core.JIVariant;
import org.jinterop.dcom.impls.JIObjectFactory;
import org.jinterop.dcom.impls.automation.IJIDispatch;
import org.jinterop.dcom.impls.automation.IJIEnumVariant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.abiquo.server.core.infrastructure.nodecollector.VirtualSystemStatusEnumType;
import com.hyper9.jwbem.SWbemServices;
/**
* Utility functions to manage HyperV data.
*
* @author ibarrera
*/
public final class HyperVUtils
{
/** The logger. */
private static final Logger LOGGER = LoggerFactory.getLogger(HyperVUtils.class);
/**
* Parses an array of raw objects and transform them into COM Objects.
*
* @param set The array to transform.
* @return The parsed Array.
* @throws JIException If transformation cannot be done.
*/
public static JIVariant[][] enumToJIVariantArray(final JIVariant[] set) throws JIException
{
final Integer A_MILLION = 1000000;
final IJIDispatch toConvertDispatch =
(IJIDispatch) narrowObject(set[0].getObjectAsComObject()
.queryInterface(IJIDispatch.IID));
final JIVariant toConvertVariant = toConvertDispatch.get("_NewEnum");
final IJIComObject toConvertComObject = toConvertVariant.getObjectAsComObject();
final IJIEnumVariant toConvertEnumVariant =
(IJIEnumVariant) narrowObject(toConvertComObject.queryInterface(IJIEnumVariant.IID));
final ArrayList<JIVariant[]> res = new ArrayList<JIVariant[]>();
int i = 0;
final int threshold = A_MILLION; // to avoid infinite loop, in both msdn and j-interop
// nothing is said about enumeration
while (true)
{
Object[] values = null;
try
{
values = toConvertEnumVariant.next(1);
}
catch (JIException e)
{
break;
}
if (values != null)
{
JIArray array = (JIArray) values[0];
res.add((JIVariant[]) array.getArrayInstance());
}
i++;
if (i >= threshold)
{
break;
}
}
return res.toArray(new JIVariant[res.size()][]);
}
/**
* Parses an array of COM Objects and transforms them to a list of {@link IJIDispatch} objects.
*
* @param set The array to transform.
* @return The list of <code>IJIDispatch</code> objects.
* @throws JIException If transformation cannot be done.
*/
public static List<IJIDispatch> enumToIJIDispatchList(final JIVariant[] set) throws JIException
{
List<IJIDispatch> results = new ArrayList<IJIDispatch>();
JIVariant[][] tmpSet = enumToJIVariantArray(set);
for (JIVariant[] element : tmpSet)
{
for (JIVariant element2 : element)
{
IJIDispatch dispatch =
(IJIDispatch) JIObjectFactory.narrowObject(element2.getObjectAsComObject()
.queryInterface(IJIDispatch.IID));
results.add(dispatch);
}
}
return results;
}
/**
* Runs a query using the specified service.
*
* @param query The query to run.
* @param service Service to use to run the query.
* @return The query results.
* @throws JIException If query can not be executed.
*/
public static List<IJIDispatch> execQuery(final String query, final SWbemServices service)
throws JIException
{
IJIDispatch dispatcher = service.getObjectDispatcher();
Object[] inParams =
new Object[] {new JIString(query), JIVariant.OPTIONAL_PARAM(),
JIVariant.OPTIONAL_PARAM(), JIVariant.OPTIONAL_PARAM()};
JIVariant[] results = dispatcher.callMethodA("ExecQuery", inParams);
return HyperVUtils.enumToIJIDispatchList(results);
}
/**
* Gets the path of the dispatch.
*
* @param dispatch the dispatch to get the path from
* @return the dispatch path
* @throws JIException If an error occurs.
*/
public static String getDispatchPath(final IJIDispatch dispatch) throws JIException
{
// Getting the dispatcher of the Path
IJIDispatch pathDispatcher =
(IJIDispatch) JIObjectFactory.narrowObject(dispatch.get("Path_").getObjectAsComObject()
.queryInterface(IJIDispatch.IID));
// Getting the path
return pathDispatcher.get("Path").getObjectAsString2();
}
/**
* Checks if the specified object is a virtual hard disk.
*
* @param dispatch The object to be checked.
* @return Boolean indicating if the specified object is a virtual hard disk.
* @throws JIException If an error occurs.
*/
public static boolean isVirtualHardDisk(final IJIDispatch dispatch) throws JIException
{
int type = dispatch.get("ResourceType").getObjectAsInt();
if (type == HyperVConstants.VIRTUAL_DISK_RESOURCE_TYPE)
{
String subType = dispatch.get("ResourceSubType").getObjectAsString2();
return subType.equalsIgnoreCase(HyperVConstants.VIRTUAL_DISK_RESOURCE_SUBTYPE);
}
return false;
}
// /**
// * Checks if the specified object is a virtual hard disk.
// *
// * @param dispatch The object to be checked.
// * @return Boolean indicating if the specified object is a virtual hard disk.
// * @throws JIException If an error occurs.
// */
// public static boolean isDiskResourceType(final IJIDispatch dispatch) throws JIException
// {
// int type = dispatch.get("ResourceType").getObjectAsInt();
//
// return (type == HyperVConstants.DISK_RESOURCE_TYPE);
// }
/**
* Checks if the specified object is a virtual hard disk.
*
* @param dispatch The object to be checked.
* @return Boolean indicating if the specified object is a virtual hard disk.
* @throws JIException If an error occurs.
*/
public static boolean isVolumeDisk(final IJIDispatch dispatch) throws JIException
{
int type = dispatch.get("ResourceType").getObjectAsInt();
if (type == HyperVConstants.DISK_RESOURCE_TYPE)
{
String subType = dispatch.get("ResourceSubType").getObjectAsString2();
return subType.equalsIgnoreCase(HyperVConstants.DISKPHYSICAL);
}
return false;
}
/**
* Checks if the specified object is a virtual hard disk.
*
* @param dispatch The object to be checked.
* @return Boolean indicating if the specified object is a virtual hard disk.
* @throws JIException If an error occurs.
*/
// public static boolean isVirtualHardDisk(final IJIDispatch dispatch) throws JIException
// {
// String subType = dispatch.get("ResourceSubType").getObjectAsString2();
// return subType.equals(HyperVConstants.DISKSYNTHETIC);
// }
/**
* Translates an HyperV state code into an {@link VirtualMachineStateType}.
*
* @param state State code to translate.
* @return Translated state.
*/
public static VirtualSystemStatusEnumType translateState(final int state)
{
HyperVState st = null;
try
{
st = HyperVState.fromValue(state);
}
catch (IllegalArgumentException e)
{
// Probably we got a transition state Starting (32770), Saving (32773), Saving (32773),
// Stopping (32774), Pausing (32776), Resuming (32777) or Unknown
LOGGER.warn("Could not translate virtual machine state: {}", state);
return null;
}
switch (st)
{
case POWER_ON:
return VirtualSystemStatusEnumType.ON;
case POWER_OFF:
return VirtualSystemStatusEnumType.OFF;
case SUSPENDED:
return VirtualSystemStatusEnumType.OFF;
case PAUSED:
return VirtualSystemStatusEnumType.PAUSED;
default:
LOGGER.warn("Could not translate virtual machine state: {}", state);
return null;
}
}
/**
* Private constructor for utility class.
*/
private HyperVUtils()
{
}
}