Issue 382: progress on libvirt from andrea

This commit is contained in:
Adrian Cole 2010-10-29 14:16:22 -07:00
commit 8522839dc2
7 changed files with 277 additions and 38 deletions

View File

@ -44,12 +44,17 @@
<artifactId>libvirt</artifactId>
<version>0.4.6</version>
</dependency>
<dependency>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
<version>3.0.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
<version>3.0.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.jamesmurty.utils</groupId>
<artifactId>java-xmlbuilder</artifactId>
<version>0.3</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>

View File

@ -19,46 +19,87 @@
package org.jclouds.libvirt.compute.functions;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import javax.inject.Singleton;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.internal.VolumeImpl;
import org.libvirt.Domain;
import org.libvirt.LibvirtException;
import org.libvirt.StorageVol;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.jamesmurty.utils.XMLBuilder;
/**
* @author Adrian Cole
*/
@Singleton
public class DomainToHardware implements Function<Domain, Hardware> {
@Override
public Hardware apply(Domain from) {
HardwareBuilder builder = new HardwareBuilder();
try {
builder.id(from.getUUIDString());
@Override
public Hardware apply(Domain from) {
HardwareBuilder builder = new HardwareBuilder();
builder.providerId(from.getID() + "");
builder.name(from.getName());
List<Processor> processors = Lists.newArrayList();
for (int i = 0; i < from.getInfo().nrVirtCpu; i++) {
processors.add(new Processor(i + 1, 1));
}
builder.processors(processors);
try {
builder.id(from.getUUIDString());
builder.providerId(from.getID() + "");
builder.name(from.getName());
List<Processor> processors = Lists.newArrayList();
for (int i = 0; i < from.getInfo().nrVirtCpu; i++) {
processors.add(new Processor(i + 1, 1));
}
builder.processors(processors);
builder.ram((int) from.getInfo().maxMem);
// TODO volumes
} catch (LibvirtException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return builder.build();
}
builder.ram((int) from.getInfo().maxMem);
// TODO volumes
List<Volume> volumes = Lists.newArrayList();
XMLBuilder xmlBuilder = XMLBuilder.parse(new InputSource(new StringReader(from.getXMLDesc(0))));
Document doc = xmlBuilder.getDocument();
XPathExpression expr = XPathFactory.newInstance().newXPath().compile("//devices/disk[@device='disk']/source/@file");
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
String diskFileName = nodes.item(0).getNodeValue();
for (int i = 0; i < nodes.getLength(); i++) {
StorageVol storageVol = from.getConnect().storageVolLookupByPath(diskFileName);
String id = storageVol.getKey();
float size = new Long(storageVol.getInfo().capacity).floatValue();
volumes.add(new VolumeImpl(id, Volume.Type.LOCAL, size, null, true, false));
}
builder.volumes((List<Volume>) volumes);
} catch (LibvirtException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XPathExpressionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return builder.build();
}
}

View File

@ -52,7 +52,7 @@ public class LibvirtImageToImage implements Function<org.jclouds.libvirt.Image,
OsFamily family = null;
try {
family = OsFamily.fromValue(from.name);
builder.operatingSystem(new OperatingSystemBuilder().name(from.name).family(family).build());
builder.operatingSystem(new OperatingSystemBuilder().name(from.name).family(family).description("ubuntu").build());
} catch (IllegalArgumentException e) {
logger.debug("<< didn't match os(%s)", from);
}

View File

@ -1,12 +1,41 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.libvirt.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
@ -17,11 +46,20 @@ import org.jclouds.libvirt.Image;
import org.libvirt.Connect;
import org.libvirt.Domain;
import org.libvirt.LibvirtException;
import org.libvirt.StoragePool;
import org.libvirt.StorageVol;
import org.libvirt.jna.Libvirt;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.jamesmurty.utils.XMLBuilder;
/**
* defines the connection between the {@link Libvirt} implementation and the jclouds
@ -30,6 +68,7 @@ import com.google.common.collect.Lists;
*/
@Singleton
public class LibvirtComputeServiceAdapter implements ComputeServiceAdapter<Domain, Domain, Image, Datacenter> {
private final Connect client;
@Inject
@ -39,14 +78,58 @@ public class LibvirtComputeServiceAdapter implements ComputeServiceAdapter<Domai
@Override
public Domain runNodeWithTagAndNameAndStoreCredentials(String tag, String name, Template template,
Map<String, Credentials> credentialStore) {
Map<String, Credentials> credentialStore) {
// create the backend object using parameters from the template.
// Domain from = client.createDomainInDC(template.getLocation().getId(), name,
// Integer.parseInt(template.getImage().getProviderId()),
// Integer.parseInt(template.getHardware().getProviderId()));
// store the credentials so that later functions can use them
// credentialStore.put("node#" + from.id + "", new Credentials(from.loginUser, from.password));
return null;
// credentialStore.put(from.id + "", new Credentials(from.loginUser, from.password));
String[] domains;
try {
domains = client.listDefinedDomains();
Domain domain = null;
String xmlDesc = "";
for (String domainName : domains) {
domain = client.domainLookupByName(domainName);
if (domainName.equals("ttylinux")) {
domain = client.domainLookupByName(domainName);
xmlDesc = domain.getXMLDesc(0);
System.out.println("domain: " + domain.getUUIDString());
XMLBuilder builder = XMLBuilder.parse(new InputSource(new StringReader(xmlDesc)));
Document doc = builder.getDocument();
XPathExpression expr = null;
NodeList nodes = null;
String xpathString = "//devices/disk[@device='disk']/source/@file"; // +
expr = XPathFactory.newInstance().newXPath().compile(xpathString);
nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
String diskFileName = nodes.item(0).getNodeValue();
System.out.println("\n *** diskFileName " + diskFileName);
StorageVol storageVol = client.storageVolLookupByPath(diskFileName);
System.out.println(storageVol.getXMLDesc(0));
// cloning volume
String poolName = "default";
StoragePool storagePool = client.storagePoolLookupByName(poolName);
StorageVol clonedVol = cloneVolume(storagePool, storageVol);
// System.out.println(generateClonedDomainXML(xmlDesc));
domain = client.domainDefineXML(generateClonedDomainXML(xmlDesc));
}
}
return domain;
} catch (LibvirtException e) {
return propogate(e);
} catch (Exception e) {
return propogate(e);
}
}
@Override
@ -56,17 +139,35 @@ public class LibvirtComputeServiceAdapter implements ComputeServiceAdapter<Domai
@Override
public Iterable<Image> listImages() {
return ImmutableSet.of();
// return ImmutableSet.of();
// TODO
// return client.listImages();
List<Image> images = Lists.newArrayList();
images.add(new Image(1, "ubuntu"));
return images;
}
// @Override
// public Iterable<Domain> listNodes() {
// try {
// List<Domain> domains = Lists.newArrayList();
// for (int domain : client.listDomains()) {
// domains.add(client.domainLookupByID(domain));
// }
// return domains;
// } catch (LibvirtException e) {
// return propogate(e);
// }
// }
@Override
public Iterable<Domain> listNodes() {
try {
List<Domain> domains = Lists.newArrayList();
for (int domain : client.listDomains()) {
domains.add(client.domainLookupByID(domain));
for (String domain : client.listDefinedDomains()) {
domains.add(client.domainLookupByName(domain));
}
return domains;
} catch (LibvirtException e) {
@ -80,6 +181,12 @@ public class LibvirtComputeServiceAdapter implements ComputeServiceAdapter<Domai
return null;
}
protected <T> T propogate(Exception e) {
Throwables.propagate(e);
assert false;
return null;
}
@Override
public Iterable<Datacenter> listLocations() {
return ImmutableSet.of(new Datacenter(1, "SFO"));
@ -111,4 +218,71 @@ public class LibvirtComputeServiceAdapter implements ComputeServiceAdapter<Domai
propogate(e);
}
}
public void createDomain() throws LibvirtException {
Domain domain = client.domainDefineXML("<domain type='test' id='2'>" + " <name>deftest</name>"
+ " <uuid>004b96e1-2d78-c30f-5aa5-f03c87d21e70</uuid>" + " <memory>8388608</memory>"
+ " <vcpu>2</vcpu>" + " <os><type arch='i686'>hvm</type></os>" + " <on_reboot>restart</on_reboot>"
+ " <on_poweroff>destroy</on_poweroff>" + " <on_crash>restart</on_crash>" + "</domain>");
}
private static StorageVol cloneVolume(StoragePool storagePool, StorageVol from) throws LibvirtException,
XPathExpressionException, ParserConfigurationException, SAXException, IOException, TransformerException {
String fromXML = from.getXMLDesc(0);
String clonedXML = generateClonedVolumeXML(fromXML);
System.out.println(clonedXML);
// return null;
return storagePool.storageVolCreateXMLFrom(clonedXML, from, 0);
}
private static String generateClonedVolumeXML(String fromXML) throws ParserConfigurationException, SAXException,
IOException, XPathExpressionException, TransformerException {
Properties outputProperties = new Properties();
// Explicitly identify the output as an XML document
outputProperties.put(javax.xml.transform.OutputKeys.METHOD, "xml");
// Pretty-print the XML output (doesn't work in all cases)
outputProperties.put(javax.xml.transform.OutputKeys.INDENT, "yes");
// Get 2-space indenting when using the Apache transformer
outputProperties.put("{http://xml.apache.org/xslt}indent-amount", "2");
XMLBuilder builder = XMLBuilder.parse(new InputSource(new StringReader(fromXML)));
String cloneAppend = "-clone";
builder.xpathFind("//volume/name").t(cloneAppend);
builder.xpathFind("//volume/key").t(cloneAppend);
builder.xpathFind("//volume/target/path").t(cloneAppend);
return builder.asString(outputProperties);
}
private static String generateClonedDomainXML(String fromXML) throws ParserConfigurationException, SAXException,
IOException, XPathExpressionException, TransformerException {
Properties outputProperties = new Properties();
// Explicitly identify the output as an XML document
outputProperties.put(javax.xml.transform.OutputKeys.METHOD, "xml");
// Pretty-print the XML output (doesn't work in all cases)
outputProperties.put(javax.xml.transform.OutputKeys.INDENT, "yes");
// Get 2-space indenting when using the Apache transformer
outputProperties.put("{http://xml.apache.org/xslt}indent-amount", "2");
XMLBuilder builder = XMLBuilder.parse(new InputSource(new StringReader(fromXML)));
String cloneAppend = "-clone";
builder.xpathFind("//domain/name").t(cloneAppend);
// change uuid domain
Element oldChild = builder.xpathFind("//domain/uuid").getElement();
Node newNode = oldChild.cloneNode(true);
newNode.getFirstChild().setNodeValue(UUID.randomUUID().toString());
builder.getDocument().getDocumentElement().replaceChild(newNode, oldChild);
builder.xpathFind("//domain/devices/disk/source").a("file", "/var/lib/libvirt/images/ttylinux.img-clone");
// TODO generate valid MAC address
builder.xpathFind("//domain/devices/interface/mac").a("address", "52:54:00:5c:dd:eb");
return builder.asString(outputProperties);
}
}

View File

@ -35,7 +35,7 @@ public class LibvirtComputeServiceContextBuilderTest {
.createContext(new StandaloneComputeServiceContextSpec<Domain, Domain, Image, Datacenter>("libvirt",
"test:///default", "1", "identity", "credential", new LibvirtComputeServiceContextModule(),
ImmutableSet.<Module> of()));
System.err.println(context.getComputeService().listNodes());
//System.err.println(context.getComputeService().
context.close();
}

View File

@ -1,6 +1,6 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,7 +23,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.StandaloneComputeServiceContextSpec;
import org.jclouds.compute.domain.Template;
import org.jclouds.libvirt.Datacenter;
import org.jclouds.libvirt.Image;
import org.jclouds.libvirt.compute.domain.LibvirtComputeServiceContextModule;
@ -63,9 +65,26 @@ public class LibvirtExperimentLiveTest {
endpoint, apiversion, identity, credential, new LibvirtComputeServiceContextModule(), ImmutableSet
.<Module> of()));
context.getComputeService().listNodes();
System.out.println("images " + context.getComputeService().listImages());
System.out.println("nodes " + context.getComputeService().listNodes());
System.out.println("hardware profiles " + context.getComputeService().listHardwareProfiles());
Template defaultTemplate = context.getComputeService().templateBuilder()
.hardwareId("c7ff2039-a9f1-a659-7f91-e0f82f59d52e").imageId("1") //.locationId("")
.build();
/*
* We will probably make a default template out of properties at some point
* You can control the default template via overriding a method in standalonecomputeservicexontextmodule
*/
// context.getComputeService().templateOptions().;
context.getComputeService().runNodesWithTag("ttylinux", 1, defaultTemplate);
} finally {
} catch (RunNodesException e) {
e.printStackTrace();
} finally {
if (context != null)
context.close();
}

View File

@ -130,7 +130,7 @@
<!-- ======================= -->
<root>
<priority value="WARN" />
<priority value="DEBUG" />
</root>
</log4j:configuration>