/*- * ============LICENSE_START======================================================= * ONAP - SO * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Modifications Copyright (c) 2019 Samsung * ================================================================================ * 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. * ============LICENSE_END========================================================= */ package org.onap.so.openstack.utils; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Optional; import org.onap.so.cloud.CloudConfig; import org.onap.so.cloud.authentication.AuthenticationMethodFactory; import org.onap.so.cloud.authentication.KeystoneAuthHolder; import org.onap.so.cloud.authentication.KeystoneV3Authentication; import org.onap.so.cloud.authentication.ServiceEndpointNotFoundException; import org.onap.so.db.catalog.beans.CloudIdentity; import org.onap.so.db.catalog.beans.CloudSite; import org.onap.so.db.catalog.beans.ServerType; import org.onap.logging.filter.base.ErrorCode; import org.onap.so.logger.MessageEnum; import org.onap.so.openstack.beans.NetworkInfo; import org.onap.so.openstack.exceptions.MsoAdapterException; import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound; import org.onap.so.openstack.exceptions.MsoException; import org.onap.so.openstack.exceptions.MsoIOException; import org.onap.so.openstack.exceptions.MsoNetworkAlreadyExists; import org.onap.so.openstack.exceptions.MsoNetworkNotFound; import org.onap.so.openstack.exceptions.MsoOpenstackException; import org.onap.so.openstack.mappers.NetworkInfoMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.woorea.openstack.base.client.OpenStackBaseException; import com.woorea.openstack.base.client.OpenStackConnectException; import com.woorea.openstack.base.client.OpenStackRequest; import com.woorea.openstack.base.client.OpenStackResponseException; import com.woorea.openstack.keystone.Keystone; import com.woorea.openstack.keystone.model.Access; import com.woorea.openstack.keystone.model.Authentication; import com.woorea.openstack.keystone.utils.KeystoneUtils; import com.woorea.openstack.quantum.Quantum; import com.woorea.openstack.quantum.model.Network; import com.woorea.openstack.quantum.model.Networks; import com.woorea.openstack.quantum.model.Port; import com.woorea.openstack.quantum.model.Segment; @Component public class MsoNeutronUtils extends MsoCommonUtils { // Fetch cloud configuration each time (may be cached in CloudConfig class) @Autowired private CloudConfig cloudConfig; @Autowired private AuthenticationMethodFactory authenticationMethodFactory; @Autowired private MsoTenantUtilsFactory tenantUtilsFactory; @Autowired private KeystoneV3Authentication keystoneV3Authentication; private static Logger logger = LoggerFactory.getLogger(MsoNeutronUtils.class); public enum NetworkType { BASIC, PROVIDER, MULTI_PROVIDER }; /** * Create a network with the specified parameters in the given cloud/tenant. * * If a network already exists with the same name, an exception will be thrown. Note that this is an MSO-imposed * restriction. Openstack does not require uniqueness on network names. *
*
* @param cloudSiteId The cloud identifier (may be a region) in which to create the network.
* @param tenantId The tenant in which to create the network
* @param type The type of network to create (Basic, Provider, Multi-Provider)
* @param networkName The network name to create
* @param provider The provider network name (for Provider or Multi-Provider networks)
* @param vlans A list of VLAN segments for the network (for Provider or Multi-Provider networks)
* @return a NetworkInfo object which describes the newly created network
* @throws MsoNetworkAlreadyExists Thrown if a network with the same name already exists
* @throws MsoOpenstackException Thrown if the Openstack API call returns an exception
* @throws MsoCloudSiteNotFound Thrown if the cloudSite is invalid or unknown
*/
public NetworkInfo createNetwork(String cloudSiteId, String tenantId, NetworkType type, String networkName,
String provider, List
* Whenever possible, the network ID should be used as it is much more efficient. Query by name requires retrieval
* of all networks for the tenant and search for matching name.
*
*
* @param networkNameOrId The network to query
* @param tenantId The Openstack tenant to look in for the network
* @param cloudSiteId The cloud identifier (may be a region) in which to query the network.
* @return a NetworkInfo object describing the queried network, or null if not found
* @throws MsoOpenstackException Thrown if the Openstack API call returns an exception
* @throws MsoCloudSiteNotFound
*/
public NetworkInfo queryNetwork(String networkNameOrId, String tenantId, String cloudSiteId) throws MsoException {
logger.debug("In queryNetwork");
// Obtain the cloud site information
CloudSite cloudSite =
cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
Quantum neutronClient = getNeutronClient(cloudSite, tenantId);
// Check if the network exists and return its info
try {
Network network = findNetworkByNameOrId(neutronClient, networkNameOrId);
if (network == null) {
logger.debug("Query Network: {} not found in tenant {}", networkNameOrId, tenantId);
return null;
}
return new NetworkInfoMapper(network).map();
} catch (OpenStackBaseException e) {
// Convert Neutron exception to an MsoOpenstackException
MsoException me = neutronExceptionToMsoException(e, "QueryNetwork");
throw me;
} catch (RuntimeException e) {
// Catch-all
MsoException me = runtimeExceptionToMsoException(e, "QueryNetwork");
throw me;
}
}
public Optional
*
* @param networkId Openstack ID of the network to delete
* @param tenantId The Openstack tenant.
* @param cloudSiteId The cloud identifier (may be a region) from which to delete the network.
* @return true if the network was deleted, false if the network did not exist
* @throws MsoOpenstackException If the Openstack API call returns an exception, this local exception will be
* thrown.
* @throws MsoCloudSiteNotFound
*/
public boolean deleteNetwork(String networkId, String tenantId, String cloudSiteId) throws MsoException {
// Obtain the cloud site information where we will create the stack
CloudSite cloudSite =
cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
Quantum neutronClient = getNeutronClient(cloudSite, tenantId);
try {
// Check that the network exists.
Network network = findNetworkById(neutronClient, networkId);
if (network == null) {
logger.info("{} Network not found! Network id: {} Cloud site: {} Tenant: {} ",
MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId);
return false;
}
OpenStackRequest
* Note that updating the 'segments' array is not normally supported by Neutron. This method relies on a Platform
* Orchestration extension (using SDN controller to manage the virtual networking).
*
* @param cloudSiteId The cloud site ID (may be a region) in which to update the network.
* @param tenantId Openstack ID of the tenant in which to update the network
* @param networkId The unique Openstack ID of the network to be updated
* @param type The network type (Basic, Provider, Multi-Provider)
* @param provider The provider network name. This should not change.
* @param vlans The list of VLAN segments to replace
* @return a NetworkInfo object which describes the updated network
* @throws MsoNetworkNotFound Thrown if the requested network does not exist
* @throws MsoOpenstackException Thrown if the Openstack API call returns an exception
* @throws MsoCloudSiteNotFound
*/
public NetworkInfo updateNetwork(String cloudSiteId, String tenantId, String networkId, NetworkType type,
String provider, List
* On successful authentication, the Quantum object will be cached for the tenantID + cloudId so that it can be
* reused without reauthenticating with Openstack every time.
*
* @param cloudSite - a cloud site definition
* @param tenantId - Openstack tenant ID
* @return an authenticated Quantum object
*/
private Quantum getNeutronClient(CloudSite cloudSite, String tenantId) throws MsoException {
String cloudId = cloudSite.getId();
String region = cloudSite.getRegionId();
// Obtain an MSO token for the tenant from the identity service
CloudIdentity cloudIdentity = cloudSite.getIdentityService();
MsoTenantUtils tenantUtils =
tenantUtilsFactory.getTenantUtilsByServerType(cloudIdentity.getIdentityServerType());
final String keystoneUrl = tenantUtils.getKeystoneUrl(cloudId, cloudIdentity);
String neutronUrl = null;
String tokenId = null;
try {
if (ServerType.KEYSTONE.equals(cloudIdentity.getIdentityServerType())) {
Keystone keystoneTenantClient = new Keystone(keystoneUrl);
Access access = null;
Authentication credentials = authenticationMethodFactory.getAuthenticationFor(cloudIdentity);
OpenStackRequest