blob: 4e2656e645c5ce37047fb42fb6d4fe8ff34d74c4 [file] [log] [blame]
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.director.v1_5.features;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.TASK_COMPLETE_TIMELY;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkConfigSection;
import static org.testng.Assert.assertTrue;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jclouds.vcloud.director.v1_5.AbstractVAppApiLiveTest;
import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.Task;
import org.jclouds.vcloud.director.v1_5.domain.Vm;
import org.jclouds.vcloud.director.v1_5.domain.network.FirewallRule;
import org.jclouds.vcloud.director.v1_5.domain.network.FirewallRuleProtocols;
import org.jclouds.vcloud.director.v1_5.domain.network.FirewallService;
import org.jclouds.vcloud.director.v1_5.domain.network.IpRange;
import org.jclouds.vcloud.director.v1_5.domain.network.IpRanges;
import org.jclouds.vcloud.director.v1_5.domain.network.IpScope;
import org.jclouds.vcloud.director.v1_5.domain.network.NatService;
import org.jclouds.vcloud.director.v1_5.domain.network.Network;
import org.jclouds.vcloud.director.v1_5.domain.network.Network.FenceMode;
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConfiguration;
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection;
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection.IpAddressAllocationMode;
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkFeatures;
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkServiceType;
import org.jclouds.vcloud.director.v1_5.domain.network.VAppNetworkConfiguration;
import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConfigSection;
import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* Tests the request/response behavior of {@link VAppTemplateApi}
*
* NOTE The environment MUST have at least one template configured
*
* @author Andrea Turli
*/
@Test(groups = { "live", "user" }, singleThreaded = true, testName = "VAppNetworksLiveTest")
public class VAppNetworksLiveTest extends AbstractVAppApiLiveTest {
private static final String HTTP_SECURITY_GROUP = "http";
private static final String DEFAULT_SECURITY_GROUP = "default";
private String key;
private Map<String, NetworkConfiguration> securityGroupToNetworkConfig;
private Network network;
@AfterClass(alwaysRun = true, dependsOnMethods = { "cleanUpEnvironment" })
protected void tidyUp() {
if (key != null) {
try {
Task remove = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).removeEntry(key);
taskDoneEventually(remove);
} catch (Exception e) {
logger.warn(e, "Error when deleting metadata entry '%s'", key);
}
}
}
@BeforeClass
void setUp() {
network = lazyGetNetwork();
securityGroupToNetworkConfig = addSecurityGroupToNetworkConfiguration(Reference.builder().fromEntity(network).build());
}
@AfterMethod
void cleanUpVmNetworks() {
disconnectVmFromVAppNetwork(vm);
}
@Test(description = "Create a vApp Network based on an org network with `default` firewall rules applied")
public void testAddVAppNetworkWithDefaultSecurityGroup() {
ImmutableList<String> securityGroups = ImmutableList.of(DEFAULT_SECURITY_GROUP);
addVAppNetworkWithSecurityGroupOnVApp(securityGroups, vAppUrn);
// Retrieve the modified section
NetworkConfigSection modified = vAppApi.getNetworkConfigSection(vAppUrn);
// Check the retrieved object is well formed
checkNetworkConfigSection(modified);
/*
* TODO
* powerOn machine, ssh to it, run sshd on a port, trying to connect
* `which sshd` -p 22
*
*/
}
@Test(description = "Create a vApp Network based on an org network with `http` firewall rules applied")
public void testAddVAppNetworkWithHttpSecurityGroup() {
ImmutableList<String> securityGroups = ImmutableList.of(HTTP_SECURITY_GROUP);
addVAppNetworkWithSecurityGroupOnVApp(securityGroups, vAppUrn);
// Retrieve the modified section
NetworkConfigSection modified = vAppApi.getNetworkConfigSection(vAppUrn);
// Check the retrieved object is well formed
checkNetworkConfigSection(modified);
/*
* TODO
* powerOn machine, ssh to it, run sshd on a port, trying to connect
* `which sshd` -p 22
*
*/
}
@Test(description = "Create a vApp Network based on an org network with both `defautl` and `http` firewall rules applied")
public void testAddVAppNetworkWithDefaultAndHttpSecurityGroup() {
ImmutableList<String> securityGroups = ImmutableList.of(DEFAULT_SECURITY_GROUP, HTTP_SECURITY_GROUP);
addVAppNetworkWithSecurityGroupOnVApp(securityGroups, vAppUrn);
// Retrieve the modified section
NetworkConfigSection modified = vAppApi.getNetworkConfigSection(vAppUrn);
// Check the retrieved object is well formed
checkNetworkConfigSection(modified);
/*
* TODO
* powerOn machine, ssh to it, run sshd on a port, trying to connect
* `which sshd` -p 22
*
*/
}
private void addVAppNetworkWithSecurityGroupOnVApp(ImmutableList<String> securityGroups, String vAppUrn) {
String newVAppNetworkName = generateVAppNetworkName(network.getName(), securityGroups);
// Create a vAppNetwork with firewall rules
NetworkConfigSection newSection = generateNetworkConfigSection(securityGroups, newVAppNetworkName);
Task editNetworkConfigSection = vAppApi.editNetworkConfigSection(vAppUrn, newSection);
assertTrue(retryTaskSuccess.apply(editNetworkConfigSection), String.format(TASK_COMPLETE_TIMELY, "editNetworkConfigSection"));
attachVmToVAppNetwork(vm, newVAppNetworkName);
}
private NetworkConfigSection generateNetworkConfigSection(List<String> securityGroups, String newVAppNetworkName) {
Set<FirewallRule> firewallRules = Sets.newLinkedHashSet();
for (String securityGroup : securityGroups) {
Set<FirewallRule> securityGroupFirewallRules = retrieveAllFirewallRules(securityGroupToNetworkConfig.get(securityGroup).getNetworkFeatures());
firewallRules.addAll(securityGroupFirewallRules);
}
FirewallService firewallService = addFirewallService(firewallRules);
NatService natService = addNatService();
IpScope ipScope = addNewIpScope();
NetworkConfiguration newConfiguration = NetworkConfiguration.builder()
.ipScope(ipScope)
.parentNetwork(Reference.builder().fromEntity(network).build())
.fenceMode(FenceMode.NAT_ROUTED)
.retainNetInfoAcrossDeployments(false)
.features(toNetworkFeatures(ImmutableSet.of(firewallService, natService)))
.build();
VAppNetworkConfiguration newVAppNetworkConfiguration = VAppNetworkConfiguration.builder().networkName(newVAppNetworkName).configuration(newConfiguration).build();
return NetworkConfigSection.builder()
.info("modified")
.networkConfigs(ImmutableSet.of(newVAppNetworkConfiguration))
.build();
}
private void attachVmToVAppNetwork(Vm vm, String vAppNetworkName) {
Set<NetworkConnection> networkConnections = vmApi.getNetworkConnectionSection(vm.getId())
.getNetworkConnections();
NetworkConnectionSection section = NetworkConnectionSection.builder()
.info("info")
.primaryNetworkConnectionIndex(0)
.build();
for (NetworkConnection networkConnection : networkConnections) {
NetworkConnection newNetworkConnection = networkConnection.toBuilder()
.network(vAppNetworkName)
.isConnected(true)
.networkConnectionIndex(0)
.ipAddressAllocationMode(IpAddressAllocationMode.POOL)
.build();
section = section.toBuilder().networkConnection(newNetworkConnection).build();
}
Task configureNetwork = vmApi.editNetworkConnectionSection(vm.getId(), section);
assertTaskSucceedsLong(configureNetwork);
}
private IpScope addNewIpScope() {
IpRange newIpRange = addIpRange();
IpRanges newIpRanges = IpRanges.builder()
.ipRange(newIpRange)
.build();
return IpScope.builder()
.isInherited(false)
.gateway("192.168.2.1")
.netmask("255.255.0.0")
.ipRanges(newIpRanges).build();
}
private IpRange addIpRange() {
IpRange newIpRange = IpRange.builder()
.startAddress("192.168.2.100")
.endAddress("192.168.2.199")
.build();
return newIpRange;
}
private Set<FirewallRule> retrieveAllFirewallRules(NetworkFeatures networkFeatures) {
Set<FirewallRule> firewallRules = Sets.newLinkedHashSet();
for (NetworkServiceType<?> networkServiceType : networkFeatures.getNetworkServices()) {
if (networkServiceType instanceof FirewallService) {
firewallRules.addAll(((FirewallService) networkServiceType).getFirewallRules());
}
}
return firewallRules;
}
private NetworkFeatures toNetworkFeatures(Set<? extends NetworkServiceType<?>> networkServices) {
NetworkFeatures networkFeatures = NetworkFeatures.builder()
.services(networkServices)
.build();
return networkFeatures;
}
private Set<FirewallRule> defaultFirewallRules() {
FirewallRuleProtocols protocols = FirewallRuleProtocols.builder()
.any(true)
.build();
FirewallRule egressAll = addFirewallRule(FirewallRuleProtocols.builder().tcp(true).build(), "allow ssh ingoing traffic", -1, 22, "in");
FirewallRule sshIngoing = addFirewallRule(protocols, "allow all outgoing traffic", -1, -1, "out");
return ImmutableSet.of(egressAll, sshIngoing);
}
private Set<FirewallRule> httpIngressFirewallRules() {
FirewallRuleProtocols protocols = FirewallRuleProtocols.builder().tcp(true).build();
FirewallRule httpIngoing = addFirewallRule(protocols , "allow http ingoing traffic", 80, 80, "in");
FirewallRule httpsIngoing = addFirewallRule(protocols , "allow https ingoing traffic", 443, 443, "in");
return ImmutableSet.of(httpIngoing, httpsIngoing);
}
private FirewallRule addFirewallRule(FirewallRuleProtocols protocols, String description, int sourcePort, int outPort, String direction) {
return FirewallRule.builder()
.isEnabled(true)
.description(description)
.policy("allow")
.protocols(protocols)
.port(outPort)
.destinationIp("Any")
.sourcePort(sourcePort)
.sourceIp("Any")
.direction(direction)
.enableLogging(false)
.build();
}
private FirewallService addFirewallService(Set<FirewallRule> firewallRules) {
FirewallService firewallService = FirewallService.builder()
.enabled(true)
.defaultAction("drop")
.logDefaultAction(false)
.firewallRules(firewallRules)
.build();
return firewallService;
}
private NatService addNatService() {
NatService natService = NatService.builder()
.enabled(true)
.natType("ipTranslation")
.policy("allowTraffic")
.build();
return natService;
}
private Map<String, NetworkConfiguration> addSecurityGroupToNetworkConfiguration(Reference parentNetworkRef) {
Set<FirewallRule> defaultFirewallRules = defaultFirewallRules();
Set<FirewallRule> httpFirewallRules = httpIngressFirewallRules();
Map<String, NetworkConfiguration> securityGroupToNetworkConfigurations = Maps.newHashMap();
securityGroupToNetworkConfigurations.put(DEFAULT_SECURITY_GROUP, addNetworkConfiguration(parentNetworkRef, defaultFirewallRules));
securityGroupToNetworkConfigurations.put(HTTP_SECURITY_GROUP, addNetworkConfiguration(parentNetworkRef, httpFirewallRules));
return securityGroupToNetworkConfigurations;
}
private NetworkConfiguration addNetworkConfiguration(Reference parentNetworkRef, Set<FirewallRule> newFirewallRules) {
FirewallService firewallService = addFirewallService(newFirewallRules);
IpScope ipScope = addNewIpScope();
NetworkConfiguration newConfiguration = NetworkConfiguration.builder()
.ipScope(ipScope)
.parentNetwork(parentNetworkRef)
.fenceMode(FenceMode.NAT_ROUTED)
.retainNetInfoAcrossDeployments(false)
.features(toNetworkFeatures(ImmutableSet.of(firewallService)))
.build();
return newConfiguration;
}
private static String generateVAppNetworkName(String orgNetworkName, List<String> securityGroupNames) {
return orgNetworkName + "-" + Joiner.on("+").join(securityGroupNames);
}
private void disconnectVmFromVAppNetwork(Vm vm) {
Set<NetworkConnection> networkConnections = vmApi.getNetworkConnectionSection(vm.getId())
.getNetworkConnections();
NetworkConnectionSection section = NetworkConnectionSection.builder()
.info("info")
.primaryNetworkConnectionIndex(0)
.build();
for (NetworkConnection networkConnection : networkConnections) {
section = section
.toBuilder()
.networkConnection(networkConnection.toBuilder()
.network("none")
.ipAddressAllocationMode(IpAddressAllocationMode.NONE)
.build())
.build();
}
Task cleanUpNetworks = vmApi.editNetworkConnectionSection(vm.getId(), section);
assertTaskSucceedsLong(cleanUpNetworks);
}
}