/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.vcloud.features;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.io.BaseEncoding.base64;
import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.vcloud.VCloudApiMetadata;
import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.compute.options.VCloudTemplateOptions;
import org.jclouds.vcloud.domain.Org;
import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VDC;
import org.jclouds.vcloud.domain.Vm;
import org.jclouds.vcloud.internal.BaseVCloudClientLiveTest;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.common.net.HostAndPort;
/**
* This tests that we can use guest customization as an alternative to bootstrapping with ssh. There
* are a few advantages to this, including the fact that it can work inside google appengine where
* network sockets (ssh:22) are prohibited.
*
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, singleThreaded = true, testName = "VmClientLiveTest")
public class VmClientLiveTest extends BaseVCloudClientLiveTest {
@Test
public void testGetThumbnailOfVm() throws Exception {
Org org = getVCloudApi().getOrgClient().findOrgNamed(null);
for (ReferenceType vdc : org.getVDCs().values()) {
VDC response = getVCloudApi().getVDCClient().getVDC(vdc.getHref());
for (ReferenceType item : response.getResourceEntities().values()) {
if (item.getType().equals(VCloudMediaType.VAPP_XML)) {
try {
VApp app = getVCloudApi().getVAppClient().getVApp(item.getHref());
assertNotNull(app);
for (Vm vm : app.getChildren()) {
assert getVCloudApi().getVmClient().getScreenThumbnailForVm(vm.getHref()) != null;
}
} catch (RuntimeException e) {
}
}
}
}
}
@Test
public void testGetVm() throws Exception {
Org org = getVCloudApi().getOrgClient().findOrgNamed(null);
for (ReferenceType vdc : org.getVDCs().values()) {
VDC response = getVCloudApi().getVDCClient().getVDC(vdc.getHref());
for (ReferenceType item : response.getResourceEntities().values()) {
if (item.getType().equals(VCloudMediaType.VAPP_XML)) {
try {
VApp app = getVCloudApi().getVAppClient().getVApp(item.getHref());
assertNotNull(app);
for (Vm vm : app.getChildren()) {
assertEquals(getVCloudApi().getVmClient().getVm(vm.getHref()).getHref(), vm.getHref());
}
} catch (RuntimeException e) {
}
}
}
}
}
@Test
public void testExtendedOptionsWithCustomizationScript() throws Exception {
String PARSE_VMTOOLSD = "vmtoolsd --cmd=\"info-get guestinfo.ovfenv\" |grep vCloud_CustomizationInfo|sed 's/.*value=\"\\(.*\\)\".*/\\1/g'";
String group = prefix + "cus";
NodeMetadata node = null;
try {
TemplateOptions options = client.templateOptions();
options.blockOnPort(22, 180);
options.as(VCloudTemplateOptions.class).customizationScript(script);
options.as(VCloudTemplateOptions.class).description(group);
node = getOnlyElement(client.createNodesInGroup(group, 1, options));
VApp vapp = client.getContext().unwrap(VCloudApiMetadata.CONTEXT_TOKEN).getApi().getVAppClient().getVApp(
node.getUri());
assertEquals(vapp.getDescription(), group);
Vm vm = Iterables.get(vapp.getChildren(), 0);
String apiOutput = vm.getGuestCustomizationSection().getCustomizationScript();
checkApiOutput(apiOutput);
ExecResponse vmTools = client.runScriptOnNode(node.getId(), PARSE_VMTOOLSD,
wrapInInitScript(false).runAsRoot(false));
checkApiOutput(new String(base64().decode(vmTools.getOutput().trim()), UTF_8));
ExecResponse foo = client.runScriptOnNode(node.getId(), "cat /root/foo.txt", wrapInInitScript(false)
.runAsRoot(false));
checkCustomizationOccurred(foo);
} finally {
if (node != null)
client.destroyNode(node.getId());
}
}
protected void checkCustomizationOccurred(ExecResponse exec) {
// note that vmwaretools throws in \r characters when executing scripts
assert exec.getOutput().equals(iLoveAscii + "\r\n") : exec;
}
protected void checkApiOutput(String apiOutput) {
checkApiOutput1_0_1(apiOutput);
}
// make sure the script has a lot of screwy characters, knowing our parser
// throws-out \r
protected String iLoveAscii = "I '\"love\"' {asc|!}*&";
String script = "cat > /root/foo.txt<<EOF\n" + iLoveAscii + "\nEOF\n";
protected void checkApiOutput1_0_1(String apiOutput) {
// in 1.0.1, vcloud director seems to pass through characters via api
// flawlessly
assertEquals(apiOutput, script);
}
protected void checkApiOutput1_0_0(String apiOutput) {
// in 1.0.0, vcloud director seems to remove all newlines
assertEquals(apiOutput, script.replace("\n", ""));
}
protected HostAndPort getSocket(NodeMetadata node) {
return HostAndPort.fromParts(get(node.getPublicAddresses(), 0), 22);
}
}