/** * 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.util.ArrayList; import java.util.List; import javax.xml.xpath.XPathExpressionException; import org.apache.commons.io.FilenameUtils; import org.libvirt.Domain; import org.libvirt.DomainInfo; import org.libvirt.LibvirtException; import org.libvirt.NodeInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.abiquo.nodecollector.aim.AimCollector; import com.abiquo.nodecollector.constants.MessageValues; import com.abiquo.nodecollector.domain.collectors.libvirt.LeaksFreeConnect; import com.abiquo.nodecollector.exception.CollectorException; import com.abiquo.nodecollector.exception.NoManagedException; import com.abiquo.nodecollector.exception.libvirt.AimException; import com.abiquo.nodecollector.utils.XPathUtils; 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; /** * Abstract class which provides common information collection for Libvirt-supported Hypervisors (In * our case KVM and XEN). * * @author jdevesa */ public abstract class AbstractLibvirtCollector extends AbstractCollector { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractLibvirtCollector.class); private LeaksFreeConnect connection; protected AimCollector aimcollector; // private LeaksFreeConnect login() throws CollectorException // { // try // { // return new LeaksFreeConnect(getConnectionURL()); // } // catch (LibvirtException e) // { // throw new CollectorException(MessageValues.CONN_EXCP_I, e); // } // } // // private void logout(LeaksFreeConnect conn) // { // try // { // conn.close(); // } // catch (LibvirtException e) // { // e.printStackTrace(); // } // } @Override public HostDto getHostInfo() throws CollectorException { final int KBYTE = 1024; final HostDto hostInfo = new HostDto(); // LeaksFreeConnect conn = login(); try { final NodeInfo nodeInfo = connection.nodeInfo(); hostInfo.setName(connection.getHostName()); hostInfo.setCpu(Long.valueOf(nodeInfo.cores)); hostInfo.setRam(nodeInfo.memory * KBYTE); hostInfo.setHypervisor(getHypervisorType().getValue()); hostInfo.setVersion(String.valueOf(connection.getVersion())); List<ResourceType> datastores = aimcollector.getDatastores(); hostInfo.getResources().addAll(aimcollector.getNetInterfaces()); hostInfo.setInitiatorIQN(aimcollector.getInitiatorIQN()); try { // [ABICLOUDPREMIUM-345] Node collector mustn't return datastores NFS equal to AM. // TODO Depends on [ABICLOUDPREMIUM-365] // datastores = removeRepositoryDatastore(datastores, repositoryLocation); hostInfo.getResources().addAll(datastores); checkPhysicalState(); hostInfo.setStatus(HostStatusEnumType.MANAGED); } catch (NoManagedException e) { hostInfo.setStatus(HostStatusEnumType.NOT_MANAGED); hostInfo.setStatusInfo(e.getMessage()); } } catch (LibvirtException e) { LOGGER.error("Unhandled exception :", e); throw new CollectorException(MessageValues.COLL_EXCP_PH, e); } catch (AimException e) { LOGGER.error("Unhandled exception :", e); throw new CollectorException(e.getMessage(), e); } // finally // { // logout(conn); // } return hostInfo; } @Override public VirtualSystemCollectionDto getVirtualMachines() throws CollectorException { final VirtualSystemCollectionDto vmc = new VirtualSystemCollectionDto(); final List<Domain> listOfDomains = new ArrayList<Domain>(); try { // Defined domains are the closed ones! for (String domainValue : connection.listDefinedDomains()) { if (domainValue != null) // Why null domains are returned? { listOfDomains.add(connection.domainLookupByName(domainValue)); } } // Domains are the started ones for (int domainInt : connection.listDomains()) { listOfDomains.add(connection.domainLookupByID(domainInt)); } // Create the list of Virtual Systems from the recovered domains for (Domain domain : listOfDomains) { if (!isDomain0(domain)) { vmc.getVirtualSystems().add(createVirtualSystemFromDomain(domain)); } } } catch (LibvirtException e1) { LOGGER.error("Unhandled exception :", e1); throw new CollectorException(e1.getMessage(), e1); } catch (XPathExpressionException e) { LOGGER.error("Unhandled exception :", e); throw new CollectorException(e.getMessage(), e); } return vmc; } protected void checkPhysicalState() throws NoManagedException { try { aimcollector.checkAIM(); } catch (AimException e) { throw new NoManagedException(e.getMessage(), e); } } @Override public void disconnect() throws CollectorException { try { if (getConnection() != null) { getConnection().close(); } } catch (LibvirtException e) { LOGGER.error("Unhandled exception when disconnect:", e); throw new CollectorException(MessageValues.CONN_EXCP_III, e); } } /** * @param domain a domain defined by libvirt. * @return a {@link VirtualSystem} object * @throws LibvirtException can be thrown when connecting to libvirt * @throws XPathExpressionException can be thrown parsing the libvirt response */ private VirtualSystemDto createVirtualSystemFromDomain(final Domain domain) throws LibvirtException, XPathExpressionException { final int KBYTE = 1024; final DomainInfo domainInfo = domain.getInfo(); final String domainXML = domain.getXMLDesc(0); final VirtualSystemDto vSys = new VirtualSystemDto(); vSys.setRam(domainInfo.memory * KBYTE); vSys.setCpu(Long.valueOf(domainInfo.nrVirtCpu)); vSys.setName(domain.getName()); vSys.setUuid(domain.getUUIDString()); // If autoport is enabled, set port to -1 to indicate that remote access will not be // available String autoport = XPathUtils.getValue("//graphics/@autoport", domainXML); if (autoport != null && autoport.equalsIgnoreCase("yes")) { vSys.setVport(-1L); } else { // Evaluate the libvirt XML desc of the domain to get the remote display port. String vPortString = XPathUtils.getValue("//graphics/@port", domainXML); if (vPortString == null || vPortString.isEmpty()) { vSys.setVport(-1L); } else { Long vPort = Long.valueOf(vPortString); vSys.setVport(vPort <= 0 ? -1 : vPort); } } // Evaluate the libvirt XML desc of the domain to get the image files // using the XPath features // final List<String> imageValues = XPathUtils.getValues("//disk/source/@file", // domainXML); // for (String imageValue : imageValues) // { // vSys.getResources().add(createDiskFromImagePath(imageValue)); // } NodeList systemdisk = XPathUtils.getNodes("//disk[target[@dev='hda']]/source", domainXML); if (systemdisk.item(0) != null) { Node image = systemdisk.item(0).getAttributes().getNamedItem("file"); if (image != null) { vSys.getResources().add(createDiskFromImagePath(image.getNodeValue())); } else { image = systemdisk.item(0).getAttributes().getNamedItem("dev"); vSys.getResources().add(createDiskFromVolumePath(image.getNodeValue())); } } // Homogenize the status switch (domainInfo.state) { case VIR_DOMAIN_RUNNING: case VIR_DOMAIN_BLOCKED: vSys.setStatus(VirtualSystemStatusEnumType.ON); break; case VIR_DOMAIN_PAUSED: vSys.setStatus(VirtualSystemStatusEnumType.PAUSED); break; default: vSys.setStatus(VirtualSystemStatusEnumType.OFF); break; } return vSys; } /** * Create a {@link Disk} objet from an image value. * * @param imagePath image where the disk is stored * @return a Disk object filled with the information */ private ResourceType createDiskFromImagePath(final String imagePath) { final ResourceType currentHardDisk = new ResourceType(); currentHardDisk.setResourceType(ResourceEnumType.HARD_DISK); currentHardDisk.setAddress(imagePath); try { long diskSize = aimcollector.getDiskFileSize(imagePath); currentHardDisk.setUnits(diskSize); } catch (AimException e) { currentHardDisk.setUnits(0L); } currentHardDisk.setResourceSubType(VirtualDiskEnumType.UNKNOWN.value()); currentHardDisk.setConnection(FilenameUtils.getFullPathNoEndSeparator(imagePath)); return currentHardDisk; } /** * Create a {@link Disk} objet from an image value. * * @param imagePath image where the disk is stored * @return a Disk object filled with the information */ private ResourceType createDiskFromVolumePath(final String imagePath) { final ResourceType currentHardDisk = new ResourceType(); currentHardDisk.setResourceType(ResourceEnumType.VOLUME_DISK); currentHardDisk.setAddress(""); // Datastore directory try { long diskSize = aimcollector.getDiskFileSize(imagePath); currentHardDisk.setUnits(diskSize); } catch (AimException e) { currentHardDisk.setUnits(0L); } currentHardDisk.setResourceSubType(VirtualDiskEnumType.STATEFUL.value()); currentHardDisk.setConnection(""); // Datastore root path return currentHardDisk; } /** * Returns true if given domain is "Domain-0" * * @param domain to evaluate * @return true if given domain is "Domain-0" * @throws LibvirtException exception */ protected abstract boolean isDomain0(Domain domain) throws LibvirtException; public LeaksFreeConnect getConnection() { return connection; } public void setConnection(final LeaksFreeConnect conn) { this.connection = conn; } }