use of org.onap.so.openstack.exceptions.MsoException in project so by onap.
the class MsoHeatUtils method createStack.
/**
* Create a new Stack in the specified cloud location and tenant. The Heat template and parameter map are passed in
* as arguments, along with the cloud access credentials. It is expected that parameters have been validated and
* contain at minimum the required parameters for the given template with no extra (undefined) parameters..
*
* The Stack name supplied by the caller must be unique in the scope of this tenant. However, it should also be
* globally unique, as it will be the identifier for the resource going forward in Inventory. This latter is managed
* by the higher levels invoking this function.
*
* The caller may choose to let this function poll Openstack for completion of the stack creation, or may handle
* polling itself via separate calls to query the status. In either case, a StackInfo object will be returned
* containing the current status. When polling is enabled, a status of CREATED is expected. When not polling, a
* status of BUILDING is expected.
*
* An error will be thrown if the requested Stack already exists in the specified Tenant and Cloud.
*
* For 1510 - add "environment", "files" (nested templates), and "heatFiles" (get_files) as parameters for
* createStack. If environment is non-null, it will be added to the stack. The nested templates and get_file entries
* both end up being added to the "files" on the stack. We must combine them before we add them to the stack if
* they're both non-null.
*
* @param cloudSiteId The cloud (may be a region) in which to create the stack.
* @param cloudOwner the cloud owner of the cloud site in which to create the stack
* @param tenantId The Openstack ID of the tenant in which to create the Stack
* @param stackName The name of the stack to create
* @param vduModel contains information about the vdu model (added for plugin adapter)
* @param heatTemplate The Heat template
* @param stackInputs A map of key/value inputs
* @param pollForCompletion Indicator that polling should be handled in Java vs. in the client
* @param environment An optional yaml-format string to specify environmental parameters
* @param files a Map<String, Object> that lists the child template IDs (file is the string, object is an int of
* Template id)
* @param heatFiles a Map<String, Object> that lists the get_file entries (fileName, fileBody)
* @param backout Donot delete stack on create Failure - defaulted to True
* @return A StackInfo object
* @throws MsoOpenstackException Thrown if the Openstack API call returns an exception.
*/
public StackInfo createStack(String cloudSiteId, String cloudOwner, String tenantId, String stackName, VduModelInfo vduModel, String heatTemplate, Map<String, ?> stackInputs, boolean pollForCompletion, int timeoutMinutes, String environment, Map<String, Object> nestedTemplates, Map<String, Object> heatFiles, boolean backout, boolean failIfExists) throws MsoException {
stripMultiCloudInputs(stackInputs);
CreateStackParam createStack = createStackParam(stackName, heatTemplate, stackInputs, timeoutMinutes, environment, nestedTemplates, heatFiles);
Stack currentStack = queryHeatStack(stackName, cloudSiteId, tenantId);
boolean operationPerformed = false;
if (currentStack != null) {
logger.debug("Existing Stack found with Status: {} ", currentStack.getStackStatus());
if (CREATE_COMPLETE.equals(currentStack.getStackStatus())) {
new StackInfoMapper(currentStack).map();
} else if (CREATE_IN_PROGRESS.equals(currentStack.getStackStatus())) {
// TODO should check poll for completion right here
currentStack = processCreateStack(cloudSiteId, tenantId, timeoutMinutes, backout, currentStack, createStack, true);
} else if (CREATE_FAILED.equals(currentStack.getStackStatus()) || DELETE_FAILED.equals(currentStack.getStackStatus())) {
try {
if (pollForCompletion) {
processCreateStack(cloudSiteId, tenantId, timeoutMinutes, backout, currentStack, createStack, true);
}
} catch (MsoException e) {
if (e instanceof StackCreationException) {
logger.warn("Error during Stack will attempt to recreate stack");
currentStack = createStack(createStack, cloudSiteId, tenantId);
currentStack.setStackName(stackName);
if (pollForCompletion) {
currentStack = processCreateStack(cloudSiteId, tenantId, timeoutMinutes, backout, currentStack, createStack, true);
}
} else {
throw e;
}
}
}
} else {
currentStack = createStack(createStack, cloudSiteId, tenantId);
currentStack.setStackName(stackName);
if (pollForCompletion) {
currentStack = processCreateStack(cloudSiteId, tenantId, timeoutMinutes, backout, currentStack, createStack, true);
}
operationPerformed = true;
}
StackInfo stackInfo = new StackInfoMapper(currentStack).map();
stackInfo.setOperationPerformed(operationPerformed);
return stackInfo;
}
use of org.onap.so.openstack.exceptions.MsoException in project so by onap.
the class MsoHeatUtils method queryStacks.
public Stacks queryStacks(String cloudSiteId, String tenantId, int limit, String marker) throws MsoCloudSiteNotFound, HeatClientException {
Heat heatClient;
try {
heatClient = getHeatClient(cloudSiteId, tenantId);
} catch (MsoException e) {
logger.error("Error Creating Heat Client", e);
throw new HeatClientException("Error Creating Heat Client", e);
}
OpenStackRequest<Stacks> request = heatClient.getStacks().list().queryParam("limit", limit).queryParam("marker", marker);
return executeAndRecordOpenstackRequest(request, false);
}
use of org.onap.so.openstack.exceptions.MsoException in project so by onap.
the class MsoKeystoneUtils method createTenant.
/**
* Create a tenant with the specified name in the given cloud. If the tenant already exists, an Exception will be
* thrown. The MSO User will also be added to the "member" list of the new tenant to perform subsequent Nova/Heat
* commands in the tenant. If the MSO User association fails, the entire transaction will be rolled back.
* <p>
* For the AIC Cloud (DCP/LCP): it is not clear that cloudId is needed, as all admin requests go to the centralized
* identity service in DCP. However, if some artifact must exist in each local LCP instance as well, then it will be
* needed to access the correct region.
* <p>
*
* @param tenantName The tenant name to create
* @param cloudSiteId The cloud identifier (may be a region) in which to create the tenant.
* @return the tenant ID of the newly created tenant
* @throws MsoTenantAlreadyExists Thrown if the requested tenant already exists
* @throws MsoOpenstackException Thrown if the Openstack API call returns an exception
*/
public String createTenant(String tenantName, String cloudSiteId, Map<String, String> metadata, boolean backout) throws MsoException {
// Obtain the cloud site information where we will create the tenant
Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
if (!cloudSiteOpt.isPresent()) {
LOGGER.error("{} MSOCloudSite {} not found {} ", MessageEnum.RA_CREATE_TENANT_ERR, cloudSiteId, ErrorCode.DataError.getValue());
throw new MsoCloudSiteNotFound(cloudSiteId);
}
Keystone keystoneAdminClient = getKeystoneAdminClient(cloudSiteOpt.get());
Tenant tenant = null;
try {
// Check if the tenant already exists
tenant = findTenantByName(keystoneAdminClient, tenantName);
if (tenant != null) {
// Tenant already exists. Throw an exception
LOGGER.error("{} Tenant name {} already exists on Cloud site id {}, {}", MessageEnum.RA_TENANT_ALREADY_EXIST, tenantName, cloudSiteId, ErrorCode.DataError.getValue());
throw new MsoTenantAlreadyExists(tenantName, cloudSiteId);
}
// Does not exist, create a new one
tenant = new Tenant();
tenant.setName(tenantName);
tenant.setDescription("SDN Tenant (via MSO)");
tenant.setEnabled(true);
OpenStackRequest<Tenant> request = keystoneAdminClient.tenants().create(tenant);
tenant = executeAndRecordOpenstackRequest(request);
} catch (OpenStackBaseException e) {
// Convert Keystone OpenStackResponseException to MsoOpenstackException
throw keystoneErrorToMsoException(e, "CreateTenant");
} catch (RuntimeException e) {
// Catch-all
throw runtimeExceptionToMsoException(e, "CreateTenant");
}
// apply tenant metadata if supported by the cloud site
try {
CloudIdentity cloudIdentity = cloudSiteOpt.get().getIdentityService();
User msoUser = findUserByNameOrId(keystoneAdminClient, cloudIdentity.getMsoId());
Role memberRole = findRoleByNameOrId(keystoneAdminClient, cloudIdentity.getMemberRole());
if (msoUser != null && memberRole != null) {
OpenStackRequest<Void> request = keystoneAdminClient.tenants().addUser(tenant.getId(), msoUser.getId(), memberRole.getId());
executeAndRecordOpenstackRequest(request);
}
if (cloudIdentity.getTenantMetadata() && metadata != null && !metadata.isEmpty()) {
Metadata tenantMetadata = new Metadata();
tenantMetadata.setMetadata(metadata);
OpenStackRequest<Metadata> metaRequest = keystoneAdminClient.tenants().createOrUpdateMetadata(tenant.getId(), tenantMetadata);
executeAndRecordOpenstackRequest(metaRequest);
}
} catch (Exception e) {
// so roll back the tenant.
if (!backout) {
LOGGER.warn("{} Create Tenant errored, Tenant deletion suppressed {} ", MessageEnum.RA_CREATE_TENANT_ERR, ErrorCode.DataError.getValue());
} else {
try {
OpenStackRequest<Void> request = keystoneAdminClient.tenants().delete(tenant.getId());
executeAndRecordOpenstackRequest(request);
} catch (Exception e2) {
// Just log this one. We will report the original exception.
LOGGER.error("{} Nested exception rolling back tenant {} ", MessageEnum.RA_CREATE_TENANT_ERR, ErrorCode.DataError.getValue(), e2);
}
}
// Propagate the original exception on user/role/tenant mapping
if (e instanceof OpenStackBaseException) {
// Convert Keystone Exception to MsoOpenstackException
throw keystoneErrorToMsoException((OpenStackBaseException) e, "CreateTenantUser");
} else {
MsoAdapterException me = new MsoAdapterException(e.getMessage(), e);
me.addContext("CreateTenantUser");
throw me;
}
}
return tenant.getId();
}
use of org.onap.so.openstack.exceptions.MsoException in project so by onap.
the class MsoNeutronUtils method deleteNetwork.
/**
* Delete the specified Network (by ID) in the given cloud. If the network does not exist, success is returned.
* <p>
*
* @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<Void> request = neutronClient.networks().delete(network.getId());
executeAndRecordOpenstackRequest(request);
logger.debug("Deleted Network {} ({})", network.getId(), network.getName());
} catch (OpenStackBaseException e) {
// Convert Neutron exception to an MsoOpenstackException
MsoException me = neutronExceptionToMsoException(e, "Delete Network");
throw me;
} catch (RuntimeException e) {
// Catch-all
MsoException me = runtimeExceptionToMsoException(e, "DeleteNetwork");
throw me;
}
return true;
}
use of org.onap.so.openstack.exceptions.MsoException in project so by onap.
the class MsoNeutronUtils method getNeutronClient.
// -------------------------------------------------------------------
// PRIVATE UTILITY FUNCTIONS FOR USE WITHIN THIS CLASS
/**
* Get a Neutron (Quantum) client for the Openstack Network service. This requires a 'member'-level userId +
* password, which will be retrieved from properties based on the specified cloud Id. The tenant in which to operate
* must also be provided.
* <p>
* 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<Access> request = keystoneTenantClient.tokens().authenticate(credentials).withTenantId(tenantId);
access = executeAndRecordOpenstackRequest(request, true);
try {
neutronUrl = KeystoneUtils.findEndpointURL(access.getServiceCatalog(), "network", region, "public");
if (!neutronUrl.endsWith("/")) {
neutronUrl += "/v2.0/";
}
} catch (RuntimeException e) {
// This comes back for not found (probably an incorrect region ID)
String error = "Network service not found: region=" + region + ",cloud=" + cloudIdentity.getId();
throw new MsoAdapterException(error, e);
}
tokenId = access.getToken().getId();
} else if (ServerType.KEYSTONE_V3.equals(cloudIdentity.getIdentityServerType())) {
try {
KeystoneAuthHolder holder = keystoneV3Authentication.getToken(cloudSite, tenantId, "network");
tokenId = holder.getId();
neutronUrl = holder.getServiceUrl();
if (!neutronUrl.endsWith("/")) {
neutronUrl += "/v2.0/";
}
} catch (ServiceEndpointNotFoundException e) {
// This comes back for not found (probably an incorrect region ID)
String error = "Network service not found: region=" + region + ",cloud=" + cloudIdentity.getId();
throw new MsoAdapterException(error, e);
}
}
} catch (OpenStackResponseException e) {
if (e.getStatus() == 401) {
// Authentication error.
String error = "Authentication Failure: tenant=" + tenantId + ",cloud=" + cloudIdentity.getId();
throw new MsoAdapterException(error);
} else {
MsoException me = keystoneErrorToMsoException(e, "TokenAuth");
throw me;
}
} catch (OpenStackConnectException e) {
// Connection to Openstack failed
MsoIOException me = new MsoIOException(e.getMessage(), e);
me.addContext("TokenAuth");
throw me;
} catch (RuntimeException e) {
// Catch-all
MsoException me = runtimeExceptionToMsoException(e, "TokenAuth");
throw me;
}
Quantum neutronClient = new Quantum(neutronUrl);
neutronClient.token(tokenId);
return neutronClient;
}
Aggregations