/******************************************************************************* * Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved * * 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.cloudifysource.esc.driver.provisioning.network.openstack; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; import org.cloudifysource.domain.cloud.Cloud; import org.cloudifysource.domain.cloud.compute.ComputeTemplate; import org.cloudifysource.esc.driver.provisioning.network.BaseNetworkDriver; import org.cloudifysource.esc.driver.provisioning.network.NetworkDriverConfiguration; import org.cloudifysource.esc.driver.provisioning.network.NetworkProvisioningException; import org.cloudifysource.esc.driver.provisioning.openstack.OpenStackCloudifyDriver; import org.cloudifysource.esc.driver.provisioning.openstack.OpenStackComputeClient; import org.cloudifysource.esc.driver.provisioning.openstack.OpenStackNetworkClient; import org.cloudifysource.esc.driver.provisioning.openstack.OpenstackException; import org.cloudifysource.esc.driver.provisioning.openstack.OpenstackJsonSerializationException; import org.cloudifysource.esc.driver.provisioning.openstack.rest.FloatingIp; import org.cloudifysource.esc.driver.provisioning.openstack.rest.NovaServer; import org.cloudifysource.esc.driver.provisioning.openstack.rest.Port; import org.cloudifysource.esc.driver.provisioning.openstack.rest.RouteFixedIp; /** * Network driver for Openstack. * * @author victor * @since 2.7.0 * */ public class OpenstackNetworkDriver extends BaseNetworkDriver { private static Logger logger = Logger.getLogger(OpenstackNetworkDriver.class.getName()); private OpenStackComputeClient computeApi; private OpenStackNetworkClient networkApi; @Override public void setConfig(final NetworkDriverConfiguration config) { super.setConfig(config); final Cloud cloud = config.getCloud(); this.initDeployer(cloud); String mngGroup = cloud.getProvider().getManagementGroup(); mngGroup = mngGroup == null ? OpenStackCloudifyDriver.getDefaultMangementPrefix() : mngGroup; } private void initDeployer(final Cloud cloud) { final String managementMachineTemplate = cloud.getConfiguration().getManagementMachineTemplate(); final ComputeTemplate cloudTemplate = cloud.getCloudCompute().getTemplates().get(managementMachineTemplate); String endpoint = null; final Map<String, Object> overrides = cloudTemplate.getOverrides(); if (overrides != null && !overrides.isEmpty()) { endpoint = (String) overrides.get(OpenStackCloudifyDriver.OPENSTACK_ENDPOINT); } final String networkVersion = (String) cloudTemplate.getOptions().get(OpenStackCloudifyDriver.OPT_NETWORK_API_VERSION); final String networkServiceName = (String) cloudTemplate.getOptions().get(OpenStackCloudifyDriver.OPT_NETWORK_SERVICE_NAME); final String computeServiceName = (String) cloudTemplate.getOptions().get(OpenStackCloudifyDriver.OPT_COMPUTE_SERVICE_NAME); final String cloudImageId = cloudTemplate.getImageId(); final String region = cloudImageId.split("/")[0]; final String cloudUser = cloud.getUser().getUser(); final String password = cloud.getUser().getApiKey(); final StringTokenizer st = new StringTokenizer(cloudUser, ":"); final String tenant = st.hasMoreElements() ? (String) st.nextToken() : null; final String username = st.hasMoreElements() ? (String) st.nextToken() : null; try { this.computeApi = new OpenStackComputeClient(endpoint, username, password, tenant, region, computeServiceName); this.networkApi = new OpenStackNetworkClient(endpoint, username, password, tenant, region, networkServiceName, networkVersion); } catch (OpenstackJsonSerializationException e) { throw new IllegalStateException(e); } } @Override public String allocateFloatingIP(final String poolName, final Map<String, Object> context, final long duration, final TimeUnit timeUnit) throws NetworkProvisioningException, TimeoutException { // poolname = external network's name try { final FloatingIp floatingIp = networkApi.allocateFloatingIp(poolName); if (floatingIp == null) { throw new NetworkProvisioningException("Floating ip has not been created from the pool '" + poolName + "'"); } return floatingIp.getFloatingIpAddress(); } catch (final OpenstackException e) { throw new NetworkProvisioningException(e); } } @Override public void assignFloatingIP(final String instanceIPAddress, final String floatingIp, final Map<String, Object> context, final long duration, final TimeUnit timeUnit) throws NetworkProvisioningException, TimeoutException { try { final FloatingIp floatingIpByIp = networkApi.getFloatingIpByIp(floatingIp); final NovaServer server = this.computeApi.getServerByIp(instanceIPAddress); final List<Port> ports = networkApi.getPortsByDeviceId(server.getId()); if (floatingIpByIp == null || ports == null || ports.isEmpty()) { throw new NetworkProvisioningException( "Couldn't assign floating ip. Missing floating ip in the pool or port does not exists."); } for (final Port port : ports) { final List<RouteFixedIp> fixedIps = port.getFixedIps(); for (final RouteFixedIp routeFixedIp : fixedIps) { if (instanceIPAddress.equals(routeFixedIp.getIpAddress())) { networkApi.assignFloatingIp(floatingIpByIp.getId(), port.getId()); return; } } } throw new NetworkProvisioningException( "Couldn't assign floating ip. Port associated to ip " + instanceIPAddress + " not found."); } catch (final OpenstackException e) { throw new NetworkProvisioningException(e); } } @Override public void releaseFloatingIP(final String floatingIP, final Map<String, Object> context, final long duration, final TimeUnit timeUnit) throws NetworkProvisioningException, TimeoutException { try { final FloatingIp floatingIp = networkApi.getFloatingIpByIp(floatingIP); if (floatingIp == null) { logger.warning("Floating ip not found ip='" + floatingIP + "'. May already be released."); } else { networkApi.releaseFloatingIp(floatingIp.getId()); } } catch (final OpenstackException e) { throw new NetworkProvisioningException(e); } } @Override public void unassignFloatingIP(final String instanceIPAddress, final String floatingIP, final Map<String, Object> context, final long duration, final TimeUnit timeUnit) throws NetworkProvisioningException, TimeoutException { try { final FloatingIp floatingIp = networkApi.getFloatingIpByIp(floatingIP); if (floatingIp == null) { throw new NetworkProvisioningException("Floating ip not found ip='" + floatingIP + "'"); } networkApi.unassignFloatingIp(floatingIp.getId()); } catch (final OpenstackException e) { throw new NetworkProvisioningException(e); } } }