/** * 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; import java.io.StringReader; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.wink.common.internal.providers.entity.csv.CsvReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.virtualbox_4_0.DeviceType; import org.virtualbox_4_0.IHost; import org.virtualbox_4_0.IHostNetworkInterface; import org.virtualbox_4_0.IMachine; import org.virtualbox_4_0.IMedium; import org.virtualbox_4_0.IMediumAttachment; import org.virtualbox_4_0.IVirtualBox; import org.virtualbox_4_0.MachineState; import org.virtualbox_4_0.VirtualBoxManager; import com.abiquo.model.enumerator.HypervisorType; import com.abiquo.nodecollector.aim.AimCollector; import com.abiquo.nodecollector.aim.impl.AimCollectorImpl; import com.abiquo.nodecollector.constants.MessageValues; import com.abiquo.nodecollector.domain.Collector; import com.abiquo.nodecollector.exception.CollectorException; import com.abiquo.nodecollector.exception.ConnectionException; import com.abiquo.nodecollector.exception.NoManagedException; import com.abiquo.nodecollector.exception.libvirt.AimException; import com.abiquo.nodecollector.utils.ResourceComparator; import com.abiquo.server.core.infrastructure.nodecollector.HostDto; import com.abiquo.server.core.infrastructure.nodecollector.HostStatusEnumType; import com.abiquo.server.core.infrastructure.nodecollector.ResourceEnumType; import com.abiquo.server.core.infrastructure.nodecollector.ResourceType; import com.abiquo.server.core.infrastructure.nodecollector.VirtualDiskEnumType; import com.abiquo.server.core.infrastructure.nodecollector.VirtualSystemCollectionDto; import com.abiquo.server.core.infrastructure.nodecollector.VirtualSystemDto; import com.abiquo.server.core.infrastructure.nodecollector.VirtualSystemStatusEnumType; /** * Special connection for VirtualBox Hypervisor. * * @author jdevesa@abiquo.com */ @Collector(type = HypervisorType.VBOX, order = 3) public class VirtualBoxCollector extends AbstractCollector { /** The vbox. */ private transient IVirtualBox vbox; /** The logger. */ private static final Logger LOGGER = LoggerFactory.getLogger(VirtualBoxCollector.class); /** The web session manager object. The root of the vBox Hypervisor WService session. */ private transient VirtualBoxManager mgr; // private long defaultDatastoreSize = 1073741824000L; String wsmanuser = "wsman"; String wsmanpassword = "secret"; Integer vboxPort = 18083; String IDECONTROLLER = "IDESController"; String SATACONTROLLER = "SATASController"; /** * WsmanCollector */ protected AimCollector aimcollector; @Override public void connect(final String user, final String password) throws ConnectionException { wsmanuser = user; wsmanpassword = password; try { mgr = VirtualBoxManager.createInstance(null); mgr.connect("http://" + this.getIpAddress() + ":" + vboxPort, user, password); vbox = mgr.getVBox(); } catch (Exception e) { throw new ConnectionException(MessageValues.CONN_EXCP_I, e); } try { aimcollector = new AimCollectorImpl(getIpAddress(), getAimPort()); } catch (AimException e) { throw new ConnectionException(MessageValues.CONN_EXCP_IV, e); } } @Override public HostDto getHostInfo() throws CollectorException { final Integer MEGABYTE = 1048576; try { final IHost host = vbox.getHost(); final HostDto info = new HostDto(); info.setName("default_vBox_name"); info.setCpu(host.getProcessorOnlineCount()); info.setRam(host.getMemorySize() * MEGABYTE); info.setInitiatorIQN("iqn.2008-04.com.sun.virtualbox.initiator"); // Getting interface resources List<IHostNetworkInterface> ifaces = host.getNetworkInterfaces(); List<ResourceType> ifacesResource = new ArrayList<ResourceType>(); for (IHostNetworkInterface iHostNetworkInterface : ifaces) { ResourceType nicResource = new ResourceType(); nicResource.setAddress(iHostNetworkInterface.getHardwareAddress()); nicResource.setElementName(iHostNetworkInterface.getName()); nicResource.setResourceType(ResourceEnumType.NETWORK_INTERFACE); ifacesResource.add(nicResource); } // String diskFolder = vbox.getSystemProperties().getDefaultHardDiskFolder(); // ResourceType diskResource = new ResourceType(); // diskResource.setAddress(diskFolder); // diskResource.setElementName(diskFolder); // diskResource.setResourceType(ResourceEnumType.STORAGE_DISK); // diskResource.setUnits(new Long(defaultDatastoreSize)); // diskResource.setAvailableUnits(new Long(defaultDatastoreSize)); List<ResourceType> datastores = aimcollector.getDatastores(); try { // [ABICLOUDPREMIUM-345] Node collector mustn't return datastores NFS equal to AM. // TODO Depends on [ABICLOUDPREMIUM-365] // datastores = removeRepositoryDatastore(datastores, repositoryLocation); info.getResources().addAll(datastores); checkPhysicalState(); info.setStatus(HostStatusEnumType.MANAGED); } catch (NoManagedException e) { info.setStatus(HostStatusEnumType.NOT_MANAGED); info.setStatusInfo(e.getMessage()); } Collections.sort(ifacesResource, new ResourceComparator()); info.getResources().addAll(ifacesResource); info.setHypervisor(getHypervisorType().getValue()); info.setVersion(vbox.getVersion()); info.setStatus(HostStatusEnumType.MANAGED); return info; } catch (Throwable e) { throw new CollectorException(MessageValues.COLL_VER_NS, e); } } @Override public VirtualSystemCollectionDto getVirtualMachines() throws CollectorException { final Integer MEGABYTE = 1048576; VirtualSystemCollectionDto machines = new VirtualSystemCollectionDto(); for (IMachine machine : vbox.getMachines()) { VirtualSystemDto nextVMachine = new VirtualSystemDto(); nextVMachine.setName(machine.getName()); nextVMachine.setVport(getFreePortFromPortsList(machine.getVRDEServer().getVRDEProperty( "TCP/Ports"))); nextVMachine.setCpu(machine.getCPUCount()); nextVMachine.setUuid(machine.getId()); nextVMachine.setRam(machine.getMemorySize() * MEGABYTE); MachineState state = machine.getState(); if (state.compareTo(MachineState.Running) == 0) { nextVMachine.setStatus(VirtualSystemStatusEnumType.ON); } else if (state.compareTo(MachineState.Paused) == 0) { nextVMachine.setStatus(VirtualSystemStatusEnumType.PAUSED); } else { nextVMachine.setStatus(VirtualSystemStatusEnumType.OFF); } List<IMediumAttachment> mediumAttachments = machine.getMediumAttachments(); for (IMediumAttachment iMediumAttachment : mediumAttachments) { ResourceType newResource = new ResourceType(); if (iMediumAttachment.getType().compareTo(DeviceType.HardDisk) == 0) { IMedium medium = iMediumAttachment.getMedium(); if (medium.getDeviceType().compareTo(DeviceType.HardDisk) == 0) { String formatName = medium.getFormat(); if (!"iSCSI".equals(formatName)) { newResource.setResourceType(ResourceEnumType.HARD_DISK); newResource.setAddress(medium.getLocation()); newResource.setUnits(medium.getSize().longValue()); newResource.setConnection(getDatastoreFromFile(medium.getLocation())); newResource .setResourceSubType(mediumFormatToVirtualDiskEnum(formatName) .value()); } else { newResource.setAddress("unknown"); newResource.setConnection("unknown"); if (iMediumAttachment.getController().contains(IDECONTROLLER)) { newResource.setResourceType(ResourceEnumType.HARD_DISK); newResource.setUnits(new Long(0)); newResource .setResourceSubType(VirtualDiskEnumType.STATEFUL.value()); } else if (iMediumAttachment.getController().contains(SATACONTROLLER)) { newResource.setResourceType(ResourceEnumType.VOLUME_DISK); newResource.setUnits(medium.getSize().longValue()); newResource.setResourceSubType(VirtualDiskEnumType.UNKNOWN.value()); } } } } nextVMachine.getResources().add(newResource); } machines.getVirtualSystems().add(nextVMachine); } return machines; } /** * Parses the fileName to get the datastore name. * * @param fileName the file name to parse * @return the datastore directory */ private String getDatastoreFromFile(final String fileName) { int count = StringUtils.countMatches(fileName, "/"); if (count == 1) { return "/"; } int indexEndDirectory = fileName.lastIndexOf('/'); return fileName.substring(0, indexEndDirectory); } @Override public void disconnect() throws CollectorException { try { mgr.disconnect(); mgr.cleanup(); } catch (Exception e) { throw new CollectorException(MessageValues.CONN_EXCP_III, e); } } private int getFreePortFromPortsList(final String csvPorts) { List<Integer> portList = new ArrayList<Integer>(); try { CsvReader reader = new CsvReader(new StringReader(csvPorts)); String[] line = reader.readLine(); if (line != null) { for (String port : line) { Integer portInt = Integer.valueOf(port); portList.add(portInt); } } } catch (NumberFormatException e) { LOGGER.debug("Ignoring not integer port"); } if (portList.isEmpty()) { return -1; } else { return portList.get(0); } } private VirtualDiskEnumType mediumFormatToVirtualDiskEnum(final String formatId) { if ("raw".equals(formatId)) { return VirtualDiskEnumType.RAW; } else if ("VMDK".equals(formatId)) { return VirtualDiskEnumType.VMDK_FLAT; } else if ("VDI".equals(formatId)) { return VirtualDiskEnumType.VDI_FLAT; } else if ("VHD".equals(formatId)) { return VirtualDiskEnumType.VHD_FLAT; } else { return VirtualDiskEnumType.INCOMPATIBLE; } } protected void checkPhysicalState() throws NoManagedException { try { aimcollector.checkAIM(); } catch (AimException e) { throw new NoManagedException(e.getMessage(), e); } } }