/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
/**
*
*/
package com.emc.storageos.computecontroller.impl.ucs;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.bind.JAXBElement;
import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.emc.cloud.platform.clientlib.ClientGeneralException;
import com.emc.cloud.platform.clientlib.ClientMessageKeys;
import com.emc.cloud.platform.ucs.out.model.ComputeBlade;
import com.emc.cloud.platform.ucs.out.model.LsServer;
import com.emc.cloud.platform.ucs.out.model.VnicFc;
import com.emc.cloud.platform.ucs.out.model.VnicFcIf;
import com.emc.cloud.ucsm.service.LsServerOperStates;
import com.emc.cloud.ucsm.service.UCSMService;
import com.emc.storageos.computecontroller.ComputeDevice;
import com.emc.storageos.computesystemcontroller.exceptions.ComputeSystemControllerException;
import com.emc.storageos.computesystemcontroller.exceptions.ComputeSystemControllerTimeoutException;
import com.emc.storageos.coordinator.client.service.CoordinatorClient;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.constraint.ContainmentConstraint;
import com.emc.storageos.db.client.constraint.URIQueryResultList;
import com.emc.storageos.db.client.model.Cluster;
import com.emc.storageos.db.client.model.ComputeElement;
import com.emc.storageos.db.client.model.ComputeElementHBA;
import com.emc.storageos.db.client.model.ComputeSystem;
import com.emc.storageos.db.client.model.ComputeVirtualPool;
import com.emc.storageos.db.client.model.DiscoveredDataObject;
import com.emc.storageos.db.client.model.ExportGroup;
import com.emc.storageos.db.client.model.ExportMask;
import com.emc.storageos.db.client.model.Host;
import com.emc.storageos.db.client.model.Initiator;
import com.emc.storageos.db.client.model.Network;
import com.emc.storageos.db.client.model.StoragePort;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.model.UCSServiceProfile;
import com.emc.storageos.db.client.model.UCSServiceProfileTemplate;
import com.emc.storageos.db.client.model.VirtualArray;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.client.util.CustomQueryUtility;
import com.emc.storageos.db.client.util.NullColumnValueGetter;
import com.emc.storageos.exceptions.DeviceControllerException;
import com.emc.storageos.networkcontroller.impl.NetworkAssociationHelper;
import com.emc.storageos.security.audit.AuditLogManager;
import com.emc.storageos.services.OperationTypeEnum;
import com.emc.storageos.svcs.errorhandling.resources.InternalException;
import com.emc.storageos.util.ExportUtils;
import com.emc.storageos.util.InvokeTestFailure;
import com.emc.storageos.volumecontroller.TaskCompleter;
import com.emc.storageos.volumecontroller.impl.ControllerUtils;
import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator;
import com.emc.storageos.workflow.Workflow;
import com.emc.storageos.workflow.WorkflowService;
import com.emc.storageos.workflow.WorkflowStepCompleter;
public class UcsComputeDevice implements ComputeDevice {
private CoordinatorClient _coordinator = null;
public void setCoordinator(CoordinatorClient coordinator) {
this._coordinator = coordinator;
}
private static final String EVENT_SERVICE_TYPE_CE = "ComputeElement";
private static final String POWER_UP = "up";
private static final String POWER_DOWN = "down";
private static final String ASSOC_STATE_UNASSOCIATED = "unassociated";
/**
* 10 Mins is the default time out if one is not set...
*/
private int deviceOperationTimeOut = 10;
private int deviceOperationPollFrequency = 30;
private WorkflowService workflowService;
public void setWorkflowService(WorkflowService workflowService) {
this.workflowService = workflowService;
}
public int getDeviceOperationPollFrequency() {
return deviceOperationPollFrequency;
}
public void setDeviceOperationPollFrequency(int deviceOperationPollFrequency) {
this.deviceOperationPollFrequency = deviceOperationPollFrequency;
}
public int getDeviceOperationTimeOut() {
return deviceOperationTimeOut;
}
public void setDeviceOperationTimeOut(int deviceOperationTimeOut) {
this.deviceOperationTimeOut = deviceOperationTimeOut;
}
private static final Logger LOGGER = LoggerFactory.getLogger(UcsComputeDevice.class);
private static final String CREATE_HOST_WORKFLOW = "CREATE_HOST_WF";
private static final String CREATE_SP_FROM_SPT_STEP = "CREATE_SP_FROM_SPT";
private static final String MODIFY_SP_BOOT_ORDER_STEP = "MODIFY_SP_BOOT_ORDER";
private static final String BIND_SERVICE_PROFILE_TO_BLADE_STEP = "BIND_SERVICE_PROFILE_TO_BLADE";
private static final String ADD_HOST_PORTS_TO_NETWORKS_STEP = "ADD_HOST_PORTS_TO_NETWORKS";
private DbClient _dbClient;
@Autowired
UCSMService ucsmService;
@Autowired
private AuditLogManager _auditMgr;
public void setDbClient(DbClient dbClient) {
_dbClient = dbClient;
}
@Override
public void discoverComputeSystem(URI computeSystemId) throws InternalException {
LOGGER.info("discoverComputeSystems");
UcsDiscoveryWorker discoveryWorker = new UcsDiscoveryWorker(ucsmService, _dbClient);
discoveryWorker.discoverComputeSystem(computeSystemId);
}
private UCSServiceProfile persistServiceProfileForHost(LsServer lsServer, ComputeSystem cs, URI hostId){
Host host = _dbClient.queryObject(Host.class, hostId);
if (host == null){
LOGGER.error("Host not found for URI:"+ hostId.toString());
throw ComputeSystemControllerException.exceptions.hostNotFound(hostId.toString());
}
UCSServiceProfile serviceProfile = new UCSServiceProfile();
URI uri = URIUtil.createId(UCSServiceProfile.class);
serviceProfile.setComputeSystem(cs.getId());
serviceProfile.setInactive(false);
serviceProfile.setId(uri);
serviceProfile.setSystemType(cs.getSystemType());
serviceProfile.setCreationTime(Calendar.getInstance());
serviceProfile.setDn(lsServer.getDn());
serviceProfile.setLabel(lsServer.getName());
serviceProfile.setUuid(lsServer.getUuid());
serviceProfile.setNativeGuid(NativeGUIDGenerator.generateNativeGuid(cs, serviceProfile));
serviceProfile.setHost(hostId);
_dbClient.createObject(serviceProfile);
host.setServiceProfile(serviceProfile.getId());
_dbClient.updateObject(host);
return serviceProfile;
}
private void setComputeElementAttrFromBoundLsServer(DbClient dbClient, ComputeElement computeElement,
LsServer lsServer, Host host, String systemType, boolean markUnregistered) {
List<ComputeElementHBA> computeElementHBAs = new ArrayList<ComputeElementHBA>();
computeElement.setUuid(lsServer.getUuid());
computeElement.setDn(lsServer.getDn());
String sptName = lsServer.getSrcTemplName();
URIQueryResultList uris = new URIQueryResultList();
_dbClient.queryByConstraint(ContainmentConstraint.Factory
.getComputeSystemServiceProfileTemplateConstraint(computeElement.getComputeSystem()), uris);
List<UCSServiceProfileTemplate> serviceTemplates = _dbClient.queryObject(UCSServiceProfileTemplate.class, uris, true);
for (UCSServiceProfileTemplate serviceTemplate : serviceTemplates) {
if (serviceTemplate.getLabel().equals(sptName)) {
computeElement.setSptId(serviceTemplate.getId().toString());
}
}
if (markUnregistered) {
computeElement.setRegistrationStatus(DiscoveredDataObject.RegistrationStatus.UNREGISTERED.name());
}
computeElement.setAvailable(false);
if (lsServer.getContent() != null && !lsServer.getContent().isEmpty()) {
for (Serializable contentElement : lsServer.getContent()) {
if (contentElement instanceof JAXBElement<?>) {
if (((JAXBElement) contentElement).getValue() instanceof VnicFc) {
VnicFc vnicFc = (VnicFc) ((JAXBElement) contentElement).getValue();
ComputeElementHBA computeElementHBA = new ComputeElementHBA();
computeElementHBA.setComputeElement(computeElement.getId());
computeElementHBA.setHost(host.getId());
computeElementHBA.setCreationTime(Calendar.getInstance());
computeElementHBA.setDn(vnicFc.getDn());
computeElementHBA.setId(URIUtil.createId(ComputeElementHBA.class));
computeElementHBA.setInactive(false);
computeElementHBA.setLabel(vnicFc.getName());
computeElementHBA.setProtocol(vnicFc.getType());
computeElementHBA.setNativeGuid(NativeGUIDGenerator.generateNativeGuid(computeElementHBA,
systemType));
computeElementHBA.setNode(vnicFc.getNodeAddr());
computeElementHBA.setPort(vnicFc.getAddr());
computeElementHBA.setVsanId(getVsanIdFromvnicFC(vnicFc));
computeElementHBAs.add(computeElementHBA);
}
}
}
}
if (!computeElementHBAs.isEmpty()) {
dbClient.createObject(computeElementHBAs);
}
/**
* For the case where the compute element exists, but we are updating
* it:
*/
if (dbClient.queryObject(ComputeElement.class, computeElement.getId()) != null) {
dbClient.updateObject(computeElement);
}
}
private String getVsanIdFromvnicFC(VnicFc vnicFc) {
if (vnicFc == null) {
return null;
}
if (vnicFc.getContent() != null && !vnicFc.getContent().isEmpty()) {
for (Serializable contentElement : vnicFc.getContent()) {
if (contentElement instanceof JAXBElement<?>) {
if (((JAXBElement) contentElement).getValue() instanceof VnicFcIf) {
VnicFcIf vnicFcIf = (VnicFcIf) ((JAXBElement) contentElement).getValue();
return vnicFcIf.getVnet();
}
}
}
}
return null;
}
private void changePowerState(URI csId, URI ceId, String state) throws DeviceControllerException {
LOGGER.info("changePowerState");
ComputeElement ce = _dbClient.queryObject(ComputeElement.class, ceId);
ComputeSystem cs = _dbClient.queryObject(ComputeSystem.class, csId);
OperationTypeEnum typeEnum = POWER_DOWN.equals(state) ? OperationTypeEnum.POWERDOWN_COMPUTE_ELEMENT
: OperationTypeEnum.POWERUP_COMPUTE_ELEMENT;
try {
URL ucsmURL = getUcsmURL(cs);
ucsmService.setLsServerPowerState(ucsmURL.toString(), cs.getUsername(), cs.getPassword(), ce.getDn(),
state);
pullAndPollManagedObject(ucsmURL.toString(), cs.getUsername(), cs.getPassword(), ce.getLabel(),
ComputeBlade.class);
} catch (ComputeSystemControllerTimeoutException cstoe) {
LOGGER.error("Unable to change power state of compute element due to a device TimeOut", cstoe);
throw cstoe;
} catch (Exception e) {
LOGGER.error("Unable to change power state of compute element due to a exception", e);
throw ComputeSystemControllerException.exceptions.powerStateChangeFailed(state, ce != null ? ce.getId()
.toString() : null, e);
}
_auditMgr.recordAuditLog(null, null, EVENT_SERVICE_TYPE_CE, typeEnum, System.currentTimeMillis(),
AuditLogManager.AUDITLOG_SUCCESS, AuditLogManager.AUDITOP_END, ce.getId().toString(), ce.getLabel(),
ce.getNativeGuid(), ce.getUuid(), ce.getOriginalUuid());
}
@Override
public void powerUpComputeElement(URI computeSystemId, URI computeElementId) throws InternalException {
LOGGER.info("powerUpComputeElement");
changePowerState(computeSystemId, computeElementId, POWER_UP);
}
@Override
public void powerDownComputeElement(URI computeSystemId, URI computeElementId) throws InternalException {
LOGGER.info("powerDownComputeElement");
changePowerState(computeSystemId, computeElementId, POWER_DOWN);
}
@Override
public String unbindHostFromTemplate(URI computeSystemId, URI hostId) throws InternalException {
LOGGER.info("unbindHostFromTemplate");
Host host = _dbClient.queryObject(Host.class, hostId);
ComputeSystem cs = _dbClient.queryObject(ComputeSystem.class, computeSystemId);
String sptDn = null;
try {
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_069);
// VBDU [DONE]: COP-28452, Check for initiators in host as well
// No need to check for initiators here, we are only unbinding the service profile template
if (host != null && !NullColumnValueGetter.isNullURI(host.getComputeElement()) && host.getUuid() != null) {
ComputeElement ce = _dbClient.queryObject(ComputeElement.class, host.getComputeElement());
URI sptId = URI.create(ce.getSptId());
UCSServiceProfileTemplate template = _dbClient.queryObject(UCSServiceProfileTemplate.class, sptId);
sptDn = template.getDn();
LsServer sp = ucsmService.getLsServer(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),
host.getUuid());
if (sp != null) {
URL ucsmURL = getUcsmURL(cs);
if(null == ucsmService.unbindSPFromTemplate(ucsmURL.toString(), cs.getUsername(), cs.getPassword(),
sp.getDn())) {
LOGGER.error("Failed to unbind service profile from template due to error from UCSM Service.");
throw new RuntimeException(
"Failed to unbind service profile from template due to error from UCSM Service.");
}
LOGGER.info("Successfully unbound host {} from template {}", host.getLabel(), template.getLabel());
} else {
LOGGER.error("Unable to unbind service profile to template. LsServer is null");
throw new RuntimeException(
"Unable to unbind service profile to template. LsServer is null");
}
} else {
LOGGER.error(
"Unable to unbind service profile to template, due to insufficient host data. Host or ComputeElement or host UUID is null");
throw new RuntimeException(
"Unable to unbind service profile to template, due to insufficient host data. Host or host's computeElement or host UUID is null");
}
} catch (Exception e) {
LOGGER.error("Unable to unbind service profile from template due to a exception", e);
throw ComputeSystemControllerException.exceptions.unbindHostFromTemplateFailed(host != null ? host.getId()
.toString() : null, e);
}
return sptDn;
}
@Override
public void rebindHostToTemplate(URI computeSystemId, URI hostId) throws InternalException {
LOGGER.info("rebindHostToTemplate");
// re-bind host to SPT
Host host = _dbClient.queryObject(Host.class, hostId);
ComputeSystem cs = _dbClient.queryObject(ComputeSystem.class, computeSystemId);
try {
if (host != null && !NullColumnValueGetter.isNullURI(host.getComputeElement()) && host.getUuid() != null) {
ComputeElement ce = _dbClient.queryObject(ComputeElement.class, host.getComputeElement());
URI sptId = URI.create(ce.getSptId());
UCSServiceProfileTemplate template = _dbClient.queryObject(UCSServiceProfileTemplate.class, sptId);
LsServer sp = ucsmService.getLsServer(getUcsmURL(cs).toString(),
cs.getUsername(), cs.getPassword(), host.getUuid());
if (sp != null && template.getLabel() != null) {
if (!sp.getSrcTemplName().equalsIgnoreCase(template.getLabel())) {
URL ucsmURL = getUcsmURL(cs);
if(null == ucsmService.bindSPToTemplate(ucsmURL.toString(), cs.getUsername(), cs.getPassword(), sp.getDn(),
template.getLabel())) {
throw new RuntimeException(
"Failed to rebind service profile to template.");
}
LOGGER.info("Successfully rebound host {} to template {}", host.getLabel(), template.getLabel());
}else {
LOGGER.info("Host is already bound to template, nothing to do. No OP.");
}
} else {
LOGGER.error(
"Unable to bind service profile to template. LsServer or UCSServiceProfileTemplate is null");
throw new RuntimeException(
"Unable to bind service profile to template. LsServer or UCSServiceProfileTemplate is null");
}
} else {
LOGGER.error(
"Unable to bind service profile to template, due to insufficient host data. Host or ComputeElement or host UUID is null");
throw new RuntimeException(
"Unable to bind service profile to template, due to insufficient host data. Host or host's computeElement or host UUID is null");
}
} catch (Exception e) {
LOGGER.error("Unable to bind service profile to template due to a exception", e);
throw ComputeSystemControllerException.exceptions.bindHostToTemplateFailed(host != null ? host.getId()
.toString() : null, e);
}
}
@Override
public void createHost(ComputeSystem computeSystem, Host host, ComputeVirtualPool vcp, VirtualArray varray,
TaskCompleter taskCompleter) throws InternalException {
LOGGER.info("create Host : " + host.getLabel());
LOGGER.info("Host ID: " + host.getId());
try {
Workflow workflow = workflowService.getNewWorkflow(this, CREATE_HOST_WORKFLOW, true,
taskCompleter.getOpId());
String sptDn = getSptDNFromVCP(computeSystem, vcp);
/**
* This condition means that we were not able to find a suitable SPT
* to do the provisioning with from the VCP! Hence abort...
*/
if (sptDn == null) {
throw ComputeSystemControllerException.exceptions.invalidComputeVirtualPool(host.getHostName(),
computeSystem.getNativeGuid(), vcp.getId().toString(),
"Unable to find a suitable ServiceProfileTemplate for provisioning host", null);
}
String createSpToken = workflow.createStepId();
createSpToken = workflow.createStep(CREATE_SP_FROM_SPT_STEP,
"create a service profile from the ServiceProfile template selected in the VCP", null,
computeSystem.getId(), computeSystem.getSystemType(), this.getClass(), new Workflow.Method(
"createLsServer", computeSystem, sptDn, host),
new Workflow.Method(
"deleteLsServer", computeSystem, host.getId(), createSpToken),
createSpToken);
String modifySpBootToken = workflow.createStepId();
modifySpBootToken = workflow
.createStep(
MODIFY_SP_BOOT_ORDER_STEP,
"Modify the created service profile to have an Empty boot policy, if a boot policy was associated, it will be over-written!",
createSpToken, computeSystem.getId(), computeSystem.getSystemType(), this.getClass(),
new Workflow.Method("modifyLsServerNoBoot", computeSystem, createSpToken),
new Workflow.Method("deleteLsServer", computeSystem, host.getId(), createSpToken), modifySpBootToken);
String bindSPStepId = workflow.createStepId();
bindSPStepId = workflow.createStep(BIND_SERVICE_PROFILE_TO_BLADE_STEP,
"bind a service profile to the blade represented by the CE associated with the Host",
modifySpBootToken, computeSystem.getId(), computeSystem.getSystemType(), this.getClass(),
new Workflow.Method("bindServiceProfileToBlade", computeSystem, host.getId(),
createSpToken),
new Workflow.Method("unbindServiceProfile", computeSystem, createSpToken),
bindSPStepId);
String addHostPortsToNetworkStepId = workflow.createStepId();
addHostPortsToNetworkStepId = workflow.createStep(ADD_HOST_PORTS_TO_NETWORKS_STEP,
"Add host ports from service profile to the corresponding network in the vArray", bindSPStepId,
computeSystem.getId(), computeSystem.getSystemType(), this.getClass(), new Workflow.Method(
"addHostPortsToVArrayNetworks", varray, host),
new Workflow.Method(ROLLBACK_NOTHING_METHOD), addHostPortsToNetworkStepId);
workflow.executePlan(taskCompleter, "Successfully created host : " + host.getHostName());
LOGGER.info("create Host : " + host.getLabel() + " Complete");
} catch (InternalException e) {
taskCompleter.error(_dbClient, e);
} catch (Exception e) {
taskCompleter.error(_dbClient, DeviceControllerException.errors.unforeseen());
}
}
public void unbindServiceProfile(ComputeSystem cs, String contextStepId, String stepId)
throws ClientGeneralException {
WorkflowStepCompleter.stepExecuting(stepId);
String spDn = (String) workflowService.loadStepData(contextStepId);
try {
if (spDn != null) {
LOGGER.info("Unbinding Service Profile : " + spDn + " from blade");
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_067);
if (null == ucsmService.unbindServiceProfile(getUcsmURL(cs).toString(), cs.getUsername(),
cs.getPassword(), spDn)) {
throw new RuntimeException("Failed to unbind service profile.");
}
LOGGER.info("Done Unbinding Service Profile : " + spDn + " from blade");
} else {
LOGGER.info("No OP");
}
WorkflowStepCompleter.stepSucceded(stepId);
} catch (Exception e) {
LOGGER.error("Unable to unbindServiceProfile...", e);
WorkflowStepCompleter.stepFailed(stepId, ComputeSystemControllerException.exceptions.unableToProvisionHost(
spDn, cs.getNativeGuid(), e));
}
}
private String getSptDNFromVCP(ComputeSystem computeSystem, ComputeVirtualPool virtualPool) {
StringSet spts = virtualPool.getServiceProfileTemplates();
if (spts == null) {
return null;
}
for (String sptId : spts) {
URI sptUri = URI.create(sptId);
UCSServiceProfileTemplate serviceProfileTemplate = _dbClient.queryObject(UCSServiceProfileTemplate.class,
sptUri);
if (serviceProfileTemplate != null && serviceProfileTemplate.getComputeSystem() != null
&& serviceProfileTemplate.getComputeSystem().equals(computeSystem.getId())) {
return serviceProfileTemplate.getDn();
}
}
return null;
}
@Override
public Map<String, Boolean> prepareOsInstallNetwork(URI computeSystemId, URI computeElementId)
throws InternalException {
LOGGER.info("prepareOsInstallNetwork");
ComputeSystem cs = _dbClient.queryObject(ComputeSystem.class, computeSystemId);
ComputeElement ce = _dbClient.queryObject(ComputeElement.class, computeElementId);
String osInstallVlan = cs.getOsInstallNetwork();
Map<String, Boolean> vlanMap = null;
try {
vlanMap = ucsmService.setOsInstallVlan(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),
ce.getDn(), osInstallVlan);
} catch (ClientGeneralException e) {
LOGGER.error(
"Unable to set os install vlan: " + cs.getOsInstallNetwork() + " On computeElement : " + ce.getId(),
e);
throw ComputeSystemControllerException.exceptions.unableToSetOsInstallNetwork(osInstallVlan, ce.getId()
.toString(), e);
}
return vlanMap;
}
@Override
public void removeOsInstallNetwork(URI computeSystemId, URI computeElementId, Map<String, Boolean> vlanMap)
throws InternalException {
LOGGER.info("removeOsInstallNetwork");
ComputeSystem cs = _dbClient.queryObject(ComputeSystem.class, computeSystemId);
ComputeElement ce = _dbClient.queryObject(ComputeElement.class, computeElementId);
String osInstallVlan = cs.getOsInstallNetwork();
try {
ucsmService.removeOsInstallVlan(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(), ce.getDn(),
osInstallVlan, vlanMap);
} catch (ClientGeneralException e) {
LOGGER.error(
"Unable to set os install vlan: " + cs.getOsInstallNetwork() + " On computeElement : " + ce.getId(),
e);
throw ComputeSystemControllerException.exceptions.unableToRemoveOsInstallNetwork(osInstallVlan, ce.getId()
.toString(), e);
}
}
private <T> T pullAndPollManagedObject(String url, String username, String password, String managedObjectDn,
Class<T> returnType) throws ClientGeneralException, ComputeSystemControllerException {
LOGGER.debug("Entering pullAndPollManagedObject for ManagedObject of Type : " + returnType + ":"
+ managedObjectDn);
T pulledManagedObject = ucsmService.getManagedObject(url, username, password, managedObjectDn, false,
returnType);
if (pulledManagedObject == null) {
throw new ClientGeneralException(ClientMessageKeys.NOT_FOUND, new String[] { managedObjectDn });
}
LOGGER.debug("Transient Initial OperState of the ManagedObject : "
+ callSimpleReadOnlyMethodOnMO(pulledManagedObject, "operState"));
LOGGER.debug("Transient Initial AssocState of the ManagedObject : "
+ callSimpleReadOnlyMethodOnMO(pulledManagedObject, "assocState"));
Calendar timeOutTime = Calendar.getInstance();
int deviceOperationTimeout = getDeviceOperationTimeOut();
timeOutTime.add(Calendar.SECOND, deviceOperationTimeout);
do {
if (Calendar.getInstance().after(timeOutTime)) {
LOGGER.warn("Time out occured waiting for operation to finish on the LsServer : " + managedObjectDn
+ "Waited for " + deviceOperationTimeout + "seconds...");
throw ComputeSystemControllerException.exceptions.timeoutWaitingForMOTerminalState(
callSimpleReadOnlyMethodOnMO(pulledManagedObject, "dn"),
callSimpleReadOnlyMethodOnMO(pulledManagedObject, "operState"), deviceOperationTimeout);
}
try {
Thread.sleep(getDeviceOperationPollFrequency() * 1000);
} catch (InterruptedException e) {
LOGGER.warn("Thread : " + Thread.currentThread().getName() + " interrupted...");
}
pulledManagedObject = ucsmService.getManagedObject(url, username, password, managedObjectDn, false,
returnType);
LOGGER.debug("Current OperState of the ManagedObject : "
+ callSimpleReadOnlyMethodOnMO(pulledManagedObject, "operState"));
LOGGER.debug("Current AssocState of the ManagedObject : "
+ callSimpleReadOnlyMethodOnMO(pulledManagedObject, "assocState"));
} while (!LsServerOperStates.isTerminal(callSimpleReadOnlyMethodOnMO(pulledManagedObject, "operState")));
LOGGER.debug("Terminal OperState of the ManagedObject : "
+ callSimpleReadOnlyMethodOnMO(pulledManagedObject, "operState"));
LOGGER.debug("Terminal AssocState of the ManagedObject : "
+ callSimpleReadOnlyMethodOnMO(pulledManagedObject, "assocState"));
return ucsmService.getManagedObject(url, username, password, managedObjectDn, true, returnType);
}
private String callSimpleReadOnlyMethodOnMO(Object obj, String property) {
if (obj == null) {
return null;
}
try {
return BeanUtils.getSimpleProperty(obj, property);
} catch (Exception e) {
// Ignore exceptions here on purpose!
}
return null;
}
/**
* Create a LsServer
* @param cs ComputeSystem instance
* @param sptDn serviceProfile template distinguished name (DN)
* @param host Host being created
* @param stepId Id of step being executed.
* @return LsServer instance
*/
public boolean createLsServer(ComputeSystem cs, String sptDn, Host host, String stepId) {
WorkflowStepCompleter.stepExecuting(stepId);
LOGGER.info("Creating Service Profile : " + host.getHostName() + " from Service Profile Template : " + sptDn);
LsServer lsServer = null;
try {
lsServer = ucsmService.createServiceProfileFromTemplate(getUcsmURL(cs).toString(), cs.getUsername(),
cs.getPassword(), sptDn, host.getHostName());
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_073);
if (lsServer == null) {
throw new RuntimeException("UCS call to create service profile from template failed, null LsServer was returned.");
}
workflowService.storeStepData(stepId, lsServer.getDn());
UCSServiceProfile serviceProfile = persistServiceProfileForHost(lsServer,cs, host.getId());
validateNewServiceProfile(cs, serviceProfile, host);
lsServer = pullAndPollManagedObject(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),
lsServer.getDn(), LsServer.class);
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_061);
if (lsServer == null) {
throw new RuntimeException("UCS call to poll for ManagedObject failed, null LsServer was returned.");
}
} catch (Exception e) {
LOGGER.error("Unable to createLsServer...", e);
WorkflowStepCompleter.stepFailed(stepId,
ComputeSystemControllerException.exceptions.unableToProvisionHost(host.getHostName(), cs.getNativeGuid(), e));
return false;
}
WorkflowStepCompleter.stepSucceded(stepId);
LOGGER.info("Done Creating Service Profile : " + lsServer.getDn() + " from Service Profile Template : " + sptDn);
return true;
}
private void validateNewServiceProfile(ComputeSystem cs, UCSServiceProfile serviceProfile, Host newHost){
Collection<URI> allHostUris = _dbClient.queryByType(Host.class, true);
Collection<Host> hosts = _dbClient.queryObjectFields(Host.class,
Arrays.asList("uuid","label", "computeElement", "registrationStatus", "inactive"), ControllerUtils.getFullyImplementedCollection(allHostUris));
for (Host host: hosts) {
if (host.getUuid()!=null && host.getUuid().equals(serviceProfile.getUuid()) && !host.getId().equals(newHost.getId()) && (host.getInactive()!=true)){
LOGGER.error("Newly created service profile :"+ serviceProfile.getLabel() + " shares same uuid "+ serviceProfile.getUuid() +" as existing active host: " + host.getLabel());
throw ComputeSystemControllerException.exceptions.newServiceProfileDuplicateUuid(serviceProfile.getLabel(), serviceProfile.getUuid(), host.getLabel());
}
}
}
/**
* Modify the LsServer to have a no boot policy
* @param cs ComputeSystem instance
* @param contextStepId parent StepId
* @param stepId Id of step being executed.
* @return LsServer instance
*/
public LsServer modifyLsServerNoBoot(ComputeSystem cs, String contextStepId, String stepId) {
WorkflowStepCompleter.stepExecuting(stepId);
String spDn = (String) workflowService.loadStepData(contextStepId);
LOGGER.info("Modifying Service Profile to have no Boot Policy: " + spDn);
LsServer lsServer = null;
try {
lsServer = ucsmService.setServiceProfileToNoBoot(getUcsmURL(cs).toString(), cs.getUsername(),
cs.getPassword(), spDn);
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_062);
if (null == lsServer) {
throw new RuntimeException("UCS invocation to set serviceProfile to No Boot failed, null LsServer was returned.");
}
WorkflowStepCompleter.stepSucceded(stepId);
LOGGER.info("Done updating Service Profile : " + spDn + " from Service Profile Template : " + spDn);
} catch (Exception e) {
LOGGER.error("Unable to modify LsServer...", e);
WorkflowStepCompleter.stepFailed(stepId,
ComputeSystemControllerException.exceptions.unableToProvisionHost(spDn, cs.getNativeGuid(), e));
}
return lsServer;
}
public void deleteLsServer(ComputeSystem cs, URI hostURI, String createSpStepId, String stepId) throws ClientGeneralException {
WorkflowStepCompleter.stepExecuting(stepId);
String spDn = null;
try {
Host host = _dbClient.queryObject(Host.class, hostURI);
UCSServiceProfile profile = null;
if (host!=null){
if (!NullColumnValueGetter.isNullURI(host.getServiceProfile())){
profile = _dbClient.queryObject(UCSServiceProfile.class, host.getServiceProfile());
if (profile == null){
throw ComputeSystemControllerException.exceptions.invalidServiceProfileReference(host.getServiceProfile().toString());
}else {
spDn = profile.getDn();
if (spDn != null) {
LOGGER.info("Deleting Service Profile : " + spDn);
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_066);
ucsmService.deleteServiceProfile(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(), spDn);
LOGGER.info("Done Deleting Service Profile : " + spDn);
_dbClient.markForDeletion(profile);
host.setServiceProfile(NullColumnValueGetter.getNullURI());
}else {
throw ComputeSystemControllerException.exceptions.invalidServiceProfile(host.getServiceProfile().toString());
}
}
}
if (!NullColumnValueGetter.isNullURI(host.getComputeElement())){
ComputeElement computeElement = _dbClient.queryObject(ComputeElement.class, host.getComputeElement());
if (computeElement!=null){
computeElement.setAvailable(true);
computeElement.setUuid(null);
_dbClient.updateObject(computeElement);
}
host.setComputeElement(NullColumnValueGetter.getNullURI());
}
_dbClient.updateObject(host);
}
WorkflowStepCompleter.stepSucceded(stepId);
} catch (Exception e) {
LOGGER.error("Unable to deleteLsServer...", e);
WorkflowStepCompleter.stepFailed(stepId, ComputeSystemControllerException.exceptions.unableToProvisionHost(
spDn, cs.getNativeGuid(), e));
}
}
public void bindServiceProfileToBlade(ComputeSystem computeSystem, URI hostURI, String contextStepId,
String stepId) {
ComputeElement computeElement = null;
LsServer serviceProfile = null;
String spDn = null;
try {
WorkflowStepCompleter.stepExecuting(stepId);
spDn = (String) workflowService.loadStepData(contextStepId);
if (spDn == null) {
throw new IllegalStateException(
"Invalid value for step data. Previous step didn't persist required data.");
}
Host host = _dbClient.queryObject(Host.class, hostURI);
computeElement = _dbClient.queryObject(ComputeElement.class, host.getComputeElement());
if (computeElement != null) {
LOGGER.info("Binding Service Profile : " + spDn + " to blade : " + computeElement.getLabel());
serviceProfile = ucsmService.bindSPToComputeElement(getUcsmURL(computeSystem).toString(),
computeSystem.getUsername(), computeSystem.getPassword(), spDn, computeElement.getLabel());
serviceProfile = pullAndPollManagedObject(getUcsmURL(computeSystem).toString(),
computeSystem.getUsername(), computeSystem.getPassword(), spDn, LsServer.class);
// Test mechanism to invoke a failure. No-op on production
// systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_063);
if (serviceProfile == null || ASSOC_STATE_UNASSOCIATED.equals(serviceProfile.getAssocState())) {
LOGGER.info("SP {} AssocState is marked unassociated or null. Bind ServiceProfileToBlade failed", spDn);
throw new RuntimeException(BIND_SERVICE_PROFILE_TO_BLADE_STEP + " failed. ServiceProfile state is "
+ (serviceProfile == null ? "null" : serviceProfile.getAssocState()));
}
// Test mechanism to invoke a failure. No-op on production
// systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_064);
setComputeElementAttrFromBoundLsServer(_dbClient, computeElement, serviceProfile, host,
computeSystem.getSystemType(), false);
LOGGER.info("Done binding Service Profile : " + spDn + " to blade : " + computeElement.getLabel());
WorkflowStepCompleter.stepSucceded(stepId);
} else {
LOGGER.info("Unable to associate computeElement and LsServer/serviceProfile attribute. ComputeElement is null.");
throw new RuntimeException(BIND_SERVICE_PROFILE_TO_BLADE_STEP + " failed.");
}
} catch (Exception e) {
LOGGER.error("Step : " + BIND_SERVICE_PROFILE_TO_BLADE_STEP + " Failed...", e);
WorkflowStepCompleter.stepFailed(
stepId,
ComputeSystemControllerException.exceptions.unableToProvisionHost(spDn,
computeSystem.getNativeGuid(), e));
}
}
private URL getUcsmURL(ComputeSystem cs) {
URL ucsmURL;
try {
if (cs.getSecure()) {
ucsmURL = new URL("https", cs.getIpAddress(), cs.getPortNumber(), "/nuova");
} else {
ucsmURL = new URL("http", cs.getIpAddress(), cs.getPortNumber(), "/nuova");
}
} catch (MalformedURLException e) {
LOGGER.error("Invalid IP Address / Hostname / Port for Compute System: " + cs.getId(), e);
throw DeviceControllerException.exceptions.invalidURI(e);
}
return ucsmURL;
}
public void addHostPortsToVArrayNetworks(VirtualArray varray, Host host, String stepId) {
LOGGER.info("Adding host ports to networks in Varray : " + varray.getLabel() + "for Host: "
+ host.getHostName());
WorkflowStepCompleter.stepExecuting(stepId);
try {
if (!NullColumnValueGetter.isNullURI(host.getComputeElement())) {
Map<Network, List<String>> networkToInitiatorMap = Collections
.synchronizedMap(new HashMap<Network, List<String>>());
Map<String, Network> networkIdNetworkMapInVarray = getVarrayNetworkMap(_dbClient, varray.getId());
URIQueryResultList ceHBAUriList = new URIQueryResultList();
_dbClient.queryByConstraint(ContainmentConstraint.Factory.getHostComputeElemetHBAsConstraint(host
.getId()), ceHBAUriList);
Iterator<URI> ceHBAUriListIterator = ceHBAUriList.iterator();
Cluster cluster = null;
if (host.getCluster() != null) {
cluster = _dbClient.queryObject(Cluster.class, host.getCluster());
}
while (ceHBAUriListIterator.hasNext()) {
URI ceHBAUri = ceHBAUriListIterator.next();
ComputeElementHBA computeElementHBA = _dbClient.queryObject(ComputeElementHBA.class, ceHBAUri);
Initiator initiator = new Initiator();
initiator.setHost(host.getId());
initiator.setHostName(host.getHostName());
initiator.setId(URIUtil.createId(Initiator.class));
if (cluster != null) {
initiator.setClusterName(cluster.getLabel());
}
initiator.setInitiatorNode(computeElementHBA.getNode());
initiator.setInitiatorPort(computeElementHBA.getPort());
initiator.setProtocol(computeElementHBA.getProtocol() != null ? computeElementHBA.getProtocol()
.toUpperCase() : null);
// Search against the database, fail if you see the wwn in the database already.
Initiator dbInitiator = ExportUtils.getInitiator(initiator.getInitiatorPort(), _dbClient);
if (dbInitiator != null) {
throw ComputeSystemControllerException.exceptions.illegalInitiator(
host.getHostName(), dbInitiator.getInitiatorPort(), dbInitiator.getHostName());
}
Network network = networkIdNetworkMapInVarray.get(computeElementHBA.getVsanId());
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_065);
if (network == null) {
LOGGER.error("No corresponding Network for HBA {} in vArray {}. Network null from DB.",
computeElementHBA.getPort(), varray.getId());
throw new RuntimeException(
ComputeSystemControllerException.exceptions.noCorrespondingNetworkForHBAInVarray(
computeElementHBA.getPort(), varray.getLabel(), null));
} else {
if (networkToInitiatorMap.get(network) == null) {
networkToInitiatorMap.put(network, new ArrayList<String>());
}
networkToInitiatorMap.get(network).add(computeElementHBA.getPort());
}
_dbClient.createObject(initiator);
}
/**
* Add all the newly added endpoints to their respective networks!
*/
for (Network network : networkToInitiatorMap.keySet()) {
network.addEndpoints(networkToInitiatorMap.get(network), false);
_dbClient.updateObject(network);
handleEndpointsAdded(network, networkToInitiatorMap.get(network), _dbClient, _coordinator);
}
}
WorkflowStepCompleter.stepSucceded(stepId);
LOGGER.info("Done adding host ports to networks in Varray : " + varray.getLabel() + "for Host: "
+ host.getHostName());
} catch (Exception ex) {
LOGGER.error("Exception while adding host ports to vArray networks. {}", ex);
WorkflowStepCompleter.stepFailed(stepId, ComputeSystemControllerException.exceptions
.unableToAddHostPortsToVArrayNetworks(varray.getLabel()
.toString(), ex));
}
}
private void handleEndpointsAdded(Network network, Collection<String> endpoints, DbClient dbClient,
CoordinatorClient coordinator) {
// find if the endpoints exit in some old transport zone
Map<String, Network> transportZoneMap = NetworkAssociationHelper.getNetworksMap(endpoints, dbClient);
if (!transportZoneMap.isEmpty()) {
LOGGER.info("Added endpoints {} to network {}", endpoints.toArray(), network.getLabel());
// before we add the endpoints, they need to be removed from their
// old transport zones
NetworkAssociationHelper.handleRemoveFromOldNetworks(transportZoneMap, network, dbClient, coordinator);
}
// now, add the the endpoints
NetworkAssociationHelper.handleEndpointsAdded(network, endpoints, dbClient, coordinator);
}
private Map<String, Network> getVarrayNetworkMap(DbClient dbClient, URI varray) {
Map<String, Network> networkIdNetworkMapInVarray = new HashMap<String, Network>();
List<Network> varrayAssociatedNetworks = CustomQueryUtility.queryActiveResourcesByRelation(dbClient, varray,
Network.class, "connectedVirtualArrays");
for (Network network : varrayAssociatedNetworks) {
networkIdNetworkMapInVarray.put(network.getNativeId(), network);
}
return networkIdNetworkMapInVarray;
}
@Override
public void setNoBoot(ComputeSystem cs, URI computeElementId, URI hostId,
boolean waitForServerRestart) throws InternalException {
ComputeElement computeElement = _dbClient.queryObject(ComputeElement.class, computeElementId);
try {
if (null != computeElement) {
LsServer lsServer = ucsmService.setServiceProfileToNoBoot(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),
computeElement.getDn());
if (lsServer != null) {
if (waitForServerRestart) {
pullAndPollManagedObject(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),
computeElement.getDn(), LsServer.class);
}
}else {
throw new RuntimeException("Failed to set no boot target due to error from UCSM Service");
}
} else {
throw new RuntimeException("ComputeElement object is null for id " + computeElementId);
}
} catch (Exception e) {
throw ComputeSystemControllerException.exceptions.unableToSetNoBoot(
computeElement != null ? computeElement.getLabel() : computeElementId.toString(), e);
}
}
@Override
public void setLanBootTarget(ComputeSystem cs, URI computeElementId, URI hostId,
boolean waitForServerRestart) throws InternalException {
ComputeElement computeElement = _dbClient.queryObject(ComputeElement.class, computeElementId);
try {
if (null != computeElement) {
LsServer lsServer = ucsmService.setServiceProfileToLanBoot(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),
computeElement.getDn());
if (lsServer != null) {
if (waitForServerRestart) {
pullAndPollManagedObject(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),
computeElement.getDn(), LsServer.class);
}
}else {
throw new RuntimeException("Failed to set LAN boot target due to error from UCSM Service");
}
} else {
throw new RuntimeException("ComputeElement object is null for id " + computeElementId);
}
} catch (Exception e) {
throw ComputeSystemControllerException.exceptions.unableToSetLanBoot(computeElementId.toString(), e);
}
}
@Override
public void setSanBootTarget(ComputeSystem cs, URI computeElementId, URI hostId, URI volumeId,
boolean waitForServerRestart) throws InternalException {
ComputeElement computeElement = _dbClient.queryObject(ComputeElement.class, computeElementId);
Map<String, Map<String, Integer>> hbaToStoragePorts = getHBAToStoragePorts(volumeId, hostId);
// VBDU TODO: COP-28455, HBAToStoragePorts are being constructed from the zoning map, for co-existence masks the
// zoning map will be empty in older releases. Do we need to still continue this operation?
try {
if (null != computeElement) {
LsServer lsServer = ucsmService.setServiceProfileToSanBoot(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),
computeElement.getDn(), hbaToStoragePorts);
if (lsServer != null) {
if (waitForServerRestart) {
pullAndPollManagedObject(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),
computeElement.getDn(), LsServer.class);
}
}else {
throw new RuntimeException("Failed to set SAN boot target due to error from UCSM Service");
}
} else {
throw new RuntimeException("ComputeElement object is null for id " + computeElementId);
}
} catch (Exception e) {
throw ComputeSystemControllerException.exceptions.unableToSetSanBootTarget(computeElementId.toString(), e);
}
}
private Map<String, Map<String, Integer>> getHBAToStoragePorts(URI volumeId, URI hostId) {
Host host = _dbClient.queryObject(Host.class, hostId);
Map<String, String> initiatorToHBAMapping = getInitiatorToHBAMapping(host.getComputeElement());
Volume volume = _dbClient.queryObject(Volume.class, volumeId);
List<Initiator> initiators = CustomQueryUtility.queryActiveResourcesByRelation(_dbClient, hostId,
Initiator.class, "host");
Map<ExportMask, ExportGroup> exportMasks = ExportUtils.getExportMasks(volume, _dbClient);
Map<String, Map<String, Integer>> hbaToStoragePortMapForBoot = new HashMap<String, Map<String, Integer>>();
for (Initiator initiator : initiators) {
for (ExportMask exportMask : exportMasks.keySet()) {
List<URI> storagePorts = ExportUtils.getInitiatorPortsInMask(exportMask, initiator, _dbClient);
if (storagePorts != null && !storagePorts.isEmpty()) {
Integer volumeHLU = Integer.valueOf(exportMask.getVolumes().get(volumeId.toString()));
for (URI storagePortUri : storagePorts) {
StoragePort port = _dbClient.queryObject(StoragePort.class, storagePortUri);
String hbaName = initiatorToHBAMapping.get(initiator.getInitiatorPort());
if (hbaName != null) {
if (hbaToStoragePortMapForBoot.get(hbaName) == null) {
hbaToStoragePortMapForBoot.put(hbaName, new HashMap<String, Integer>());
}
hbaToStoragePortMapForBoot.get(hbaName).put(port.getPortNetworkId(), volumeHLU);
}
}
}
}
}
return hbaToStoragePortMapForBoot;
}
private Map<String, String> getInitiatorToHBAMapping(URI computeElement) {
Map<String, String> hostInitiatorToHBAMapping = new HashMap<String, String>();
List<ComputeElementHBA> hbas = CustomQueryUtility.queryActiveResourcesByRelation(_dbClient, computeElement,
ComputeElementHBA.class, "computeElement");
for (ComputeElementHBA hba : hbas) {
hostInitiatorToHBAMapping.put(hba.getPort(), hba.getLabel());
}
return hostInitiatorToHBAMapping;
}
@Override
public void clearDeviceSession(URI computeSystemId) throws InternalException {
try {
ComputeSystem cs = _dbClient.queryObject(ComputeSystem.class, computeSystemId);
URL ucsmURL = getUcsmURL(cs);
ucsmService.clearDeviceSession(ucsmURL.toString(), cs.getUsername(), cs.getPassword());
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
@Override
public void deactivateHost(ComputeSystem cs, Host host) throws ClientGeneralException {
LOGGER.info("deactivateHost");
try{
unbindHostFromComputeElement(cs,host);
deleteServiceProfile(cs,host);
}catch (ClientGeneralException e){
LOGGER.error("Unable to deactivate host : ", e);
throw e;
}catch (Exception ex) {
LOGGER.error("Error while deactivating host {} check stacktrace", host.getLabel(), ex);
throw ex;
}
}
/*
* Unbinds the host's service profile from the associated blade.
* Determines the service profile to unbind using host's serviceProfile association.
* In case of host provisioned using pre-Anakin version of ViPR and no serviceProfile association yet set,
* serviceprofile to unbind will be determined by trying to find a serviceProfile that matches
* the computeElement's uuid.
*/
private void unbindHostFromComputeElement(ComputeSystem cs, Host host) throws ClientGeneralException {
// VBDU [DONE]: COP-28452, Check initiators count, if empty do we still need to delete service profile?
// We already checked for empty initiators in a step before we get here
if (host != null && !NullColumnValueGetter.isNullURI(host.getComputeElement())) {
ComputeElement computeElement = _dbClient.queryObject(ComputeElement.class, host.getComputeElement());
if (computeElement == null){
LOGGER.error("Host "+ host.getLabel()+ " has associated computeElementURI: "+ host.getComputeElement()+ " which is an invalid reference");
LOGGER.info("Service profile unbind will not be triggered");
return ;
}
String spDn = null;
LOGGER.info("Host.uuid: "+host.getUuid() + " ComputeElement.uuid: "+ computeElement.getUuid());
if (NullColumnValueGetter.isNullURI(host.getServiceProfile())){
LOGGER.error("Host has no asscoaited serviceProfile. Service profile unbind will not be triggered.");
return;
}
UCSServiceProfile serviceProfile = _dbClient.queryObject(UCSServiceProfile.class, host.getServiceProfile());
if (serviceProfile == null){
LOGGER.error("Host "+ host.getLabel()+ " has associated serviceProfileURI: "+ host.getServiceProfile()+ " which is an invalid reference");
LOGGER.info("Service profile unbind will not be triggered");
return ;
}else {
spDn = serviceProfile.getDn();
LOGGER.info("Host.uuid: "+host.getUuid() + " ComputeElement.uuid: "+ computeElement.getUuid() + "serviceProfile.uuid:" + serviceProfile.getUuid());
}
if (spDn!=null){
LOGGER.info("Unbinding service profile with dn: "+ spDn);
LsServer unboundServiceProfile = ucsmService.unbindServiceProfile(getUcsmURL(cs).toString(),
cs.getUsername(), cs.getPassword(), spDn);
LOGGER.info("Operational state of Deleted Service Profile : " + unboundServiceProfile.getOperState());
ComputeBlade computeBlade = pullAndPollManagedObject(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),
computeElement.getLabel(), ComputeBlade.class);
if (computeBlade == null){
LOGGER.info("ComputeBlade "+ computeElement.getLabel()+ " not found on UCS");
} else {
// Release the computeElement back into the pool as soon as we have unbound it from the service profile
if (LsServerOperStates.UNASSOCIATED.equals(LsServerOperStates.fromString(computeBlade.getOperState()))) {
computeElement.setAvailable(true);
computeElement.setUuid(null);
_dbClient.updateObject(computeElement);
}
}
} else {
LOGGER.error("spDn is null. Cannot determine the service profile to unbind");
}
} else {
LOGGER.info("NO OP. Host is null or has no associated compute element");
}
}
/*
* Deletes the host's service profile.
* Determines the service profile to delete using host's serviceProfile association.
* In case of host provisioned using pre-Anakin version of ViPR and no serviceProfile association yet set,
* serviceprofile to delete will be determined by trying to find a serviceProfile that matches
* the computeElement's uuid.
*/
private void deleteServiceProfile(ComputeSystem cs, Host host) throws ClientGeneralException {
UCSServiceProfile serviceProfile = null;
if (host!=null){
String spDn = null;
if (NullColumnValueGetter.isNullURI(host.getServiceProfile())){
LOGGER.info("Host has no associated service profile. cannot delete service profile.");
return;
} else {
serviceProfile = _dbClient.queryObject(UCSServiceProfile.class, host.getServiceProfile());
if (serviceProfile == null){
LOGGER.error("Host "+ host.getLabel()+ " has associated serviceProfileURI: "+ host.getServiceProfile()+ " which is an invalid reference");
LOGGER.info("Service profile deletion will not be triggered");
return;
}else {
spDn = serviceProfile.getDn();
}
}
if (spDn!=null){
LOGGER.info("Deleting serviceProfile " + spDn );
ucsmService.deleteServiceProfile(getUcsmURL(cs).toString(), cs.getUsername(), cs.getPassword(),spDn);
host.setServiceProfile(NullColumnValueGetter.getNullURI());
host.setComputeElement(NullColumnValueGetter.getNullURI());
_dbClient.updateObject(host);
if (serviceProfile!=null){
_dbClient.markForDeletion(serviceProfile);
}
} else {
LOGGER.info("No service profile to delete");
}
// On successful deletion of the service profile - get rid of the objects that represent objects from the service profile
LOGGER.info("Removing host endpoints");
removeHostInitiatorsFromNetworks(host);
}else {
LOGGER.info("host is null. NO OP");
}
}
/**
* Gets rid of the Initiators that were added to network. Also gets rid of
* the ComputeElementHBAs that were created when the service profile was
* bound to the host
*
* @param host
*/
private void removeHostInitiatorsFromNetworks(Host host) {
URIQueryResultList ceHBAUriList = new URIQueryResultList();
_dbClient.queryByConstraint(
ContainmentConstraint.Factory.getHostComputeElemetHBAsConstraint(host.getId()),
ceHBAUriList);
Set<Network> networks = new HashSet<Network>();
List<String> endpoints = new ArrayList<String>();
List<ComputeElementHBA> computeElementHBAs = _dbClient.queryObject(ComputeElementHBA.class, ceHBAUriList, true);
for (ComputeElementHBA computeElementHBA : computeElementHBAs) {
endpoints.add(computeElementHBA.getPort());
networks.addAll(CustomQueryUtility.queryActiveResourcesByAltId(_dbClient, Network.class, "nativeId",
computeElementHBA.getVsanId()));
_dbClient.markForDeletion(computeElementHBA);
}
for (Network network : networks) {
Collection<String> removedEndpoints = network.removeEndpoints(endpoints);
NetworkAssociationHelper.handleEndpointsRemoved(network, removedEndpoints, _dbClient, _coordinator);
}
_dbClient.persistObject(networks);
}
private static final String ROLLBACK_NOTHING_METHOD = "rollbackNothingMethod";
/**
* This is needed if any of the workflow steps do not have a real rollback method.
*
* @param stepId
*/
public void rollbackNothingMethod(String stepId) {
LOGGER.info("ROLLBACK_NOTHING_METHOD invoked nothing to be done, apart from success...");
WorkflowStepCompleter.stepSucceded(stepId);
}
/**
* initialize timeout defaults for UCS operations.
*/
public void initializeDefaults() {
int deviceTimeout = -1;
int pollfrequency = -1;
try {
deviceTimeout = Integer.valueOf(ControllerUtils.getPropertyValueFromCoordinator(_coordinator,
"controller_ucs_communication_timeout"));
pollfrequency = Integer.valueOf(ControllerUtils.getPropertyValueFromCoordinator(_coordinator,
"controller_ucs_device_operation_pollfrequency"));
} catch (Exception e) {
LOGGER.warn(
"Exception while retriving ucs device operation timeout or poll frequency values from coordinator.",
e);
}
if(deviceTimeout > -1) {
deviceOperationTimeOut = deviceTimeout;
}
if(pollfrequency > -1) {
deviceOperationPollFrequency = pollfrequency;
}
}
}